Merge branch 'feature/automatic'
This commit is contained in:
+18
-2
@@ -2,6 +2,7 @@ import PySimpleGUI as sg
|
|||||||
|
|
||||||
# First the window layout in 2 columns
|
# First the window layout in 2 columns
|
||||||
from main import start_book
|
from main import start_book
|
||||||
|
from pojo.ModeEnum import ModeEnum
|
||||||
|
|
||||||
KEY_CHOOSE_STORE = "CHOOSE_STORE"
|
KEY_CHOOSE_STORE = "CHOOSE_STORE"
|
||||||
KEY_START_NUMBER = "KEY_START_NUMBER"
|
KEY_START_NUMBER = "KEY_START_NUMBER"
|
||||||
@@ -13,6 +14,9 @@ KEY_PROXY_CC = "KEY_PROXY_CC"
|
|||||||
KEY_FAUBOURG = "KEY_FAUBOURG"
|
KEY_FAUBOURG = "KEY_FAUBOURG"
|
||||||
KEY_GEORGE = "KEY_GEORGE"
|
KEY_GEORGE = "KEY_GEORGE"
|
||||||
KEY_SEVRES = "KEY_SEVRES"
|
KEY_SEVRES = "KEY_SEVRES"
|
||||||
|
KEY_AUTOMATIC = "KEY_AUTOMATIC"
|
||||||
|
KEY_MANUAL = "KEY_MANUAL"
|
||||||
|
GROUP_MODE = "GROUP_MODE"
|
||||||
GROUP_STORE = "STORE"
|
GROUP_STORE = "STORE"
|
||||||
GROUP_PROXY = "GROUP_PROXY"
|
GROUP_PROXY = "GROUP_PROXY"
|
||||||
|
|
||||||
@@ -36,12 +40,19 @@ proxy_settings_column = [
|
|||||||
[sg.Radio('res(速度)', group_id=GROUP_PROXY, key=KEY_PROXY_RES, default=True)],
|
[sg.Radio('res(速度)', group_id=GROUP_PROXY, key=KEY_PROXY_RES, default=True)],
|
||||||
[sg.Radio('cc(稳定)', group_id=GROUP_PROXY, key=KEY_PROXY_CC, default=False)],
|
[sg.Radio('cc(稳定)', group_id=GROUP_PROXY, key=KEY_PROXY_CC, default=False)],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
mode_settings_column = [
|
||||||
|
[sg.Text("约会模式")],
|
||||||
|
[sg.Radio('手动', group_id=GROUP_MODE, key=KEY_MANUAL, default=True)],
|
||||||
|
[sg.Radio('自动', group_id=GROUP_MODE, key=KEY_AUTOMATIC, default=False)],
|
||||||
|
]
|
||||||
# ----- Full layout -----
|
# ----- Full layout -----
|
||||||
layout = [
|
layout = [
|
||||||
[
|
[
|
||||||
sg.Column(file_list_column),
|
sg.Column(file_list_column),
|
||||||
sg.Column(store_settings_column),
|
sg.Column(store_settings_column),
|
||||||
sg.Column(proxy_settings_column)
|
sg.Column(proxy_settings_column),
|
||||||
|
sg.Column(mode_settings_column)
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -57,6 +68,7 @@ while True:
|
|||||||
end_line = int(values[KEY_END_NUMBER])
|
end_line = int(values[KEY_END_NUMBER])
|
||||||
max_workers = int(values[KEY_MAX_WORKERS])
|
max_workers = int(values[KEY_MAX_WORKERS])
|
||||||
store_type = 0
|
store_type = 0
|
||||||
|
mode = ModeEnum.MANUAL
|
||||||
if values[KEY_FAUBOURG]:
|
if values[KEY_FAUBOURG]:
|
||||||
store_type = 1
|
store_type = 1
|
||||||
elif values[KEY_GEORGE]:
|
elif values[KEY_GEORGE]:
|
||||||
@@ -69,7 +81,11 @@ while True:
|
|||||||
proxy_type = 1
|
proxy_type = 1
|
||||||
elif values[KEY_PROXY_RES]:
|
elif values[KEY_PROXY_RES]:
|
||||||
proxy_type = 0
|
proxy_type = 0
|
||||||
start_book(start_line, end_line, store_choose_state=store_type, max_workers=max_workers, proxy_type=proxy_type)
|
|
||||||
|
if values[KEY_AUTOMATIC]:
|
||||||
|
mode = ModeEnum.AUTOMATIC
|
||||||
|
start_book(start_line, end_line, store_choose_state=store_type, max_workers=max_workers, proxy_type=proxy_type,
|
||||||
|
mode=mode)
|
||||||
# except Exception as error:
|
# except Exception as error:
|
||||||
# print("Not Integer: ")
|
# print("Not Integer: ")
|
||||||
# print(error)
|
# print(error)
|
||||||
|
|||||||
+6
-6
@@ -21,7 +21,7 @@ BLANK_URL = "about:blank"
|
|||||||
class TlsPlaywright(threading.local):
|
class TlsPlaywright(threading.local):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.playwright = sync_playwright().start()
|
self.playwright = sync_playwright().start()
|
||||||
print("Create playwright instance in Thread", threading.current_thread().name)
|
print("创建浏览器实例,线程: ", threading.current_thread().name)
|
||||||
|
|
||||||
|
|
||||||
class ResultChecker:
|
class ResultChecker:
|
||||||
@@ -108,7 +108,7 @@ if __name__ == '__main__':
|
|||||||
# get the list
|
# get the list
|
||||||
params.oracle_log_sender.send_log(msg="开始检查约会结果", subject=LOG_SUBJECT_EVENT, type=TYPE_EVENT_CHECK_RESULTS)
|
params.oracle_log_sender.send_log(msg="开始检查约会结果", subject=LOG_SUBJECT_EVENT, type=TYPE_EVENT_CHECK_RESULTS)
|
||||||
db_manager = params.firebase_store_manager
|
db_manager = params.firebase_store_manager
|
||||||
# collection = db_manager.get_all_successful_items_for_day("2022-05-14", "landd")
|
# collection = db_manager.get_successful_item_for_day_by_status("2022-05-17", ResultEnum.ACCEPTED)
|
||||||
collection = db_manager.get_all_successful_items()
|
collection = db_manager.get_all_successful_items()
|
||||||
count = 0
|
count = 0
|
||||||
result_list = []
|
result_list = []
|
||||||
@@ -116,12 +116,12 @@ if __name__ == '__main__':
|
|||||||
reserve_pojo = ReserveResultPojo.from_firestore_dict(appointment.to_dict())
|
reserve_pojo = ReserveResultPojo.from_firestore_dict(appointment.to_dict())
|
||||||
result_list.append(reserve_pojo)
|
result_list.append(reserve_pojo)
|
||||||
|
|
||||||
with ThreadPoolExecutor(max_workers=10) as executor:
|
|
||||||
|
with ThreadPoolExecutor(max_workers=25) as executor:
|
||||||
for reserve in result_list:
|
for reserve in result_list:
|
||||||
count = count + 1
|
count = count + 1
|
||||||
if reserve.accepted is None or ResultEnum.PENDING.value == reserve.accepted:
|
if reserve.accepted is None or ResultEnum.ACCEPTED.value == reserve.accepted:
|
||||||
if reserve.url != BLANK_URL:
|
executor.submit(ResultChecker().run, reserve, collection)
|
||||||
executor.submit(ResultChecker().run, reserve, collection)
|
|
||||||
else:
|
else:
|
||||||
print("status is " + reserve.accepted)
|
print("status is " + reserve.accepted)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import firebase_admin
|
|||||||
from firebase_admin import credentials, firestore
|
from firebase_admin import credentials, firestore
|
||||||
|
|
||||||
import definitions
|
import definitions
|
||||||
|
from pojo import ResultEnum
|
||||||
from pojo.MailPojo import MailPojo
|
from pojo.MailPojo import MailPojo
|
||||||
from pojo.ReserveResultPojo import ReserveResultPojo
|
from pojo.ReserveResultPojo import ReserveResultPojo
|
||||||
from pojo.SimInfoPojo import SimInfoPojo
|
from pojo.SimInfoPojo import SimInfoPojo
|
||||||
@@ -38,6 +39,12 @@ class DataManager:
|
|||||||
doc_ref.where(u'source_from', u'==', source_from)
|
doc_ref.where(u'source_from', u'==', source_from)
|
||||||
return doc_ref
|
return doc_ref
|
||||||
|
|
||||||
|
def get_successful_item_for_day_by_status(self, day, status: ResultEnum):
|
||||||
|
doc_ref = self._db.collection(day)
|
||||||
|
if status is not None:
|
||||||
|
doc_ref.where(u'accepted', u'==', status.value)
|
||||||
|
return doc_ref
|
||||||
|
|
||||||
def save_sim_info(self, sim_info: SimInfoPojo):
|
def save_sim_info(self, sim_info: SimInfoPojo):
|
||||||
doc_ref = self._db.collection(SIM_INFOS).document(sim_info.phone)
|
doc_ref = self._db.collection(SIM_INFOS).document(sim_info.phone)
|
||||||
doc_ref.set(sim_info.to_firestore_dict())
|
doc_ref.set(sim_info.to_firestore_dict())
|
||||||
|
|||||||
+254
File diff suppressed because one or more lines are too long
@@ -25,6 +25,7 @@ LOG_ERROR = "ERROR"
|
|||||||
LOG_TYPE_INFO = "INFO"
|
LOG_TYPE_INFO = "INFO"
|
||||||
LOG_ERROR_TYPE_DOUBLE_DATA = "DOUBLE_REQUEST_FOR_SAME_DATA"
|
LOG_ERROR_TYPE_DOUBLE_DATA = "DOUBLE_REQUEST_FOR_SAME_DATA"
|
||||||
LOG_ERROR_TOO_MANY_REQUEST_TODAY = "TOO_MANY_REQUEST_TODAY"
|
LOG_ERROR_TOO_MANY_REQUEST_TODAY = "TOO_MANY_REQUEST_TODAY"
|
||||||
|
LOG_ERROR_CAPTCHA_ERROR_MESSAGE = "CAPTCHA_ERROR"
|
||||||
LOG_SUBJECT_ERROR = "ERROR"
|
LOG_SUBJECT_ERROR = "ERROR"
|
||||||
LOG_APPOINTMENT_ERROR = "APPOINTMENT_ERROR"
|
LOG_APPOINTMENT_ERROR = "APPOINTMENT_ERROR"
|
||||||
LOG_APPOINTMENT_TIMEOUT = "TIMEOUT"
|
LOG_APPOINTMENT_TIMEOUT = "TIMEOUT"
|
||||||
@@ -78,6 +79,10 @@ class LogSender:
|
|||||||
error_msg = contact.mail
|
error_msg = contact.mail
|
||||||
self.send_log(msg=error_msg, type=LOG_ERROR_TOO_MANY_REQUEST_TODAY, subject=LOG_SUBJECT_ERROR)
|
self.send_log(msg=error_msg, type=LOG_ERROR_TOO_MANY_REQUEST_TODAY, subject=LOG_SUBJECT_ERROR)
|
||||||
|
|
||||||
|
def send_captcha_error(self, contact: ContactPojo):
|
||||||
|
error_msg = contact.mail
|
||||||
|
self.send_log(msg=error_msg, type=LOG_ERROR_CAPTCHA_ERROR_MESSAGE, subject=LOG_SUBJECT_ERROR)
|
||||||
|
|
||||||
def send_appoint_result(self, result: ReserveResultPojo):
|
def send_appoint_result(self, result: ReserveResultPojo):
|
||||||
if result.type == PublishType.SUCCESS:
|
if result.type == PublishType.SUCCESS:
|
||||||
# get id
|
# get id
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from concurrent.futures import ThreadPoolExecutor
|
|||||||
|
|
||||||
import params
|
import params
|
||||||
from logs.AppLogging import init_logger
|
from logs.AppLogging import init_logger
|
||||||
|
from pojo.ModeEnum import ModeEnum
|
||||||
from utils.excel_reader import ExcelHelper
|
from utils.excel_reader import ExcelHelper
|
||||||
from workers.commandor_page import CommandorPage
|
from workers.commandor_page import CommandorPage
|
||||||
|
|
||||||
@@ -13,7 +14,8 @@ logger = logging.getLogger()
|
|||||||
logger.addHandler(logging.StreamHandler(stream=sys.stdout))
|
logger.addHandler(logging.StreamHandler(stream=sys.stdout))
|
||||||
|
|
||||||
|
|
||||||
def start_book(start_number, end_number, store_choose_state=0, max_workers=10, proxy_type=0):
|
def start_book(start_number, end_number, store_choose_state=0, max_workers=10, proxy_type=0,
|
||||||
|
mode: ModeEnum = ModeEnum.MANUAL):
|
||||||
# read the contact, and contact the 2 objects together
|
# read the contact, and contact the 2 objects together
|
||||||
excel_reader = ExcelHelper()
|
excel_reader = ExcelHelper()
|
||||||
all_contacts = excel_reader.read_contacts()
|
all_contacts = excel_reader.read_contacts()
|
||||||
@@ -25,8 +27,9 @@ def start_book(start_number, end_number, store_choose_state=0, max_workers=10, p
|
|||||||
for contact in contacts:
|
for contact in contacts:
|
||||||
proxy = get_proxy(contact.phone, proxy_type)
|
proxy = get_proxy(contact.phone, proxy_type)
|
||||||
# start the task in thread
|
# start the task in thread
|
||||||
executor.submit(CommandorPage(contact, store_type=store_choose_state, proxy_type=proxy_type).start_page,
|
executor.submit(
|
||||||
proxy)
|
CommandorPage(contact, store_type=store_choose_state, proxy_type=proxy_type, mode=mode).start_page,
|
||||||
|
proxy)
|
||||||
|
|
||||||
|
|
||||||
def get_proxy(phone_number, proxy_type=0):
|
def get_proxy(phone_number, proxy_type=0):
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
import configparser
|
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
from playwright.sync_api import sync_playwright
|
|
||||||
|
|
||||||
from db.DbManager import DataManager
|
from db.DbManager import DataManager
|
||||||
from logs.LogSender import LogSender
|
from logs.LogSender import LogSender
|
||||||
|
|
||||||
@@ -22,6 +19,7 @@ def get_proxy_name_prefix(proxy_type = 0) -> str:
|
|||||||
else:
|
else:
|
||||||
return PROXY_NAME_PREFIX_CC
|
return PROXY_NAME_PREFIX_CC
|
||||||
|
|
||||||
|
|
||||||
def get_random_id_number_for_proxy() -> str:
|
def get_random_id_number_for_proxy() -> str:
|
||||||
S = 8 # number of characters in the string.
|
S = 8 # number of characters in the string.
|
||||||
ran = ''.join(random.choices(string.digits, k=S))
|
ran = ''.join(random.choices(string.digits, k=S))
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class ModeEnum(Enum):
|
||||||
|
AUTOMATIC = "AUTOMATIC"
|
||||||
|
MANUAL = "MANUAL"
|
||||||
+2
-1
@@ -8,4 +8,5 @@ XlsxWriter~=3.0.3
|
|||||||
boto3~=1.21.13
|
boto3~=1.21.13
|
||||||
openpyxl==3.0.9
|
openpyxl==3.0.9
|
||||||
google-cloud-firestore==2.4.0
|
google-cloud-firestore==2.4.0
|
||||||
PySimpleGUI==4.60.0
|
PySimpleGUI==4.60.0
|
||||||
|
SpeechRecognition==3.8.1
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# for recaptcha
|
||||||
|
import logging
|
||||||
|
import random
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
|
||||||
|
CAPCHA_NOT_READY = "CAPCHA_NOT_READY"
|
||||||
|
REGEX_DATA_SITE_KEY = "data-sitekey=[\"a-z0-9A-Z]+"
|
||||||
|
API_KEY = "d66aaf490d8aa424a5175e1fbd1aadea"
|
||||||
|
|
||||||
|
|
||||||
|
class SolveCaptcha:
|
||||||
|
def __init__(self, page):
|
||||||
|
self.page = page
|
||||||
|
self.logger = logging.getLogger("SolveCaptcha")
|
||||||
|
self.main_frame = None
|
||||||
|
self.recaptcha = None
|
||||||
|
|
||||||
|
def delay(self):
|
||||||
|
self.page.wait_for_timeout(random.randint(1, 3) * 1000)
|
||||||
|
|
||||||
|
def start(self, handle_solution_received):
|
||||||
|
self.logger.info("start to resolve captcha")
|
||||||
|
content = self.page.content()
|
||||||
|
data_sitekey = re.findall(REGEX_DATA_SITE_KEY, content)
|
||||||
|
self.logger.info(data_sitekey)
|
||||||
|
if len(data_sitekey) == 1:
|
||||||
|
key_with_comma = data_sitekey[0].split("=")[-1]
|
||||||
|
key = key_with_comma.replace("\"", '')
|
||||||
|
self.logger.info("key is : " + key)
|
||||||
|
self.solve_captcha(key, handle_solution_received)
|
||||||
|
|
||||||
|
def solve_captcha(self, google_key: str, handle_solution_received):
|
||||||
|
self.logger.info("solve_captcha()")
|
||||||
|
url_get = "http://2captcha.com/in.php?key={}&method=userrecaptcha&googlekey={}&pageurl={}".format(API_KEY,
|
||||||
|
google_key,
|
||||||
|
self.page.url)
|
||||||
|
res = requests.get(url_get)
|
||||||
|
self.logger.info(res.text)
|
||||||
|
results = res.text.split("|")
|
||||||
|
self.captcha_id = results[-1]
|
||||||
|
# wait for 15 seconds
|
||||||
|
time.sleep(15)
|
||||||
|
# get result of the captcha
|
||||||
|
url_response = "http://2captcha.com/res.php?key={}&action=get&id={}".format(API_KEY,
|
||||||
|
self.captcha_id)
|
||||||
|
solution = CAPCHA_NOT_READY
|
||||||
|
while solution == CAPCHA_NOT_READY:
|
||||||
|
solution_res = requests.get(url_response)
|
||||||
|
time.sleep(5)
|
||||||
|
solution = solution_res.text
|
||||||
|
print(solution)
|
||||||
|
handle_solution_received(solution.split("|")[-1])
|
||||||
+83
-35
@@ -10,8 +10,10 @@ from playwright.sync_api import sync_playwright
|
|||||||
|
|
||||||
import params
|
import params
|
||||||
from params import PROXY_SERVER, PROXY_PASSWORD
|
from params import PROXY_SERVER, PROXY_PASSWORD
|
||||||
|
from pojo.ModeEnum import ModeEnum
|
||||||
from pojo.ReserveResultPojo import ReserveResultPojo, PublishType
|
from pojo.ReserveResultPojo import ReserveResultPojo, PublishType
|
||||||
from pojo.contact_pojo import ContactPojo
|
from pojo.contact_pojo import ContactPojo
|
||||||
|
from workers.SolveCaptch import SolveCaptcha
|
||||||
|
|
||||||
RDV_URL = "https://rendezvousparis.hermes.com/client/register"
|
RDV_URL = "https://rendezvousparis.hermes.com/client/register"
|
||||||
|
|
||||||
@@ -26,9 +28,10 @@ MESSAGE_FIELD_CLASS = ".message"
|
|||||||
CONFIRMED_MESSAGE = "Your request for a Leather Goods appointment has been registered"
|
CONFIRMED_MESSAGE = "Your request for a Leather Goods appointment has been registered"
|
||||||
DOUBLE_REQUEST_ERROR_MESSAGE = "A request with the same data has already been validated today."
|
DOUBLE_REQUEST_ERROR_MESSAGE = "A request with the same data has already been validated today."
|
||||||
TOO_MANY_REQUEST_ERROR_MESSAGE = "Due to a large number of requests"
|
TOO_MANY_REQUEST_ERROR_MESSAGE = "Due to a large number of requests"
|
||||||
|
CAPTCHA_ERROR_MESSAGE = "Error verifying captcha, please try again"
|
||||||
TIME_OUT = 400000
|
TIME_OUT = 400000
|
||||||
OTP_TIMEOUT = 240
|
OTP_TIMEOUT = 240
|
||||||
PAGE_TIMEOUT = 30000
|
PAGE_TIMEOUT = 40000
|
||||||
|
|
||||||
|
|
||||||
def get_random_wait_time() -> float:
|
def get_random_wait_time() -> float:
|
||||||
@@ -44,12 +47,16 @@ class Tls(threading.local):
|
|||||||
class CommandorPage:
|
class CommandorPage:
|
||||||
tls = Tls()
|
tls = Tls()
|
||||||
|
|
||||||
def __init__(self, contact: ContactPojo, store_type=0, proxy_type=0):
|
def __init__(self, contact: ContactPojo, store_type=0, proxy_type=0, mode: ModeEnum = ModeEnum.MANUAL):
|
||||||
self.otp_value = None
|
self.otp_value = None
|
||||||
self.logger = logging.getLogger("CommandorPage")
|
self.logger = logging.getLogger("CommandorPage:" + str(contact.phone))
|
||||||
self.is_finished = False
|
self.is_finished = False
|
||||||
self.contact = contact
|
self.contact = contact
|
||||||
self.proxy_type = proxy_type
|
self.proxy_type = proxy_type
|
||||||
|
self.is_event_sent = False
|
||||||
|
self.is_captcha_in_error = False
|
||||||
|
self.is_filling_fields = False
|
||||||
|
self.appointment_mode = mode
|
||||||
# 0: random
|
# 0: random
|
||||||
# 1: faubourg
|
# 1: faubourg
|
||||||
# 2: George
|
# 2: George
|
||||||
@@ -63,9 +70,12 @@ class CommandorPage:
|
|||||||
|
|
||||||
def on_success(self, result: ReserveResultPojo):
|
def on_success(self, result: ReserveResultPojo):
|
||||||
self.logger.info("on_success called.")
|
self.logger.info("on_success called.")
|
||||||
self.logger.info(result)
|
|
||||||
params.oracle_log_sender.send_appoint_result(result)
|
|
||||||
self.is_finished = True
|
self.is_finished = True
|
||||||
|
if not self.is_event_sent:
|
||||||
|
self.logger.info("will send successful event")
|
||||||
|
self.logger.info(result)
|
||||||
|
params.oracle_log_sender.send_appoint_result(result)
|
||||||
|
self.is_event_sent = True
|
||||||
|
|
||||||
def timeout_occurred(self):
|
def timeout_occurred(self):
|
||||||
params.oracle_log_sender.send_timeout_log(self.contact)
|
params.oracle_log_sender.send_timeout_log(self.contact)
|
||||||
@@ -89,7 +99,6 @@ class CommandorPage:
|
|||||||
"username": proxy_username,
|
"username": proxy_username,
|
||||||
"password": params.PROXY_PASSWORD
|
"password": params.PROXY_PASSWORD
|
||||||
}
|
}
|
||||||
self.fill_fields()
|
|
||||||
# wait for sms_code field
|
# wait for sms_code field
|
||||||
# self.clickOnValidBtn()
|
# self.clickOnValidBtn()
|
||||||
self.thread_event = e
|
self.thread_event = e
|
||||||
@@ -103,7 +112,6 @@ class CommandorPage:
|
|||||||
self.clickOnValidBtn()
|
self.clickOnValidBtn()
|
||||||
otp_sent = self.page.locator(MESSAGE_FIELD_CLASS)
|
otp_sent = self.page.locator(MESSAGE_FIELD_CLASS)
|
||||||
otp_sent.wait_for(state='visible', timeout=TIME_OUT)
|
otp_sent.wait_for(state='visible', timeout=TIME_OUT)
|
||||||
# print("message is:" + message)
|
|
||||||
time.sleep(get_random_wait_time())
|
time.sleep(get_random_wait_time())
|
||||||
message = self.page.content()
|
message = self.page.content()
|
||||||
if CONFIRMED_MESSAGE in message:
|
if CONFIRMED_MESSAGE in message:
|
||||||
@@ -115,20 +123,25 @@ class CommandorPage:
|
|||||||
self.termine()
|
self.termine()
|
||||||
|
|
||||||
def fill_fields(self):
|
def fill_fields(self):
|
||||||
self._set_name(self.contact.last_name, self.contact.first_name)
|
if not self.is_filling_fields:
|
||||||
self._setPhoneCountryAndStore()
|
self.is_filling_fields = True
|
||||||
self._setPhoneNumber(self.contact.phone)
|
self.logger.info("填充信息: " + str(self.contact.phone))
|
||||||
self._set_email(self.contact.mail)
|
self._set_name(self.contact.last_name, self.contact.first_name)
|
||||||
self.setIdNumber(self.contact.passport)
|
self._setPhoneCountryAndStore()
|
||||||
#
|
self._setPhoneNumber(self.contact.phone)
|
||||||
self._checkCgu()
|
self._set_email(self.contact.mail)
|
||||||
|
self.setIdNumber(self.contact.passport)
|
||||||
|
self._checkCgu()
|
||||||
|
if self.appointment_mode == ModeEnum.AUTOMATIC:
|
||||||
|
self.resolve_captcha()
|
||||||
|
self.is_filling_fields = False
|
||||||
|
|
||||||
def start_browser(self, proxy, pwright, device) -> Union[str, None]:
|
def start_browser(self, proxy, pwright, device) -> Union[str, None]:
|
||||||
try:
|
try:
|
||||||
self.browser = pwright.webkit.launch(headless=False, timeout=PAGE_TIMEOUT, proxy=proxy)
|
self.browser = pwright.webkit.launch(headless=False, timeout=PAGE_TIMEOUT, proxy=proxy)
|
||||||
self.logger.info("模拟设备: " + device)
|
self.logger.info("模拟设备: " + device)
|
||||||
pixel_2 = pwright.devices[device]
|
pixel_2 = pwright.devices[device]
|
||||||
context = self.browser.new_context(**pixel_2, locale='en-GB')
|
context = self.browser.new_context(**pixel_2, locale='fr-FR')
|
||||||
self.page = context.new_page()
|
self.page = context.new_page()
|
||||||
# hide webdriver information
|
# hide webdriver information
|
||||||
self.page.add_init_script("""() => {
|
self.page.add_init_script("""() => {
|
||||||
@@ -154,7 +167,7 @@ class CommandorPage:
|
|||||||
pattern = re.compile(REGEX_RDV_URL)
|
pattern = re.compile(REGEX_RDV_URL)
|
||||||
if pattern.match(response.url):
|
if pattern.match(response.url):
|
||||||
self.logger.info("result url found: " + response.url)
|
self.logger.info("result url found: " + response.url)
|
||||||
self.publish_message_to_queue(self.contact, PublishType.PENDING, response.url)
|
# self.publish_message_to_queue(self.contact, PublishType.PENDING, response.url)
|
||||||
|
|
||||||
def start_page(self, proxy):
|
def start_page(self, proxy):
|
||||||
e = threading.Event()
|
e = threading.Event()
|
||||||
@@ -166,26 +179,29 @@ class CommandorPage:
|
|||||||
self.logger.info("url is " + self.page.url)
|
self.logger.info("url is " + self.page.url)
|
||||||
if self.page.url == RDV_URL:
|
if self.page.url == RDV_URL:
|
||||||
self.fill_fields()
|
self.fill_fields()
|
||||||
message = self.page.content()
|
try:
|
||||||
if CONFIRMED_MESSAGE in message:
|
message = self.page.content()
|
||||||
# publish the successful message
|
if CONFIRMED_MESSAGE in message:
|
||||||
self.publish_message_to_queue(self.contact, PublishType.SUCCESS, self.page.url)
|
# publish the successful message
|
||||||
self.get_errors()
|
self.publish_message_to_queue(self.contact, PublishType.SUCCESS, self.page.url)
|
||||||
|
self.get_errors()
|
||||||
|
except Exception as error:
|
||||||
|
self.logger.error(error)
|
||||||
|
|
||||||
def on_document_loaded(self):
|
def on_document_loaded(self):
|
||||||
print("on_document_loaded called")
|
self.logger.info("on_document_loaded called")
|
||||||
|
|
||||||
def _setPhoneCountryAndStore(self):
|
def _setPhoneCountryAndStore(self):
|
||||||
try:
|
try:
|
||||||
if self.store_type == 0:
|
if self.store_type == 0:
|
||||||
self.page.evaluate("""()=>{
|
self.page.evaluate("""()=>{
|
||||||
document.getElementById("phone_country").focus();
|
//document.getElementById("phone_country").focus();
|
||||||
document.getElementById("phone_country").value = \"FR\" }""")
|
document.getElementById("phone_country").value = \"FR\" }""")
|
||||||
else:
|
else:
|
||||||
store_to_choose = self.store_map[self.store_type]
|
store_to_choose = self.store_map[self.store_type]
|
||||||
self.page.evaluate("""(store_to_choose)=>{
|
self.page.evaluate("""(store_to_choose)=>{
|
||||||
document.getElementById("prefer").value = store_to_choose;
|
document.getElementById("prefer").value = store_to_choose;
|
||||||
document.getElementById("phone_country").focus();
|
//document.getElementById("phone_country").focus();
|
||||||
document.getElementById("phone_country").value = \"FR\" }""", store_to_choose)
|
document.getElementById("phone_country").value = \"FR\" }""", store_to_choose)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
self.logger.error(error)
|
self.logger.error(error)
|
||||||
@@ -204,7 +220,7 @@ class CommandorPage:
|
|||||||
self.page.evaluate("""(name)=> {
|
self.page.evaluate("""(name)=> {
|
||||||
let surname = document.getElementById("surname");
|
let surname = document.getElementById("surname");
|
||||||
if(surname.value.length == 0){
|
if(surname.value.length == 0){
|
||||||
surname.focus();
|
// surname.focus();
|
||||||
surname.value = name.lastName;
|
surname.value = name.lastName;
|
||||||
document.getElementById("name").focus();
|
document.getElementById("name").focus();
|
||||||
document.getElementById("name").value = name.firstName
|
document.getElementById("name").value = name.firstName
|
||||||
@@ -220,7 +236,7 @@ class CommandorPage:
|
|||||||
items = self.page.query_selector("div.alert")
|
items = self.page.query_selector("div.alert")
|
||||||
if items:
|
if items:
|
||||||
erro_content = items.inner_html()
|
erro_content = items.inner_html()
|
||||||
print("错误:" + erro_content)
|
self.logger.info("错误:" + erro_content)
|
||||||
self._handle_errors(erro_content)
|
self._handle_errors(erro_content)
|
||||||
except Exception as ext:
|
except Exception as ext:
|
||||||
self.logger.error(ext)
|
self.logger.error(ext)
|
||||||
@@ -228,16 +244,25 @@ class CommandorPage:
|
|||||||
def _handle_errors(self, erro_content: str):
|
def _handle_errors(self, erro_content: str):
|
||||||
if DOUBLE_REQUEST_ERROR_MESSAGE in erro_content:
|
if DOUBLE_REQUEST_ERROR_MESSAGE in erro_content:
|
||||||
# this email has been already used
|
# this email has been already used
|
||||||
params.oracle_log_sender.send_double_data_error(self.contact)
|
if not self.is_finished:
|
||||||
# close browser
|
params.oracle_log_sender.send_double_data_error(self.contact)
|
||||||
time.sleep(2)
|
self.is_finished = True
|
||||||
self.browser.close()
|
self.termine()
|
||||||
elif TOO_MANY_REQUEST_ERROR_MESSAGE in erro_content:
|
elif TOO_MANY_REQUEST_ERROR_MESSAGE in erro_content:
|
||||||
# this email has been already used
|
# this email has been already used
|
||||||
params.oracle_log_sender.send_too_many_error(self.contact)
|
if not self.is_finished:
|
||||||
# close browser
|
params.oracle_log_sender.send_too_many_error(self.contact)
|
||||||
time.sleep(2)
|
self.is_finished = True
|
||||||
self.browser.close()
|
self.termine()
|
||||||
|
elif CAPTCHA_ERROR_MESSAGE in erro_content:
|
||||||
|
# this email has been already used
|
||||||
|
self.is_captcha_in_error = True
|
||||||
|
if not self.is_finished:
|
||||||
|
params.oracle_log_sender.send_captcha_error(self.contact)
|
||||||
|
self.is_finished = True
|
||||||
|
# no need to retry captcha, if retry ,will generate DOUBLE_REQUEST_ERROR_MESSAGE
|
||||||
|
self.termine()
|
||||||
|
# self.resolve_captcha()
|
||||||
|
|
||||||
def _set_email(self, email):
|
def _set_email(self, email):
|
||||||
time.sleep(get_random_wait_time())
|
time.sleep(get_random_wait_time())
|
||||||
@@ -260,7 +285,6 @@ class CommandorPage:
|
|||||||
self.logger.error(error)
|
self.logger.error(error)
|
||||||
|
|
||||||
def _checkCgu(self):
|
def _checkCgu(self):
|
||||||
# self.page.mouse.wheel(0, random.randint(200, 600))
|
|
||||||
try:
|
try:
|
||||||
self.page.evaluate("""
|
self.page.evaluate("""
|
||||||
document.getElementById("cgu").focus();
|
document.getElementById("cgu").focus();
|
||||||
@@ -290,6 +314,7 @@ class CommandorPage:
|
|||||||
|
|
||||||
def termine(self):
|
def termine(self):
|
||||||
self.logger.info("will close browser")
|
self.logger.info("will close browser")
|
||||||
|
time.sleep(1)
|
||||||
self.browser.close()
|
self.browser.close()
|
||||||
|
|
||||||
def publish_message_to_queue(self, contact: ContactPojo, status: PublishType, url: str):
|
def publish_message_to_queue(self, contact: ContactPojo, status: PublishType, url: str):
|
||||||
@@ -305,6 +330,29 @@ class CommandorPage:
|
|||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
self.browser.close()
|
self.browser.close()
|
||||||
|
|
||||||
|
def resolve_captcha(self):
|
||||||
|
self.captcha_solver = SolveCaptcha(self.page)
|
||||||
|
self.captcha_solver.start(self.fill_captcha_solution)
|
||||||
|
|
||||||
|
def fill_captcha_solution(self, solution):
|
||||||
|
self.logger.info("will input solution: " + solution)
|
||||||
|
try:
|
||||||
|
self.page.evaluate("""(solution)=>{
|
||||||
|
document.getElementById("g-recaptcha-response").innerHTML=solution;}""", solution)
|
||||||
|
self.logger.info("will click on valid btn")
|
||||||
|
self.clickOnValidBtn()
|
||||||
|
# wait for 20s
|
||||||
|
time.sleep(20)
|
||||||
|
if not self.is_finished:
|
||||||
|
if not self.is_captcha_in_error:
|
||||||
|
self.clickOnValidBtn()
|
||||||
|
else:
|
||||||
|
self.is_captcha_in_error = False
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
self.logger.error(error)
|
||||||
|
self.page.reload(timeout=PAGE_TIMEOUT)
|
||||||
|
|
||||||
|
|
||||||
def get_random_id_number() -> str:
|
def get_random_id_number() -> str:
|
||||||
S = 8 # number of characters in the string.
|
S = 8 # number of characters in the string.
|
||||||
|
|||||||
Reference in New Issue
Block a user