Django - Whatsapp Sessions for scheduled messages - django

I'm developing a system where users, in addition to all the bureaucratic part, can register their clients' whatsapp so that automatic billing messages, congratulations, etc. are sent. Where the user would read the QR code and the system would be in charge of sending messages over time, using the user's whatsapp, thus opening a user<-> clinet conversation. I'm dividing this problem into parts, for now I'm trying to read the Whatsapp Web Qr Code and display it in a template. This is already happening. The problem is that the webdriver is terminated first, as soon as the image is returned to the template, then the session cannot be validated. The webdriver remains open forever, or closes before the image is sent to the template, the image needs to go to the template via return (or another way) and the webdriver remains active for a while. How to solve this concurrent task?
# views.py
from django.shortcuts import render
from django.http import HttpResponse
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import base64
import time
from django.shortcuts import render
def read_qr_code(request):
driver = webdriver.Firefox()
# driver.implicitly_wait(30) # mantém o webdriver ativo por 2 minutos
driver.get('https://web.whatsapp.com/')
wait = WebDriverWait(driver, 10)
qr_element = wait.until(EC.presence_of_element_located((By.XPATH, '//*[#id="app"]/div/div/div[3]/div[1]/div/div/div[2]/div/canvas')))
qr_image_binary = qr_element.screenshot_as_png
qr_image_base64 = base64.b64encode(qr_image_binary).decode('utf-8')
context = {
'image_data': qr_image_base64
}
# send_qr(request, context)
# time.sleep(20) # aguarda por 2 minutos
# driver.quit() # fecha o webdriver
return render(request, 'read_qr_code.html', context)

I solved this problmes using Threds, the code is.
# views.py
from django.shortcuts import render
from django.http import HttpResponse
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import base64
import time
from django.shortcuts import render
import threading
def quit_driver_thread():
time.sleep(40)
driver.quit()
def read_qr_code(request):
global driver
driver = webdriver.Firefox()
driver.implicitly_wait(120)
driver.get('https://web.whatsapp.com/')
wait = WebDriverWait(driver, 10)
qr_element = wait.until(EC.presence_of_element_located((By.XPATH, '//*[#id="app"]/div/div/div[3]/div[1]/div/div/div[2]/div/canvas')))
qr_image_binary = qr_element.screenshot_as_png
qr_image_base64 = base64.b64encode(qr_image_binary).decode('utf-8')
context = {
'image_data': qr_image_base64
}
thread = threading.Thread(target=quit_driver_thread)
thread.start()
return render(request, 'read_qr_code.html', context)

Related

APScheduler duplicating jobs in Flask app hosted on Heroku

I have an app structured as below which allows a user to schedule tasks to query FB API each morning, afternoon etc to pull page/post data (3am in this case).
The problem I am experiencing is that the scheduler is executing each job twice which is obviously undesirable. Oddly, the issue doesn’t seem to occur locally, only when in production mode and I am hosting this in Heroku with 1 web dyno and 1 worker dyno, each with only 1 process each. I am therefore leaning towards Heroku being the issue.
I have a page to list the current scheduled jobs and when I inspect it, upon refreshing the page the same job instance will flick between two different values (screenshot below). It is as if there are two BackgroundScheduler's instances running.
I suspected this was to do with the BackgroundScheduler being initiated twice (once in flasky.py and again in tasks.py) so I created a temporary solution to stop the double initialising of the BackgroundScheduler and I still experience the same issue and am now stuck. Any help would be much appreciated.
-->app
-->__init__.py
-->decorators.py
-->models.py
-->tasks.py
-->auth
-->__init__.py
-->errors.py
-->forms.py
-->views.py
-->main
-->__init__.py
-->errors.py
-->forms.py
-->views.py
-->static
-->templates
-->migrations
config.py
flasky.py
Procfile
requirements.txt
app/flasky.py
from flask import Flask,render_template, session, redirect, url_for, flash
import os
from app import create_app,db
from app.models import User,Role
from datetime import datetime
from flask_migrate import Migrate,upgrade
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
app/_ init _.py
from flask import Flask, render_template
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from config import config
from flask_session import Session
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
import rq
from redis import Redis
from flask_login import LoginManager
from worker import conn
import os
bootstrap = Bootstrap()
moment = Moment()
db = SQLAlchemy()
scheduler = BackgroundScheduler()
migrate = Migrate()
session= Session()
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
def create_app(config_name='default'):
app = Flask(__name__)
app.config.from_object(config[config_name])
db.init_app(app)
bootstrap.init_app(app)
moment.init_app(app)
migrate.init_app(app,db)
session.init_app(app)
login_manager.init_app(app)
if not scheduler.running:
scheduler.start()
jobstore_url = os.environ.get('DATABASE_URL')
scheduler.add_jobstore(SQLAlchemyJobStore(url=jobstore_url),'sqlalchemy')
from .main import main as main_blueprint
from .auth import auth as auth_blueprint
app.register_blueprint(main_blueprint)
app.register_blueprint(auth_blueprint,url_prefix='/auth')
app.task_queue = rq.Queue('flasky',connection=Redis.from_url(os.environ.get(REDIS_URL))
if app.config['SSL_REDIRECT']:
from flask_sslify import SSLify
sslify = SSLify(app)
return app
app/tasks.py
from . import create_app,db
from .models import User,Tokens,Files
from .decorators import token_getter
from flask_login import current_user
import requests
import datetime as dt
import urllib
import os
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
<FUNCTIONS HERE>
app/auth/views.py
from flask import render_template,url_for,redirect,request,flash,session,current_app,Response
from .. import db,scheduler
from . import auth
from ..models import User,Role,Tokens,Files
from flask_login import login_user, logout_user, login_required
from ..decorators import admin_required, token_setter, token_getter,permission_required
import requests
import urllib
from .forms import LoginForm, SubmitConnection, ScheduleJobForm
from app.tasks import refreshed_google_client,test_context
app/main/views.py
from flask import render_template, session, redirect, url_for, flash,current_app,request
from datetime import datetime
from . import main
from .. import db,scheduler
from ..models import User,Tokens
from .forms import NameForm,AnalyticsForm
from flask_login import login_required,current_user
from ..decorators import admin_required,permission_required
import requests
import rq
from redis import Redis
from app.tasks import refreshed_google_client,load_analytics
#main.route('/ig_sync',methods=['GET','POST'])
#login_required
#permission_required(4)
def ig_sync():
form = IGAnalyticsForm()
if request.method=='POST':
from app.tasks import load_ig_sync
if form.validate_on_submit():
if form.submit_analytics_schedule.data:
#GET VARIABLES FROM FORM
scheduler.add_job(func=load_ig_sync,args=[#VARIABLES HERE],trigger='cron',hour=3,id=f'SYNC_IG_{page_name}',jobstore='sqlalchemy')
return(redirect(url_for('main.job_schedule')))
return render_template('ig_sync.html',form=form)
app/Procfile
web: gunicorn flasky:app
worker: rq worker -u $REDIS_URL flasky

How to set repeat interval time in background-tasks using django?

I tried to run the background task code in Django. its working fine but interval time is not working. it working every second how to fix it anyone gives some solution.
views.py
from django.shortcuts import render
from django.http import HttpResponse
from background_task import background
from django.core.mail import send_mail
#background(schedule=5)
def hello():
print('hello_world')
# Create your views here.
def index(request):
hello()
return HttpResponse('<h1> Hello World </h1>')
I tried to pass repeat parameter also
from django.shortcuts import render
from django.http import HttpResponse
from background_task import background
from django.core.mail import send_mail
#background(schedule=5)
def hello():
print('hello_world')
# Create your views here.
def index(request):
hello(repeat=10)
return HttpResponse('<h1> Hello World </h1>')
I tried many ways. But still is not working.I need every One hour to print hello world.

unable to locate ImageView element from android in appium (python)

I am trying to find highlighted button in below screenshot of uiautomatorviewer. I am using id of that element, but code gives me NoSuchElementException. I tried using class too but no luck. What's wrong?
uiautomatorviewer screenshot-
code(please check comment for the exact line which gives error)-
import os
from time import sleep
import unittest
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
from appium.webdriver.common.touch_action import TouchAction
# Returns abs path relative to this file and not cwd
PATH = lambda p: os.path.abspath(
os.path.join(os.path.dirname(__file__), p)
)
class SimpleAndroidTests(unittest.TestCase):
def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '7.0'
desired_caps['deviceName'] = 'mishra'
desired_caps['app'] = PATH(
'Shopronto.apk'
)
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
#def tearDown(self):
# end the session
#self.driver.quit()
def test_01_correct_username_correct_password(self):
print "test1"
Wait = WebDriverWait(self.driver, 10)
login_tab=Wait.until(EC.presence_of_element_located((By.ID, "com.shopronto.customer:id/tvLogin")))
login_tab.click()
email = self.driver.find_element_by_id("com.shopronto.customer:id/etEmail")
email.send_keys("user1#gmail.com")
password = self.driver.find_element_by_id("com.shopronto.customer:id/etPwd")
password.send_keys("user123")
self.driver.back()
login = self.driver.find_element_by_id("com.shopronto.customer:id/tvBottomBtn")
login.click()
Wait.until(EC.presence_of_element_located((By.ID, "com.android.packageinstaller:id/permission_allow_button"))).click()
#below line gives error
self.driver.find_element_by_id("com.shopronto.customer:id/ivCategory")
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(SimpleAndroidTests)
unittest.TextTestRunner(verbosity=2).run(suite)
When I replace this-
self.driver.find_element_by_id("com.shopronto.customer:id/ivCategory")
with-
mylist=[]
self.driver.back()
mylist = self.driver.find_elements(By.XPATH, "//android.widget.ImageView")
The code keeps running without giving any output (for over 15 mins).
I have also tried this-
Wait.until(EC.presence_of_element_located((By.XPATH, "//android.widget.ImageView[#index='0']"))).click()
But no luck.
I think your all image view's have same ID, So you should use find element by xpath with index as there is no text with image view.

Indentation error: unident doesnt mach any outer dent level, whle executing python selenium webdriver

from Libs.Core.GetConfig import GetConfig
from Libs.Common import Logging
import os
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from HtmlTestRunner import HTMLTestRunner
import HtmlTestRunner
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
class Dummy(GetConfig):
def __init__(self, namespace=__name__, level="info"):
super(Dummy, self).__init__(namespace, level)
self._level = level
self._namespace = namespace
self._log = Logging.GetLogger(namespace, self._level)
def test_ail_login(self):
driver=self.driver
driver=webdriver.firefox()
driver.get("www.ultimatix.net")
self.username1=self.driver.find_element_by_id("USER")
self.username1.clear()
self.password1=self.driver.find_element_by_id("PASSWORD")
self.password1.clear()
#title1=self.driver.title()
#self.assertIn("Ultimatix - Digitally Connected !", driver.title,"both the names of titles are not identicle")
self.assertTrue(driver.title=="Ultimatix - Digitally Connected !" ,"both titles are not same")
assert "No results found." not in driver.page_source
self.username1.send_keys("asdfasdfasdfasdf")
self.password1.send_keys("asdfasdfasdf")
driver.find_element_by_id("login_button").click()
driver.close()
error is : at
from Libs.Core.GetConfig import GetConfig
from Libs.Common import Logging
import os
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from HtmlTestRunner import HTMLTestRunner
import HtmlTestRunner
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
class Dummy(GetConfig):
def __init__(self, namespace=__name__, level="info"):
super(Dummy, self).__init__(namespace, level)
self._level = level
self._namespace = namespace
self._log = Logging.GetLogger(namespace, self._level)
def test_tcsmail_login(self):
driver=self.driver
driver=webdriver.firefox()
driver.get("www.ultimatix.net")
self.username1=self.driver.find_element_by_id("USER")
self.username1.clear()
self.password1=self.driver.find_element_by_id("PASSWORD")
self.password1.clear()
#title1=self.driver.title()
#self.assertIn("Ultimatix - Digitally Connected !", driver.title,"both the names of titles are not identicle")
self.assertTrue(driver.title=="Ultimatix - Digitally Connected !" ,"both titles are not same")
assert "No results found." not in driver.page_source
self.username1.send_keys("dfds")
self.password1.send_keys("afdssd")
driver.find_element_by_id("login_button").click()
driver.close()

One Chrome browser window in selenium webdriver --python

I have some issue with the init constructor related to selenium webdriver's chrome instances.
Here are the pieces of my scripts:
First one named methods.py
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import paths
class PagePatterns(object):
def __init__(self, title=None):
self.driver = webdriver.Chrome('C:\Python27\chromedriver.exe')
self.title = title
def get_page_title(self):
return self.get_driver().title
Second one named login.py
from utils.methods import PagePatterns
from selenium.webdriver.common.by import By
from utils import paths
methods = PagePatterns()
class LoginPage(object):
def login(self):
country_choose = (By.XPATH, paths.country_list_login)
methods.click(country_choose)
Next one - register.py
from utils.methods import PagePatterns
from selenium.webdriver.common.by import By
from utils import utils, paths
from selenium.webdriver.support.wait import WebDriverWait
methods = PagePatterns()
class MainPage(object):
def open_homepage(self):
methods.open_base_page()
title_check = methods.get_page_title()
assert title_check == paths.page_title
The last one main_test.py is using LoginPage class
from register import MainPage
from login import LoginPage
MainPage().open_homepage()
LoginPage().login()
That's all about the code. My question is - when I am running main_test.py Chrome is called two times (two windows), but I want only one window of the browser - how to make it?
Thanks.