#!/usr/bin/python3.10 from modules.config import * from modules.error import * from modules.driver_tools import * from modules.cards import * import modules.globals as g from modules.Classes.Config import Config from modules.Classes.UserCredentials import UserCredentials from modules.Tools.logger import warning, info, debug, error, critical driver = g.driver display = g.display # create a webdriver def create_driver(mobile=False): PC_USER_AGENT = ( "Mozilla/5.0 (X11; Linux x86_64)" "AppleWebKit/537.36 (KHTML, like Gecko)" "Chrome/122.0.0.0 Safari/537.36 Edg/122.0.2088.46" ) MOBILE_USER_AGENT = ( "Mozilla/5.0 (Linux; Android 7.0; Nexus 5 Build/MRA58N)" "AppleWebKit/537.36 (KHTML, like Gecko)" "Chrome/22 Mobile Safari/537.36" ) chrome_options = webdriver.ChromeOptions() if mobile: chrome_options.add_argument(f"--user-agent={MOBILE_USER_AGENT}") else: chrome_options.add_argument(f"--user-agent={PC_USER_AGENT}") # disabled as it may cause detection if g.proxy_enabled: chrome_options.add_argument(f'--proxy-server={g.proxy_address}:{g.proxy_port}') driver = uc.Chrome(options=chrome_options) set_language(driver) return driver def log_error(error_message, l_driver=driver, log=g.full_log): global driver if l_driver is None: l_driver = driver if type(error_message) is not str: error_message = format_error(error_message) error(str(error_message)) if g.discord_enabled_error: with open("page.html", "w") as f: try: f.write(l_driver.page_source) except: f.write("the driver has closed or crashed. Can't access page content") try: img = display.waitgrab() img.save("screenshot.png") except: l_driver.save_screenshot("screenshot.png") if not log: embed = Embed( title="An Error has occured", description=str(error_message), colour=Colour.red(), ) else: embed = Embed( title="Full log is enabled", description=str(error_message), colour=Colour.blue(), ) file = File("screenshot.png") embed.set_image(url="attachment://screenshot.png") embed.set_footer(text=g._mail) webhookFailure.send(embed=embed, username="error", file=file, avatar_url=g.avatar_url) webhookFailure.send(username="error", file=File("page.html"), avatar_url=g.avatar_url) # close the tab currently on and go back to the one first, or the one specified def close_tab(tab, switch_to: int = 0) -> None: driver.switch_to.window(tab) driver.close() driver.switch_to.window(driver.window_handles[switch_to]) # play_quiz[N]([int : override]) make the quiz with N choice each time. They usually have between 4 and 10 questions. # override is the number of question, by default, it's the number of question in this specific quiz. # Can be useful in some case, where the program crashes before finishing the quiz def play_quiz2(override=10) -> None: info("Starting to play quiz 2.") debug(f"override: {override}") for j in range(override): custom_sleep(uniform(3, 5)) js_function = """ function get_correct_answer(){ function br(n) { for (var r, t = 0, i = 0; i < n.length; i++)t += n.charCodeAt(i); return r = parseInt(_G.IG.substr(_G.IG.length - 2), 16), t += r, t.toString() } // Ms check function function namedRAValue() { //allow calls to getRAvalue return _w.getRAValue() }; if (br(document.getElementById("rqAnswerOption0").attributes["data-option"].value) == namedRAValue()){ return(0); } else { return(1); } }; return(get_correct_answer()) """ correct_answer_value = driver.execute_script(js_function) try: answer_elem = driver.find_element(By.ID, f"rqAnswerOption{correct_answer_value}") answer_elem.click() except exceptions.ElementNotInteractableException: answer_elem = driver.find_element(By.ID, f"rqAnswerOption{correct_answer_value}") driver.execute_script("arguments[0].click();", answer_elem) except Exception as e: log_error(e) break info("Quiz 2 done.") custom_sleep(3) def play_quiz8(): info(f"Starting Quiz 8") override = len(findall("", driver.page_source)) + 1 debug(f"override : {override}") correct_answers = ["Should", "be", "reset", "before", "you", "see", "this."] # supress warning try: for _ in range(override): sleep(uniform(3, 5)) correct_answers = [] for i in range(1, 9): # todo: remove this odd 1-offset try: element = driver.find_element(By.ID, f"rqAnswerOption{i - 1}") if 'iscorrectoption="True"' in element.get_attribute("outerHTML"): correct_answers.append(f'rqAnswerOption{i - 1}') except Exception as e: warning(f"can't find rqAnswerOption{i - 1}. Probably already clicked" + str(e)) shuffle(correct_answers) for answer_id in correct_answers: wait_until_visible(By.ID, answer_id, timeout=20, browser=driver) try: answer_elem = driver.find_element(By.ID, answer_id) answer_elem.click() sleep(1) except exceptions.NoSuchElementException: driver.refresh() sleep(10) answer_elem = driver.find_element(By.ID, answer_id) answer_elem.click() except ElementClickInterceptedException: rgpd_popup(driver) correct_answers.append(answer_id) except Exception as e: log_error(f"{format_error(e)} \n Good answers : {' '.join(correct_answers)}") info("Quiz 8 done.") custom_sleep(3) def play_quiz4(override: int = None): info(f"Starting Quiz 4") if not override: try: # fidelity quiz are much longer than usual ones override = int(findall('rqQuestionState([\d]{1,2})"', driver.page_source)[-1]) except: override = 3 debug(f"Override : {override}") try: for i in range(override): custom_sleep(uniform(3, 5)) txt = driver.page_source answer_option = search('correctAnswer":"([^"]+)', txt)[1] answer_option = answer_option.replace("\\u0027", "'") # replace Unicode weird symbols answer_element = driver.find_element(By.CSS_SELECTOR, f'[data-option="{answer_option}"]') try: answer_element.click() except exceptions.ElementNotInteractableException: driver.execute_script("arguments[0].click();", answer_element) except Exception as e: log_error(e) raise ValueError(e) info("Quiz 8 done.") custom_sleep(3) # do_poll() answer a random thing to poll, on of daily activities def do_poll(): info("Starting poll") try: answer_elem = driver.find_element(By.ID, f"btoption{choice([0, 1])}") try: answer_elem.click() except exceptions.ElementNotInteractableException: driver.execute_script("arguments[0].click();", answer_elem) custom_sleep(uniform(2, 2.5)) except Exception as err: log_error(err) raise ValueError(err) info("Poll done.") custom_sleep(3) # Find each playable card and tries to click on it to earn points # todo : refactor def all_cards(): driver.get("https://rewards.bing.com") wait_until_visible(By.CLASS_NAME, "c-card-content", 10, driver) liste = driver.find_elements(By.CLASS_NAME, "c-card-content") custom_sleep(2) try: promo() except Exception as e: info("no promo card") if (len(liste) < 10): # most likely an error during loading if "suspendu" in driver.page_source: raise Banned() driver.refresh() liste = driver.find_elements(By.CLASS_NAME, "c-card-content") if (len(liste) < 10): log_error("Less than 10 cards. Most likely an error with login.", driver) return ("PAS ASSEZ DE CARTES") if (len(liste) < 20): # most likely not in france printf("moins de 20 cartes. Probablement pas en France.") for i in range(len(liste)): printf(f"carte {i}") try: checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) except StaleElementReferenceException: driver.refresh() liste = driver.find_elements(By.CLASS_NAME, "c-card-content") printf(f"staled, {len(liste)}") checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) except IndexError: driver.get("https://rewards.bing.com") custom_sleep(10) liste = driver.find_elements(By.CLASS_NAME, "c-card-content") try: checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) except IndexError: if i == len(liste) & i > 15: checked = False # input("2") if checked: custom_sleep(1.5) driver.execute_script("arguments[0].scrollIntoView();", liste[i]) custom_sleep(1.5) # input("3") liste[i].click() # input("4") if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) # input("5") try_play(driver.title) close_tab(driver.window_handles[1]) try: driver.refresh() liste = driver.find_elements(By.CLASS_NAME, "c-card-content") if ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")): printf(f"carte {i} not okay. Retrying.") try: liste[i].click() except: log_error("problème inconnu ? sauf si c'est un element obscure...", driver) driver.get("https://rewards.bing.com") checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) driver.switch_to.window(driver.window_handles[1]) try_play(driver.title) close_tab(driver.window_handles[1]) if ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")): driver.execute_script("arguments[0].scrollIntoView();", liste[i]) log_error(f"Card {i} Can't be completed. Why MS ?", driver) liste[i].click() driver.switch_to.window(driver.window_handles[1]) log_error(f"Cart completion - log - 2", driver) custom_sleep(10) log_error(f"Cart completion - log - 3 - after 10 sec", driver) try: try_play(driver.title) # go back to the main page try: close_tab(driver.window_handles[1]) except: pass except: driver.get("https://rewards.bing.com") except: pass else: try: welcome_tour(liste[i], driver) except Exception as e: printf("no new windows" + format_error(e)) driver.get("https://rewards.bing.com") custom_sleep(3) def promo(): for i in range(5): elm = driver.find_element(By.ID, "promo-item") wait_until_visible(By.ID, "promo-item", 5, driver) if not elm: break if i > 3: log_error("plus de 3 promo cards, probablement une pa skipable", driver) try: driver.find_element(By.CSS_SELECTOR, 'i[class="mee-icon pull-left icon mee-icon-Cancel ng-scope"]').click() except Exception as e: log_error(f"can't click to close : {e}") return () try: elm.click() except Exception as e: # log_error(e, driver) driver.execute_script("arguments[0].click();", elm) # log_error(e, driver) printf(f"that should't be there (promo), but the workarround seemed to work {e}") custom_sleep(3) if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[len(driver.window_handles) - 1]) try_play(driver.title) close_tab(driver.window_handles[1]) else: try: spotify(driver) except: warning("no new windows") driver.get("https://rewards.bing.com") driver.refresh() custom_sleep(3) # Find out which type of action to do def try_play(nom="inconnu"): rgpd_popup(driver) def play(number): if number in [8, 9]: try: debug(f"Quiz 8 detected on `{nom}`.") play_quiz8() except Exception as err: error(f"fail of PlayQuiz 8. Aborted {err}") elif number in [4, 5]: try: debug(f"Quiz 4 detected on `{nom}`") play_quiz4() except Exception as err: error(f"Fail of PlayQuiz 4. Aborted {err}.") elif number in [2, 3]: try: debug(f"\033[96mQuiz 2 detected on `{nom}`\033[0m") play_quiz2() except Exception as err: error(f"fail of PlayQuiz 2. Aborted {err}") else: error("`rqAnswerOption` present in page but no action to do.") custom_sleep(uniform(3, 5)) if "pas connecté à Microsoft Rewards" in driver.page_source: custom_sleep(5) driver.find_element(By.CSS_SELECTOR, '[onclick="setsrchusr()"]').click() custom_sleep(5) rgpd_popup(driver) custom_sleep(5) debug("Detected and fixed connection popup") if "bt_PollRadio" in driver.page_source: debug("Poll detected") do_poll() elif "rqQuestionState" in driver.page_source: number = driver.page_source.count("rqAnswerOption") warning(f"recovery détecté. quiz : {number}") play(number - 1) elif search("([0-9]) de ([0-9]) finalisée", driver.page_source): info("On fidelity page.") fidelity() elif wait_until_visible(By.ID, "rqStartQuiz", 5, driver): custom_sleep(3) driver.find_element(By.ID, "rqStartQuiz").click() # start the quiz answer_number = driver.page_source.count("rqAnswerOption") play(answer_number) else: printf(f"Nothing to do on page `{nom}`") custom_sleep(uniform(3, 5)) # Login with password or with cookies. # The driver should be in the same state on both case def pwd_login(ldriver, cred: UserCredentials): printf("pwd_login : start") ldriver.get("https://login.live.com") wait_until_visible(By.ID, "i0116", browser=ldriver) mail_elem = ldriver.find_element(By.ID, "i0116") send_keys_wait(mail_elem, cred.get_mail()) mail_elem.send_keys(Keys.ENTER) wait_until_visible(By.ID, "i0118", browser=ldriver) pwd_elem = ldriver.find_element(By.ID, "i0118") send_keys_wait(pwd_elem, cred.get_password()) pwd_elem.send_keys(Keys.ENTER) custom_sleep(2) # 2FA if "Entrez le code de sécurité" in ldriver.page_source: try: a2f_elem = ldriver.find_element(By.ID, "idTxtBx_SAOTCC_OTC") a2f_elem.send_keys(g._otp.now()) a2f_elem.send_keys(Keys.ENTER) except Exception as e: log_error(e) def cookie_login(ldriver): printf("cookies_login : start") ldriver.get("https://login.live.com") try: load_cookies(ldriver) except FileNotFoundError: printf("No cookies file Found.") return (False) except Exception as e: # log_error(f"Error performing cookies login. Trying with password instead. \n{str(e)}", driver) print("error with cookies login. IDK why (yet)") return (False) try: ldriver.refresh() except Exception as e: printf(format_error(e)) printf("FIX YOUR SITE MS.......") return (True) # Accept all cookies question, and check if the account is locked def login_part_2(ldriver, cookies=False): custom_sleep(5) if ('Abuse' in ldriver.current_url): raise Banned() if ('identity' in ldriver.current_url): raise Identity() if ('notice' in ldriver.current_url): ldriver.find_element(By.ID, "id__0").click() if ("proof" in ldriver.current_url): ldriver.find_element(By.ID, "iLooksGood") if cookies: save_cookies(ldriver) for id in ["iNext", "KmsiCheckboxField", "id__0", "iLooksGood", "idSIButton9", "iCancel"]: if get_domain(ldriver) == "account.microsoft.com": break try: ldriver.find_element(By.ID, id).click() except Exception as e: pass wait_until_visible(By.CSS_SELECTOR, '[data-bi-id="sh-sharedshell-home"]', 20, ldriver) # login() tries to login to your Microsoft account. # it uses global variable g._mail and g._password to login def login(ldriver, cred: Credentials): try: pwd_login(ldriver, cred) login_part_2(ldriver, 0) ldriver.get("https://rewards.bing.com/") except Banned: raise Banned() except Identity: raise Banned() except Exception as e: log_error(e) ldriver.quit() return (False) # Makes 30 search as PC Edge def bing_pc_search(override=randint(35, 40)): mot = choice(Liste_de_mot).replace(" ", "+") driver.get(f"https://www.bing.com/search?q={mot}") # {choice(Liste_de_mot)}') custom_sleep(uniform(1, 2)) rgpd_popup(driver) send_keys_wait( driver.find_element(By.ID, "sb_form_q"), Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE + Keys.BACKSPACE ) for _ in range(override): word = choice(Liste_de_mot) try: send_keys_wait(driver.find_element(By.ID, "sb_form_q"), word) driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER) except Exception as e: printf(e) sleep(10) driver.get(f'https://www.bing.com/search?q={word}') sleep(3) send_keys_wait(driver.find_element(By.ID, "sb_form_q"), word) driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER) custom_sleep(uniform(3, 7)) try: driver.find_element(By.ID, "sb_form_q").clear() except Exception as e: printf(e) try: driver.get('https://www.bing.com/search?q=plans') driver.find_element(By.ID, "sb_form_q").clear() except Exception as e: log_error(f"clear la barre de recherche - {format_error(e)}") # Sends points to database, discord and whatever service you want def log_points(account="unknown"): def get_points(): driver.get("https://rewards.bing.com") custom_sleep(1) if "/proofs/" in driver.current_url: webhookFailure.send(f"Is /proof Useful in logpoints?", username="Dev tests", avatar_url="https://cdn.discordapp.com/attachments/793934298977009677/1144560898879541268/image.png") for id in ["KmsiCheckboxField", "iLooksGood", "idSIButton9", "iCancel"]: try: driver.find_element(By.ID, id).click() except Exception as e: pass wait_until_visible(By.CSS_SELECTOR, 'span[mee-element-ready="$ctrl.loadCounterAnimation()"]', browser=driver) try: point = search('availablePoints\":([\d]+)', driver.page_source)[1] except Exception as e: sleep(5) log_error( f"Dev error, checking why it doesn't work (waited a bit, is this still white ?) {format_error(e)}", driver, True) driver.refresh() sleep(5) point = search('availablePoints\":([\d]+)', driver.page_source)[1] return (point) for _ in range(3): try: points = get_points() break except Exception as e: custom_sleep(300) log_error(e) points = None if not points: log_error(f"impossible d'avoir les points") custom_sleep(uniform(3, 20)) account_name = account.split("@")[0] if g.discord_enabled_success: if g.discord_embed: embed = Embed( title=f"{account_name} actuellement à {str(points)} points", colour=Colour.green() ) embed.set_footer(text=account_name) webhookSuccess.send(embed=embed) else: webhookSuccess.send(f"{account_name} actuellement à {str(points)} points") try: add_to_database(account_name, points) except Exception as e: log_error(e) def fidelity(): def sub_fidelity(): try: wait_until_visible(By.CSS_SELECTOR, 'div[class="pull-left spacer-48-bottom punchcard-row"]', browser=driver) answer_number = search("([0-9]) of ([0-9]) completed", driver.page_source) if answer_number is None: answer_number = search("([0-9]) défi\(s\) terminé\(s\) sur ([0-9])", driver.page_source) if answer_number is None: answer_number = search("([0-9]) de ([0-9]) finalisé", driver.page_source) if answer_number is None: answer_number = search("([0-9]) licence\(s\) sur ([0-9]) disponible\(s\)", driver.page_source) if answer_number is None: answer_number = [0, 0, 0] for _ in range(int(answer_number[2]) - int(answer_number[1])): driver.refresh() custom_sleep(2) card_elem = driver.find_element(By.CLASS_NAME, "spacer-48-bottom") try: button_text = search('([^<^>]+)', card_elem.get_attribute("innerHTML"))[1] bouton_card = driver.find_element(By.XPATH, f'//span[text()="{button_text}"]') bouton_card.click() except Exception as e1: try: recover_elem = driver.find_element(By.XPATH, '/html/body/div[1]/div[2]/main/div[2]/div[2]/div[7]/div[3]/div[1]/a') recover_elem.click() except Exception as e2: log_error(f"fidélité - double erreur - e1 : {format_error(e1)} - e2 {format_error(e2)}") break custom_sleep(uniform(3, 5)) driver.switch_to.window(driver.window_handles[2]) try_play(driver.title) custom_sleep(uniform(3, 5)) try: close_tab(driver.window_handles[2], 1) except Exception as e: printf(e) printf("fidelity - done") except Exception as e: log_error(e) if driver.current_url != "https://rewards.bing.com": driver.get("https://rewards.bing.com") try: pause = driver.find_element(By.CSS_SELECTOR, f'[class="c-action-toggle c-glyph f-toggle glyph-pause"]') # mettre le truc en pause pause.click() except Exception as e: printf(f"erreur lors du click de pause: probablement pas de cartes {e}") return ("no cards") cartes = driver.find_elements(By.CSS_SELECTOR, f'[ng-repeat="item in $ctrl.transcludedItems"]') nb_cartes = len(cartes) checked_list_all = driver.find_elements(By.CSS_SELECTOR, f'[ng-if="$ctrl.complete"]') for i in range(nb_cartes): cartes[i].click() # affiche la bonne carte checked_txt = checked_list_all[i].get_attribute("innerHTML") ok = checked_txt.count("StatusCircleOuter checkmark") total = checked_txt.count("StatusCircleOuter") if (ok != total): elm = driver.find_elements(By.CLASS_NAME, 'clickable-link')[i] if not "moviesandtv" in elm.get_attribute("innerHTML"): # not the film card elm.click() driver.switch_to.window(driver.window_handles[len(driver.window_handles) - 1]) sub_fidelity() close_tab(driver.window_handles[1]) custom_sleep(1) cartes = driver.find_elements(By.CSS_SELECTOR, f'[ng-repeat="item in $ctrl.transcludedItems"]') checked_list_all = driver.find_elements(By.CSS_SELECTOR, f'[ng-if="$ctrl.complete"]') def mobile_alert_popup(): try: alert = mobile_driver.switch_to.alert alert.dismiss() except exceptions.NoAlertPresentException as e: pass except Exception as e: log_error(e, mobile_driver) def bing_mobile_search(override=randint(22, 25)): global mobile_driver mobile_driver = create_driver(mobile=True) try: login(mobile_driver) mot = choice(Liste_de_mot).replace(" ", "+") mobile_driver.get(f"https://www.bing.com/search?q={mot}") custom_sleep(uniform(1, 2)) rgpd_popup(mobile_driver) custom_sleep(uniform(1, 1.5)) for i in range(override): # 20 try: mot = choice(Liste_de_mot) send_keys_wait(mobile_driver.find_element(By.ID, "sb_form_q"), mot) mobile_driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER) custom_sleep(uniform(3, 7)) mobile_alert_popup() # check for alert (asking for position or for allowing notifications) mobile_driver.find_element(By.ID, "sb_form_q").clear() except Exception as e: printf(e) mobile_driver.refresh() custom_sleep(30) i -= 1 mobile_driver.quit() except Exception as e: log_error(e, mobile_driver) mobile_driver.quit() def daily_routine(cred: UserCredentials, custom=False): try: if not custom: # custom already login login(driver, cred) except Banned: log_error("This account is locked.", driver) return except Identity: log_error("This account has an issue.", driver) return try: all_cards() except Banned: log_error("banned", driver) return ("BANNED") except Exception as e: log_error(e) try: fidelity() except Exception as e: log_error(e) try: bing_pc_search() except Exception as e: log_error(e) try: bing_mobile_search() except Exception as e: log_error(e) try: log_points(g._mail) except Exception as e: log_error(e) def json_start(json): global driver display = SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=2345, color_depth=24) display.start() for i in range(5): cred = g._cred[i] g._mail = cred[0] g._password = cred[1] if cred[2] != '': g._otp = TOTP(cred[2]) start = False for j in ["unban", "tout", "pc", "mobile", "daily"]: try: if str(i) in json[j]: start = True print(f"{g._mail} : {j}") except KeyError: pass if start: driver = create_driver() try: if str(i) in json["unban"]: pwd_login(driver) print("\nGO TO example.com TO PROCEED or wait 1200 secs.") for _ in range(1200): sleep(1) if driver.current_url == "https://example.com/": print("proceeding") break else: login(driver) except KeyError: login(driver) try: if str(i) in json["tout"]: daily_routine(True) except KeyError: pass # print("none is set to \"tout\"") else: try: if str(i) in json["daily"]: try: all_cards() except Exception as e: log_error(e) except KeyError: pass # print("none is set to \"daily\"") try: if str(i) in json["pc"]: try: bing_pc_search() except Exception as e: log_error(e) except KeyError: pass try: if str(i) in json["mobile"]: try: bing_mobile_search() except Exception as e: log_error(e) except KeyError: pass try: log_points(g._mail) except Exception as e: printf(f"CustomStart {e}") driver.close() display.stop() if g.very_custom: dict_data = json.loads(g.very_custom.replace("'", "\"")) json_start(dict_data) else: c = Config(args) if g.vnc_enabled or g.dev: display = SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=g.vnc_port, color_depth=24) else: display = SmartDisplay(size=(1920, 1080)) display.start() if g.update_version != "None": if g.discord_enabled_error: webhookFailure.send(f"Updated to {g.update_version}", username="UPDATE", avatar_url="https://cdn-icons-png.flaticon.com/512/1688/1688988.png") while c.UserCredentials.is_valid(): g._mail = c.UserCredentials.get_mail() g._password = c.UserCredentials.get_password() if c.UserCredentials.tfa_enable(): g._otp = TOTP(c.UserCredentials.get_tfa()) custom_sleep(1) info("Starting driver.") driver = create_driver() info("Driver started.") driver.implicitly_wait(3) try: wait_time = uniform(1200, 3600) info(f"Waiting for {round(wait_time / 60)}min before starting") daily_routine(c.UserCredentials) driver.quit() custom_sleep(wait_time) except KeyboardInterrupt: critical("Canceled by user. Closing driver and display.") driver.quit() display.stop() break except Exception as e: log_error(f"Error not caught. Skipping this account. " + format_error(e), driver) critical(f"Error not caught. Skipping this account. {e}") driver.quit() c.UserCredentials.next_account() display.stop()