implemented classes to remove global file

This commit is contained in:
piair 2024-02-27 14:52:55 +01:00
parent 3c9d20891c
commit 9857607eb3
17 changed files with 411 additions and 346178 deletions

309
V6.py
View File

@ -1,4 +1,5 @@
#!/usr/bin/python3.10 #!/usr/bin/python3.10
from modules.Classes.DiscordLogger import DiscordLogger
from modules.config import * from modules.config import *
from modules.error import * from modules.error import *
from modules.driver_tools import * from modules.driver_tools import *
@ -8,10 +9,7 @@ import modules.globals as g
from modules.Classes.Config import Config from modules.Classes.Config import Config
from modules.Classes.UserCredentials import UserCredentials from modules.Classes.UserCredentials import UserCredentials
from modules.Tools.logger import warning, info, debug, error, critical from modules.Tools.logger import warning, info, debug, error, critical
from modules.Tools.tools import format_error
driver = g.driver
display = g.display
# create a webdriver # create a webdriver
@ -39,46 +37,9 @@ def create_driver(mobile=False):
return 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 # 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: def close_tab(tab, switch_to: int = 0) -> None:
driver = config.WebDriver.driver
driver.switch_to.window(tab) driver.switch_to.window(tab)
driver.close() driver.close()
driver.switch_to.window(driver.window_handles[switch_to]) driver.switch_to.window(driver.window_handles[switch_to])
@ -89,6 +50,7 @@ def close_tab(tab, switch_to: int = 0) -> None:
# Can be useful in some case, where the program crashes before finishing the quiz # Can be useful in some case, where the program crashes before finishing the quiz
def play_quiz2(override=10) -> None: def play_quiz2(override=10) -> None:
info("Starting to play quiz 2.") info("Starting to play quiz 2.")
driver = config.WebDriver.driver
debug(f"override: {override}") debug(f"override: {override}")
for j in range(override): for j in range(override):
custom_sleep(uniform(3, 5)) custom_sleep(uniform(3, 5))
@ -122,6 +84,7 @@ def play_quiz2(override=10) -> None:
def play_quiz8(): def play_quiz8():
driver = config.WebDriver.driver
info(f"Starting Quiz 8") info(f"Starting Quiz 8")
override = len(findall("<span id=\"rqQuestionState.\" class=\"emptyCircle\"></span>", driver.page_source)) + 1 override = len(findall("<span id=\"rqQuestionState.\" class=\"emptyCircle\"></span>", driver.page_source)) + 1
debug(f"override : {override}") debug(f"override : {override}")
@ -161,6 +124,7 @@ def play_quiz8():
def play_quiz4(override: int = None): def play_quiz4(override: int = None):
info(f"Starting Quiz 4") info(f"Starting Quiz 4")
driver = config.WebDriver.driver
if not override: if not override:
try: # fidelity quiz are much longer than usual ones try: # fidelity quiz are much longer than usual ones
@ -191,6 +155,7 @@ def play_quiz4(override: int = None):
# do_poll() answer a random thing to poll, on of daily activities # do_poll() answer a random thing to poll, on of daily activities
def do_poll(): def do_poll():
info("Starting poll") info("Starting poll")
driver = config.WebDriver.driver
try: try:
answer_elem = driver.find_element(By.ID, f"btoption{choice([0, 1])}") answer_elem = driver.find_element(By.ID, f"btoption{choice([0, 1])}")
try: try:
@ -208,6 +173,7 @@ def do_poll():
# Find each playable card and tries to click on it to earn points # Find each playable card and tries to click on it to earn points
# todo : refactor # todo : refactor
def all_cards(): def all_cards():
driver = config.WebDriver.driver
driver.get("https://rewards.bing.com") driver.get("https://rewards.bing.com")
wait_until_visible(By.CLASS_NAME, "c-card-content", 10, driver) wait_until_visible(By.CLASS_NAME, "c-card-content", 10, driver)
liste = driver.find_elements(By.CLASS_NAME, "c-card-content") liste = driver.find_elements(By.CLASS_NAME, "c-card-content")
@ -222,7 +188,7 @@ def all_cards():
driver.refresh() driver.refresh()
liste = driver.find_elements(By.CLASS_NAME, "c-card-content") liste = driver.find_elements(By.CLASS_NAME, "c-card-content")
if (len(liste) < 10): if (len(liste) < 10):
log_error("Less than 10 cards. Most likely an error with login.", driver) log_error("Less than 10 cards. Most likely an error with login.")
return ("PAS ASSEZ DE CARTES") return ("PAS ASSEZ DE CARTES")
if (len(liste) < 20): # most likely not in france if (len(liste) < 20): # most likely not in france
printf("moins de 20 cartes. Probablement pas en France.") printf("moins de 20 cartes. Probablement pas en France.")
@ -265,7 +231,7 @@ def all_cards():
try: try:
liste[i].click() liste[i].click()
except: except:
log_error("problème inconnu ? sauf si c'est un element obscure...", driver) log_error("problème inconnu ? sauf si c'est un element obscure...")
driver.get("https://rewards.bing.com") driver.get("https://rewards.bing.com")
checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")) checked = ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML"))
driver.switch_to.window(driver.window_handles[1]) driver.switch_to.window(driver.window_handles[1])
@ -273,12 +239,12 @@ def all_cards():
close_tab(driver.window_handles[1]) close_tab(driver.window_handles[1])
if ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")): if ("mee-icon-AddMedium" in liste[i].get_attribute("innerHTML")):
driver.execute_script("arguments[0].scrollIntoView();", liste[i]) driver.execute_script("arguments[0].scrollIntoView();", liste[i])
log_error(f"Card {i} Can't be completed. Why MS ?", driver) log_error(f"Card {i} Can't be completed. Why MS ?")
liste[i].click() liste[i].click()
driver.switch_to.window(driver.window_handles[1]) driver.switch_to.window(driver.window_handles[1])
log_error(f"Cart completion - log - 2", driver) log_error(f"Cart completion - log - 2")
custom_sleep(10) custom_sleep(10)
log_error(f"Cart completion - log - 3 - after 10 sec", driver) log_error(f"Cart completion - log - 3 - after 10 sec")
try: try:
try_play(driver.title) # go back to the main page try_play(driver.title) # go back to the main page
try: try:
@ -299,13 +265,14 @@ def all_cards():
def promo(): def promo():
driver = config.WebDriver.driver
for i in range(5): for i in range(5):
elm = driver.find_element(By.ID, "promo-item") elm = driver.find_element(By.ID, "promo-item")
wait_until_visible(By.ID, "promo-item", 5, driver) wait_until_visible(By.ID, "promo-item", 5, driver)
if not elm: if not elm:
break break
if i > 3: if i > 3:
log_error("plus de 3 promo cards, probablement une pa skipable", driver) log_error("plus de 3 promo cards, probablement une pa skipable")
try: try:
driver.find_element(By.CSS_SELECTOR, driver.find_element(By.CSS_SELECTOR,
'i[class="mee-icon pull-left icon mee-icon-Cancel ng-scope"]').click() 'i[class="mee-icon pull-left icon mee-icon-Cancel ng-scope"]').click()
@ -336,6 +303,7 @@ def promo():
# Find out which type of action to do # Find out which type of action to do
def try_play(nom="inconnu"): def try_play(nom="inconnu"):
driver = config.WebDriver.driver
rgpd_popup(driver) rgpd_popup(driver)
def play(number): def play(number):
@ -398,62 +366,65 @@ def try_play(nom="inconnu"):
# Login with password or with cookies. # Login with password or with cookies.
# The driver should be in the same state on both case # The driver should be in the same state on both case
def login_part_1(ldriver, cred: UserCredentials): def login_part_1():
printf("pwd_login : start") info("Starting part 1 of login")
ldriver.get("https://login.live.com") driver = config.WebDriver.driver
wait_until_visible(By.ID, "i0116", browser=ldriver) config.WebDriver.driver.get("https://login.live.com")
mail_elem = ldriver.find_element(By.ID, "i0116") wait_until_visible(By.ID, "i0116", browser=config.WebDriver.driver)
send_keys_wait(mail_elem, cred.get_mail()) mail_elem = driver.find_element(By.ID, "i0116")
send_keys_wait(mail_elem, config.UserCredentials.get_mail())
mail_elem.send_keys(Keys.ENTER) mail_elem.send_keys(Keys.ENTER)
wait_until_visible(By.ID, "i0118", browser=ldriver) wait_until_visible(By.ID, "i0118", browser=driver)
pwd_elem = ldriver.find_element(By.ID, "i0118") pwd_elem = driver.find_element(By.ID, "i0118")
send_keys_wait(pwd_elem, cred.get_password()) send_keys_wait(pwd_elem, config.UserCredentials.get_password())
pwd_elem.send_keys(Keys.ENTER) pwd_elem.send_keys(Keys.ENTER)
custom_sleep(2) custom_sleep(2)
# 2FA # 2FA
if "Entrez le code de sécurité" in ldriver.page_source: if "Entrez le code de sécurité" in driver.page_source:
try: try:
a2f_elem = ldriver.find_element(By.ID, "idTxtBx_SAOTCC_OTC") a2f_elem = driver.find_element(By.ID, "idTxtBx_SAOTCC_OTC")
a2f_elem.send_keys(g._otp.now()) a2f_elem.send_keys(config.UserCredentials.get_tfa().now())
a2f_elem.send_keys(Keys.ENTER) a2f_elem.send_keys(Keys.ENTER)
except Exception as e: except Exception as err:
log_error(e) log_error(err)
# Accept all cookies question, and check if the account is locked # Accept all cookies question, and check if the account is locked
def login_part_2(ldriver): def login_part_2():
driver = config.WebDriver.driver
custom_sleep(5) custom_sleep(5)
if 'Abuse' in ldriver.current_url: if 'Abuse' in driver.current_url:
raise Banned() raise Banned()
if 'identity' in ldriver.current_url: if 'identity' in driver.current_url:
raise Identity() raise Identity()
if 'notice' in ldriver.current_url: if 'notice' in driver.current_url:
ldriver.find_element(By.ID, "id__0").click() driver.find_element(By.ID, "id__0").click()
if "proof" in ldriver.current_url: if "proof" in driver.current_url:
ldriver.find_element(By.ID, "iLooksGood") driver.find_element(By.ID, "iLooksGood")
for elm_id in ["iNext", "KmsiCheckboxField", "id__0", "iLooksGood", "idSIButton9", "iCancel"]: for elm_id in ["iNext", "KmsiCheckboxField", "id__0", "iLooksGood", "idSIButton9", "iCancel"]:
if get_domain(ldriver) == "account.microsoft.com": if get_domain(driver) == "account.microsoft.com":
break break
try: try:
ldriver.find_element(By.ID, elm_id).click() driver.find_element(By.ID, elm_id).click()
except Exception as e: except Exception as e:
pass pass
wait_until_visible(By.CSS_SELECTOR, '[data-bi-id="sh-sharedshell-home"]', 20, ldriver) wait_until_visible(By.CSS_SELECTOR, '[data-bi-id="sh-sharedshell-home"]', 20, driver)
# login() tries to login to your Microsoft account. # login() tries to login to your Microsoft account.
# it uses global variable g._mail and g._password to login # it uses global variable g._mail and g._password to login
def login(ldriver, cred: UserCredentials): def login():
driver = config.WebDriver.driver
try: try:
login_part_1(ldriver, cred) login_part_1()
login_part_2(ldriver) login_part_2()
ldriver.get("https://rewards.bing.com/") driver.get("https://rewards.bing.com/")
except Banned: except Banned:
raise Banned() raise Banned()
except Identity: except Identity:
@ -461,14 +432,14 @@ def login(ldriver, cred: UserCredentials):
except Exception as e: except Exception as e:
critical("Error not caught during login.") critical("Error not caught during login.")
log_error(e) log_error(e)
ldriver.quit() driver.quit()
return False return False
# Makes 30 search as PC Edge # Makes 30 search as PC Edge
def bing_pc_search(override=randint(35, 40)): def bing_pc_search(override=randint(35, 40)):
mot = choice(Liste_de_mot).replace(" ", "+") driver = config.WebDriver.driver
driver.get(f"https://www.bing.com/search?q={mot}") driver.get(f"https://www.bing.com/search?q={config.wordlist.get_word().replace(' ', '+')}")
custom_sleep(uniform(1, 2)) custom_sleep(uniform(1, 2))
rgpd_popup(driver) rgpd_popup(driver)
send_keys_wait( send_keys_wait(
@ -477,7 +448,7 @@ def bing_pc_search(override=randint(35, 40)):
) )
for _ in range(override): for _ in range(override):
word = choice(Liste_de_mot) word = config.wordlist.get_word()
try: try:
send_keys_wait(driver.find_element(By.ID, "sb_form_q"), word) send_keys_wait(driver.find_element(By.ID, "sb_form_q"), word)
driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER) driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
@ -502,7 +473,9 @@ def bing_pc_search(override=randint(35, 40)):
# Sends points to database, discord and whatever service you want # Sends points to database, discord and whatever service you want
# todo: refactor # todo: refactor
def log_points(account="unknown"): def log_points():
driver = config.WebDriver.driver
account = config.UserCredentials.get_mail()
def get_points(): def get_points():
driver.get("https://rewards.bing.com") driver.get("https://rewards.bing.com")
custom_sleep(1) custom_sleep(1)
@ -510,9 +483,7 @@ def log_points(account="unknown"):
try: try:
point = search('availablePoints\":([\d]+)', driver.page_source)[1] point = search('availablePoints\":([\d]+)', driver.page_source)[1]
except Exception as e: except Exception as e:
log_error( log_error(f"Dev error, checking why it doesn't work (waited a bit, is this still white ?) {format_error(e)}")
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.") error("Can't get points.")
return -1 return -1
return point return point
@ -521,16 +492,6 @@ def log_points(account="unknown"):
custom_sleep(uniform(3, 20)) custom_sleep(uniform(3, 20))
account_name = account.split("@")[0] 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: try:
add_to_database(account_name, points) add_to_database(account_name, points)
except Exception as e: except Exception as e:
@ -539,6 +500,7 @@ def log_points(account="unknown"):
# todo: refactor and check if it works at all # todo: refactor and check if it works at all
def fidelity(): def fidelity():
driver = config.WebDriver.driver
def sub_fidelity(): def sub_fidelity():
try: try:
wait_until_visible(By.CSS_SELECTOR, 'div[class="pull-left spacer-48-bottom punchcard-row"]', browser=driver) wait_until_visible(By.CSS_SELECTOR, 'div[class="pull-left spacer-48-bottom punchcard-row"]', browser=driver)
@ -610,61 +572,67 @@ def fidelity():
def mobile_alert_popup(): def mobile_alert_popup():
driver = config.WebDriver.driver
try: try:
alert = mobile_driver.switch_to.alert alert = driver.switch_to.alert
alert.dismiss() alert.dismiss()
except exceptions.NoAlertPresentException: except exceptions.NoAlertPresentException:
pass pass
except Exception as err: except Exception as err:
log_error(err, mobile_driver) log_error(err)
# todo: be coherent with pc search regarding error management # todo: be coherent with pc search regarding error management
def bing_mobile_search(cred: UserCredentials, override=randint(22, 25)): def bing_mobile_search(cred: UserCredentials, override=randint(22, 25)):
global mobile_driver config.WebDriver.set_mobile_driver(create_driver(mobile=True))
mobile_driver = create_driver(mobile=True) config.WebDriver.switch_to_driver("Mobile")
driver = config.WebDriver.driver
try: try:
login(mobile_driver, cred) login()
mot = choice(Liste_de_mot).replace(" ", "+") mot = config.wordlist.get_word().replace(" ", "+")
mobile_driver.get(f"https://www.bing.com/search?q={mot}") driver.get(f"https://www.bing.com/search?q={mot}")
custom_sleep(uniform(1, 2)) custom_sleep(uniform(1, 2))
rgpd_popup(mobile_driver) rgpd_popup(config)
custom_sleep(uniform(1, 1.5)) custom_sleep(uniform(1, 1.5))
for i in range(override): # 20 for i in range(override): # 20
try: try:
mot = choice(Liste_de_mot) mot = config.wordlist.get_word()
send_keys_wait(mobile_driver.find_element(By.ID, "sb_form_q"), mot) send_keys_wait(driver.find_element(By.ID, "sb_form_q"), mot)
mobile_driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER) driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
custom_sleep(uniform(3, 7)) custom_sleep(uniform(3, 7))
mobile_alert_popup() # check for alert (asking for position or for allowing notifications) mobile_alert_popup() # check for alert (asking for position or for allowing notifications)
mobile_driver.find_element(By.ID, "sb_form_q").clear() driver.find_element(By.ID, "sb_form_q").clear()
except Exception as err: except Exception as err:
error(err) error(err)
mobile_driver.refresh() driver.refresh()
custom_sleep(30) custom_sleep(30)
i -= 1 i -= 1
mobile_driver.quit() driver.quit()
except Exception as err: except Exception as err:
log_error(err, mobile_driver) log_error(err)
mobile_driver.quit() driver.quit()
finally:
config.WebDriver.switch_to_driver("PC")
def daily_routine(cred: UserCredentials, custom=False): def daily_routine(cred: UserCredentials, custom=False):
try: try:
if not custom: # custom already is logged in if not custom: # custom already is logged in
login(driver, cred) login()
except Banned: except Banned:
log_error("This account is locked.", driver) log_error("This account is locked.")
return return
except Identity: except Identity:
log_error("This account has an issue.", driver) log_error("This account has an issue.")
return return
try: try:
all_cards() all_cards()
except Banned: except Banned:
log_error("banned", driver) log_error("banned")
raise Banned raise Banned
except Exception as err: except Exception as err:
log_error(err) log_error(err)
@ -685,58 +653,58 @@ def daily_routine(cred: UserCredentials, custom=False):
log_error(err) log_error(err)
try: try:
log_points(cred.get_mail()) log_points()
except Exception as err: except Exception as err:
log_error(err) log_error(err)
def json_start(json_entry, cred: UserCredentials): def json_start(json_entry, cred: UserCredentials):
global driver json_entry = json.loads(json_entry)
display = SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=2345, color_depth=24)
display.start()
for i in range(5): 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 start = False
for j in ["unban", "tout", "pc", "mobile", "daily"]: for action in ["unban", "tout", "pc", "mobile", "daily"]:
try: try:
if str(i) in json_entry[j]: if str(account_id) in json_entry[action]:
start = True start = True
info(f"{cred.get_mail()} : {j}") info(f"{cred.get_mail()} : {action}")
except KeyError: except KeyError:
pass pass
if start: if start:
driver = create_driver() config.WebDriver.set_pc_driver(create_driver())
driver = config.WebDriver.driver
try: try:
if str(i) in json_entry["unban"]: if str(account_id) in json_entry["unban"]:
login_part_1(driver, cred) login_part_1()
print("\nGO TO example.com TO PROCEED or wait 1200 secs.") info("\nGO TO example.com TO PROCEED or wait 1200 secs.")
for _ in range(1200): for _ in range(1200):
sleep(1) sleep(1)
if driver.current_url == "https://example.com/": if driver.current_url == "https://example.com/":
print("proceeding") info("proceeding")
break break
else: else:
login(driver, cred) login()
except KeyError: except KeyError:
login(driver, cred) login()
try: try:
if str(i) in json_entry["tout"]: if str(account_id) in json_entry["tout"]:
daily_routine(cred) daily_routine(cred)
except KeyError: except KeyError:
pass pass
# print("none is set to \"tout\"")
else: else:
try: try:
if str(i) in json_entry["daily"]: if str(account_id) in json_entry["daily"]:
try: try:
all_cards() all_cards()
except Exception as e: except Exception as e:
log_error(e) log_error(e)
except KeyError: except KeyError:
pass pass
# print("none is set to \"daily\"")
try: try:
if str(i) in json_entry["pc"]: if str(account_id) in json_entry["pc"]:
try: try:
bing_pc_search() bing_pc_search()
except Exception as e: except Exception as e:
@ -744,7 +712,7 @@ def json_start(json_entry, cred: UserCredentials):
except KeyError: except KeyError:
pass pass
try: try:
if str(i) in json_entry["mobile"]: if str(account_id) in json_entry["mobile"]:
try: try:
bing_mobile_search(cred) bing_mobile_search(cred)
except Exception as e: except Exception as e:
@ -752,55 +720,64 @@ def json_start(json_entry, cred: UserCredentials):
except KeyError: except KeyError:
pass pass
try: try:
log_points(g._mail) log_points()
except Exception as e: except Exception as e:
printf(f"CustomStart {e}") printf(f"CustomStart {e}")
driver.close() driver.close()
cred.next_account() cred.next_account()
display.stop() config.display.stop()
c = Config(args) def default_start():
if config.vnc_enabled():
if g.json_start: config.set_display(SmartDisplay(backend="xvnc", size=(1920, 1080), rfbport=config.vnc, color_depth=24))
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: else:
display = SmartDisplay(size=(1920, 1080)) config.set_display(SmartDisplay(size=(1920, 1080)))
display.start() config.display.start()
if g.update_version != "None": while config.UserCredentials.is_valid():
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) custom_sleep(1)
info("Starting driver.") info("Starting and configuring driver.")
driver = create_driver() config.WebDriver.set_pc_driver(create_driver())
info("Driver started.") info("Driver started.")
driver.implicitly_wait(3) config.WebDriver.pc_driver.implicitly_wait(3)
try: try:
wait_time = uniform(1200, 3600) wait_time = uniform(1200, 3600)
info(f"Waiting for {round(wait_time / 60)}min before starting") info(f"Waiting for {round(wait_time / 60)}min before starting")
daily_routine(c.UserCredentials)
driver.quit()
custom_sleep(wait_time) custom_sleep(wait_time)
daily_routine(config.UserCredentials)
config.WebDriver.pc_driver.quit()
except KeyboardInterrupt: except KeyboardInterrupt:
critical("Canceled by user. Closing driver and display.") critical("Canceled by user. Closing driver and display.")
driver.quit() config.WebDriver.pc_driver.quit()
display.stop() config.display.stop()
break break
except Exception as e: except Exception as e:
log_error(f"Error not caught. Skipping this account. " + format_error(e), driver) log_error(f"Error not caught. Skipping this account. " + format_error(e))
critical(f"Error not caught. Skipping this account. {e}") critical(f"Error not caught. Skipping this account. {e}")
driver.quit() config.WebDriver.pc_driver.quit()
c.UserCredentials.next_account() config.UserCredentials.next_account()
config.display.stop()
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()

View File

@ -1,15 +1,75 @@
import json import json
from discord import Webhook, RequestsWebhookAdapter
from modules.Classes.Driver import Driver
from modules.Classes.Proxy import Proxy
from modules.Classes.UserCredentials import UserCredentials from modules.Classes.UserCredentials import UserCredentials
from modules.Classes.DiscordConfig import DiscordConfig, FakeWebHook
from modules.Classes.WordList import WordList
class Config: class Config:
def __init__(self, args): def __init__(self, args):
self.args = args """
self.UserCredentials = UserCredentials() open config file
"""
with open("/app/MsRewards-Reborn/user_data/discord.json", "r") as inFile:
discord = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/settings.json", "r") as inFile:
settings = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/proxy.json", "r") as inFile:
proxy = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
config = json.load(inFile)
"""
setup standalone stuff
"""
self.args = args
self.start = "json" if args.json else "default"
self.json_entry = args.json.replace("'", "\"")
self.wordlist = WordList("/usr/share/dict/french")
self.vnc = args.vnc
self.version = args.update_version
self.WebDriver = Driver()
self.display = None
"""
setup UserCredential
"""
self.UserCredentials = UserCredentials()
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile: with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
configs = json.load(inFile) configs = json.load(inFile)
for i in configs[str(args.config)]["accounts"]: for i in configs[str(args.config)]["accounts"]:
d = configs[str(args.config)]["accounts"][i] d = configs[str(args.config)]["accounts"][i]
self.UserCredentials.add(d["mail"], d["pwd"], d["2fa"]) self.UserCredentials.add(d["mail"], d["pwd"], d["2fa"])
"""
Setup discord
"""
self.discord = DiscordConfig()
self.discord.avatar_url = settings["avatar_url"]
self.discord.wh_link = discord[config[args.config]["discord"]]["errorsL"]
if self.discord.wh_link != "":
self.discord.wh = Webhook.from_url(self.discord.wh_link, adapter=RequestsWebhookAdapter())
else:
self.discord.wh = FakeWebHook()
"""
setup proxy
"""
proxy_conf = config[args.config]["proxy"]
proxy_address = proxy[config[args.config]["proxy"]]["address"]
proxy_port = proxy[config[args.config]["proxy"]]["port"]
self.proxy = Proxy(proxy_conf, proxy_address, proxy_port)
def vnc_enabled(self):
return self.vnc != "None"
def set_display(self, display):
self.display = display
def has_been_updated(self):
return self.version != "None"

View File

@ -0,0 +1,14 @@
from modules.Tools.logger import debug
class DiscordConfig:
def __init__(self):
self.avatar_url = ""
self.wh_link = None
self.wh = None
class FakeWebHook:
def send(self, *args):
debug(f"Used a webhook call without webhook url with {args}")

View File

@ -0,0 +1,38 @@
from discord import Embed, Colour, File
from modules.Classes.Config import Config
from modules.Classes.UserCredentials import UserCredentials
from modules.Tools.logger import info, warning, error, critical
from modules.Tools.tools import format_error
class DiscordLogger:
def __init__(self, config: Config):
self.config = config
def send(self, message: str):
driver = self.config.WebDriver.driver
if type(message) is not str:
message = format_error(message)
error(message)
with open("page.html", "w") as f:
try:
f.write(driver.page_source)
except Exception as e:
error(e)
f.write("the driver has closed or crashed. Can't access page content")
img = self.config.display.waitgrab()
img.save("screenshot.png")
embed = Embed(
title="An Error has occured",
description=str(message),
colour=Colour.red(),
)
file = File("screenshot.png")
embed.set_image(url="attachment://screenshot.png")
embed.set_footer(text=self.config.UserCredentials.creds.get_mail())
self.config.discord.wh.send(embed=embed, username="error", file=file, avatar_url=self.config.discord.avatar_url)
self.config.discord.wh.send(username="error", file=File("page.html"), avatar_url=self.config.discord.avatar_url)

22
modules/Classes/Driver.py Normal file
View File

@ -0,0 +1,22 @@
class Driver:
def __init__(self):
self.pc_driver = None
self.mobile_driver = None
self.driver = None
def set_pc_driver(self, pc_driver):
self.pc_driver = pc_driver
def set_mobile_driver(self, mobile_driver):
self.mobile_driver = mobile_driver
def switch_to_driver(self, driver: str):
match driver:
case "pc" | "PC" | "Pc":
self.driver = self.pc_driver
case "mobile" | "Mobile":
self.driver = self.mobile_driver
case _:
raise ValueError("The driver must be either pc or mobile")

9
modules/Classes/Proxy.py Normal file
View File

@ -0,0 +1,9 @@
class Proxy:
def __init__(self, enabled: str, ip: str = None, port: str = None):
self.ip = ip
self.port = port
self.enabled = enabled != "-1"
def is_enabled(self):
return self.enabled

View File

@ -1,4 +1,7 @@
import json import json
from pyotp import TOTP
from modules.Tools.logger import debug, warning from modules.Tools.logger import debug, warning
@ -29,7 +32,7 @@ class UserCredentials:
def get_tfa(self): def get_tfa(self):
if not self.tfa_enable(): if not self.tfa_enable():
warning("Warning: TFA is not enabled. Calling get_tfa is an expected behaviour.") warning("Warning: TFA is not enabled. Calling get_tfa is an expected behaviour.")
return self.data[self.current]["tfa"] return TOTP(self.data[self.current]["tfa"])
def next_account(self): def next_account(self):
self.current += 1 self.current += 1

View File

@ -0,0 +1,13 @@
import random
class WordList:
def __init__(self, path):
with open(path, "r", encoding="utf-8") as h:
lines = h.readlines()
self.words = [x.replace('\n', "") for x in lines]
random.shuffle(self.words)
def get_word(self):
return self.words.pop(0)

32
modules/Tools/tools.py Normal file
View File

@ -0,0 +1,32 @@
from time import sleep
# return current page domain
def get_domain(driver):
return driver.current_url.split("/")[2]
def custom_sleep(temps):
try:
if True: # todo: change this awful condition
points = ["", "", "", "", "", "", "", ""]
passe = 0
for i in range(int(temps)):
for _ in range(8):
sleep(0.125)
passe += 0.125
print(f"{points[i]} - {round(float(temps) - passe, 3)}", end="\r")
print(" ", end="\r")
else:
sleep(temps)
except KeyboardInterrupt:
print("attente annulée")
def format_error(e) -> str:
tb = e.__traceback__
txt = ""
while tb is not None:
txt = txt + f" -> {tb.tb_frame.f_code.co_name} ({tb.tb_lineno}) "
tb = tb.tb_next
return txt + "\n" + str(e)

View File

@ -1,14 +1,5 @@
#!/usr/bin/python3.10 #!/usr/bin/python3.10
from modules.driver_tools import *
from modules.imports import * from modules.imports import *
import modules.globals as g
import json
class FakeWebHook:
def send(self, text="", username='', avatar_url='', embed="", file=""):
print(text)
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@ -39,69 +30,4 @@ parser.add_argument(
default="" default=""
) )
with open("/app/MsRewards-Reborn/user_data/discord.json", "r") as inFile:
discord = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/settings.json", "r") as inFile:
settings = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/proxy.json", "r") as inFile:
proxy = json.load(inFile)
with open("/app/MsRewards-Reborn/user_data/configs.json", "r") as inFile:
config = json.load(inFile)
args = parser.parse_args() args = parser.parse_args()
g.json_start = args.json
g.vnc_enabled = args.vnc != "None"
g.vnc_port = args.vnc
g.update_version = args.update_version
# global variables used later in the code
g.start_time = time()
# path configurations
g.mot_path = "/usr/share/dict/french"
g.credential_path = "/app/MsRewards-Reborn/user_data/login.csv"
discord_conf = config[args.config]["discord"]
# discord configuration
g.discord_success_link = discord[discord_conf]["successL"]
g.discord_error_link = discord[discord_conf]["errorsL"]
g.discord_enabled_error = discord[discord_conf]["errorsT"] == "True"
g.discord_enabled_success = discord[discord_conf]["successT"] == "True"
g.avatar_url = settings["avatarlink"]
if not g.json_start:
if g.discord_enabled_error:
webhookFailure = Webhook.from_url(g.discord_error_link, adapter=RequestsWebhookAdapter())
if g.discord_enabled_success:
webhookSuccess = Webhook.from_url(g.discord_success_link, adapter=RequestsWebhookAdapter())
else:
webhookFailure = FakeWebHook()
webhookSuccess = FakeWebHook()
# base settings
g.discord_embed = False # send new point value in an embed, fixed for now
g.headless = False
# proxy settings
g.proxy_enabled = config[args.config]["proxy"] != "-1"
if g.proxy_enabled:
g.proxy_address = proxy[config[args.config]["proxy"]]["address"]
g.proxy_port = proxy[config[args.config]["proxy"]]["port"]
# list of words
with open(g.mot_path, "r", encoding="utf-8") as h:
lines = h.readlines()
if len(lines) < 3:
Liste_de_mot = list(lines[0].split(","))
else:
Liste_de_mot = [x.replace('\n', "") for x in lines]
if g.proxy_enabled:
setup_proxy(g.proxy_address, g.proxy_port)

View File

@ -1,67 +1,66 @@
import sqlite3 import sqlite3
#Create a new row, for the account [compte] whith [points] points
def add_row(compte, points, mycursor, mydb): # Create a new row, for the account [compte] whith [points] points
def add_row(account, points, mycursor, mydb):
sql = "INSERT INTO daily (compte, points, date) VALUES (?, ?, date())" sql = "INSERT INTO daily (compte, points, date) VALUES (?, ?, date())"
val = (compte, points) val = (account, points)
mycursor.execute(sql, val) mycursor.execute(sql, val)
mydb.commit() mydb.commit()
#printf(mycursor.rowcount, "record created.") # printf(mycursor.rowcount, "record created.")
#update the ammount of points for the account [compte] # update the ammount of points for the account [compte]
def update_row(compte, points, mycursor, mydb): def update_row(account, points, mycursor, mydb):
sql = f"UPDATE daily SET points = {points} WHERE compte = '{compte}' AND date = date() ;" sql = f"UPDATE daily SET points = {points} WHERE compte = '{account}' AND date = date() ;"
mycursor.execute(sql) mycursor.execute(sql)
mydb.commit() mydb.commit()
#printf(mycursor.rowcount, "record(s) updated")
# update the value of last_pts for the table comptes # update the value of last_pts for the table comptes
def update_last(compte, points, mycursor, mydb): def update_last(account, points, mycursor, mydb):
sql1 = f"UPDATE comptes SET last_pts = {points} WHERE compte = '{compte}';" sql1 = f"UPDATE comptes SET last_pts = {points} WHERE compte = '{account}';"
sql2 = f"select * from comptes where compte = '{compte}'" sql2 = f"select * from comptes where compte = '{account}'"
sql3 = f"INSERT INTO comptes (compte, last_pts,banned) VALUES ('{compte}', {points}, 0)" sql3 = f"INSERT INTO comptes (compte, last_pts,banned) VALUES ('{account}', {points}, 0)"
cmd = mycursor.execute(sql2) cmd = mycursor.execute(sql2)
if len(list(cmd)) == 0: if len(list(cmd)) == 0:
mycursor.execute(sql3) mycursor.execute(sql3)
else : else:
mycursor.execute(sql1) mycursor.execute(sql1)
mydb.commit() mydb.commit()
#printf(mycursor.rowcount, "record(s) updated")
# if return if there already is a line in the database for the account [compte]. if same_point is enabled, the line must also have the same number of points
# Return if there already is a line in the database for the account [account].
# if same_point is enabled, the line must also have the same number of points
# SQLITE # SQLITE
def get_row(compte, points, mycursor, same_points = True): def get_row(account, points, mycursor, same_points=True):
if same_points : if same_points:
mycursor.execute(f"SELECT * FROM daily WHERE points = {points} AND compte = '{compte}' AND date = date() ;") mycursor.execute(f"SELECT * FROM daily WHERE points = {points} AND compte = '{account}' AND date = date() ;")
else : else:
mycursor.execute(f"SELECT * FROM daily WHERE compte = '{compte}' AND date = date() ;") mycursor.execute(f"SELECT * FROM daily WHERE compte = '{account}' AND date = date() ;")
myresult = mycursor.fetchall() myresult = mycursor.fetchall()
return(len(myresult) == 1) return (len(myresult) == 1)
def add_to_database(compte, points, save_if_fail=True): def add_to_database(account, points):
if points is None: if points is None:
pass pass
else: else:
mydb = sqlite3.connect("/app/MsRewards-Reborn/MsRewards.db") mydb = sqlite3.connect("/app/MsRewards-Reborn/MsRewards.db")
mycursor = mydb.cursor() mycursor = mydb.cursor()
if get_row(compte, points,mycursor, True): #check if the row exist with the same ammount of points and do nothind if it does
#printf("les points sont deja bon") if get_row(account, points, mycursor, True):
#return(0) # check if the row exist with the same amount of points and do nothing if it does
pass pass
elif get_row(compte, points,mycursor, False) : #check if the row exist, but without the same ammount of points and update the point account then
update_row(compte, points,mycursor,mydb) # check if the row exist, but without the same amount of points and update the point account then
#printf("row updated") elif get_row(account, points, mycursor, False):
#return(1) update_row(account, points, mycursor, mydb)
else : # if the row don't exist, create it with the good ammount of points
add_row(compte, points,mycursor,mydb) else: # if the row don't exist, create it with the good amount of points
#return(2) #printf("row added") add_row(account, points, mycursor, mydb)
if int(points) > 10 :
update_last(compte, points, mycursor, mydb) if int(points) > 10:
update_last(account, points, mycursor, mydb)
mycursor.close() mycursor.close()
mydb.close() mydb.close()

View File

@ -1,7 +1,12 @@
from modules.imports import * from random import uniform
from modules.config import *
from modules.tools import * from selenium.common import TimeoutException
import modules.globals as g from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from modules.Tools.tools import *
def set_language(ldriver): def set_language(ldriver):
@ -16,10 +21,10 @@ def set_language(ldriver):
# scroll down # scroll down
action.reset_actions() action.reset_actions()
elm = ldriver.find_element(By.XPATH, "/html/body") elm = ldriver.find_element(By.XPATH, "/html/body")
ActionChains(ldriver)\ ActionChains(ldriver) \
.send_keys("french")\ .send_keys("french") \
.pause(0.5)\ .pause(0.5) \
.send_keys(Keys.TAB + Keys.TAB + Keys.ENTER + Keys.TAB + Keys.TAB + Keys.ENTER)\ .send_keys(Keys.TAB + Keys.TAB + Keys.ENTER + Keys.TAB + Keys.TAB + Keys.ENTER) \
.perform() .perform()
x_coord = 1163 x_coord = 1163
y_coord = 717 y_coord = 717
@ -33,64 +38,34 @@ def set_language(ldriver):
action.click().perform() action.click().perform()
def setup_proxy(ip: str, port: str) -> None: # Deal with RGPD popup as well as some random popup like 'are you satisfied' one
PROXY = f"{ip}:{port}" def rgpd_popup(config) -> None:
webdriver.DesiredCapabilities.FIREFOX['proxy'] = { for i in ["bnp_btn_accept", "bnp_hfly_cta2", "bnp_hfly_close"]:
"httpProxy": PROXY,
"sslProxy": PROXY,
"proxyType": "MANUAL",
}
#Deal with RGPD popup as well as some random popup like 'are you satisfied' one
def rgpd_popup(driver) -> None:
for i in ["bnp_btn_accept", "bnp_hfly_cta2", "bnp_hfly_close"] :
try: try:
driver.find_element(By.ID, i).click() config.WebDriver.driver.find_element(By.ID, i).click()
except: except:
pass pass
# save webdriver cookies
def save_cookies(driver) -> None:
if g.dev:
f = open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}_unsafe.pkl", "w")
for i in driver.get_cookies():
f.write(str(i) + "\n")
f.close()
else :
pickle.dump(driver.get_cookies(), open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}.pkl", "wb"))
# load cookies previously saved to the driver
def load_cookies(driver) -> None:
if g.dev:
f = open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}_unsafe.pkl", "r")
lines = f.readlines()
f.close()
cookies = [literal_eval(x) for x in lines]
else :
cookies = pickle.load(open(f"{'/'.join(__file__.split('/')[:-2])}/user_data/cookies/{g._mail}.pkl", "rb"))
for cookie in cookies:
driver.add_cookie(cookie)
""" """
send_keys_wait([selenium element:element, str:keys]) send the different keys to the field element, with a random time between each press to simulate human action. send_keys_wait([selenium element:element, str:keys]) send the different keys to the field element, with a random
time between each press to simulate human action.
keys can be an string, but also selenium keys keys can be an string, but also selenium keys
""" """
def send_keys_wait(element, keys: str) -> None: def send_keys_wait(element, keys: str) -> None:
for i in keys: for i in keys:
element.send_keys(i) element.send_keys(i)
sleep(uniform(0.1, 0.3)) sleep(uniform(0.1, 0.3))
# Wait for the presence of the element identifier or [timeout]s # Wait for the presence of the element identifier or [timeout]s
def wait_until_visible(search_by: str, identifier: str, timeout = 20, browser = None) -> None: def wait_until_visible(search_by: str, identifier: str, timeout: int = 20, browser=None) -> bool:
try : try:
WebDriverWait(browser, timeout).until(EC.visibility_of_element_located((search_by,identifier)), "element not found") WebDriverWait(browser, timeout).until(
return(True) expected_conditions.visibility_of_element_located((search_by, identifier)), "element not found")
return True
except TimeoutException as e: except TimeoutException as e:
printf(f"element {identifier} not found after {timeout}s") printf(f"element {identifier} not found after {timeout}s")
return(False) return False

View File

@ -1,8 +1,10 @@
class Banned(Exception): class Banned(Exception):
pass pass
class NotBanned(Exception): class NotBanned(Exception):
pass pass
class Identity(Exception): class Identity(Exception):
pass pass

View File

@ -1,30 +0,0 @@
driver = None
display = None
log = False
full_log = False
vnc_enabled = False
vnc_port = 2345
points_file = "/"
update_version = False
start_time = 0
mot_path = "/"
credential_path = "/"
discord_success_link = "https://example.com"
discord_error_link = "https://example.com"
discord_enabled_error = False
discord_enabled_success = False
avatar_url = ""
fidelity_link = "None"
discord_embed = False
headless = False
proxy_enabled = False
proxy_address = "0.0.0.0"
proxy_port = "0"
sql_enabled = False
sql_usr = "None"
sql_pwd = "azerty"
sql_host = "https://example.com"
sql_database = "MsRewards"
norvege = False
database_error_override = False
json_start = ""

View File

@ -1,82 +0,0 @@
from modules.imports import *
from modules.config import *
from modules.db import *
import modules.globals as g
# add the time arround the text given in [text]&
def Timer(text: str) -> str:
return(f"[{g._mail.split('@')[0]} - {datetime.today().strftime('%d/%m')} - {timedelta(seconds = round(float(time() - g.start_time)))}] " + str(text))
# replace the function print, with more options
# [txt] : string, [driver] : selenium webdriver
def printf(txt):
print(Timer(txt))
# return current page domain
def get_domain(driver):
return(driver.current_url.split("/")[2])
# check if the user is using IPV4 using ipify.org
# [driver] : selenium webdriver
# never used here
# can be useful as Ms had issues with IPV6 at some point
def check_ipv4(driver):
driver.get("https://api64.ipify.org")
elm = driver.find_element(By.TAG_NAME, "body")
if len(elm.text.split('.')) == 4 :
return True
return False
def custom_sleep(temps):
try :
if g.log : #only print sleep when user see it
points = ["", "", "", "", "", "", "", ""]
passe = 0
for i in range(int(temps)):
for i in range(8):
sleep(0.125)
passe += 0.125
print(f"{points[i]} - {round(float(temps) - passe, 3)}", end="\r")
print(" ", end="\r")
else:
sleep(temps)
except KeyboardInterrupt :
print("attente annulée")
def format_error(e) -> str:
tb = e.__traceback__
txt = ""
while tb != None :
txt = txt + f" -> {tb.tb_frame.f_code.co_name} ({tb.tb_lineno}) "
tb = tb.tb_next
return(txt + "\n" + str(e))
def progressBar(current, total=30, barLength=20, name="Progress"):
percent = float(current + 1) * 100 / total
arrow = "-" * int(percent / 100 * barLength - 1) + ">"
spaces = " " * (barLength - len(arrow))
print(name + ": [%s%s] %d %%" % (arrow, spaces, percent), end="\r")
def save_points_from_file(file):
with open(file) as f:
read = reader(f)
points_list = list(read)
for item in points_list:
compte, points = item[0], item[1]
add_to_database(compte, points, g.sql_host,g.sql_usr,g.sql_pwd,g.sql_database, save_if_fail=False)
with open(file, "w") as f:
f.write("")
def select_accounts(multiple = True):
system("clear") # clear from previous command to allow a clean choice
emails = [x[0] for x in g._cred] # list of all email adresses
emails_selected = enquiries.choose(f"quel{'s' if multiple else ''} compte{'s' if multiple else ''} ?", emails, multi=multiple)
return([x for x in g._cred if x[0] in emails_selected])

6
test.py Normal file
View File

@ -0,0 +1,6 @@
from modules.Classes.WordList import WordList
w = WordList("/usr/share/dict/french")
for i in range(100):
print(w.get_word())

File diff suppressed because it is too large Load Diff