#!/usr/bin/python3 import random from modules.Classes.Config import Config from modules.Classes.DiscordLogger import DiscordLogger from modules.Classes.UserCredentials import UserCredentials from modules.Tools.logger import critical, warning from modules.cards import * from modules.config import * from modules.db import add_to_database from modules.driver_tools import * from modules.error import * # 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_profile_dir = init_profile(config.UserCredentials.get_mail(), mobile=mobile) # Full list on https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md arguments = [ "--no-first-run", "--ash-no-nudges", "--no-default-browser-check", "--disable-features=PrivacySandboxSettings4,Translate", "--disable-search-engine-choice-screen", f"--user-data-dir={chrome_profile_dir}/" ] if mobile: arguments.append(f"--user-agent={mobile_user_agent}") else: arguments.append(f"--user-agent={pc_user_agent}") # disabled as it may cause detection if config.proxy.is_enabled(): arguments.append(f'--proxy-server={config.proxy.ip}:{config.proxy.port}') chrome_options = webdriver.ChromeOptions() for arg in arguments: chrome_options.add_argument(arg) driver = uc.Chrome(options=chrome_options) return driver # 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 = config.WebDriver.driver 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.") driver = config.WebDriver.driver 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(): driver = config.WebDriver.driver 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(8): try: element = driver.find_element(By.ID, f"rqAnswerOption{i}") if 'iscorrectoption="True"' in element.get_attribute("outerHTML"): correct_answers.append(f'rqAnswerOption{i}') except Exception as e: warning(f"can't find rqAnswerOption{i}. 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(config) correct_answers.append(answer_id) except Exception as e: log_error(f"{format_error(e)} \n Good answers : {' '.join(correct_answers)}") raise ValueError(format_error(e)) info("Quiz 8 done.") custom_sleep(3) def play_quiz4(override: int = None): info(f"Starting Quiz 4") driver = config.WebDriver.driver if not override: try: # fidelity quiz are much longer than usual ones override = int(findall('rqQuestionState([\d]{1,2})"', driver.page_source)[-1]) except Exception as err: debug(err) 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 4 done.") custom_sleep(3) # do_poll() answer a random thing to poll, on of daily activities def do_poll(): info("Starting poll") driver = config.WebDriver.driver try: answer_elem = driver.find_element(By.ID, f"btoption{choice([0, 1])}") try: answer_elem.click() except exceptions.ElementNotInteractableException: warning("element not clickable. Waiting a bit and retrying.") custom_sleep(uniform(2, 2.5)) 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 def all_cards(): driver = config.WebDriver.driver def check_welcome_tour() -> bool: if "rewards.bing.com/welcometour" not in driver.current_url: return False info("Popup 'Explorer le programme' reçue") wait_until_visible(By.ID, "welcome-tour", timeout=5, browser=driver) custom_sleep(1.5) welcome_tour = driver.find_element(By.ID, "welcome-tour") interest_button_box = welcome_tour.find_element(By.CLASS_NAME, "interest-buttons") interests = interest_button_box.find_elements(By.CLASS_NAME, "ng-binding") debug("Got the following interests: " + str(interests)) random.choice(interests).click() # Choose interest custom_sleep(1.5) claim_button = welcome_tour.find_element(By.ID, "claim-button") claim_button.click() # submit custom_sleep(1.5) return True driver.get("https://rewards.bing.com") wait_until_visible(By.CLASS_NAME, "c-card-content", 10, driver) card_list = driver.find_elements(By.CLASS_NAME, "c-card-content") custom_sleep(2) try: promo() except Exception as e: debug(e) info("no promo card") if len(card_list) < 10: # most likely an error during loading if "suspendu" in driver.page_source or "suspended" in driver.page_source: raise Banned() driver.refresh() card_list = driver.find_elements(By.CLASS_NAME, "c-card-content") if len(card_list) < 10: log_error("Less than 10 cards. Most likely an error with login.") return "Not enough cards" for i in range(len(card_list)): debug(f"carte {i}") checked = False try: checked = "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML") except StaleElementReferenceException: driver.refresh() card_list = driver.find_elements(By.CLASS_NAME, "c-card-content") warning(f"staled, {len(card_list)}") checked = "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML") except IndexError: driver.get("https://rewards.bing.com") custom_sleep(10) card_list = driver.find_elements(By.CLASS_NAME, "c-card-content") try: checked = "mee-icon-AddMedium" in card_list[i].get_attribute("innerHTML") except IndexError: if i == len(card_list) and i > 15: checked = False if not checked: continue try: activity = findall("data-bi-id=\"([^\"]+)\"", card_list[i].get_attribute("innerHTML"))[0] except Exception as e: warning("Can't find activity." + str(e)) activity = "" custom_sleep(1.5) check_welcome_tour() driver.execute_script("arguments[0].scrollIntoView();", card_list[i]) custom_sleep(1.5) card_list[i].click() if len(driver.window_handles) > 1: driver.switch_to.window(driver.window_handles[1]) try_play(driver.title, activity) close_tab(driver.window_handles[1]) try: driver.refresh() card_list = driver.find_elements(By.CLASS_NAME, "c-card-content") if "mee-icon-AddMedium" not in card_list[i].get_attribute("innerHTML"): continue check_welcome_tour() driver.execute_script("arguments[0].scrollIntoView();", card_list[i]) card_list[i].click() driver.switch_to.window(driver.window_handles[1]) custom_sleep(10) log_error(f"Card {i} Can't be completed. Why MS ?") try: try_play(driver.title) # go back to the main page try: close_tab(driver.window_handles[1]) except Exception as e: debug(e) except Exception as e: debug(e) driver.get("https://rewards.bing.com") except Exception as err: log_error(err) custom_sleep(3) def promo(): driver = config.WebDriver.driver 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("There is more than 3 promo cards, most likely an unskippable one.") 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: driver.execute_script("arguments[0].click();", elm) warning(f"that shouldn't be there (promo), but the workaround 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 Exception as e: warning(f"no new windows {format_error(e)}") driver.get("https://rewards.bing.com") driver.refresh() custom_sleep(3) def explore_on_bing(activity: str, config: Config): driver = config.WebDriver.driver def search_bing(txt): search_elm = driver.find_element(By.ID, "sb_form_q") send_keys_wait(search_elm, txt) send_keys_wait(search_elm, Keys.ENTER) if "lyrics" in activity: search_bing( f"paroles de {['Gata', 'Pyramide', 'Dolce Camara', 'Position', 'Mami Wata'][randint(0, 4)]}") # merci bing copilot pour les titres elif "flight" in activity: search_bing( f"vol {['Paris - New York', 'Londres Amsterdam', 'Bora-Bora Miami', 'Los Angeles Toulouse', 'Rome Dubai'][randint(0, 4)]}") elif "shopping" in activity: search_bing(f"idée cadeau {['Noel', 'Anniversaire'][randint(0, 1)]}") elif "movie" in activity: search_bing( f"Distribution {['Code 8 part 2', 'The Hunger Games: The ballad of Songbirds & Snakes', 'Rebel Moon: Part Two', 'Dune II', 'Wonka'][randint(0, 4)]}") elif "translator" in activity: search_bing(f"traduction {config.wordlist.get_word()} en anglais") elif "map" in activity: search_bing(f"{['Paris', 'Nice', 'Marseille', 'Bordeaux', 'Lyon'][randint(0, 4)]} carte") else: log_error(f"Explore on bing: {activity} not found.") # Find out which type of action to do def try_play(nom="unknown", activity=""): driver = config.WebDriver.driver rgpd_popup(config) 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(config) custom_sleep(5) debug("Detected and fixed connection popup") if "bt_PollRadio" in driver.page_source: debug("Poll detected") do_poll() 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, raise_error=False): custom_sleep(3) driver.find_element(By.ID, "rqStartQuiz").click() # start the quiz answer_number = driver.page_source.count("rqAnswerOption") play(answer_number) elif "rqQuestionState" in driver.page_source: number = driver.page_source.count("rqAnswerOption") warning(f"recovery detected. quiz : {number}") play(number - 1) elif "exploreonbing" in activity: info(f"Explore on bing: {activity}") explore_on_bing(activity, config) custom_sleep(uniform(3, 5)) else: info(f"Nothing obvious 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 login_part_1(): info("Starting part 1 of login") driver = config.WebDriver.driver driver.get("https://login.live.com") wait_until_visible(By.ID, "i0116", browser=driver) send_wait_and_confirm( driver.find_element(By.ID, "i0116"), config.UserCredentials.get_mail() ) wait_until_visible(By.ID, "i0118", browser=driver) send_wait_and_confirm( driver.find_element(By.ID, "i0118"), config.UserCredentials.get_password() ) # 2FA try: if not wait_until_visible(By.ID, "idTxtBx_SAOTCC_OTC", browser=driver, timeout=5, raise_error=False): custom_sleep(2) return tfa = config.UserCredentials.get_tfa() if tfa is None: error("2FA needed but no code available for this account, sending error") raise ValueError("2FA needed but no code available for this account") else: a2f_code = tfa.now() info(f"Need 2FA, I have code: {a2f_code}") send_wait_and_confirm( driver.find_element(By.ID, "idTxtBx_SAOTCC_OTC"), a2f_code ) except Exception as err: log_error(err) # Accept all cookies question, and check if the account is locked def login_part_2(): driver = config.WebDriver.driver custom_sleep(5) if 'Abuse' in driver.current_url: raise Banned() if 'identity' in driver.current_url: raise Identity() if 'notice' in driver.current_url: driver.find_element(By.ID, "id__0").click() if "proof" in driver.current_url: driver.find_element(By.ID, "iLooksGood") for elm_id in ["checkboxField", "KmsiCheckboxField", "acceptButton", "iNext", "id__0", "iLooksGood", "idSIButton9", "iCancel"]: if get_domain(driver) == "account.microsoft.com": break try: driver.find_element(By.ID, elm_id).click() except Exception as e: debug(e) wait_until_visible(By.CSS_SELECTOR, '[data-bi-id="sh-sharedshell-home"]', 20, driver) # login() tries to login to your Microsoft account. # it uses global variable g._mail and g._password to login def login(): def logged_in(): driver.get("https://login.live.com") custom_sleep(10) debug(get_domain(driver)) if get_domain(driver) == "account.microsoft.com": return True return False info("Logging in...") driver = config.WebDriver.driver try: if not logged_in(): login_part_1() login_part_2() driver.get("https://rewards.bing.com/") except Banned: raise Banned() except Identity: raise Banned() except Exception as err: critical("Error not caught during login." + format_error(err)) log_error(err) driver.quit() return False # Makes 30 search as PC Edge def bing_pc_search(override=randint(35, 40)): driver = config.WebDriver.driver driver.get(f"https://www.bing.com/search?q={config.wordlist.get_word().replace(' ', '+')}") custom_sleep(uniform(1, 2)) rgpd_popup(config) 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 = config.wordlist.get_word() 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: error(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: error(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)}") # what is this message ??? todo # Sends current account's points to database def log_points(): driver = config.WebDriver.driver account = config.UserCredentials.get_mail() driver.get("https://rewards.bing.com") custom_sleep(1) wait_until_visible(By.CSS_SELECTOR, 'span[mee-element-ready="$ctrl.loadCounterAnimation()"]', browser=driver) try: points = search('availablePoints\":([\d]+)', driver.page_source)[1] except Exception as err: log_error( f"Dev error, checking why it doesn't work (waited a bit, is this still white ?) {format_error(err)}") error(f"Can't get points. {format_error(err)}") return -1 custom_sleep(uniform(3, 20)) account_name = account.split("@")[0] try: add_to_database(account_name, points) except Exception as e: log_error(e) # todo: refactor and check if it works at all def fidelity(): driver = config.WebDriver.driver 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] button_card = driver.find_element(By.XPATH, f'//span[text()="{button_text}"]') button_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"Fidelity: Multiples error - 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 err: error(err) info("fidelity - done") except Exception as err: log_error(err) 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"]') pause.click() except Exception as e: debug("No pause button.") cartes = driver.find_elements(By.CSS_SELECTOR, f'[ng-repeat="item in $ctrl.transcludedItems"]') nb_cartes = len(cartes) if nb_cartes == 0: warning("No fidelity cards detected") return "No cards." checked_list_all = driver.find_elements(By.CSS_SELECTOR, f'[ng-if="$ctrl.complete"]') for i in range(nb_cartes): cartes[i].click() 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] # legacy code. Should be removed if "moviesandtv" not 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(): driver = config.WebDriver.driver try: alert = driver.switch_to.alert alert.dismiss() except exceptions.NoAlertPresentException: pass except Exception as err: log_error(err) # todo: be coherent with pc search regarding error management def bing_mobile_search(cred: UserCredentials, override=randint(22, 25)): config.WebDriver.set_mobile_driver(create_driver(mobile=True)) config.WebDriver.switch_to_driver("Mobile") driver = config.WebDriver.driver try: login() mot = config.wordlist.get_word().replace(" ", "+") driver.get(f"https://www.bing.com/search?q={mot}") custom_sleep(uniform(1, 2)) rgpd_popup(config) custom_sleep(uniform(1, 1.5)) for i in range(override): # 20 try: mot = config.wordlist.get_word() send_keys_wait(driver.find_element(By.ID, "sb_form_q"), mot) 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) driver.find_element(By.ID, "sb_form_q").clear() except Exception as err: error(err) driver.refresh() custom_sleep(30) i -= 1 driver.quit() except Exception as err: log_error(err) driver.quit() finally: config.WebDriver.switch_to_driver("PC") def daily_routine(cred: UserCredentials, custom=False): try: if not custom: # custom already is logged in login() except Banned: log_error("This account is locked.") raise Banned() except Identity: log_error("This account has an issue.") return try: all_cards() except Banned: log_error("banned") raise Banned except Exception as err: log_error(err) try: fidelity() except Exception as err: log_error(err) try: bing_pc_search() except Exception as err: log_error(err) try: bing_mobile_search(cred) except Exception as err: log_error(err) try: log_points() except Exception as err: log_error(err) def json_start(json_entry, cred: UserCredentials): json_entry = json.loads(json_entry) config.set_display(SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=2345, color_depth=24)) config.display.start() account_id = 0 while config.UserCredentials.is_valid(): start = False for action in ["unban", "tout", "pc", "mobile", "daily"]: try: if str(account_id) in json_entry[action]: start = True info(f"{cred.get_mail()} : {action}") except KeyError: pass if start: config.WebDriver.set_pc_driver(create_driver()) config.WebDriver.switch_to_driver("PC") driver = config.WebDriver.driver try: if "unban" in json_entry and str(account_id) in json_entry["unban"]: login() info("\nGO TO example.com TO PROCEED or wait 1200 secs.") for _ in range(1200): sleep(1) if driver.current_url == "https://example.com/": info("proceeding") break else: login() except KeyError: login() try: if str(account_id) in json_entry["tout"]: daily_routine(cred, True) except KeyError: pass else: try: if str(account_id) in json_entry["daily"]: try: all_cards() except Exception as e: log_error(e) except KeyError: pass try: if str(account_id) in json_entry["pc"]: try: bing_pc_search() except Exception as e: log_error(e) except KeyError: pass try: if str(account_id) in json_entry["mobile"]: try: bing_mobile_search(cred) except Exception as e: log_error(e) except KeyError: pass try: log_points() except Exception as e: error(f"CustomStart {e}") driver.close() cred.next_account() account_id += 1 config.display.stop() def default_start(): if config.vnc_enabled(): config.set_display(SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=config.vnc, color_depth=24)) else: config.set_display(SmartDisplay(size=(1920, 1080))) config.display.start() while config.UserCredentials.is_valid(): custom_sleep(1) info("Starting and configuring driver.") config.WebDriver.set_pc_driver(create_driver()) config.WebDriver.switch_to_driver("PC") info("Driver started.") config.WebDriver.pc_driver.implicitly_wait(3) try: wait_time = uniform(1200, 3600) wait_time = 10 # the display closes when I ctrl + c info(f"Waiting for {round(wait_time / 60)}min before starting") custom_sleep(wait_time) daily_routine(config.UserCredentials) config.WebDriver.pc_driver.quit() except KeyboardInterrupt: critical("Canceled by user. Closing driver and display.") config.WebDriver.pc_driver.quit() config.display.stop() break except Banned: warning("this account is banned. Switching to next account") except Exception as e: log_error(f"Error not caught. Skipping this account. " + format_error(e)) critical(f"Error not caught. Skipping this account. {e}") config.WebDriver.pc_driver.quit() finally: config.UserCredentials.next_account() config.display.stop() def log_error(msg): DiscordLogger(config).send(msg) def check_updated(): if config.has_been_updated(): config.discord.wh.send(f"Updated to {config.version}", username="update", avatar_url="https://cdn-icons-png.flaticon.com/512/1688/1688988.png") if __name__ == "__main__": config = Config(args) check_updated() match config.start: case "json": json_start(config.json_entry, config.UserCredentials) case "default": default_start()