From e156ad9085b9f124d4276fd0d3e3c92f36041865 Mon Sep 17 00:00:00 2001 From: Tim Reibe <38082956+iamnotturner@users.noreply.github.com> Date: Wed, 16 Jun 2021 16:38:21 +0200 Subject: [PATCH] fix(seleniumwire): added chrome_options to selenium-wire, added selenium-wire certificates (#485) * added chrome_options to seleniumwire, pep8 changes * added seleniumwire certificates --- specs/linux-64-terminservice.spec | 2 +- specs/windows-terminservice-gui.spec | 2 +- specs/windows-terminservice.spec | 2 +- tools/its.py | 258 ++++++++++++++++----------- tools/seleniumwire/ca.crt | 30 ++++ tools/seleniumwire/ca.key | 52 ++++++ 6 files changed, 239 insertions(+), 107 deletions(-) create mode 100644 tools/seleniumwire/ca.crt create mode 100644 tools/seleniumwire/ca.key diff --git a/specs/linux-64-terminservice.spec b/specs/linux-64-terminservice.spec index fd7e5169..cbc3180e 100644 --- a/specs/linux-64-terminservice.spec +++ b/specs/linux-64-terminservice.spec @@ -6,7 +6,7 @@ block_cipher = None a = Analysis(['../main.py'], pathex=['./specs'], binaries=[('../tools/chromedriver/chromedriver-linux-64', 'tools/chromedriver/')], - datas=[('../tools/cloudscraper', './cloudscraper/'), ('../version.txt', '.')], + datas=[('../tools/cloudscraper', './cloudscraper/'), ('../tools/seleniumwire', './seleniumwire/'), ('../version.txt', '.')], hiddenimports=['cloudscraper'], hookspath=['../tools/additional_hooks'], runtime_hooks=[], diff --git a/specs/windows-terminservice-gui.spec b/specs/windows-terminservice-gui.spec index 0af83123..ec7f4acd 100644 --- a/specs/windows-terminservice-gui.spec +++ b/specs/windows-terminservice-gui.spec @@ -7,7 +7,7 @@ block_cipher = None a = Analysis(['..\\gui.py'], pathex=['specs//'], binaries=[('..\\tools\\chromedriver\\chromedriver-windows.exe', 'tools\\chromedriver\\'), ('..\\tools\\gui\\kontaktdaten.ui', 'tools\\gui\\'), ('..\\tools\\gui\\main.ui', 'tools\\gui\\'), ('..\\tools\\gui\\terminsuche.ui', 'tools\\gui\\'), ('..\\tools\\gui\\impfzentren.ui', 'tools\\gui\\'), ('..\\tools\\gui\\ui_qtcodegen.ui', 'tools\\gui\\'), ('..\\images\\spritze.ico', 'images\\')], - datas=[('../tools/cloudscraper', './cloudscraper/'), ('../version.txt', '.')], + datas=[('../tools/cloudscraper', './cloudscraper/'), ('../tools/seleniumwire', './seleniumwire/'), ('../version.txt', '.')], hiddenimports=['plyer.platforms.win.notification', 'cloudscraper'], hookspath=['../tools/additional_hooks'], runtime_hooks=[], diff --git a/specs/windows-terminservice.spec b/specs/windows-terminservice.spec index fd8d688b..1fe70022 100644 --- a/specs/windows-terminservice.spec +++ b/specs/windows-terminservice.spec @@ -10,7 +10,7 @@ block_cipher = None a = Analysis(['..\\main.py'], pathex=['specs//'], binaries=[('..\\tools\\chromedriver\\chromedriver-windows.exe', 'tools\\chromedriver\\')], - datas=[('../tools/cloudscraper', './cloudscraper/'), ('../version.txt', '.')], + datas=[('../tools/cloudscraper', './cloudscraper/'), ('../tools/seleniumwire', './seleniumwire/'), ('../version.txt', '.')], hiddenimports=['plyer.platforms.win.notification', 'cloudscraper'], hookspath=['../tools/additional_hooks'], runtime_hooks=[], diff --git a/tools/its.py b/tools/its.py index 82263578..287f13c3 100644 --- a/tools/its.py +++ b/tools/its.py @@ -25,7 +25,8 @@ from selenium.webdriver.support.ui import WebDriverWait from seleniumwire import webdriver as selenium_wire -from tools.chromium_downloader import chromium_executable, check_chromium, webdriver_executable, check_webdriver +from tools.chromium_downloader import chromium_executable, check_chromium, webdriver_executable, \ + check_webdriver from tools.clog import CLogger from tools.exceptions import AppointmentGone, BookingError, TimeframeMissed, UnmatchingCodeError from tools.kontaktdaten import decode_wochentag, validate_codes, validate_kontakt, \ @@ -266,7 +267,7 @@ def get_chromedriver_path(self): else: raise ValueError(f"Nicht unterstütztes Betriebssystem {self.operating_system}") - def get_chromedriver(self, headless): + def get_chrome_options(self, headless): chrome_options = Options() # deaktiviere Selenium Logging @@ -292,7 +293,10 @@ def get_chromedriver(self, headless): chrome_options.headless = headless - return Chrome(self.get_chromedriver_path(), options=chrome_options) + return chrome_options + + def get_chromedriver(self, headless): + return Chrome(self.get_chromedriver_path(), options=self.get_chrome_options(headless)) def driver_enter_code(self, driver, impfzentrum, code): """ @@ -322,10 +326,9 @@ def driver_enter_code(self, driver, impfzentrum, code): driver.get(location) driver.refresh() - # random start position - current_mouse_positon = (randint(1, driver.get_window_size()["width"]-1), - randint(1, driver.get_window_size()["height"]-1)) + current_mouse_positon = (randint(1, driver.get_window_size()["width"] - 1), + randint(1, driver.get_window_size()["height"] - 1)) # Simulation der Mausbewegung current_mouse_positon = move_mouse_to_coordinates(self.log, 0, 0, current_mouse_positon[0], current_mouse_positon[1], driver) @@ -344,8 +347,7 @@ def driver_enter_code(self, driver, impfzentrum, code): element.location['y'], driver) action.click(button).perform() - - + # Klick auf "Vermittlungscode bereits vorhanden" button_xpath = "//input[@name=\"vaccination-approval-checked\"]/.." button = WebDriverWait(driver, 1).until( @@ -378,8 +380,8 @@ def driver_enter_code(self, driver, impfzentrum, code): # Code etwas realistischer eingeben # Zu schnelle Eingabe erzeugt ebenfalls manchmal "Ein unerwarteter Fehler ist aufgetreten" - for index, subcode in enumerate(code.split("-")): - + for index, subcode in enumerate(code.split("-")): + if index == 0: # Auswahl des ersten Code-Input-Feldes input_xpath = "//input[@name=\"ets-input-code-0\"]" @@ -391,14 +393,15 @@ def driver_enter_code(self, driver, impfzentrum, code): input_xpath = "//input[@name=\"ets-input-code-2\"]" # Input Feld auswählen - input_field = WebDriverWait(driver, 1).until(EC.element_to_be_clickable((By.XPATH, input_xpath))) + input_field = WebDriverWait(driver, 1).until(EC.element_to_be_clickable((By.XPATH, + input_xpath))) action = ActionChains(driver) - action.move_to_element(input_field).click().perform() - + action.move_to_element(input_field).click().perform() + # Chars einzeln eingeben mit kleiner Pause - for char in subcode: + for char in subcode: input_field.send_keys(char) - time.sleep(randint(500,1000)/1000) + time.sleep(randint(500, 1000) / 1000) # Klick auf "Termin suchen" button_xpath = "//app-corona-vaccination-yes//button[@type=\"submit\"]" @@ -423,22 +426,19 @@ def driver_enter_code(self, driver, impfzentrum, code): pass time.sleep(1.5) - def driver_get_cookies(self, driver, url, manual): # Erstelle zufälligen Vermittlungscode für die Cookie-Generierung - legal_chars = string.ascii_uppercase + string.digits - subcode1 = f"{choices(legal_chars)[0]}{choices(legal_chars)[0]}{choices(legal_chars)[0]}{choices(legal_chars)[0]}" - subcode2 = f"{choices(legal_chars)[0]}{choices(legal_chars)[0]}{choices(legal_chars)[0]}{choices(legal_chars)[0]}" - subcode3 = f"{choices(legal_chars)[0]}{choices(legal_chars)[0]}{choices(legal_chars)[0]}{choices(legal_chars)[0]}" - random_code = f"{subcode1}-{subcode2}-{subcode3}" + chars = string.ascii_uppercase + string.digits + random_code = f"{choices(chars, k=4)}-{choices(chars, k=4)}-{choices(chars, k=4)}" # Kann WebDriverException nach außen werfen: self.driver_enter_code( driver, choice(self.impfzentren[url]), random_code) if manual: self.log.warn( - "Du hast jetzt 30 Sekunden Zeit möglichst viele Elemente im Chrome Fenster anzuklicken. Das Fenster schließt sich automatisch.") + "Du hast jetzt 30 Sekunden Zeit möglichst viele Elemente im Chrome Fenster " + "anzuklicken. Das Fenster schließt sich automatisch.") time.sleep(30) required = ["bm_sz", "akavpau_User_allowed"] @@ -479,7 +479,8 @@ def driver_termin_buchen(self, driver, reservierung): except: self.log.error("Termine können nicht gesucht werden") try: - driver.save_screenshot(os.path.join(filepath, "errorterminsuche" + timestamp + ".png")) + driver.save_screenshot( + os.path.join(filepath, "errorterminsuche" + timestamp + ".png")) except: self.log.error("Screenshot konnte nicht gespeichert werden") pass @@ -487,7 +488,8 @@ def driver_termin_buchen(self, driver, reservierung): # Termin auswählen try: time.sleep(3) - button_xpath = '//*[@id="itsSearchAppointmentsModal"]/div/div/div[2]/div/div/form/div[1]/div[2]/label/div[2]/div' + button_xpath = '//*[@id="itsSearchAppointmentsModal"]/div/div/div[2]/div/div/form/' \ + 'div[1]/div[2]/label/div[2]/div' button = WebDriverWait(driver, 1).until( EC.element_to_be_clickable((By.XPATH, button_xpath))) action = ActionChains(driver) @@ -499,7 +501,8 @@ def driver_termin_buchen(self, driver, reservierung): with open(os.path.join(filepath, "errorterminauswahl" + timestamp + ".html"), 'w', encoding='utf-8') as file: file.write(str(driver.page_source)) - driver.save_screenshot(os.path.join(filepath, "errorterminauswahl" + timestamp + ".png")) + driver.save_screenshot( + os.path.join(filepath, "errorterminauswahl" + timestamp + ".png")) except: self.log.error("HTML und Screenshot konnten nicht gespeichert werden") pass @@ -518,7 +521,8 @@ def driver_termin_buchen(self, driver, reservierung): # Klick Daten erfassen try: - button_xpath = '/html/body/app-root/div/app-page-its-search/div/div/div[2]/div/div/div[5]/div/div[2]/div[2]/div[2]/button' + button_xpath = '/html/body/app-root/div/app-page-its-search/div/div/div[2]/div/div/' \ + 'div[5]/div/div[2]/div[2]/div[2]/button' button = WebDriverWait(driver, 1).until( EC.element_to_be_clickable((By.XPATH, button_xpath))) action = ActionChains(driver) @@ -531,10 +535,14 @@ def driver_termin_buchen(self, driver, reservierung): # Klick Anrede arrAnreden = ["Herr", "Frau", "Kind", "Divers"] if self.kontakt['anrede'] in arrAnreden: - button_xpath = '//*[@id="itsSearchContactModal"]//app-booking-contact-form//div[contains(@class,"ets-radio-wrapper")]/label[@class="ets-radio-control"]/span[contains(text(),"' + \ + button_xpath = '//*[@id="itsSearchContactModal"]//app-booking-contact-form//' \ + 'div[contains(@class,"ets-radio-wrapper")]/label[@class=' \ + '"ets-radio-control"]/span[contains(text(),"' + \ self.kontakt['anrede'] + '")]' else: - button_xpath = '//*[@id="itsSearchContactModal"]//app-booking-contact-form//div[contains(@class,"ets-radio-wrapper")]/label[@class="ets-radio-control"]/span[contains(text(),"Divers")]' + button_xpath = '//*[@id="itsSearchContactModal"]//app-booking-contact-form//div' \ + '[contains(@class,"ets-radio-wrapper")]/label[@class=' \ + '"ets-radio-control"]/span[contains(text(),"Divers")]' button = WebDriverWait(driver, 1).until( EC.element_to_be_clickable((By.XPATH, button_xpath))) @@ -542,7 +550,8 @@ def driver_termin_buchen(self, driver, reservierung): action.move_to_element(button).click().perform() # Input Vorname - input_xpath = '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input[@formcontrolname="firstname"]' + input_xpath = '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input' \ + '[@formcontrolname="firstname"]' input_field = WebDriverWait(driver, 1).until( EC.element_to_be_clickable((By.XPATH, input_xpath))) action.move_to_element(input_field).click().perform() @@ -550,42 +559,50 @@ def driver_termin_buchen(self, driver, reservierung): # Input Nachname input_field = driver.find_element_by_xpath( - '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input[@formcontrolname="lastname"]') + '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input' + '[@formcontrolname="lastname"]') input_field.send_keys(self.kontakt['nachname']) # Input PLZ input_field = driver.find_element_by_xpath( - '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input[@formcontrolname="zip"]') + '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input' + '[@formcontrolname="zip"]') input_field.send_keys(self.kontakt['plz']) # Input City input_field = driver.find_element_by_xpath( - '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input[@formcontrolname="city"]') + '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input' + '[@formcontrolname="city"]') input_field.send_keys(self.kontakt['ort']) # Input Strasse input_field = driver.find_element_by_xpath( - '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input[@formcontrolname="street"]') + '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input' + '[@formcontrolname="street"]') input_field.send_keys(self.kontakt['strasse']) # Input Hasunummer input_field = driver.find_element_by_xpath( - '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input[@formcontrolname="housenumber"]') + '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input' + '[@formcontrolname="housenumber"]') input_field.send_keys(self.kontakt['hausnummer']) # Input Telefonnummer input_field = driver.find_element_by_xpath( - '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input[@formcontrolname="phone"]') + '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input' + '[@formcontrolname="phone"]') input_field.send_keys(self.kontakt['phone'].replace("+49", "")) # Input Mail input_field = driver.find_element_by_xpath( - '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input[@formcontrolname="notificationReceiver"]') + '//*[@id="itsSearchContactModal"]//app-booking-contact-form//input' + '[@formcontrolname="notificationReceiver"]') input_field.send_keys(self.kontakt['notificationReceiver']) except: self.log.error("Kontaktdaten können nicht eingegeben werden") try: - driver.save_screenshot(os.path.join(filepath, "errordateneingeben" + timestamp + ".png")) + driver.save_screenshot( + os.path.join(filepath, "errordateneingeben" + timestamp + ".png")) except: self.log.error("Screenshot konnte nicht gespeichert werden") pass @@ -604,7 +621,8 @@ def driver_termin_buchen(self, driver, reservierung): # Termin buchen try: - button_xpath = '/html/body/app-root/div/app-page-its-search/div/div/div[2]/div/div/div[5]/div/div[3]/div[2]/div[2]/button' + button_xpath = '/html/body/app-root/div/app-page-its-search/div/div/div[2]/' \ + 'div/div/div[5]/div/div[3]/div[2]/div[2]/button' button = WebDriverWait(driver, 1).until( EC.element_to_be_clickable((By.XPATH, button_xpath))) action = ActionChains(driver) @@ -912,7 +930,8 @@ def termin_buchen(self, reservierung): # Example response data with status 400: # {"errors":[{"code":"BU004","text":"Slot nicht frei"}]} # {"errors":[{"code":"WP009","text":"Buchung bereits durchgefuehrt"}]} - # {"errors":[{"code":"WP011","text":"Der ausgewählte Termin ist nicht mehr verfügbar. Bitte wählen Sie einen anderen Termin aus"}]} + # {"errors":[{"code":"WP011","text":"Der ausgewählte Termin ist nicht mehr verfügbar. + # Bitte wählen Sie einen anderen Termin aus"}]} raise AppointmentGone() if res.status_code != 201: raise RuntimeError( @@ -996,7 +1015,7 @@ def code_anfordern(self, mail, telefonnummer, return (token, cookies) def selenium_code_anfordern(self, mail, telefonnummer, - plz_impfzentrum, geburtsdatum): + plz_impfzentrum, geburtsdatum): """ SMS-Code beim Impfterminservice via Selenium anfordern. @@ -1008,7 +1027,6 @@ def selenium_code_anfordern(self, mail, telefonnummer, """ url = self.impfzentrum_in_plz(plz_impfzentrum)["URL"] - location = f"{url}rest/smspin/anforderung" data = { "plz": plz_impfzentrum, @@ -1020,7 +1038,8 @@ def selenium_code_anfordern(self, mail, telefonnummer, } # Wire Selenium driver um request im webdriver auszulesen - driver = selenium_wire.Chrome(self.get_chromedriver_path()) + driver = selenium_wire.Chrome(self.get_chromedriver_path(), + options=self.get_chrome_options(False)) while True: @@ -1044,36 +1063,47 @@ def selenium_code_anfordern(self, mail, telefonnummer, driver.get(f"{url}impftermine/service?plz={plz_impfzentrum}") driver.refresh() + # ets-session-its-cv-quick-check im SessionStorage setzen um verfügbare Termine + # zu simulieren + ets_session_its_cv_quick_check = '{"birthdate":"' + data["birthday"] + \ + '","slotsAvailable":{"pair":true,"single":false}}' + driver.execute_script( + 'window.sessionStorage.setItem("ets-session-its-cv-quick-check",\'' + + ets_session_its_cv_quick_check + '\');') + self.log.info( + "\"ets-session-its-cv-quick-check\" Key:Value zum sessionStorage hinzugefügt.") - # ets-session-its-cv-quick-check im SessionStorage setzen um verfügbare Termine zu simulieren - ets_session_its_cv_quick_check = '{"birthdate":"'+ data["birthday"] +'","slotsAvailable":{"pair":true,"single":false}}' - driver.execute_script('window.sessionStorage.setItem("ets-session-its-cv-quick-check",\''+ ets_session_its_cv_quick_check +'\');') - self.log.info("\"ets-session-its-cv-quick-check\" Key:Value zum sessionStorage hinzugefügt.") - - # Durch ets-session-its-cv-quick-check im SessionStorage kann direkt der Check aufgerufen werden + # Durch ets-session-its-cv-quick-check im SessionStorage kann direkt der Check + # aufgerufen werden driver.get(f"{url}impftermine/check") - self.log.info("Überprüfung der Impfberechtigung übersprungen / Vorhandene Termine simuliert und impftermine/check geladen.") + self.log.info("Überprüfung der Impfberechtigung übersprungen / Vorhandene Termine " + "simuliert und impftermine/check geladen.") time.sleep(1) # Anpassen der HTML elemente im Browser um Nutzer aktuellen Status anzuzeigen check_h1_xpath = "//app-its-check-success//h1" check_h1 = driver.find_element_by_xpath(check_h1_xpath) - driver.execute_script("arguments[0].setAttribute('style','color: #FF0000;font-weight: bold; font-size: 35px;')", check_h1) - driver.execute_script(f"arguments[0].innerText='Vaccipy! - Bitte nichts eingeben oder anklicken.'", check_h1) + driver.execute_script("arguments[0].setAttribute('style','color: #FF0000;font-weight: " + "bold; font-size: 35px;')", check_h1) + driver.execute_script(f"arguments[0].innerText='Vaccipy! - Bitte nichts eingeben " + f"oder anklicken.'", check_h1) check_p_xpath = "//app-its-check-success//p" check_p = driver.find_element_by_xpath(check_p_xpath) - driver.execute_script("arguments[0].setAttribute('style','font-weight: bold; font-size: 25px;')", check_p) - + driver.execute_script("arguments[0].setAttribute('style','font-weight: bold; " + "font-size: 25px;')", check_p) + # random start position - current_mouse_positon = (randint(1,driver.get_window_size()["width"]-1), - randint(1,driver.get_window_size()["height"]-1)) + current_mouse_positon = (randint(1, driver.get_window_size()["width"] - 1), + randint(1, driver.get_window_size()["height"] - 1)) # Simulation der Mausbewegung - driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x:{current_mouse_positon[0]}, y:{current_mouse_positon[1]}'", check_p) - current_mouse_positon = move_mouse_to_coordinates(self.log, 0, 0, current_mouse_positon[0], - current_mouse_positon[1], driver) - + driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x: " + f"{current_mouse_positon[0]}, y:{current_mouse_positon[1]}'", + check_p) + current_mouse_positon = move_mouse_to_coordinates(self.log, 0, 0, + current_mouse_positon[0], + current_mouse_positon[1], driver) # Klick auf "Auswahl bestätigen" im Cookies-Banner button_xpath = "//a[contains(@class,'cookies-info-close')][1]" @@ -1083,35 +1113,41 @@ def selenium_code_anfordern(self, mail, telefonnummer, # Simulation der Mausbewegung element = driver.find_element_by_xpath(button_xpath) - driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x: {element.location['x']}, y: {element.location['y']}'", check_p) + driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x: " + f"{element.location['x']}, y: {element.location['y']}'", check_p) current_mouse_positon = move_mouse_to_coordinates(self.log, current_mouse_positon[0], - current_mouse_positon[1], - element.location['x'], - element.location['y'], driver) - driver.execute_script(f"arguments[0].innerText='Status: Cookie-Banner Anklicken'", check_p) + current_mouse_positon[1], + element.location['x'], + element.location['y'], driver) + driver.execute_script(f"arguments[0].innerText='Status: Cookie-Banner Anklicken'", + check_p) action.click(button).perform() time.sleep(0.5) # Eingabe Mail input_xpath = "//input[@formcontrolname=\"email\"]" # Input Feld auswählen - input_field = WebDriverWait(driver, 1).until(EC.element_to_be_clickable((By.XPATH, input_xpath))) + input_field = WebDriverWait(driver, 1).until(EC.element_to_be_clickable((By.XPATH, + input_xpath))) action = ActionChains(driver) # Simulation der Mausbewegung element = driver.find_element_by_xpath(input_xpath) - driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x: {element.location['x']}, y: {element.location['y']}'", check_p) + driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x: " + f"{element.location['x']}, y: {element.location['y']}'", + check_p) current_mouse_positon = move_mouse_to_coordinates(self.log, current_mouse_positon[0], - current_mouse_positon[1], - element.location['x'], - element.location['y'], driver) + current_mouse_positon[1], + element.location['x'], + element.location['y'], driver) action.move_to_element(input_field).click().perform() # Chars einzeln eingeben mit kleiner Pause - driver.execute_script(f"arguments[0].innerText='Status: E-Mail wird eingegeben'", check_p) + driver.execute_script(f"arguments[0].innerText='Status: E-Mail wird eingegeben'", + check_p) for char in data['email']: input_field.send_keys(char) - time.sleep(randint(500,1000)/1000) + time.sleep(randint(500, 1000) / 1000) self.log.info("E-Mail Adresse eingegeben.") time.sleep(0.5) @@ -1119,40 +1155,47 @@ def selenium_code_anfordern(self, mail, telefonnummer, # Eingabe Phone input_xpath = "//input[@formcontrolname=\"phone\"]" # Input Feld auswählen - input_field = WebDriverWait(driver, 1).until(EC.element_to_be_clickable((By.XPATH, input_xpath))) + input_field = WebDriverWait(driver, 1).until(EC.element_to_be_clickable((By.XPATH, + input_xpath))) action = ActionChains(driver) # Simulation der Mausbewegung element = driver.find_element_by_xpath(input_xpath) - driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x: {element.location['x']}, y: {element.location['y']}'", check_p) + driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x: " + f"{element.location['x']}, y: {element.location['y']}'", check_p) current_mouse_positon = move_mouse_to_coordinates(self.log, current_mouse_positon[0], - current_mouse_positon[1], - element.location['x'], - element.location['y'], driver) + current_mouse_positon[1], + element.location['x'], + element.location['y'], driver) action.move_to_element(input_field).click().perform() # Chars einzeln eingeben mit kleiner Pause - driver.execute_script(f"arguments[0].innerText='Status: Phone wird eingegeben'", check_p) + driver.execute_script(f"arguments[0].innerText='Status: Telefonnummer wird eingegeben'", + check_p) for char in data['phone'][3:]: input_field.send_keys(char) - time.sleep(randint(500,1000)/1000) + time.sleep(randint(500, 1000) / 1000) self.log.info("Telefonnummer eingegeben.") time.sleep(0.5) # Anfrage absenden button_xpath = "//app-its-check-success//button[@type=\"submit\"]" - button = WebDriverWait(driver, 1).until(EC.element_to_be_clickable((By.XPATH, button_xpath))) + button = WebDriverWait(driver, 1).until( + EC.element_to_be_clickable((By.XPATH, button_xpath))) action = ActionChains(driver) # Simulation der Mausbewegung element = driver.find_element_by_xpath(button_xpath) - driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x: {element.location['x']}, y: {element.location['y']}'", check_p) + driver.execute_script(f"arguments[0].innerText='Status: Maussimulation nach x: " + f"{element.location['x']}, y: {element.location['y']}'", check_p) current_mouse_positon = move_mouse_to_coordinates(self.log, current_mouse_positon[0], - current_mouse_positon[1], - element.location['x'], - element.location['y'], driver) - driver.execute_script(f"arguments[0].innerText='Status: Versuche Anfrage abzuschicken'", check_p) + current_mouse_positon[1], + element.location['x'], + element.location['y'], driver) + driver.execute_script( + f"arguments[0].innerText='Status: Versuche Anfrage abzuschicken'", + check_p) action.move_to_element(button).click().perform() # Zweiter Klick-Versuch, falls Meldung "Es ist ein unerwarteter Fehler aufgetreten" erscheint @@ -1166,7 +1209,8 @@ def selenium_code_anfordern(self, mail, telefonnummer, if element: if element.text == "Es ist ein unerwarteter Fehler aufgetreten": - driver.execute_script(f"arguments[0].innerText='Status: Zweiter Versuch Anfrage abzuschicken'", check_p) + driver.execute_script(f"arguments[0].innerText='Status: Zweiter Versuch " + f"Anfrage abzuschicken'", check_p) action.move_to_element(button).click().perform() elif element.text == "Anfragelimit erreicht.": driver.close() @@ -1182,13 +1226,15 @@ def selenium_code_anfordern(self, mail, telefonnummer, sms_verifizierung_h1 = driver.find_element_by_xpath(sms_verifizierung_h1_xpath) if sms_verifizierung_h1.text != "SMS Verifizierung": driver.close() - raise RuntimeError("Vermittlungscode kann derzeit nicht angefragt werden. Versuchen Sie es später erneut.") + raise RuntimeError("Vermittlungscode kann derzeit nicht angefragt werden. " + "Versuchen Sie es später erneut.") # Ab jetzt befinden wir uns auf der SMS Verifizierung Seite location = f"{url}rest/smspin/verifikation" self.log.info("SMS-Anfrage an Server versandt.") - self.log.info("Bitte SMS-Code innerhalb der nächsten 60 Sekunden im Browser-Fenster eingeben.") - + self.log.info("Bitte SMS-Code innerhalb der nächsten 60 Sekunden im Browser-Fenster " + "eingeben.") + # 90 Sekunden lang auf Antwort vom Server warten # Eventuell gibt User seinen Pin falsch ein etc. max_sms_code_eingabe_sekunden = 90 @@ -1196,12 +1242,14 @@ def selenium_code_anfordern(self, mail, telefonnummer, # Verbleibende Zeit anzeigen try: - driver.execute_script(f"arguments[0].innerText='Vaccipy! - Bitte SMS-Code im Browser eingeben. Noch {max_sms_code_eingabe_sekunden} Sekunden verbleibend.'", sms_verifizierung_h1) + driver.execute_script(f"arguments[0].innerText='Vaccipy! - Bitte SMS-Code " + f"im Browser eingeben. Noch {max_sms_code_eingabe_sekunden} " + f"Sekunden verbleibend.'", sms_verifizierung_h1) except Exception as e: pass # Alle bisherigen Requests laden - sms_verification_responses= [] + sms_verification_responses = [] for request in driver.requests: if request.url == location: sms_verification_responses.append(request.response) @@ -1209,7 +1257,8 @@ def selenium_code_anfordern(self, mail, telefonnummer, if sms_verification_responses: # Neuste Antowrt vom Server auslesen - # User kann z.B 2 mal den Pin falsch eingeben uns interessiert nur die neuste Antwort vom Server + # User kann z.B 2 mal den Pin falsch eingeben + # uns interessiert nur die neuste Antwort vom Server latest_reponse = sms_verification_responses[-1] if latest_reponse is not None: @@ -1224,22 +1273,23 @@ def selenium_code_anfordern(self, mail, telefonnummer, self.log.info("Der eingegebene SMS-Code ist ungültig.") elif latest_reponse.status_code == 200: - self.log.info(f"SMS-Code erfolgreich übermittelt. Bitte Prüfen Sie Ihre E-Mails.") - driver.close() - return True + self.log.info(f"SMS-Code erfolgreich übermittelt. Bitte Prüfen " + f"Sie Ihre E-Mails.") + driver.close() + return True elif latest_reponse.status_code == 429: - driver.close() - raise RuntimeError("SMS-Code konnte nicht übermittelt werden. Blockiert durch Botprotection.") + driver.close() + raise RuntimeError("SMS-Code konnte nicht übermittelt werden. " + "Blockiert durch Botprotection.") time.sleep(1) max_sms_code_eingabe_sekunden -= 1 - - driver.close() - self.log.info(f"SMS-Verifikation nicht innerhalb von 90 Sekunden abgeschlossen. Versuchen Sie es später erneut.") + driver.close() + self.log.info(f"SMS-Verifikation nicht innerhalb von 90 Sekunden abgeschlossen. " + f"Versuchen Sie es später erneut.") return False - def code_bestaetigen(self, token, cookies, sms_pin, plz_impfzentrum): """ Bestätigung der Code-Generierung mittels SMS-Code @@ -1259,13 +1309,12 @@ def code_bestaetigen(self, token, cookies, sms_pin, plz_impfzentrum): manual = False while True: - if cookies is None: + if not cookies: try: cookies = self.get_cookies(url, manual=manual) except RuntimeError as exc: self.log.error(str(exc)) continue # Neuer Versuch in nächster Iteration - try: self.s.cookies.clear() res = self.s.post( @@ -1303,7 +1352,6 @@ def code_bestaetigen(self, token, cookies, sms_pin, plz_impfzentrum): "bitte prüfe deine Mails!") return True - def impfzentrum_in_plz(self, plz_impfzentrum): for url, gruppe in self.impfzentren.items(): for iz in gruppe: @@ -1385,7 +1433,9 @@ def terminsuche(codes: list, plz_impfzentren: list, kontakt: dict, its.termin_buchen(reservierung) msg = "Termin erfolgreich gebucht!" its.log.success(msg) - its.log.info("[SPENDE] Unterstütze hier unsere Spendenkampagne für 'Ärzte ohne Grenzen': https://www.aerzte-ohne-grenzen.de/spenden-sammeln?cfd=pjs3m") + its.log.info( + "[SPENDE] Unterstütze hier unsere Spendenkampagne für 'Ärzte ohne " + "Grenzen': https://www.aerzte-ohne-grenzen.de/spenden-sammeln?cfd=pjs3m") its.notify(title="Terminbuchung:", msg=msg) # Programm beenden, wenn Termin gefunden wurde return diff --git a/tools/seleniumwire/ca.crt b/tools/seleniumwire/ca.crt new file mode 100644 index 00000000..d9d6d553 --- /dev/null +++ b/tools/seleniumwire/ca.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFFzCCAv+gAwIBAgIUIUc6dnnqhYX3ZYXQzpZyJ1gtUwcwDQYJKoZIhvcNAQEL +BQAwGzEZMBcGA1UEAwwQU2VsZW5pdW0gV2lyZSBDQTAeFw0xODA3MjAxMDQxMDNa +Fw0yODA3MTcxMDQxMDNaMBsxGTAXBgNVBAMMEFNlbGVuaXVtIFdpcmUgQ0EwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKKpm14AHiJb4onGES4Echs2qB +XsfeMAbsA7x4blJkMGyHGx9B8OpXqlRtcNnWD2JGnjc0/k92uuZaV2prDnZwH5Jl +nJSZuGEzUUAnrwhTHTqMhM9pfT8RpltE0lyplQni8rjH5oshBrzzAHILm/iAm1WI +HCFUClQaJ7sVVzAikaPfg4WUXLHP7/AjxIejp/SVI8Ycn1BPIlDwp1pIq4WawJoZ +TZ75GwvsT1ohH4YSRM+BxwBuBUqjusaYJiWwpnR801XV290i3/bBOkS2fEa4+ciS +LEGEi4SaaC6Nhap3sd80npJUQff4ltVGaxX0jCG/zswf2XGEDtsw2FF848KePj4X +Ilgm4xcuhhBvcsgob/bwEvDTrXPk38YQEJEKH8uGf37AOv2TQmqj45WZt7jSZ2YH +ZGn4RunJAO/J7toqJ7upjx66Pq8WkXQ6faSeTNENmXclYPRQFujVbFkECRcOtS6W +fUkHM+tgXHKqSMcfVVp46o/4HfHzoTyvrUDryHJB3h/IrqWK1433rYp3bJzkpjM9 +JT71vh6sDo/Ys+4HK5rwrwkeP7b+6dUx1nHOgPX88njVI6cuxnjex6AfSld5d4BH +YZdviXRqCxpiudmnN+cMKAdJgRZFmVNH/djQqtq3y/gmjwKnyW95y3uJu4Xz5+R4 +9jhAZGJFiHK/vE+XwwIDAQABo1MwUTAdBgNVHQ4EFgQUPvrTydSlYhMQJy8lvBvh +nLeQsvQwHwYDVR0jBBgwFoAUPvrTydSlYhMQJy8lvBvhnLeQsvQwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAmIvadNtFca9vuMuSewSXHlOd9p7d +9xYkp8Yj5RvFUGL32zYUatH9YsRh5K9Wz5jifjwBLMRDZIm48xhxYjqVvTZoQpL6 +Qyzbu2EsRCbmQ+861U4SfcP2uetJuFM6Ug0/CKviyNpUaX/8YWupFXsEiCRJM9pk +sh2b+dqljy9kvrOosfehz8CRbxUfgPsL2IVZa0mHsuOZDa/XHAAW9ns5TdBlFHwo +W/2KDvvPGL/3t7Zah2jwu8D8w397looMXxqyT/DAjH6+bd5Kg/7mELaqbg/pM3EJ +mENd5ButBkhpVbyAKLn7TvpZYSEF/VMNPcZHOKoKrx1utZwLFuVIb07WDMRov0GO +hg/rrIBWvA1ySi/4yrnRDc7GBHSUh0Krx6LLZ/ZtE3j7/4rwj51MwqqNhQrCxGhz +ksqn8V6XY7UUKnlTlAWRyuBLiA+yvf9GdgNJxUblZYMNpPbeLwe2Be/utROuMqwr +G4RA1sfPuEdyfdXB/7c8ViOPxKYFH0POXuwB+Z1JlXDtR8rbjyVPUwqQarAuNIbw +NC8P+GWSzviG544BQyW1xKqLgQcEMSU73icDOOb9COcl1h7URSO9WB6CZXykpQSk +hceDiwojCDsyM84uXyyXKXCRPtseCIRsA1zZwrXU7NDDBXrIC7moVbxkDu2G4V1g +b5JFYe4FNI0yw/o= +-----END CERTIFICATE----- diff --git a/tools/seleniumwire/ca.key b/tools/seleniumwire/ca.key new file mode 100644 index 00000000..f726d618 --- /dev/null +++ b/tools/seleniumwire/ca.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +M4ASYgjl3b4eb4ejEp9ylbMJ/I7G0mU= +-----END PRIVATE KEY-----