#!/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 login_part_1(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)
# Accept all cookies question, and check if the account is locked
def login_part_2(ldriver):
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")
for elm_id in ["iNext", "KmsiCheckboxField", "id__0", "iLooksGood", "idSIButton9", "iCancel"]:
if get_domain(ldriver) == "account.microsoft.com":
break
try:
ldriver.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, ldriver)
# login() tries to login to your Microsoft account.
# it uses global variable g._mail and g._password to login
def login(ldriver, cred: UserCredentials):
try:
login_part_1(ldriver, cred)
login_part_2(ldriver)
ldriver.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)
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}")
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:
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(account="unknown"):
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)}",
driver)
error("Can't get points.")
return -1
return point
points = get_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)
# todo: refactor and check if it works at all
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:
pass
except Exception as err:
log_error(err, mobile_driver)
# todo: be coherent with pc search regarding error management
def bing_mobile_search(cred: UserCredentials, override=randint(22, 25)):
global mobile_driver
mobile_driver = create_driver(mobile=True)
try:
login(mobile_driver, cred)
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 err:
error(err)
mobile_driver.refresh()
custom_sleep(30)
i -= 1
mobile_driver.quit()
except Exception as err:
log_error(err, mobile_driver)
mobile_driver.quit()
def daily_routine(cred: UserCredentials, custom=False):
try:
if not custom: # custom already is logged in
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)
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(cred.get_mail())
except Exception as err:
log_error(err)
def json_start(json_entry, cred: UserCredentials):
global driver
display = SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=2345, color_depth=24)
display.start()
for i in range(5):
start = False
for j in ["unban", "tout", "pc", "mobile", "daily"]:
try:
if str(i) in json_entry[j]:
start = True
info(f"{cred.get_mail()} : {j}")
except KeyError:
pass
if start:
driver = create_driver()
try:
if str(i) in json_entry["unban"]:
login_part_1(driver, cred)
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, cred)
except KeyError:
login(driver, cred)
try:
if str(i) in json_entry["tout"]:
daily_routine(cred)
except KeyError:
pass
# print("none is set to \"tout\"")
else:
try:
if str(i) in json_entry["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_entry["pc"]:
try:
bing_pc_search()
except Exception as e:
log_error(e)
except KeyError:
pass
try:
if str(i) in json_entry["mobile"]:
try:
bing_mobile_search(cred)
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()
cred.next_account()
display.stop()
c = Config(args)
if g.json_start:
dict_data = json.loads(g.json_start.replace("'", "\""))
json_start(dict_data, c.UserCredentials)
else:
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():
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()