#!/usr/bin/python3.10 from modules.Classes.DiscordLogger import DiscordLogger 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 from modules.Tools.tools import format_error # 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 # 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(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") 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: 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") driver = config.WebDriver.driver 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 = config.WebDriver.driver 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.") 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.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 ?") liste[i].click() driver.switch_to.window(driver.window_handles[1]) log_error(f"Cart completion - log - 2") custom_sleep(10) log_error(f"Cart completion - log - 3 - after 10 sec") 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(): 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("plus de 3 promo cards, probablement une pa skipable") 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"): driver = config.WebDriver.driver 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 login_part_1(): info("Starting part 1 of login") driver = config.WebDriver.driver config.WebDriver.driver.get("https://login.live.com") wait_until_visible(By.ID, "i0116", browser=config.WebDriver.driver) mail_elem = driver.find_element(By.ID, "i0116") send_keys_wait(mail_elem, config.UserCredentials.get_mail()) mail_elem.send_keys(Keys.ENTER) wait_until_visible(By.ID, "i0118", browser=driver) pwd_elem = driver.find_element(By.ID, "i0118") send_keys_wait(pwd_elem, config.UserCredentials.get_password()) pwd_elem.send_keys(Keys.ENTER) custom_sleep(2) # 2FA if "Entrez le code de sécurité" in driver.page_source: try: a2f_elem = driver.find_element(By.ID, "idTxtBx_SAOTCC_OTC") a2f_elem.send_keys(config.UserCredentials.get_tfa().now()) a2f_elem.send_keys(Keys.ENTER) 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 ["iNext", "KmsiCheckboxField", "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: pass 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(): driver = config.WebDriver.driver try: login_part_1() login_part_2() driver.get("https://rewards.bing.com/") except Banned: raise Banned() except Identity: raise Banned() except Exception as e: critical("Error not caught during login.") log_error(e) 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(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 = 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 points to database, discord and whatever service you want # todo: refactor def log_points(): driver = config.WebDriver.driver account = config.UserCredentials.get_mail() def get_points(): driver.get("https://rewards.bing.com") custom_sleep(1) 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: log_error(f"Dev error, checking why it doesn't work (waited a bit, is this still white ?) {format_error(e)}") error("Can't get points.") return -1 return point points = get_points() 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] 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(): 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.") return 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() for account_id in range(5): 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()) driver = config.WebDriver.driver try: if str(account_id) in json_entry["unban"]: login_part_1() 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) 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: printf(f"CustomStart {e}") driver.close() cred.next_account() 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()) info("Driver started.") config.WebDriver.pc_driver.implicitly_wait(3) try: wait_time = uniform(1200, 3600) 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 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() config.UserCredentials.next_account() config.display.stop() def log_error(msg): DiscordLogger(config) 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()