diff --git a/.gitignore b/.gitignore index a38c0e3..f9c67df 100644 --- a/.gitignore +++ b/.gitignore @@ -133,3 +133,22 @@ dmypy.json # Pyre type checker .pyre/ + +# pip file +Pipfile +Pipfile.lock + +# Wallet address +account.txt + +# Signin check file +sign.file + +# Throttle file check +throttle.txt + +# vscode config files +.vscode + +# .png files +*.png diff --git a/README.md b/README.md index 91e3198..f6f9a1f 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,47 @@ # awbot -Alien Worlds automation using Python +###### Alien Worlds automation using Python. ### Requirements -- Python 3.6 or later (You may download Python from here https://www.python.org/downloads) -- Chrome Driver (Downloaded automatically during runtime. If Chrome Driver could not be downloaded automatically, please manually download the correct version from here https://chromedriver.chromium.org/downloads) -- Python Packages (Listed in requirements.txt) -- Active Alien Worlds account +- ###### Python 3.6 or later (You may download Python from here https://www.python.org/downloads), +- ###### Chrome Driver (Downloaded automatically during runtime. If Chrome Driver could not be downloaded automatically, please manually download the correct version from here https://chromedriver.chromium.org/downloads), +- ###### Python Packages (Listed in requirements.txt), +- ###### Active Alien Worlds account. ### Installation Instructions -- Clone this repository +- ###### Clone this repository, ``` -git clone https://github.com/dobizz/awbot.git +git clone https://github.com/theDebonair/awbot.git cd awbot ``` -- Install all the required Python packages + +- ###### Install all the required Python packages. ``` pip install -r requirements.txt ``` ### Running Instructions -After all the dependencies have been downloaded and installed, simply run awbot.py +- ###### After all the dependencies have been downloaded and installed, simply run "awbot.py". ``` python awbot.py ``` -On the first run you need to login to your wax account, on the succeeding runs you will be logged in automatically as the session cookies will be saved. - -Follow the prompts in the command terminal. - -### Donations -Donations are much welcome to buy needed coffee. - -BTC `1zdraxHPQfZ8wvpMXt2VYhnGwmkLCf7UL` - -ETH `0x4e1736Db4d3912e6Ddd4E5a7A710D85ed369B987` - -XRP `rU2mEJSLqBRkYLVTv55rFTgQajkLTnT6mA` Destination Tag `107601` +### Attention +###### Using bot or any kind of automation is not recommended by the Aliens World. I'm not responsible for any kind of your loss(es). USE AT YOUR OWN RISK! + +### Features +- ###### "Bot resource(s) throttling" feature disables the check for CPU, NET, RAM usage. This enables the bot to click even when the resources are above 100%. +- ###### "Headless mode" is the mode where browser will completely run in the background without disturbing you. When login will be required, headless mode will be turned OFF automatically. +- ###### "Screenshot" of the last opened pages. +- ###### Added a feature to sell the "TLM" tokens. This can be done by creating a file "sell.file" in the bot's directory. + +### PS +- ###### On the first run you need to login to your wax account, on the succeeding runs you will be logged in automatically as the session cookies will be saved. +- ###### Follow the prompts in the command terminal. +- ###### You must open the terminal in the same directory where the files are stored. +- ###### To prevent any errors, click the "Mine" button and "claim" manually very first time of using the bot. Their is some issue with WAX wallet, or you must have some "TLM" tokens in your wallet. +- ###### To take screenshot, you've to uncomment 4 lines under the comment ```# full page screenshot``` within the bot. +- ###### Feel free to make suggestions, report bugs on this project's [discussions](https://github.com/theDebonair/awbot/discussions) tab. + +### Want to buy me a lambo? +- ###### WAX: xau3c.c.wam +- ###### BNB, ETH: 0xaA98aAE37F98ce7d657f4472e14891266c13e321 \ No newline at end of file diff --git a/awapi.py b/awapi.py index 0be2899..d69785e 100644 --- a/awapi.py +++ b/awapi.py @@ -51,12 +51,18 @@ def get_balance(self, contract:str, currency:str) -> float: try: url = 'https://wax.greymass.com/v1/chain/get_currency_balance' reply = self._session.post(url, json=json_payload, timeout=Account.HTTP_TIMEOUT) + assert reply.status_code == 200 + balance = float(reply.json()[0].split()[0]) + return balance except ReadTimeout: url = 'https://chain.wax.io/v1/chain/get_currency_balance' reply = self._session.post(url, json=json_payload, timeout=Account.HTTP_TIMEOUT) - assert reply.status_code == 200 - balance = float(reply.json()[0].split()[0]) - return balance + assert reply.status_code == 200 + balance = float(reply.json()[0].split()[0]) + return balance + except: + balance = "Error retrieving values" + return balance def get_account(self) -> dict: """ diff --git a/awbot.py b/awbot.py index 5f11310..61b7033 100644 --- a/awbot.py +++ b/awbot.py @@ -1,35 +1,130 @@ -#!/usr/bin/env python3 -import os import sys -import json +import os import time import random import pathlib -import platform +import http.client as httplib from itertools import count +from plyer import notification from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as ec -from selenium.common.exceptions import NoSuchElementException -from webdriver_manager.chrome import ChromeDriverManager from selenium_stealth import stealth +from webdriver_manager.chrome import ChromeDriverManager from awapi import Account +path = os.path.dirname(__file__) + +# initialize loop count +loop_count = 0 + +# initialize mine loop count +mine_loop_count = 0 + +# variable as condition to exit script +exit_sc = False -def _print_(text:str) -> None: +sell_file = False + +sign_file = True + +def _print_(text: str) -> None: sys.stdout.write(text) sys.stdout.flush() - def main(): + global path, exit_sc, loop_count, mine_loop_count, sell_file, sign_file + + # clear terminal + os.system("cls" if os.name == "nt" else "clear") + + # check internet connection + conn = httplib.HTTPConnection("1.1.1.1", timeout = 10) + + try: + print("Internet check.") + conn.request("HEAD", "/") + conn.close() + print("Internet available.") + + except KeyboardInterrupt: + print("\nStopping bot.") + exit_sc = True + return + + except: + conn.close() + print("No Internet. Re-checking in 30 seconds.") + for x in range(30): + time.sleep(1) + _print_(".") + return + # define game url url = "https://play.alienworlds.io" + # wax signin page + signin = "https://all-access.wax.io/" + + # alcor to sell tlm + sell = "https://wax.alcor.exchange/trade/tlm-alien.worlds_wax-eosio.token" + + # for account.txt file + try: + # check for account.txt file + if os.path.exists("account.txt"): + # check for file size & read + if os.stat("account.txt").st_size != 0: + afile = open("account.txt", "r") + wallet = afile.read().rstrip("\n") + afile.close() + + # delete the file if found empty account.txt file + else: + print("\nDeleting corrupted \"account.txt\".") + os.remove("account.txt") + print("File deleted.") + print("Restarting bot.") + return + + # create account.txt file if not found + else: + anfile = open("account.txt", "w") + anfile.write(input("\nPlease enter your wax wallet address: ")) + anfile.close() + print("Restarting bot.") + return + + except KeyboardInterrupt: + print("\nStopping bot.") + exit_sc = True + return + + except: + print("\nBot encountered an error. Restarting.") + return + + # check for sign.file and sell.file file + if os.path.exists("sell.file"): + print("\n\"sell.file\" found.") + headless = False + sell_file = True + + elif os.path.exists("sign.file"): + headless = True + sign_file = True + + else: + headless = False + sign_file = False + # create AW Account instance - aw = Account(input("Please enter account name (e.g abcde.wam): ")) + aw = Account(wallet) + + print(f"\nWallet address: \"{wallet}\"") # define range for loop delay delay_min = 60 # min delay before next loop @@ -39,190 +134,528 @@ def main(): resource_limit = 100 # skip mining if resources are above the set limit resource_sleep = 30 # sleep for given time if there is not enough resources - # set Chrome options chrome_options = Options() + + # set Chrome options chrome_options.add_argument("--log-level=3") chrome_options.add_argument("--ignore-certificate-errors") chrome_options.add_argument("--ignore-certificate-errors-spki-list") chrome_options.add_argument("--ignore-ssl-errors") - # when there is already a persistent session, you may activate headless mode - # chrome_options.add_argument('--headless') + chrome_options.add_argument("--disable-blink-features=AutomationControlled") + chrome_options.add_argument("--mute-audio") + chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36") - chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"]) - chrome_options.add_experimental_option("useAutomationExtension", False) + # headless mode when signed in + if headless: + # to open in hidden browser window + chrome_options.add_argument("--headless") # save current browsing session to make it persistent pwd = pathlib.Path().absolute() chrome_options.add_argument(f"--user-data-dir={pwd}\\chrome-data") + # check for latest chromedriver + driver_service = Service() + # instantiate Chrome driver with given Chrome options try: - driver = webdriver.Chrome( - service=Service(ChromeDriverManager().install()), - options=chrome_options, - ) + driver = webdriver.Chrome(service = driver_service, options = chrome_options) + + # instantiate stealth + stealth(driver, + languages=["en-US", "en"], + vendor="Google Inc.", + platform="Win32", + webgl_vendor="Intel Inc.", + renderer="Intel Iris OpenGL Engine", + fix_hairline=True, + ) + + # save current window handle + main_window = driver.current_window_handle + + # change page load timeout + driver.set_page_load_timeout(60) + + # make GET request + if headless: + driver.get(url) + + else: + if sell_file: + driver.get(sell) + driver.set_window_position(0, 0) + input("\nPress any key when selling of \"TLM\" tokens is done.") + os.remove("sell.file") + print("\"sell.file\" deleted.") + print("Restarting bot.") + return + + else: + driver.get(signin) + driver.set_window_position(0, 0) + + print(f"\nSuccessfully loaded \"{driver.title}\".") + except TypeError: - print("Please update your selenium package") + print("\nPlease update your selenium package.") + exit_sc = True + return + + except KeyboardInterrupt: + print("\nStopping bot.") + exit_sc = True + return + + except: + print("\nBot encountered an error. Restarting.") return - # change page load timeout - driver.set_page_load_timeout(60) - - # instatiate stealth - stealth( - driver, - languages=["en-US", "en"], - vendor="Google Inc.", - platform="Win32", - webgl_vendor="Intel Inc.", - renderer="Intel Iris OpenGL Engine", - fix_hairline=True, - ) + try: + # check for sign.file file + if sign_file: + print("\nStarting bot in 3 seconds. \n\t- Delete \"sign.file\" in case of re-login. \n\t- Press \"Ctrl + C\" to stop") + for x in range(3): + time.sleep(1) + _print_(".") - # save current window handle - main_window = driver.current_window_handle + # create sign.file if not found + else: + driver.execute_script(""" + var wallet = arguments[0]; + document.title = wallet; + alert(wallet); + """, wallet) + print("\nPausing bot.") + notification.notify(title = os.path.basename(path) + "\\" + os.path.basename(__file__), message = "Sign-in required.") + input("Please sign-in, then press any key to continue.") + open("sign.file", "a").close() + print("Restarting bot.") + return + + except KeyboardInterrupt: + print("\nStopping bot.") + exit_sc = True + driver.quit() + return - # make GET request - driver.get(url) + except: + print("\nBot encountered an error. Restarting.") + return - input("\nPlease login and press when ready to Mine") + # load tlm balance + tlm_old = aw.tlm_balance - print("\nStarting bot.\n") + # initialize tlm_sum + tlm_sum = 0 - # initialize crash count - crashes = 0 + # activation switch for checking tlm mined per click + i = False # main bot loop - for loop_count in count(1): + for y in count(1): + loop_count += 1 + + # clear terminal + os.system("cls" if os.name == "nt" else "clear") + + print(f"Wallet address: \"{wallet}\"") + try: # fetch cpu usage details cpu_usage = aw.cpu_usage - cpu_max = cpu_usage['max'] - cpu_used = cpu_usage['used'] + cpu_max = cpu_usage["max"] + cpu_used = cpu_usage["used"] cpu_pct = int(cpu_used / cpu_max * 100) # fetch ram usage details ram_usage = aw.ram_usage - ram_max = ram_usage['max'] - ram_used = ram_usage['used'] + ram_max = ram_usage["max"] + ram_used = ram_usage["used"] ram_pct = int(ram_used / ram_max * 100) # fetch net usage details net_usage = aw.net_usage - net_max = net_usage['max'] - net_used = net_usage['used'] + net_max = net_usage["max"] + net_used = net_usage["used"] net_pct = int(net_used / net_max * 100) - # line width - width = 80 - - print("=" * width) - print("CPU: [ {:,} / {:,} ms ]\t\t\tUsed: {} %".format(cpu_used, cpu_max, cpu_pct)) + print("\nCPU: [ {:,} / {:,} ms ]\t\t\tUsed: {} %".format(cpu_used, cpu_max, cpu_pct)) print("NET: [ {:,} / {:,} B ]\t\t\tUsed: {} %".format(net_used, net_max, net_pct)) print("RAM: [ {:,} / {:,} B ]\t\t\tUsed: {} %".format(ram_used, ram_max, ram_pct)) - print("=" * width) - # get balances - wax = aw.wax_balance - tlm = aw.tlm_balance - # show balances - print("WAX Balance:", wax) - print("TLM Balance:", tlm) + print(f"\nWAX Balance: {aw.wax_balance:.4f}") + + try: + print(f"TLM Balance: {aw.tlm_balance:.4f}") + + except: + print("Unable to retrieve the TLM value.") + + tlm_new = aw.tlm_balance + + # show tlm mined per click + if i and tlm_old < tlm_new: + try: + # to find the value of tlm mined + tlm_mined = tlm_new - tlm_old + print(f"\nTLM mined in last claim: {tlm_mined:.4f}") + tlm_old = tlm_new + + # to find average rate of tlm mining + tlm_sum += tlm_mined + avg = tlm_sum/mine_loop_count + print(f"Average rate for TLM mining: {avg:.4f}/claim") - if (cpu_pct > resource_limit) or (ram_pct > resource_limit) or (net_pct > resource_limit): - print("\nResource utilization is above the set threshold of {} %".format(resource_limit)) - print("\nSleeping for {} seconds\n".format(resource_sleep)) - time.sleep(resource_sleep) - continue + # to show sum of tlm mined + print(f"Total TLM mined in this session: {tlm_sum:.4f}") + except KeyboardInterrupt: + print("\nStopping bot.") + exit_sc = True + driver.quit() + return + + except: + print("\nUnable to show the value(s).") + + # check for throttle.txt file + if os.path.exists("throttle.txt"): + + # check for file size & read + if os.stat("throttle.txt").st_size != 0: + tfile = open("throttle.txt", "r") + throttle = tfile.read().rstrip("\n") + tfile.close() + + if throttle == "Y" or throttle == "y": + # resource utilization throttling + if (cpu_pct > resource_limit) or (ram_pct > resource_limit) or (net_pct > resource_limit): + print(f"\nResource utilization is above the set threshold of {resource_limit} %.") + print(f"Sleeping for {resource_sleep} seconds.") + for x in range(resource_sleep): + time.sleep(1) + _print_(".") + continue + + elif throttle == "N" or throttle == "n": + print("\nResource utilization throttling is OFF. Turn ON by changing value to \"Y\" in the \"throttle.txt\" file.") + + # delete the file if value found other than Y or N + else: + print("\nAppropriate input not found.") + print("Deleting corrupted \"throttle.txt\".") + os.remove("throttle.txt") + print("File deleted.") + print("Restarting bot.") + driver.quit() + return + + # delete the file if found empty throttle.txt file + else: + print("\nDeleting corrupted \"throttle.txt\".") + os.remove("throttle.txt") + print("File deleted.") + print("Restarting bot.") + driver.quit() + return + + # create throttle.txt file if not found + else: + ntfile = open("throttle.txt", "w") + ntfile.write(input("\nDo you want to enable the bot resource(s) throttling [Y/N]: ")) + ntfile.close() + driver.quit() + return + # wait for mine button to be found - print("\nWaiting for Mine button") + print("\nSearching for \"Start Now\" button.") + + while True: + # try to search for "start now" button + try: + start_btn = WebDriverWait(driver, 5).until(ec.visibility_of_element_located((By.XPATH, "//*[starts-with(text(), 'Start')]"))) + + except KeyboardInterrupt: + print("\nStopping bot.") + exit_sc = True + driver.quit() + return + + # if button is not found + except: + print('\n\tUnable to load or find \"Start Now\" button.') + break + + # if button is found, then click + else: + print("Found \"Start Now\" button!") + + # full page screenshot + # total_width = driver.execute_script("return document.body.offsetWidth") + # total_height = driver.execute_script("return document.body.scrollHeight") + # driver.set_window_size(total_width, total_height) + # driver.save_screenshot("sc_main_mine.png") # image will be saved as "sc_main_mine.png" in the bot's directory + + start_btn.click() + break + + # wait for mine button to be found + print("\nSearching for \"Mine\" button.") while True: - _print_(".") # try to find mine button try: - mine_btn = driver.find_element(By.XPATH, '//*[text()="Mine"]') + mine_btn = WebDriverWait(driver, 30).until(ec.visibility_of_element_located((By.XPATH, "//*[starts-with(text(), 'Mine')]"))) except KeyboardInterrupt: - print('Stopping bot.') + print("\nStopping bot.") + exit_sc = True driver.quit() - sys.exit() + return # if button is not found - except NoSuchElementException: - time.sleep(5) + except: + print('\n\tUnable to load or find \"Mine\" button.') + break - # if button is found + # if button is found, then click else: - _print_(":") - print("\nFound Mine button!") - # click + print("Found \"Mine\" button!") + + # full page screenshot + # total_width = driver.execute_script("return document.body.offsetWidth") + # total_height = driver.execute_script("return document.body.scrollHeight") + # driver.set_window_size(total_width, total_height) + # driver.save_screenshot("sc_main_mine.png") # image will be saved as "sc_main_mine.png" in the bot's directory + mine_btn.click() break # wait for claim button - claim_btn = WebDriverWait(driver, 60).until(ec.visibility_of_element_located((By.XPATH, '//*[text()="Claim Mine"]'))) - print("Found Claim button!") + print("\nSearching for \"Claim\" button.") + + try: + claim_btn = WebDriverWait(driver, 15).until(ec.visibility_of_element_located((By.XPATH, "//*[starts-with(text(), 'Claim')]"))) + print("Found \"Claim\" button!") + + # full page screenshot + # total_width = driver.execute_script("return document.body.offsetWidth") + # total_height = driver.execute_script("return document.body.scrollHeight") + # driver.set_window_size(total_width, total_height) + # driver.save_screenshot("sc_main_claim.png") # image will be saved as "sc_main_claim.png" in the bot's directory + + # click claim button + claim_btn.click() + + except KeyboardInterrupt: + print("\nStopping bot.") + exit_sc = True + driver.quit() + return + + except: + print('\n\tUnable to load or find \"Claim\" button. Restarting.') + driver.quit() + return - # click claim button - claim_btn.click() + # wait for pop-up window + print("\n\tSearching for pop-up window.") - # pause for 3 seconds - time.sleep(3) + # to continue below while loop + switch = False - # switch control to pop-up window - for this_window in driver.window_handles: - if this_window != main_window: - print('\n\tSwitching to new window.') - driver.switch_to.window(this_window) + while True: + if switch: break - # wait for approve button to be visible and click button - btn = WebDriverWait(driver, 60).until(ec.visibility_of_element_located((By.XPATH, "//*[contains(text(), 'Approve')]"))) + else: + this_window = None + + # switch control to pop-up window + for this_window in driver.window_handles: + if this_window != main_window: + try: + print("\tSwitching to pop-up window.") + driver.switch_to.window(this_window) + print(f"\tSwitched successfully to \"{driver.title}\".") + + except KeyboardInterrupt: + print("\n\tStopping bot.") + exit_sc = True + driver.quit() + return + + except: + print("\n\tBot encountered an error. Restarting.") + driver.quit() + return + + # to exit while loop + switch = True + break + + # for pop-up window click(s) + try: + # wait for approve button to be visible & click button + btn = WebDriverWait(driver, 30).until(ec.visibility_of_element_located((By.XPATH, "//*[contains(text(), 'Approve')]"))) + + # if button found then it'll be clicked + if btn: + print("\n\tFound \"Approve\" button!") + + # full page screenshot + # total_width = driver.execute_script("return document.body.offsetWidth") + # total_height = driver.execute_script("return document.body.scrollHeight") + # driver.set_window_size(total_width, total_height) + # driver.save_screenshot("sc_popup_approve.png") # image will be saved as "sc_popup_approve.png" in the bot's directory + + btn.click() + print("\tApproving transaction.") + mine_loop_count += 1 + + except KeyboardInterrupt: + print("\n\tStopping bot.") + exit_sc = True + driver.quit() + return + + except: + try: + # wait for cancel button to be visible & click button + btn_can = WebDriverWait(driver, 5).until(ec.visibility_of_element_located((By.XPATH, "//*[contains(text(), 'Cancel')]"))) - # if approve button is found - if btn: - print('\tFound Approve button.') - btn.click() - print('\tApproving transaction.') + # if cancel button found then it'll be clicked + if btn_can: + print("\n\tFound \"Cancel\" button!") - # if approve button could not be found - else: - raise IOError('\tUnable to load or find approve button.') + # full page screenshot + # total_width = driver.execute_script("return document.body.offsetWidth") + # total_height = driver.execute_script("return document.body.scrollHeight") + # driver.set_window_size(total_width, total_height) + # driver.save_screenshot("sc_popup_can.png") # image will be saved as "sc_popup_can.png" in the bot's directory + + btn_can.click() + print("\tCancelling transaction.") + + except KeyboardInterrupt: + print("\n\tStopping bot.") + exit_sc = True + driver.quit() + return + + except: + try: + # wait for login button to be visible + btn_login = WebDriverWait(driver, 5).until(ec.visibility_of_element_located((By.XPATH, "//*[contains(text(), 'Login')]"))) + + # if login button found then print message & restart + if btn_login: + # full page screenshot + # total_width = driver.execute_script("return document.body.offsetWidth") + # total_height = driver.execute_script("return document.body.scrollHeight") + # driver.set_window_size(total_width, total_height) + # driver.save_screenshot("sc_popup_login.png") # image will be saved as "sc_popup_login.png" in the bot's directory + + os.remove("sign.file") + print("\n\tRestarting bot.") + driver.quit() + return + + except KeyboardInterrupt: + print("\n\tStopping bot.") + exit_sc = True + driver.quit() + return + + except: + print('\n\tUnable to load or find button(s). Restarting.') + driver.quit() + return # go control back to main window - print('\tSwitching back to main window.\n') + print("\n\tSwitching back to main window.") driver.switch_to.window(main_window) + print(f"\tSwitched successfully to \"{driver.title}\".") + + try: + WebDriverWait(driver, 5).until(ec.visibility_of_element_located((By.XPATH, "//*[contains(text(), 'Nothing')]"))) + notification.notify(title = os.path.basename(path) + "\\" + os.path.basename(__file__), message = "Nothing to be mined!") + print("\n\tNothing to be mined!") + time.sleep(5) + + except KeyboardInterrupt: + print("\nStopping bot.") + exit_sc = True + driver.quit() + return + + except: + pass + + else: + continue + + # full page screenshot + # total_width = driver.execute_script("return document.body.offsetWidth") + # total_height = driver.execute_script("return document.body.scrollHeight") + # driver.set_window_size(total_width, total_height) + # driver.save_screenshot("sc_main.png") # image will be saved as "sc_main.png" in the bot's directory + + # show the number of loops done + print(f"\nTotal number of execution(s): {loop_count}") # show the number of loops done - print(f"Total runs: {loop_count}") + print(f"Total number of approval(s): {mine_loop_count}") + + i = True # delay the bot before starting next loop delay = random.randint(delay_min, delay_max) print(f"\nSleeping for {delay} seconds.") - time.sleep(delay) - print("\nDone sleeping.\n") + for x in range(delay): + time.sleep(1) + _print_(".") + print("Done sleeping.") except KeyboardInterrupt: - print('Stopping bot.') - break + print("\nStopping bot.") + exit_sc = True + driver.quit() + return - # if error occured + # if any error occured except: - crashes += 1 - print(f"Bot encountered an error. {crashes} Total crashes since start.") - # make GET request - driver.get(url) + print("\nBot encountered an error. Restarting.") + driver.quit() + return # close the webdriver driver.quit() - - -if __name__ == '__main__': - assert sys.version_info >= (3, 6), 'Python 3.6+ required.' - # call main routine - main() +while True: + assert sys.version_info >= (3, 6), "Python 3.6+ required." + try: + if not exit_sc: + # call main routine + main() + + else: + # notification for termination + notification.notify(title = os.path.basename(path) + "\\" + os.path.basename(__file__), message = "Script terminated.") + print("\nScript terminated.") + os._exit(0) + + except KeyboardInterrupt: + # notification for termination + notification.notify(title = os.path.basename(path) + "\\" + os.path.basename(__file__), message = "Script terminated.") + print("\nScript terminated.") + os._exit(0) + + except: + # notification for termination + notification.notify(title = os.path.basename(path) + "\\" + os.path.basename(__file__), message = "Script unable to restart.") + print("\nScript cannot be restarted due to an unknown error.") + os._exit(0) diff --git a/requirements.txt b/requirements.txt index a3feb2a..8ae7a29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,25 @@ -requests -selenium -lxml -selenium-stealth -webdriver-manager +async-generator==1.10 +attrs==21.4.0 +certifi==2022.5.18.1 +cffi==1.15.0 +charset-normalizer==2.0.12 +cryptography==37.0.2 +h11==0.13.0 +idna==3.3 +lxml==4.9.0 +outcome==1.1.0 +plyer==2.0.0 +pycparser==2.21 +pyOpenSSL==22.0.0 +PySocks==1.7.1 +python-dotenv==0.20.0 +requests==2.27.1 +selenium==4.2.0 +selenium-stealth==1.0.6 +sniffio==1.2.0 +sortedcontainers==2.4.0 +trio==0.21.0 +trio-websocket==0.9.2 +urllib3==1.26.9 +webdriver-manager==3.7.0 +wsproto==1.1.0 \ No newline at end of file