2023-01-29 00:51:30 +01:00
#!/usr/bin/python3.10
import asyncio
import csv
from os import sys , system , path
from random import choice , randint , shuffle , uniform
from re import findall , search
from sys import platform
from time import sleep
from requests import get
from selenium import webdriver
from selenium . common import exceptions
2023-03-26 22:56:57 +02:00
from selenium . common . exceptions import WebDriverException
2023-01-29 00:51:30 +01:00
from selenium . webdriver . common . by import By
from selenium . webdriver . common . keys import Keys
from selenium . webdriver . firefox . options import Options
from selenium . webdriver . support . ui import WebDriverWait
from selenium . webdriver . support import expected_conditions as EC
from selenium . webdriver . support . ui import Select
2023-03-18 19:12:27 +01:00
from pyotp import TOTP
2023-02-25 19:05:47 +01:00
from pyvirtualdisplay import Display
2023-01-29 00:51:30 +01:00
from pyvirtualdisplay . smartdisplay import SmartDisplay
2023-03-25 18:14:41 +01:00
import pickle
2023-01-29 00:51:30 +01:00
from modules . db import add_to_database
from modules . config import *
from modules . tools import *
from modules . error import *
import modules . progress
global driver
driver = None
2023-03-18 19:12:27 +01:00
global _mail , _password , _otp , display
2023-01-29 00:51:30 +01:00
2023-02-27 13:41:54 +01:00
# TODO : replace by a better print (with logging, cf https://realpython.com/python-logging/)
2023-02-08 15:14:13 +01:00
def printf ( e , f = " " ) :
2023-03-19 10:17:28 +01:00
print ( str ( e ) + f )
2023-02-08 15:14:13 +01:00
# TODO
# handle "panda"'s error: error while logging in preventing some task to be done
2023-03-19 10:17:28 +01:00
# check that each card worked (lot of misses lately) -- test that -- don't crash at least
2023-03-25 18:14:41 +01:00
2023-03-12 15:33:35 +01:00
2023-01-29 00:51:30 +01:00
custom_sleep = CustomSleep
2023-03-25 18:14:41 +01:00
def save_cookies ( ) :
pickle . dump ( driver . get_cookies ( ) , open ( f " { ' / ' . join ( __file__ . split ( ' / ' ) [ : - 1 ] ) } /user_data/cookies/ { _mail } .pkl " , " wb " ) )
def load_cookies ( driver ) :
cookies = pickle . load ( open ( f " { ' / ' . join ( __file__ . split ( ' / ' ) [ : - 1 ] ) } /user_data/cookies/ { _mail } .pkl " , " rb " ) )
for cookie in cookies :
driver . add_cookie ( cookie )
2023-03-18 19:12:27 +01:00
2023-03-19 10:17:28 +01:00
def log_error ( error , ldriver = driver , log = FULL_LOG ) :
2023-03-19 12:21:57 +01:00
global driver
if ldriver is None :
ldriver = driver
2023-03-18 19:12:27 +01:00
if type ( error ) != str :
error = format_error ( error )
print ( f " \n \n \033 [93m Erreur : { str ( error ) } \033 [0m \n \n " )
if DISCORD_ENABLED_ERROR :
with open ( " page.html " , " w " ) as f :
2023-03-19 10:17:28 +01:00
f . write ( ldriver . page_source )
2023-03-26 22:56:57 +02:00
try :
img = display . waitgrab ( )
img . save ( " screenshot.png " )
except :
ldriver . save_screenshot ( " screenshot.png " )
2023-03-18 19:12:27 +01:00
if not log :
embed = discord . Embed (
title = " An Error has occured " ,
description = str ( error ) ,
colour = Colour . red ( ) ,
)
else :
embed = discord . Embed (
title = " Full log is enabled " ,
description = str ( error ) ,
colour = Colour . blue ( ) ,
)
file = discord . File ( " screenshot.png " )
embed . set_image ( url = " attachment://screenshot.png " )
embed . set_footer ( text = _mail )
webhookFailure . send ( embed = embed , file = file )
webhookFailure . send ( file = discord . File ( " page.html " ) )
2023-03-25 18:14:41 +01:00
2023-01-29 00:51:30 +01:00
# Wait for the presence of the element identifier or [timeout]s
def wait_until_visible ( search_by : str , identifier : str , timeout = 20 , browser = driver ) - > None :
try :
WebDriverWait ( browser , timeout ) . until ( EC . visibility_of_element_located ( ( search_by , identifier ) ) , " element not found " )
except TimeoutException as e :
print ( f " element not found after { timeout } s " )
2023-02-25 19:05:47 +01:00
def setup_proxy ( ip , port , options , socks = False ) :
PROXY = f " { ip } : { port } "
if socks :
options . set_preference ( ' network.proxy.type ' , 1 )
options . set_preference ( ' network.proxy.socks ' , ip )
options . set_preference ( ' network.proxy.socks_port ' , int ( port ) )
options . set_preference ( " browser.link.open_newwindow " , 3 )
else :
webdriver . DesiredCapabilities . FIREFOX [ ' proxy ' ] = {
" httpProxy " : PROXY ,
" sslProxy " : PROXY ,
" proxyType " : " MANUAL " ,
}
# create a webdriver
2023-03-26 22:56:57 +02:00
def firefox_driver ( mobile = False , headless = False ) :
2023-01-29 00:51:30 +01:00
PC_USER_AGENT = (
" Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
2023-02-25 19:05:47 +01:00
" AppleWebKit/537.36 (KHTML, like Gecko) "
" Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.56 " )
2023-01-29 00:51:30 +01:00
MOBILE_USER_AGENT = (
" Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) "
2023-02-25 19:05:47 +01:00
" AppleWebKit/605.1.15 (KHTML, like Gecko) "
" CriOS/103.0.5060.63 Mobile/15E148 Safari/604.1 "
2023-01-29 00:51:30 +01:00
)
2023-02-25 19:05:47 +01:00
options = Options ( )
options . set_preference ( ' intl.accept_languages ' , ' fr-FR, fr ' )
2023-01-29 00:51:30 +01:00
if proxy_enabled :
2023-02-25 19:05:47 +01:00
setup_proxy ( proxy_address , proxy_port , options )
options . set_preference ( " browser.link.open_newwindow " , 3 )
2023-01-29 00:51:30 +01:00
if FAST :
2023-03-17 22:37:35 +01:00
options . set_preference ( " permissions.default.image " , 2 ) #disable image loading. You shouldn't use it except if really nessecary
2023-03-26 22:56:57 +02:00
if headless :
2023-02-25 19:05:47 +01:00
options . add_argument ( " -headless " )
2023-01-29 00:51:30 +01:00
if mobile :
2023-02-25 19:05:47 +01:00
options . set_preference ( " general.useragent.override " , MOBILE_USER_AGENT )
2023-03-18 14:11:51 +01:00
driver = webdriver . Firefox ( options = options )
2023-03-17 22:37:35 +01:00
driver . set_window_size ( 1070 + hash ( _mail ) % 20 , 1900 + hash ( _password + " salt " ) % 10 ) # mobile resolution are crazy high now, right ?
2023-01-29 00:51:30 +01:00
else :
2023-02-25 19:05:47 +01:00
options . set_preference ( " general.useragent.override " , PC_USER_AGENT )
2023-03-18 14:11:51 +01:00
driver = webdriver . Firefox ( options = options )
2023-03-17 22:37:35 +01:00
driver . set_window_size ( 1900 + hash ( _mail ) % 20 , 1070 + hash ( _password + " salt " ) % 10 )
2023-01-29 00:51:30 +01:00
return ( driver )
# close the tab currently on and go back to the one first, or the one specified
def close_tab ( tab , SwitchTo = 0 ) - > None :
driver . switch_to . window ( tab )
driver . close ( )
driver . switch_to . window ( driver . window_handles [ SwitchTo ] )
#Deal with rgpd popup as well as some random popup like 'are you satisfied' one
2023-03-25 18:14:41 +01:00
def rgpd_popup ( driver ) - > None :
2023-01-29 00:51:30 +01:00
for i in [ " bnp_btn_accept " , " bnp_hfly_cta2 " , " bnp_hfly_close " ] :
try :
driver . find_element ( By . ID , i ) . click ( )
except :
pass
# 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 :
printf ( " starting play_quiz2 " )
for j in range ( override ) :
try :
2023-03-25 18:14:41 +01:00
rgpd_popup ( driver )
2023-01-29 00:51:30 +01:00
custom_sleep ( uniform ( 3 , 5 ) )
page_html = driver . page_source
secret_answer = search ( ' IG: " ([^ " ]+) " ' , page_html ) [ 1 ] # variable used to calculate offset
answers_values = search ( ' data-option= " ([^ " ]+) " ' , page_html ) [ 1 ]
offset = int ( secret_answer [ - 2 : ] , 16 ) # the last two character converted to int are the offset
correct_answer_value = search ( ' correctAnswer " : " ([0-9]+) ' , page_html ) [ 1 ]
somme = 0
for answer in answers_values :
somme + = ord ( answer )
if somme + offset == int ( correct_answer_value ) :
answer_elem = driver . find_element ( By . ID , " rqAnswerOption0 " )
answer_elem . click ( )
progressBar ( j , 10 , name = " quiz 2 " )
else :
answer_elem = driver . find_element ( By . ID , " rqAnswerOption1 " )
answer_elem . click ( )
progressBar ( j , 10 , name = " quiz 2 " )
except exceptions . ElementNotInteractableException as e :
driver . execute_script ( " arguments[0].click(); " , answer_elem )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
break
printf ( " play_quiz2 done " )
2023-03-19 18:50:29 +01:00
def play_quiz8 ( ) :
2023-01-29 00:51:30 +01:00
override = len ( findall ( " <span id= \" rqQuestionState. \" class= \" emptyCircle \" ></span> " , driver . page_source ) ) + 1
printf ( f " play_quiz8 : start, override : { override } " )
try :
counter = 0
2023-03-25 18:14:41 +01:00
rgpd_popup ( driver )
2023-01-29 00:51:30 +01:00
for _ in range ( override ) :
custom_sleep ( uniform ( 3 , 5 ) )
2023-03-12 11:22:49 +01:00
correct_answers = [ ]
for i in range ( 1 , 9 ) :
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 :
printf ( f " can ' t find rqAnswerOption { i - 1 } . Probably already clicked " + str ( e ) )
2023-01-29 00:51:30 +01:00
shuffle ( correct_answers )
for answer_id in correct_answers :
2023-02-27 18:31:31 +01:00
wait_until_visible ( By . ID , answer_id , timeout = 20 , browser = driver )
2023-01-29 00:51:30 +01:00
counter + = 1
progressBar ( counter , 16 , name = " Quiz 8 " )
try :
answer_elem = driver . find_element ( By . ID , answer_id )
answer_elem . click ( )
2023-02-27 18:31:31 +01:00
custom_sleep ( 1 )
2023-01-29 00:51:30 +01:00
except exceptions . NoSuchElementException :
driver . refresh ( )
custom_sleep ( 10 )
answer_elem = driver . find_element ( By . ID , answer_id )
answer_elem . click ( )
except ElementClickInterceptedException :
2023-03-25 18:14:41 +01:00
rgpd_popup ( driver )
2023-01-29 00:51:30 +01:00
correct_answers . append ( answer_id )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( f " { format_error ( e ) } \n Good answers : { ' ' . join ( correct_answers ) } " )
2023-01-29 00:51:30 +01:00
printf ( " play_quiz8 : fin " )
def play_quiz4 ( override = None ) :
printf ( " play_quiz4 : start " )
if not override :
try : # fidelity quiz are much longer than usual ones
override = int ( findall ( ' rqQuestionState([ \ d] { 1,2}) " ' , driver . page_source ) [ - 1 ] )
printf ( f " Override : { override } " )
except :
override = 3
try :
for i in range ( override ) :
custom_sleep ( uniform ( 3 , 5 ) )
txt = driver . page_source
2023-03-25 18:14:41 +01:00
rgpd_popup ( driver )
2023-01-29 00:51:30 +01:00
answer_option = search ( ' correctAnswer " : " ([^ " ]+) ' , txt ) [ 1 ]
answer_option = answer_option . replace ( " \\ u0027 " , " ' " ) # replace Unicode weird symbols
try :
answer_element = driver . find_element ( By . CSS_SELECTOR , f ' [data-option= " { answer_option } " ] ' )
answer_element . click ( )
except exceptions . ElementNotInteractableException :
driver . execute_script ( " arguments[0].click(); " , answer_element )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
raise ValueError ( e )
printf ( " play_quiz4 : end " )
# do_poll() answer a random thing to poll, on of daily activities
def do_poll ( ) :
printf ( " do_poll : start " )
try :
try :
answer_elem = driver . find_element ( By . ID , f " btoption { choice ( [ 0 , 1 ] ) } " )
answer_elem . click ( )
except exceptions . ElementNotInteractableException :
driver . execute_script ( " arguments[0].click(); " , answer_elem )
custom_sleep ( uniform ( 2 , 2.5 ) )
except Exception as error :
2023-03-18 19:12:27 +01:00
log_error ( error )
2023-01-29 00:51:30 +01:00
raise ValueError ( error )
printf ( " do_poll : end " )
# finds all task to do, and launch them
def all_cards ( ) :
def reset ( part2 = False ) :
if len ( driver . window_handles ) == 1 :
driver . get ( " https://www.bing.com/rewardsapp/flyout " )
if part2 :
driver . find_element (
By . XPATH , " /html/body/div/div/div[3]/div[2]/div[2]/div[2]/div[1] "
) . click ( )
else :
driver . switch_to . window ( driver . window_handles [ 1 ] )
printf ( f " fermeture : { driver . current_url } " )
driver . close ( )
driver . switch_to . window ( driver . window_handles [ 0 ] )
reset ( part2 )
def daily_cards ( ) :
try :
for i in range ( 3 ) :
custom_sleep ( uniform ( 3 , 5 ) )
try :
titre = " erreur "
driver . find_element (
By . XPATH , f " /html/body/div/div/div[3]/div[2]/div[1]/div[2]/div/div[ { i + 1 } ]/a/div/div[2] " ,
) . click ( )
sleep ( 1 )
titre = driver . title
2023-03-19 18:50:29 +01:00
try_play ( titre )
2023-01-29 00:51:30 +01:00
sleep ( 1 )
reset ( )
printf ( f " DailyCard { titre } ok " )
except Exception as e :
printf ( f " all_cards card { titre } error ( { e } ) " )
2023-03-18 19:12:27 +01:00
try : # devrait renvoyer vrai si la carte i est faite ou pas, a l'aide su symbole en haut a droite de la carte
elm = driver . find_element ( By . XPATH , f " /html/body/div/div/div[3]/div[2]/div[1]/div[2]/div/div[ { i + 1 } ]/a/div/div[2]/div[1]/div[2]/div " )
if not ( " correctCircle " in elm . get_attribute ( " innerHTML " ) ) :
print ( f " missed card { i } " )
2023-03-19 18:50:29 +01:00
try_play ( titre )
2023-03-18 19:12:27 +01:00
sleep ( 3 )
reset ( )
except :
pass # if it fail, it's probably okay
2023-01-29 00:51:30 +01:00
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-03-17 22:37:35 +01:00
2023-01-29 00:51:30 +01:00
def weekly_cards ( ) :
try :
driver . find_element (
By . XPATH , " /html/body/div/div/div[3]/div[2]/div[2]/div[2]/div[1] "
) . click ( ) # declenche la premiere partie ?
except :
reset ( )
try :
driver . find_element (
By . XPATH , " /html/body/div/div/div[3]/div[2]/div[2]/div[2]/div[1] "
) . click ( ) # declenche la deuxieme partie ?
except :
pass
for i in range ( 20 ) :
printf ( " début de l ' une des cartes " )
driver . find_element (
By . XPATH ,
" /html/body/div/div/div[3]/div[2]/div[2]/div[3]/div/div[1]/a/div/div[2] " ,
) . click ( )
driver . switch_to . window ( driver . window_handles [ len ( driver . window_handles ) - 1 ] )
sleep ( 1 )
titre = driver . title
print ( f " carte { titre } en cours " )
try_play ( titre )
reset ( True )
sleep ( 1 )
try :
findall ( ' href= " ([^<]+) " title= " " ' , driver . page_source ) [ 3 ] # return error if there is no cards left to do
except :
break
def top_cards ( ) :
for _ in range ( 10 ) :
try :
driver . find_element ( By . ID , " /html/body/div/div/div[3]/div[1]/div/div[1]/div[2] " ) . click ( )
close_tab ( driver . window_handles [ 1 ] )
2023-03-14 16:52:46 +01:00
except Exception as e :
print ( e )
2023-01-29 00:51:30 +01:00
break
try :
top_cards ( )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
try :
daily_cards ( )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
try :
weekly_cards ( )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
# Find out which type of action to do
2023-03-19 18:50:29 +01:00
def try_play ( nom = " inconnu " ) :
2023-03-25 18:14:41 +01:00
rgpd_popup ( driver )
2023-01-29 00:51:30 +01:00
printf ( " try_play en cours " )
def play ( number ) :
if number == 8 or number == 9 :
try :
printf ( f " \033 [96m Quiz 8 detected on { nom } \033 [0m " )
2023-03-19 18:50:29 +01:00
play_quiz8 ( )
2023-01-29 00:51:30 +01:00
printf ( f " \033 [92m Quiz 8 succeeded on { nom } \033 [0m " )
2023-03-14 16:52:46 +01:00
custom_sleep ( uniform ( 3 , 5 ) )
2023-01-29 00:51:30 +01:00
except Exception as e :
printf ( f " fail of PlayQuiz 8. Aborted { e } \033 [0m " )
elif number == 5 or number == 4 :
try :
printf ( f " \033 [96m Quiz 4 detected on { nom } \033 [0m " )
play_quiz4 ( )
printf ( f " \033 [92m Quiz 4 succeeded on { nom } \033 [0m " )
2023-03-14 16:52:46 +01:00
custom_sleep ( uniform ( 3 , 5 ) )
2023-01-29 00:51:30 +01:00
except Exception as e :
printf ( f " fail of PlayQuiz 4. Aborted { e } \033 [0m " )
elif number == 3 or number == 2 :
try :
printf ( f " \033 [96m Quiz 2 detected on { nom } \033 [0m " )
play_quiz2 ( )
printf ( f " \033 [92m Quiz 2 succeeded on { nom } \033 [0m " )
except Exception as e :
printf ( f " fail of PlayQuiz 2. Aborted { e } " )
else :
2023-03-18 19:12:27 +01:00
log_error ( " There is an error. rqAnswerOption present in page but no action to do. skipping. " )
2023-01-29 00:51:30 +01:00
try :
driver . find_element ( By . ID , " rqStartQuiz " ) . click ( ) # start the quiz
answer_number = driver . page_source . count ( " rqAnswerOption " )
play ( answer_number )
except Exception as e : # if there is no start button, an error is thrown
if " bt_PollRadio " in driver . page_source :
try :
printf ( " Poll detected " )
2023-03-25 18:14:41 +01:00
rgpd_popup ( driver )
2023-01-29 00:51:30 +01:00
do_poll ( )
printf ( " Poll succeeded " )
except Exception as e :
printf ( f " try_play - 1 - Poll aborted { e } " )
elif " rqQuestionState " in driver . page_source :
try :
number = driver . page_source . count ( " rqAnswerOption " )
printf ( f " recovery détecté. quiz : { number } " )
play ( number - 1 )
except Exception as e :
printf ( f " try_play - 2 - { e } " )
elif search ( " ([0-9]) de ([0-9]) finalisée " , driver . page_source ) :
print ( " fidélité " )
2023-03-25 18:14:41 +01:00
rgpd_popup ( driver )
2023-01-29 00:51:30 +01:00
fidelity ( )
else :
printf ( f " rien à faire sur la page { nom } " )
2023-03-25 18:14:41 +01:00
rgpd_popup ( driver )
2023-01-29 00:51:30 +01:00
custom_sleep ( uniform ( 3 , 5 ) )
# login() tries to login to your Microsoft account.
# it uses global variable _mail and _password to login
2023-03-25 18:14:41 +01:00
def login ( ldriver ) :
def pwd_login ( ) :
printf ( " pwd_login : start " )
ldriver . get ( " https://login.live.com " )
2023-03-19 10:17:28 +01:00
custom_sleep ( 2 )
2023-03-25 18:14:41 +01:00
wait_until_visible ( By . ID , " i0116 " , browser = ldriver )
mail_elem = ldriver . find_element ( By . ID , " i0116 " )
2023-01-29 00:51:30 +01:00
send_keys_wait ( mail_elem , _mail )
mail_elem . send_keys ( Keys . ENTER )
2023-03-19 10:17:28 +01:00
custom_sleep ( 2 )
2023-03-25 18:14:41 +01:00
wait_until_visible ( By . ID , " i0118 " , browser = ldriver )
pwd_elem = ldriver . find_element ( By . ID , " i0118 " )
2023-01-29 00:51:30 +01:00
send_keys_wait ( pwd_elem , _password )
pwd_elem . send_keys ( Keys . ENTER )
2023-03-18 19:12:27 +01:00
custom_sleep ( 2 )
2023-03-25 18:14:41 +01:00
if " Entrez le code de sécurité " in ldriver . page_source :
2023-03-18 19:12:27 +01:00
try :
2023-03-25 18:14:41 +01:00
a2f_elem = ldriver . find_element ( By . ID , " idTxtBx_SAOTCC_OTC " )
2023-03-18 19:12:27 +01:00
a2f_elem . send_keys ( _otp . now ( ) )
a2f_elem . send_keys ( Keys . ENTER )
except Exception as e :
log_error ( e )
2023-01-29 00:51:30 +01:00
custom_sleep ( 5 )
2023-03-25 18:14:41 +01:00
if ( ' Abuse ' in ldriver . current_url ) :
2023-03-18 19:12:27 +01:00
log_error ( " account suspended " )
2023-01-29 00:51:30 +01:00
raise Banned ( )
2023-03-25 18:14:41 +01:00
save_cookies ( )
2023-01-29 00:51:30 +01:00
for id in [ " KmsiCheckboxField " , " iLooksGood " , " idSIButton9 " , " iCancel " ] :
try :
2023-03-25 18:14:41 +01:00
ldriver . find_element ( By . ID , id ) . click ( )
2023-02-25 19:05:47 +01:00
restart = True
2023-01-29 00:51:30 +01:00
except Exception as e :
pass
2023-02-25 19:05:47 +01:00
2023-01-29 00:51:30 +01:00
try :
2023-03-25 18:14:41 +01:00
body_elem = ldriver . find_element ( By . TAG_NAME , " body " ) # in case of any random popup
2023-01-29 00:51:30 +01:00
body_elem . send_keys ( Keys . ENTER )
except :
pass
2023-02-27 18:31:31 +01:00
printf ( " login completed - going to MsRewards " )
2023-01-29 00:51:30 +01:00
custom_sleep ( uniform ( 3 , 5 ) )
2023-03-25 18:14:41 +01:00
ldriver . get ( " https://www.bing.com/rewardsapp/flyout " )
2023-01-29 00:51:30 +01:00
custom_sleep ( uniform ( 3 , 5 ) )
2023-02-25 19:05:47 +01:00
for i in [ f ' [title= " Rejoindre maintenant " ] ' , f ' [title= " Rejoindre " ] ' , f ' [title= " Join now " ] ' ] :
try :
2023-03-25 18:14:41 +01:00
ldriver . find_element ( By . CSS_SELECTOR , i ) . click ( ) # depend of the language of the page
2023-02-25 19:05:47 +01:00
except :
2023-02-27 18:31:31 +01:00
print ( f " element { i } not found " )
2023-03-25 18:14:41 +01:00
rgpd_popup ( ldriver )
2023-02-27 18:31:31 +01:00
custom_sleep ( uniform ( 3 , 5 ) )
2023-03-25 18:14:41 +01:00
ldriver . get ( " https://www.bing.com/rewardsapp/flyout " )
2023-03-17 22:37:35 +01:00
try :
2023-03-25 18:14:41 +01:00
ldriver . find_element ( By . CSS_SELECTOR , ' [title= " Rejoindre maintenant " ] ' ) . click ( ) # depend of the language of the page
2023-03-17 22:37:35 +01:00
except :
print ( f " unlock test: fail, probably normal " )
2023-02-27 18:31:31 +01:00
print ( ' on MsRewards ' )
2023-03-25 18:14:41 +01:00
def cookie_login ( ) :
ldriver . get ( " https://login.live.com " )
2023-01-29 00:51:30 +01:00
try :
2023-03-25 18:14:41 +01:00
load_cookies ( ldriver )
except FileNotFoundError :
print ( " Creating cookies file " )
2023-03-26 22:56:57 +02:00
return ( False )
try : # truc chelou sur docker (O)
ldriver . refresh ( )
except WebDriverException as e :
if " Reached error page: about:neterror?e=netTimeout " in str ( e ) :
print ( " Timeout error occurred. \" normal \" ..... " )
else :
log_error ( e )
2023-03-25 18:14:41 +01:00
CustomSleep ( 10 )
if ( " account.microsoft.com " in ldriver . current_url ) :
ldriver . get ( " https://bing.com " )
rgpd_popup ( ldriver )
ldriver . get ( " https://www.bing.com/rewardsapp/flyout " )
return ( True )
2023-03-26 22:56:57 +02:00
print ( " cookies plus valides " )
2023-03-25 18:14:41 +01:00
return ( False )
try :
if cookie_login ( ) :
return ( ldriver . current_window_handle )
pwd_login ( )
return ( ldriver . current_window_handle )
except Banned :
raise Banned ( )
except Exception as e :
log_error ( e )
ldriver . quit ( )
2023-01-29 00:51:30 +01:00
# Makes 30 search as PC Edge
def bing_pc_search ( override = randint ( 35 , 40 ) ) :
2023-03-19 10:44:00 +01:00
mot = choice ( Liste_de_mot ) . replace ( " " , " + " )
driver . get ( f " https://www.bing.com/search?q= { mot } " ) # {choice(Liste_de_mot)}')
2023-01-29 00:51:30 +01:00
custom_sleep ( uniform ( 1 , 2 ) )
2023-03-25 18:14:41 +01:00
rgpd_popup ( driver )
2023-01-29 00:51:30 +01:00
send_keys_wait (
driver . find_element ( By . ID , " sb_form_q " ) ,
Keys . BACKSPACE + Keys . BACKSPACE + Keys . BACKSPACE + Keys . BACKSPACE + Keys . BACKSPACE + Keys . BACKSPACE
)
for _ in range ( override ) :
word = choice ( Liste_de_mot )
try :
send_keys_wait ( driver . find_element ( By . ID , " sb_form_q " ) , word )
driver . find_element ( By . ID , " sb_form_q " ) . send_keys ( Keys . ENTER )
except Exception as e :
printf ( e )
sleep ( 10 )
driver . get ( f ' https://www.bing.com/search?q= { word } ' )
sleep ( 3 )
send_keys_wait ( driver . find_element ( By . ID , " sb_form_q " ) , word )
driver . find_element ( By . ID , " sb_form_q " ) . send_keys ( Keys . ENTER )
custom_sleep ( uniform ( 5 , 20 ) )
try :
driver . find_element ( By . ID , " sb_form_q " ) . clear ( )
except Exception as e :
printf ( e )
try :
2023-02-25 19:05:47 +01:00
driver . get ( ' https://www.bing.com/search?q=plans ' )
2023-01-29 00:51:30 +01:00
driver . find_element ( By . ID , " sb_form_q " ) . clear ( )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( f " clear la barre de recherche - { format_error ( e ) } " )
2023-03-19 18:50:29 +01:00
2023-01-29 00:51:30 +01:00
2023-02-27 13:41:54 +01:00
# Unban an account, called with -u parameter. You will need a phone number
2023-01-29 00:51:30 +01:00
def unban ( ) - > None :
driver . find_element ( By . ID , " StartAction " ) . click ( )
custom_sleep ( 2 )
txt = driver . page_source
uuid0 = findall ( ' wlspispHIPCountrySelect([a-z0-9]+) ' , txt ) [ 0 ]
uuid1 = findall ( ' wlspispHIPPhoneInput([a-z0-9]+) ' , txt ) [ 0 ]
uuid2 = findall ( ' wlspispHipSendCode([a-z0-9]+) ' , txt ) [ 0 ]
uuid3 = findall ( ' wlspispSolutionElement([a-z0-9]+) ' , txt ) [ 0 ]
country_code_select = Select ( driver . find_element ( By . ID , " wlspispHIPCountrySelect " + uuid0 ) )
country_code_input = input ( " enter Country code (FR, ...) " )
country_code_select . select_by_value ( country_code_input )
wait_until_visible ( By . ID , " wlspispHIPPhoneInput " + uuid1 , browser = driver )
phone_input = input ( " phone number : +33 " )
phone_elem = driver . find_element ( By . ID , " wlspispHIPPhoneInput " + uuid1 )
phone_elem . send_keys ( phone_input )
wait_until_visible ( By . ID , " wlspispHipSendCode " + uuid2 , browser = driver )
send_sms_elem = driver . find_element ( By . ID , " wlspispHipSendCode " + uuid2 )
send_sms_elem . click ( )
wait_until_visible ( By . ID , " wlspispSolutionElement " + uuid3 , browser = driver )
sms_code_elem = driver . find_element ( By . ID , " wlspispSolutionElement " + uuid3 )
sms_code_input = input ( " entrez le contenu du msg : " )
sms_code_elem . send_keys ( sms_code_input )
send_box = driver . find_element ( By . ID , " ProofAction " )
send_box . click ( )
wait_until_visible ( By . ID , " FinishAction " , browser = driver )
end_elem = driver . find_element ( By . ID , " FinishAction " )
end_elem . click ( )
2023-02-25 19:05:47 +01:00
# Sends points to database, discord and whatever service you want
2023-01-29 00:51:30 +01:00
def log_points ( account = " unknown " ) :
def get_points ( ) :
driver . get ( " https://www.bing.com/rewardsapp/flyout " )
regex1 = ' <a href= " https://rewards \ .bing \ .com/ " title= " ((. { 1,3}),(. { 1,3})) points " target= " _blank " '
try :
point = search ( regex1 , driver . page_source ) [ 1 ] . replace ( " , " , " " )
except Exception as e :
elem = driver . find_element ( By . CSS_SELECTOR , ' [title= " Microsoft Rewards " ] ' )
elem . click ( )
custom_sleep ( 5 )
driver . switch_to . window ( driver . window_handles [ len ( driver . window_handles ) - 1 ] )
custom_sleep ( uniform ( 5 , 7 ) )
2023-03-19 18:50:29 +01:00
try :
point = search ( ' availablePoints " :([ \ d]+) ' , driver . page_source ) [ 1 ]
except :
driver . refresh ( )
sleep ( 5 )
point = search ( ' availablePoints " :([ \ d]+) ' , driver . page_source ) [ 1 ]
2023-01-29 00:51:30 +01:00
return ( point )
for _ in range ( 3 ) :
try :
points = get_points ( )
break
except Exception as e :
custom_sleep ( 300 )
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
points = None
if not points :
2023-03-18 19:12:27 +01:00
log_error ( f " impossible d ' avoir les points " )
2023-01-29 00:51:30 +01:00
custom_sleep ( uniform ( 3 , 20 ) )
account_name = account . split ( " @ " ) [ 0 ]
if DISCORD_ENABLED_SUCCESS :
if DISCORD_EMBED :
embed = discord . 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 " )
if sql_enabled :
add_to_database ( account_name , points , sql_host , sql_usr , sql_pwd , sql_database )
def fidelity ( ) :
try :
while 1 : #close all tabs
try :
close_tab ( 1 )
except :
break
try :
fidelity_link_page = get ( FidelityLink ) #get the url of fidelity page
except Exception as e :
printf ( e )
fidelity_link_page = False
if fidelity_link_page :
fidelity_link = fidelity_link_page . content . decode ( " UTF-8 " )
if ( fidelity_link . split ( " : " ) [ 0 ] == " https " ) or ( fidelity_link . split ( " : " ) [ 0 ] == " http " ) :
driver . get ( fidelity_link )
wait_until_visible ( By . CSS_SELECTOR , ' div[class= " pull-left spacer-48-bottom punchcard-row " ] ' , browser = driver )
choix = driver . find_element ( By . CSS_SELECTOR , ' div[class= " pull-left spacer-48-bottom punchcard-row " ] ' ) # pull-left spacer-48-bottom punchcard-row? USELESS ?
answer_number = search ( " ([0-9]) of ([0-9]) completed " , 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 ( ' <span class= " pull-left margin-right-15 " >([^<^>]+)</span> ' , 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 :
2023-03-18 19:12:27 +01:00
log_error ( f " fidélité - double erreur - e1 : { format_error ( e1 ) } - e2 { format_error ( e2 ) } " )
2023-01-29 00:51:30 +01:00
break
custom_sleep ( uniform ( 3 , 5 ) )
driver . switch_to . window ( driver . window_handles [ 1 ] )
try_play ( driver . title )
driver . get ( fidelity_link ) # USELESS ?
custom_sleep ( uniform ( 3 , 5 ) )
try :
close_tab ( driver . window_handles [ 1 ] )
except Exception as e :
printf ( e )
printf ( " fidelity - done " )
else :
printf ( " invalid fidelity link. " )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
2023-03-25 18:14:41 +01:00
def mobile_login_pwd ( error ) :
2023-01-29 00:51:30 +01:00
try :
2023-03-17 22:37:35 +01:00
# TODO
2023-03-25 18:14:41 +01:00
# seems fine, check if there are no issues NO
2023-03-18 19:26:00 +01:00
mot = choice ( Liste_de_mot ) . replace ( " " , " + " )
mobile_driver . get ( f " https://www.bing.com/search?q= { mot } " )
2023-03-25 18:14:41 +01:00
rgpd_popup ( mobile_driver )
2023-01-29 00:51:30 +01:00
printf ( " start of Mobile login " )
2023-03-17 22:37:35 +01:00
try :
mobile_driver . find_element ( By . ID , " mHamburger " ) . click ( )
except Exception as e :
2023-03-18 14:21:27 +01:00
elm = mobile_driver . find_element ( By . ID , " mHamburger " )
mobile_driver . execute_script ( " arguments[0].scrollIntoView(); " , elm )
2023-03-17 22:37:35 +01:00
mobile_driver . find_element ( By . ID , " mHamburger " ) . click ( )
2023-01-29 00:51:30 +01:00
wait_until_visible ( By . ID , " hb_s " , browser = mobile_driver )
mobile_driver . find_element ( By . ID , " hb_s " ) . click ( )
wait_until_visible ( By . ID , " i0116 " , browser = mobile_driver )
mail_elem = mobile_driver . find_element ( By . ID , " i0116 " )
send_keys_wait ( mail_elem , _mail )
mail_elem . send_keys ( Keys . ENTER )
wait_until_visible ( By . ID , " i0118 " , browser = mobile_driver )
pwd_elem = mobile_driver . find_element ( By . ID , " i0118 " )
send_keys_wait ( pwd_elem , _password )
pwd_elem . send_keys ( Keys . ENTER )
custom_sleep ( uniform ( 1 , 2 ) )
2023-03-19 10:44:00 +01:00
if " Entrez le code de sécurité " in driver . page_source :
try :
a2f_elem = mobile_driver . find_element ( By . ID , " idTxtBx_SAOTCC_OTC " )
a2f_elem . send_keys ( _otp . now ( ) )
a2f_elem . send_keys ( Keys . ENTER )
except Exception as e :
log_error ( e )
custom_sleep ( uniform ( 1 , 2 ) )
2023-01-29 00:51:30 +01:00
for i in [ " KmsiCheckboxField " , " iLooksGood " , " idSIButton9 " ] :
try :
mobile_driver . find_element ( By . ID , i ) . click ( )
except Exception as e :
pass
printf ( " end of Mobile login " )
except Exception as e :
error + = 1
if error < = 3 :
printf ( f " failure on mobile_login. Retrying( { error } /3), { e } " )
custom_sleep ( uniform ( 5 , 10 ) )
2023-03-25 18:14:41 +01:00
mobile_login_pwd ( error )
2023-01-29 00:51:30 +01:00
else :
2023-03-18 19:12:27 +01:00
log_error ( f " login impossible 3 fois de suite. { e } " , mobile_driver )
2023-01-29 00:51:30 +01:00
mobile_driver . quit ( )
return ( True )
def mobile_alert_popup ( ) :
try :
alert = mobile_driver . switch_to . alert
alert . dismiss ( )
except exceptions . NoAlertPresentException as e :
pass
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e , mobile_driver )
2023-01-29 00:51:30 +01:00
def bing_mobile_search ( override = randint ( 22 , 25 ) ) :
2023-03-25 18:14:41 +01:00
print ( 1 )
2023-01-29 00:51:30 +01:00
global mobile_driver
2023-03-14 19:54:12 +01:00
mobile_driver = firefox_driver ( mobile = True )
2023-01-29 00:51:30 +01:00
try :
2023-03-25 18:14:41 +01:00
login ( mobile_driver )
mot = choice ( Liste_de_mot ) . replace ( " " , " + " )
mobile_driver . get ( f " https://www.bing.com/search?q= { mot } " )
custom_sleep ( uniform ( 1 , 2 ) )
rgpd_popup ( mobile_driver )
custom_sleep ( uniform ( 1 , 1.5 ) )
for i in range ( override ) : # 20
try :
mot = choice ( Liste_de_mot )
send_keys_wait ( mobile_driver . find_element ( By . ID , " sb_form_q " ) , mot )
mobile_driver . find_element ( By . ID , " sb_form_q " ) . send_keys ( Keys . ENTER )
custom_sleep ( uniform ( 5 , 20 ) )
mobile_alert_popup ( ) # check for alert (asking for position or for allowing notifications)
mobile_driver . find_element ( By . ID , " sb_form_q " ) . clear ( )
except Exception as e :
print ( e )
mobile_driver . refresh ( )
custom_sleep ( 30 )
i - = 1
mobile_driver . quit ( )
2023-01-29 00:51:30 +01:00
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e , mobile_driver )
2023-01-29 00:51:30 +01:00
mobile_driver . quit ( )
2023-03-14 19:54:12 +01:00
def daily_routine ( custom = False ) :
2023-01-29 00:51:30 +01:00
try :
if not custom : # custom already login
2023-03-25 18:14:41 +01:00
login ( driver )
2023-01-29 00:51:30 +01:00
except Banned :
2023-03-18 19:12:27 +01:00
log_error ( " THIS ACCOUNT IS BANNED. FIX THIS ISSUE WITH -U " )
2023-01-29 00:51:30 +01:00
return ( )
try :
all_cards ( )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
try :
bing_pc_search ( )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
try :
bing_mobile_search ( )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
try :
fidelity ( )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
try :
log_points ( _mail )
except Exception as e :
2023-03-18 19:12:27 +01:00
log_error ( e )
2023-01-29 00:51:30 +01:00
def dev ( ) :
pass
def CustomStart ( Credentials ) :
global START_TIME
if not LINUX_HOST :
raise NameError ( ' You need to be on linux to do that, due to the utilisation of a module named enquieries, sorry. ' )
2023-03-19 18:50:29 +01:00
global driver , _mail , _password , p , _otp
2023-01-29 00:51:30 +01:00
system ( " clear " ) # clear from previous command to allow a clean choice
actions = [ " tout " , " daily " , " pc " , " mobile " , " log_points " , " fidelity " , " dev " ]
Actions = enquiries . choose ( " quels Actions ? " , actions , multi = True )
liste = select_accounts ( )
START_TIME = time ( ) # Reset timer to the start of the actions
2023-03-19 18:50:29 +01:00
for cred in liste :
_mail = cred [ 0 ]
_password = cred [ 1 ]
if len ( cred ) == 3 :
_otp = TOTP ( cred [ 2 ] )
2023-01-29 00:51:30 +01:00
2023-03-19 18:50:29 +01:00
driver = firefox_driver ( )
driver . implicitly_wait ( 3 )
2023-01-29 00:51:30 +01:00
2023-03-25 18:14:41 +01:00
if login ( driver ) != " STOP " :
2023-03-19 18:50:29 +01:00
if " tout " in Actions :
daily_routine ( True )
if " daily " in Actions :
try :
all_cards ( )
except Exception as e :
log_error ( e )
if " pc " in Actions :
try :
bing_pc_search ( )
except Exception as e :
log_error ( e )
if " mobile " in Actions :
try :
bing_mobile_search ( )
except Exception as e :
log_error ( e )
if " fidelity " in Actions :
try :
fidelity ( )
except Exception as e :
log_error ( e )
if " dev " in Actions :
try :
dev ( )
except Exception as e :
printf ( e )
break
if not " tout " in Actions :
try :
log_points ( _mail )
except Exception as e :
print ( f " CustomStart { e } " )
2023-01-29 00:51:30 +01:00
driver . close ( )
def select_accounts ( multiple = True ) :
system ( " clear " ) # clear from previous command to allow a clean choice
emails = [ x [ 0 ] for x in Credentials ] # 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 Credentials if x [ 0 ] in emails_selected ] )
def SavePointsFromFile ( file ) :
with open ( file ) as f :
reader = csv . reader ( f )
points_list = list ( reader )
for item in points_list :
compte , points = item [ 0 ] , item [ 1 ]
add_to_database ( compte , points , sql_host , sql_usr , sql_pwd , sql_database , save_if_fail = False )
2023-03-25 18:14:41 +01:00
2023-01-29 00:51:30 +01:00
with open ( file , " w " ) as f :
f . write ( " " )
2023-02-25 19:05:47 +01:00
if VNC_ENABLED :
2023-03-19 10:17:28 +01:00
display = SmartDisplay ( backend = " xvnc " , size = ( 2160 , 2160 ) , rfbport = VNC_PORT , color_depth = 24 )
2023-02-25 19:05:47 +01:00
else :
2023-03-19 10:17:28 +01:00
display = SmartDisplay ( size = ( 2160 , 2160 ) )
2023-01-29 00:51:30 +01:00
display . start ( )
if CUSTOM_START :
CustomStart ( Credentials )
elif UNBAN :
_mail , _password = select_accounts ( False ) [ 0 ]
2023-02-25 19:05:47 +01:00
driver = firefox_driver ( )
2023-02-08 15:14:13 +01:00
try :
2023-03-25 18:14:41 +01:00
login ( driver )
2023-02-08 15:14:13 +01:00
except Banned :
2023-01-29 00:51:30 +01:00
unban ( )
2023-02-08 15:14:13 +01:00
2023-01-29 00:51:30 +01:00
driver . quit ( )
elif POINTS_FILE != " " :
SavePointsFromFile ( POINTS_FILE )
else :
2023-03-19 18:50:29 +01:00
for cred in Credentials :
_mail = cred [ 0 ]
_password = cred [ 1 ]
if len ( cred ) == 3 :
_otp = TOTP ( cred [ 2 ] )
print ( " \n \n " )
print ( _mail )
custom_sleep ( 1 )
printf ( " début du driver " )
driver = firefox_driver ( )
printf ( " driver demarré " )
driver . implicitly_wait ( 3 )
try :
daily_routine ( )
driver . quit ( )
attente = uniform ( 1200 , 3600 )
printf ( f " finis. attente de { round ( attente / 60 ) } min " )
custom_sleep ( attente )
except KeyboardInterrupt :
print ( " canceled. Closing driver and display. " )
driver . quit ( )
display . stop ( )
except Exception as e :
2023-03-26 22:56:57 +02:00
print ( f " error not catched. skipping this account. { e } " )
2023-03-19 18:50:29 +01:00
driver . quit ( )
2023-01-29 00:51:30 +01:00
2023-02-27 13:41:54 +01:00
display . stop ( )