diff --git a/README.md b/README.md index 5c766d7..cd9996d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,69 @@ -# selenium-energy-bot +# selenium-energy-bot_v2018 -The project contains a selenium bot which was created to automate the Energy Air or Energy Star Night competition. It is only intended as a POC and not to be used to win real tickets. (If you want to win tickets with it, you do it at your own risk.) \ No newline at end of file +The project contains a selenium bot which was created to automate the Energy Air or Energy Star Night competition. It is only intended as a POC and not to be used to win real tickets. (If you want to win tickets with it, you do it at your own risk.) + +It is written in Python3 and requires an Android app to redirect the SMS. +After successful implementation of the Smartphone app and the Python Bot, the SMS code is automatically read after the end of the session and the game starts from the beginning. + +## Configuration +[Download Python 3.7.4](https://www.python.org/ftp/python/3.7.4/python-3.7.4.exe)\ +After downloading the file, run it. During the installation it is important to note that the check mark under "Add Python 3.7 to PATH" is set.\ +Now open CMD and navigate to the folder "selenium-energy-bot": +``` +cd \path\to\your\folder\selenium-energy-bot +``` +There virtualenv must be installed: +``` +pip3 install virtualenv +virtualenv venv +``` +or: +``` +python -m .\venv +``` +Afterwards: +``` +venv\Scripts\activate.bat +pip install -r requirements.txt +``` + +### Gmail Account needed + * Click on [Enable The GMAIL API](https://developers.google.com/gmail/api/quickstart/python) and "Download Client Config". + * In the Gmail Inbox [mail.google.com](https://mail.google.com/) create a new "label". + * Under Settings (top right), go to "Filters & blocked addresses "Create new filter". + * As subject: *Forward SMS message from number [+41YOURNR] (sender - Energy (No contact specified))* + * Contains the words: *Dein Code für game.energy.ch* + * Create a filter and apply it to the newly created label. + +### Download APP PlayStore +* Download App [SMS to mail/phone - auto redirect](https://play.google.com/store/apps/details?id=com.gawk.smsforwarder) +* Configure the app to forward the SMS to your previously configured Gmail. +* Attention: The app must remain open in the background, so do not delete the app from the "open apps". Possibly adjust the energy plan on your mobile phone. + +### App Iphone (optional) +* If you don't have an Android, you can also use a corresponding app from the Appstore, which redirects SMS to Mail. The regex to find the code in the string has to be adjusted in the gmail_nrg_code.py script.\ +Possible App: [mysms mirror: Forward SMS](https://apps.apple.com/ch/app/mysms-mirror-sms-weiterleiten/id681057282) + +### Other Downloads (REQUIRED) +* Download the [Chrome Webdriver](https://chromedriver.chromium.org/downloads) in the appropriate version for your browser.\ +Find out the Webdriver version: +1. open Chrome Browser +2. click on the three points in the upper right corner +3. help, then "about Google Chrome" +4. at the top you will see "Version 78.0.3904.97" +* Alternatively you can also use webdriver of Edge or IE. But I personally had the best experiences with Chrome (adjust the webdriver in the script nggame_2019.py if you want to change it). + +## Usage +### Unique execution +* Place credentials.json (GMAIL Api Auth) and chromedriver.exe in the project folder. +* In gmail_nrg_code.py there is a place (marked with Uncomment). Comment this block (Attention: After the "#" there is still a space, delete it). +* Comment the function (main()) at the last place in the code and execute the script. +``` +python gmail_nrg_code.py +``` +* Copy the id of the label and paste it at the following code position: +* ```results = service.users().messages().list(userId='me', labelIds=['UNREAD', 'Label_YOURIDHERE'],``` +* Comment code out again. Also the function at the end! + +### Execute +```python energy-bot.py``` \ No newline at end of file diff --git a/energy-bot.py b/energy-bot.py index da155a5..87cadb0 100644 --- a/energy-bot.py +++ b/energy-bot.py @@ -1,96 +1,55 @@ # -*- coding: utf-8 -*- from selenium import webdriver import time +import gmail_nrg_code as nrg_code -print("© 2019 Michael Reber . ALL RIGHTS RESERVED.") +print("© 2018 Michael Reber . ALL RIGHTS RESERVED.") print("Created to win the endless energy game..") print("\r") print("May the Force be with you.") print("Patience you must have, my young padawan.") -driver = webdriver.Chrome(executable_path=r"D:\Energy-Bot-2019\chromedriver.exe") +driver = webdriver.Chrome(executable_path=r"D:\selenium-energy-bot\chromedriver.exe") driver.get("https://game.energy.ch/") +# assert "Energy" in driver.title +# ANSWERS FOR ENERGY AIR: answers = [ - -################################################################# -# ANTWORTEN FUERS ENERGY AIR 2019: - #"One Republic", - #"1300", - #"gewinnen", - #"XTRA-Circle", - #"Twitter", - #"E-Mail", - #"2014", - #"450 Tonnen", - #"70 Meter", - #"Die sechste", - #"Lo & Leduc", - #"im Radio, auf der Website und über Social Media", - #"40’000", - #"Energy Air findet trotzdem statt", - #"Im Privatjet", - #"Stade de Suisse, Bern", - #"Bastian Baker", - #"60", - #"Um 17 Uhr", ## Kontzertbeginn 19:00 - #"250", - #"Alvaro Soler", - #"14", - #"...der unter freiem Himmel stattfindet.", - #"Averdeck", - #"Sein Mami", - #"Eine komplett weisse Garderobe", - #"BSC Young Boys", - #"7. September 2019", - -################################################################# -# AB HIER ANTWORTEN FUER ENERGY STAR NIGHT: - "Swisscom", # ---------------------------------------------- (WELCHES UNTERNEHMEN IST «PRESENTING PARTNER» DER ENERGY STAR NIGHT?) - "Über 1'000'000", #Geraten --------------------------------- (WIE VIELE KUNDEN BESUCHEN LIPO JÄHRLICH?) - "2003", # -------------------------------------------------- (WANN FAND DIE ENERGY STAR NIGHT (EHEMALS ENERGY STARS FOR FREE) ZUM ERSTEN MAL STATT?) - "Mark Forster", # ------------------------------------------ (WELCHER DIESER ACTS HATTE EINEN AUFTRITT AN DER ENERGY STAR NIGHT 2017?) - "Um 19:00 Uhr", # ------------------------------------------ (WANN IST KONZERTBEGINN DER ENERGY STAR NIGHT?) - "Reinach (Kanton Basel)", # -------------------------------- (IN WELCHER STADT ERÖFFNETE 1976 DIE ERSTE LIPO FILIALE DER SCHWEIZ?) - "Energy Star Night 2017", # -------------------------------- (WELCHE AUSGABE DER ENERGY STAR NIGHT WURDE ZULETZT AUF PRO7 SCHWEIZ ÜBERTRAGEN?) - "14'000", # ------------------------------------------------ (WIE VIELE ENERGY STAR NIGHT TICKETS WERDEN VERLOST?) - "Graubünden",# --------------------------------------------- - "Jastina Doreen, Ex-Miss Schweiz", # ----------------------- (WEN KÜSSTE ENERGY MODERATOR JONTSCH AN DER LETZTJÄHRIGEN ENERGY STAR NIGHT?) - "3", # ----------------------------------------------------- (WIE VIELE ENERGY MUSIC AWARDS (IN ZUSAMMENARBEIT MIT DEM SCHWEIZERISCHEN ROTEN KREUZ) WURDEN BISHER VERLIEHEN?) - "gewinnen", # ---------------------------------------------- (ENERGY STAR NIGHT TICKETS KANN MAN AUSSCHLIESSLICH…) - "Die fünfzehnte", # Dieses Jahr ist die 17 Energy Star Night! - "Energy Stars For Free", # --------------------------------- (DIE ENERGY STAR NIGHT HIESS EHEMALS...) - "dem Schweizerischen Roten Kreuz",# ------------------------ (DER ENERGY MUSIC AWARD WIRD JEWEILS IN ZUSAMMENARBEIT MIT ... VERLIEHEN?) - "Ein Schweizer Musikpreis", # ------------------------------ (WAS IST DER ENERGY MUSIC AWARD?) - "Energy Star Night findet trotzdem statt", # --------------- - "Möbel", # ------------------------------------------------- (WAS KANN MAN BEI LIPO KAUFEN?) - "Oktober 2016", # ------------------------------------------ (WANN WURDE ENERGY STARS FOR FREE IN ENERGY STAR NIGHT UMBENANNT?) - "Stefanie Heinzmann", # ------------------------------------ (WELCHER ACT ERÖFFNETE DIE ENERGY STAR NIGHT 2018?) - "Usgang.ch", # --------------------------------------------- (WELCHES UNTERNEHMEN IST «MEDIENPARTNER» DER ENERGY STAR NIGHT 2019?) - "im Radio, auf der Event-Website und über Social Media", # - (WO ERFÄHRST DU IMMER DIE NEUSTEN INFOS RUND UM DIE ENERGY STAR NIGHT?) - "Vorhänge individuell konfigurieren", # -------------------- (WAS VERSTECKT SICH HINTER DEM BEGRIFF «MASSDESIGN» BEI LIPO?) - "Orange", # ------------------------------------------------ (WELCHE FARBE HAT DAS LIPO LOGO?) - "das grösste Indoor Musik-Event der Schweiz", # ------------ (DIE ENERGY STAR NIGHT IST…) - "22", # ---------------------------------------------------- (AN WIE VIELEN STANDORTEN BIETET LIPO AKTUELL ALLES AN, WAS ES ZUM WOHNEN BRAUCHT) - "22. November 2019", # ------------------------------------- (WANN FINDET DIE ENERGY STAR NIGHT 2019 STATT?) - "Postkarte", # --------------------------------------------- (AUF WELCHEM WEG KANN MAN KEINE ENERGY STAR NIGHT TICKETS GEWINNEN?) - "Hallenstadion, Zürich", # --------------------------------- (IN WELCHER EVENTLOCATION FINDET DIE ENERGY STAR NIGHT STATT?) - "«The Game Is On»", #Geraten ------------------------------- (WIE LAUTETE DAS MOTTO DER ENERGY STAR NIGHT 2018?) - "Hiltl Club, Zürich",# ------------------------------------- - "Nemo", # -------------------------------------------------- (WELCHER SCHWEIZER ACT RÄUMTE DEN ENERGY MUSIC AWARD 2018 AB?) - "VIP", # --------------------------------------------------- (WELCHE TICKETKATEGORIE WIRD NICHT FÜR DIE ENERGY STAR NIGHT VERLOST?) - "Winterthur und Villeneuve", #Geraten ---------------------- (IN WELCHEN BEIDEN STÄDTEN ERÖFFNET LIPO AM 22. NOVEMBER 2019 JEWEILS EINE NEUE FILIALE?) - "Die tiefsten Preise der Schweiz", # ----------------------- (WAS GARANTIERT LIPO SEINEN KUNDEN?) - "#esn19", # ------------------------------------------------ (WIE LAUTET DER OFFIZIELLE HASHTAG DER ENERGY STAR NIGHT 2019?) - "Twitter", # ----------------------------------------------- (AUF WELCHER SOCIAL MEDIA PLATTFORM KANN MAN KEINE ENERGY STAR NIGHT TICKETS GEWINNEN?) - "Mex" #Geraten --------------------------------------------- (WIE HEISST DER HUND IM AKTUELLEN WERBESPOT?) + "One Republic", + "1300", + "gewinnen", + "XTRA-Circle", + "Twitter", + "E-Mail", + "2014", + "450 Tonnen", + "70 Meter", + "Die sechste", + "Lo & Leduc", + "im Radio, auf der Website und über Social Media", + "40’000", + "Energy Air findet trotzdem statt", + "Im Privatjet", + "Stade de Suisse, Bern", + "Bastian Baker", + "60", + "Um 17 Uhr", + "250", + "Alvaro Soler", + "14", + "...der unter freiem Himmel stattfindet.", + "Averdeck", + "Sein Mami", + "Eine komplett weisse Garderobe", + "BSC Young Boys", + "7. September 2019" ] def press_answer(quest_nr): for answer in answers: try: - labelname = '//label[@for="' + answer + '"]' + labelname = "//label[@for='" + answer + "']" elem1 = driver.find_elements_by_xpath(labelname)[0] time.sleep(2) elem1.click() @@ -105,11 +64,8 @@ def press_answer(quest_nr): question_Nr = 0 counter = 0 input("Press to enter script") - -print("Enter Your Energy Registered Account Email:") -account_mail = input("Email: ") -print("Enter Your Passwort:") -account_password = input("Passwort: ") +print("Enter Phone Nr: (do not enter starting '0'! Example: 798765432") +tel_nr = int(input("+41")) while True: while question_Nr < 10: @@ -117,11 +73,8 @@ while True: question_Nr += 1 else: try: - win1 = driver.find_elements_by_xpath("//button[@class='btn btn-primary game-button game-button-slot']")[0] - win1.click() elem2 = driver.find_elements_by_xpath("//div[@class='circle col-xs-4 col-sm-3 col-md-4 col-lg-3']")[6] elem2.click() - try: elem1 = driver.find_elements_by_xpath("//button[@class='btn btn-primary game-button btn-lg']")[0] elem1.click() @@ -130,24 +83,33 @@ while True: except: try: try: - try: - energyLogin = driver.find_elements_by_xpath("//input[@name='email']")[0] - energyLogin.send_keys(account_mail) - elem3 = driver.find_elements_by_xpath("//button[@id='first-step-continue-btn']")[0] - elem3.click() - except: - try: - energyPass = driver.find_elements_by_xpath("//input[@name='password']")[0] - energyPass.send_keys(account_password) - elem4 = driver.find_elements_by_xpath("//button[@id='native-login-btn']")[0] - elem4.click() - except: - pass + elem3 = driver.find_elements_by_xpath("//input[@placeholder='Handynummer']")[0] + elem3.send_keys(tel_nr) + elem1 = driver.find_elements_by_xpath("//button[@class='btn btn-primary game-button btn-lg']")[0] + elem1.click() + found_mail = False + while found_mail is False: + sms_code = nrg_code.main() + if sms_code is not None: + found_mail = True + print(sms_code + "....................................................") + code_numb_list = [] + for numb in sms_code: + code_numb_list.append(numb) + driver.find_elements_by_xpath("//input[@id='1']")[0].send_keys(code_numb_list[0]) + driver.find_elements_by_xpath("//input[@id='2']")[0].send_keys(code_numb_list[1]) + driver.find_elements_by_xpath("//input[@id='3']")[0].send_keys(code_numb_list[2]) + driver.find_elements_by_xpath("//input[@id='4']")[0].send_keys(code_numb_list[3]) + elem1 = \ + driver.find_elements_by_xpath( + "//button[@class='btn btn-primary game-button btn-lg btn-declined']")[0] + elem1.click() + else: + time.sleep(5) except: pass elem1 = driver.find_elements_by_xpath("//button[@class='btn btn-primary game-button btn-lg']")[0] elem1.click() - except: pass question_Nr = 0 @@ -155,7 +117,7 @@ while True: print("COUNT:", counter) if counter == 115: driver.close() - driver = webdriver.Chrome(executable_path=r"D:\Energy-Bot-2019\chromedriver.exe") + driver = webdriver.Chrome(executable_path=r"D:\selenium-energy-bot\chromedriver.exe") driver.get("https://game.energy.ch/") assert "Energy" in driver.title counter = 0 \ No newline at end of file diff --git a/gmail_nrg_code.py b/gmail_nrg_code.py new file mode 100644 index 0000000..f4f400e --- /dev/null +++ b/gmail_nrg_code.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +import pickle +import os.path +from googleapiclient.discovery import build +from google_auth_oauthlib.flow import InstalledAppFlow +from google.auth.transport.requests import Request +import re + +# If modifying these scopes, delete the file token.pickle. +SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/gmail.modify'] + + +def main(): + """Shows basic usage of the Gmail API. + Lists the user's Gmail labels. + """ + creds = None + # The file token.pickle stores the user's access and refresh tokens, and is + # created automatically when the authorization flow completes for the first + # time. + if os.path.exists('token.pickle'): + with open('token.pickle', 'rb') as token: + creds = pickle.load(token) + # If there are no (valid) credentials available, let the user log in. + if not creds or not creds.valid: + if creds and creds.expired and creds.refresh_token: + creds.refresh(Request()) + else: + flow = InstalledAppFlow.from_client_secrets_file( + 'credentials.json', SCOPES) + creds = flow.run_local_server(port=0) + # Save the credentials for the next run + with open('token.pickle', 'wb') as token: + pickle.dump(creds, token) + + service = build('gmail', 'v1', credentials=creds) + +############################################################################### + """Uncomment to print label_name + label_id + is needed to determine Energy Label id. + """ +# results = service.users().labels().list(userId='me').execute() +# +# labels = results.get('labels', []) +# +# if not labels: +# print('No labels found.') +# else: +# print('Labels:') +# for label in labels: +# print(label['name'] + " " + label['id']) +############################################################################### + + # Call the Gmail API to fetch INBOX Energy, only unread messages + results = service.users().messages().list(userId='me', labelIds=['UNREAD', 'Label_5204902350138961179'], + maxResults=1).execute() + messages = results.get('messages', []) + + if not messages: + print("No messages found.") + return None + else: + print("Message snippets:") + for message in messages: + msg = service.users().messages().get(userId='me', format='full', id=message['id']).execute() + # marks mail as read + service.users().messages().modify(userId='me', id=message['id'], + body={'removeLabelIds': ['UNREAD']}).execute() + snippet = msg['snippet'] + print(snippet) + verification_code = str(snippet).split("Dein Code für game.energy.ch")[-1] + verification_code = verification_code.split(re.match('[0-3][0-9]/[0-1][0-9]/2019', verification_code))[ + 0].strip() + print(verification_code) + return verification_code +############################################################################### + """uncomment to run once to fetch label id or for development""" +#if __name__ == '__main__': +# main() +############################################################################### \ No newline at end of file