diff --git a/.gitignore b/.gitignore index 92f5ffe..e9f213e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -__pycache__/ +**/__pycache__/ chrome-profile/ misc/ -chromedriver \ No newline at end of file +chromedriver +bash-test.sh \ No newline at end of file diff --git a/misc/qwiklabs_accounts.txt b/misc/qwiklabs_accounts.txt index 97f8427..a35c4f5 100644 --- a/misc/qwiklabs_accounts.txt +++ b/misc/qwiklabs_accounts.txt @@ -1,5 +1,3 @@ -# '!' before an email address means it still needs to be activated. Password is 'hellogoodbye' when not specified - 06prgzamm96@esiix.com jhv8mtemi@esiix.com 6bgfngq6@yoggm.com @@ -7,13 +5,10 @@ fohxil@xojxe.com b4d0o0y5pg@esiix.com i3z8qtab@xojxe.com l5wbup@1secmail.com - -! ryysw0@1secmail.net -! m5l7868ar@wwjmp.com -! m5i8g3@1secmail.com -! ue8oqa0lf0j@1secmail.net -! 17k2l9@1secmail.com -! 08hyvaejbr@xojxe.com -! c5xm6j@1secmail.net -! mud0ud@esiix.com -! t788egrvdp@wwjmp.com \ No newline at end of file +ryysw0@1secmail.net +m5l7868ar@wwjmp.com +ue8oqa0lf0j@1secmail.net +17k2l9@1secmail.com +c5xm6j@1secmail.net +mud0ud@esiix.com +t788egrvdp@wwjmp.com \ No newline at end of file diff --git a/src/colab/__pycache__/colab.cpython-39.pyc b/src/colab/__pycache__/colab.cpython-39.pyc index 86a506a..46aa1bb 100644 Binary files a/src/colab/__pycache__/colab.cpython-39.pyc and b/src/colab/__pycache__/colab.cpython-39.pyc differ diff --git a/src/colab/colab.py b/src/colab/colab.py index 6fef432..a55bd0d 100644 --- a/src/colab/colab.py +++ b/src/colab/colab.py @@ -2,7 +2,9 @@ from utils import browser_manager from selenium import webdriver from selenium.webdriver.common.by import By import time -from threading import Thread +from threading import Thread, Event + +from utils.global_vars import PROXY class ColabGist(Thread): @@ -13,21 +15,27 @@ class ColabGist(Thread): For future-proofness each Gist is started in its own thread, this makes possible to run multiple gists in different threads at the same time ''' - def __init__(self, url, account, minutes=40, backend='N', proxy=False): + def __init__(self, url, account, minutes=5, backend='N'): self.url = url self.account = account self.minutes = minutes self.backend = backend - self.proxy = proxy + + self.refresh_event = Event() + self.stop_event = Event() + print("[ColabGist {}] New Colab Gist Thread created!".format(self.url)) def run(self): self.run_colab() def run_colab(self): + print("[ColabGist {}] Starting the gist".format(self.url)) self.start_browser() self.start_session() def sign_in(self): + print("[ColabGist {}] Signing in...".format(self.url)) + try: self.driver.get("https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&prompt=consent&response_type=code&client_id=407408718192.apps.googleusercontent.com&scope=email&access_type=offline&flowName=GeneralOAuthFlow") #need a fallback for when browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#identifierId", self.account[0] + "\n") @@ -48,13 +56,51 @@ class ColabGist(Thread): # Run the desired Colab notebook. Logging into Google account by profile is mandatory def start_session(self): if not self.sign_in(): - print("Got the old login screen, trying again") + print("[ColabGist {}] Got the old login screen, trying again".format(self.url)) self.driver.quit() self.run_colab() return self.driver.get(self.url) + self.start_gist() + # Leave the colab be for the specified time + starting = time.time() + print("[ColabGist {}] Executing the gist for the next {} minutes. Using Backend {}".format(self.url, self.minutes, self.backend) ) + while (int(time.time() - starting))/60 < self.minutes: + + if self.stop_event.is_set(): + self.actual_quit() + if self.refresh_event.is_set(): + self.start_gist() + + if(int(time.time() - starting > 15)): + try: + if self.driver.find_elements(By.XPATH, "//*[contains(text(),'No backend')]"): + print("[ColabGist {}] This account {} has been blocked :/ try again with another one".format(self.url, self.account)) + self.driver.quit() + elif self.driver.find_elements(By.XPATH, "//*[contains(text(),'Cannot connect')]"): + print("[ColabGist {}] No backend was available, maybe the service is overflooded or this account/computer is about to be blocked :(".format(self.url)) + self.driver.quit() + return + except Exception as e: + print(e) + + '''char = input() + if char == "t": + break + elif char == "g": + elapsed = time()-starting + elapsed_min = int(elapsed / 60) + elapsed_sec = int(elapsed % 60) + print("Elapsed time: {}m{}s".format(elapsed_min, elapsed_sec)) + else: + print("Unrecognized option")''' + + print("[ColabGist {}] Time's up! Closing the browser".format(self.url)) + self.actual_quit() + + def start_gist(self): browser_manager.clickButton(self.driver, By.CSS_SELECTOR, "#runtime-menu-button") browser_manager.clickButton(self.driver, By.XPATH, '//*[@id=":24"]') @@ -80,39 +126,6 @@ class ColabGist(Thread): browser_manager.clickButton(self.driver, By.CSS_SELECTOR, "#ok") time.sleep(1.5) - # need a fallback for then it can't connect to the backend - - # Leave the colab be for the specified time - starting = time.time() - print("Executing the gist for the next {} minutes. Using Backend {}".format(self.minutes, self.backend) ) - while (time.time() - starting)/60 < self.minutes: - if(time.time() - starting > 15): - try: - if self.driver.find_elements(By.XPATH, "//*[contains(text(),'No backend')]"): - print("This account has been blocked :/ try again with another one") - self.driver.quit() - elif self.driver.find_elements(By.XPATH, "//*[contains(text(),'Cannot connect')]"): - print("No backend was available, maybe the service is overflooded or this account/computer is about to be blocked :(") - self.driver.quit() - return - except Exception as e: - print(e) - - '''char = input() - if char == "t": - break - elif char == "g": - elapsed = time()-starting - elapsed_min = int(elapsed / 60) - elapsed_sec = int(elapsed % 60) - print("Elapsed time: {}m{}s".format(elapsed_min, elapsed_sec)) - else: - print("Unrecognized option")''' - - print("Time's up! Closing the browser") - - self.terminate_session() - self.stop_browser() def terminate_session(): # Terminate the session @@ -125,8 +138,15 @@ class ColabGist(Thread): time.sleep(60) def start_browser(self): - self.driver=browser_manager.start_browser(self.proxy) + self.driver=browser_manager.start_browser() def stop_browser(self): # Close browser - self.driver.quit() \ No newline at end of file + self.driver.quit() + + def actual_quit(self): + self.terminate_session() + self.stop_browser() + + def quit(self): + self.stop_event.set() \ No newline at end of file diff --git a/src/colab_automator.sh b/src/colab_automator.sh old mode 100644 new mode 100755 index 3a0c41e..400f212 --- a/src/colab_automator.sh +++ b/src/colab_automator.sh @@ -9,8 +9,12 @@ pip install -r requirements.txt #Start xephyr window Xephyr -br -ac -noreset -screen 1280x720 :1 & +sleep 5 +DISPLAY=:1 Xephyr -br -ac -noreset -screen 800x600 :2 & +sleep 5 # Start a copyq server, that will be used to copy the email and password of the obtained account from the clipboard of Xephyr -# DISPLAY=:1 copyq & +DISPLAY=:2 copyq & +sleep 2 #Now start the actual bot, we're in a safe environment -DISPLAY=:1 python get_account_from_qwiklabs.py \ No newline at end of file +DISPLAY=:1 python src/main.py \ No newline at end of file diff --git a/src/main.py b/src/main.py index f11fb59..730b007 100644 --- a/src/main.py +++ b/src/main.py @@ -1,8 +1,11 @@ -from qwiklabs import account_list +import subprocess +from utils import global_vars, proxy -ql_list = account_list.QL_AccountList('/home/emamaker/Documents/Projects/GColabAutomator/GColabAutomator-v2/src/qwiklabs_available_accounts.txt') -print(ql_list.request_new_account()) +print("[MAIN] Entering main script!") +p = proxy.Proxy() while True: - ql_list.update_account_list() - print(ql_list.suspended_list) \ No newline at end of file + p.request_new_proxy() + print(global_vars.PROXY) + + time.sleep(30) \ No newline at end of file diff --git a/src/ngrok/__pycache__/ngrok.cpython-39.pyc b/src/ngrok/__pycache__/ngrok.cpython-39.pyc index 45c03ad..252caee 100644 Binary files a/src/ngrok/__pycache__/ngrok.cpython-39.pyc and b/src/ngrok/__pycache__/ngrok.cpython-39.pyc differ diff --git a/src/ngrok/ngrok.py b/src/ngrok/ngrok.py index ee80f16..f0e26aa 100644 --- a/src/ngrok/ngrok.py +++ b/src/ngrok/ngrok.py @@ -8,25 +8,9 @@ from selenium.webdriver.common.by import By import time from colab import colab -# def start_proxy_get_ip(): -# c = colab.ColabGist('https://colab.research.google.com/gist/EmaMaker/4e1478c9913a2df58fc1b8ff422fa161/proxy.ipynb', , minutes=3) -# c.run() - -# time.sleep(120) - -# n = Ngrok() -# n.start_browser() -# n.access_ngrok() - -# return n.get_proxy_ip() - class Ngrok: def __init__(self, account): - Ngrok.ACCOUNTS = [ - ('giangillo.rossi1@gmail.com', 'emamaker02') - ('giangillo.rossi2@gmail.com', 'emamaker02') - ] self.account = account def start_browser(self): diff --git a/src/qwiklabs/__pycache__/account_list.cpython-39.pyc b/src/qwiklabs/__pycache__/account_list.cpython-39.pyc index 45f04ce..a57e13d 100644 Binary files a/src/qwiklabs/__pycache__/account_list.cpython-39.pyc and b/src/qwiklabs/__pycache__/account_list.cpython-39.pyc differ diff --git a/src/qwiklabs/account_list.py b/src/qwiklabs/account_list.py index 9a2fc69..6f14847 100644 --- a/src/qwiklabs/account_list.py +++ b/src/qwiklabs/account_list.py @@ -1,7 +1,7 @@ # There is a more efficient way of doing this, but i don't want to think about it rn import time import random -from qwiklabs import create_account, delete_account +# from qwiklabs import create_account, delete_account class QL_AccountList(): @@ -14,6 +14,7 @@ class QL_AccountList(): self.to_delete = [] self.last_action_time = time.time() self.last_action = 0 #0 added, 1 removed + print("[QL_AccountList] New account list created! Using list from file: {} " .format(account_list)) def request_new_account(self): with open(self.account_list, 'r') as accounts: @@ -25,10 +26,13 @@ class QL_AccountList(): while True: account = accounts_lines[random.randint(0, len(accounts_lines)-1)] if self.is_account_valid(account): + print("[QL_AccountList] A new account has been requested! choosen {}".format(account)) + self.suspend_account(account) return account def suspend_account(self, account): + print("[QL_AccountList] Account {} will be suspended for the next {} seconds".format(account, QL_AccountList.SUSPEND_TIME)) self.suspended_list[account] = int(time.time()) def is_account_suspended(self, account): @@ -38,6 +42,7 @@ class QL_AccountList(): return (not self.is_account_suspended(account)) and (not account in self.to_delete) def mark_account_for_deletition(self): + print("[QL_AccountList] Account {} has been marked for deletition".format(account)) self.to_delete.append(account) def update_account_list(self): @@ -50,13 +55,13 @@ class QL_AccountList(): for d in to_delete: del self.suspended_list[d] - if time.time() - self.last_action_time > QL_AccountList.ACTION_WAIT_TIME: - # TODO: add the requesting of a proxy when doing these actions + # if time.time() - self.last_action_time > QL_AccountList.ACTION_WAIT_TIME: + # # TODO: add the requesting of a proxy when doing these actions - if last_action == 0: - # removed an account from the "to delete" lsit - delete_account.QL_DeleteAccount(False, to_delete[random.randint(0, len(to_delete)-1)]) - else: - # otherwise create a new account - create_account.QL_CreateAccount(False) + # if last_action == 0: + # # removed an account from the "to delete" lsit + # delete_account.QL_DeleteAccount(False, to_delete[random.randint(0, len(to_delete)-1)]) + # else: + # # otherwise create a new account + # create_account.QL_CreateAccount(False) diff --git a/src/qwiklabs/create_account.py b/src/qwiklabs/create_account.py index a28b9b3..a1d1b9e 100644 --- a/src/qwiklabs/create_account.py +++ b/src/qwiklabs/create_account.py @@ -13,16 +13,15 @@ import pydub import speech_recognition as sr from bs4 import BeautifulSoup +from utils.global_vars import PROXY class QL_CreateAccount: - def __init__(self, proxy=False): - self.proxy = proxy def create_account(self): self.info = RandomNameGenerator(self.proxy).get_person_info() - self.driver = browser_manager.start_browser(self.proxy) - self.temp_mail = TempMail(self.proxy) + self.driver = browser_manager.start_browser() + self.temp_mail = TempMail() self.temp_mail_address = self.temp_mail.get_new_temp_mail() @@ -141,15 +140,14 @@ class QL_CreateAccount: class RandomNameGenerator(): - def __init__(self, proxy=False): - self.proxy = proxy + def __init__(self): self.proxyDict = { - "socks" : proxy, + "socks" : PROXY, "socksVersion" : 5 } def get_person_info(self): - if self.proxy: + if PROXY: r = requests.get('https://randomuser.me/api', proxies=self.proxyDict) else: r = requests.get('https://randomuser.me/api') @@ -162,10 +160,9 @@ class RandomNameGenerator(): # get a temp mail from https://www.1secmail.com/api/ and handle it using requests class TempMail: - def __init__(self, proxy=False): - self.proxy = proxy + def __init__(self): self.proxyDict = { - "socks" : proxy, + "socks" : PROXY, "socksVersion" : 5 } diff --git a/src/qwiklabs/delete_account.py b/src/qwiklabs/delete_account.py index ed12baa..b7c8cef 100644 --- a/src/qwiklabs/delete_account.py +++ b/src/qwiklabs/delete_account.py @@ -5,12 +5,11 @@ from selenium.webdriver.common.alert import Alert from selenium.webdriver.common.alert import Command class QL_DeleteAccount: - def __init__(self, proxy, account): - self.proxy = proxy + def __init__(self, account): self.account = account def delete_account(self): - self.driver = browser_manager.start_browser(self.proxy) + self.driver = browser_manager.start_browser() self.sign_in() self.delete() diff --git a/src/qwiklabs/get_account.py b/src/qwiklabs/get_account.py index e3f4145..1e6fe47 100644 --- a/src/qwiklabs/get_account.py +++ b/src/qwiklabs/get_account.py @@ -1,19 +1,61 @@ -import gui -import pyautogui -import time -import subprocess -def get_account(account_list): +class Gui: + def __init__(self, width, height): + Gui.chrome_gui = Chrome(width, height) + Gui.qwiklabs_gui = Qwiklabs(width, height) + +class Chrome(Gui): + SEARCH_BAR_PERCENTAGE = (0.5, 0.1) + + def __init__(self, width, height): + Chrome.SEARCH_BAR=width*Chrome.SEARCH_BAR_PERCENTAGE[0], height*Chrome.SEARCH_BAR_PERCENTAGE[1] + + def click_searchbar(self): + pyautogui.moveTo(Chrome.SEARCH_BAR[0], Chrome.SEARCH_BAR[1]) + pyautogui.click() + pyautogui.keyDown('ctrl') + pyautogui.press('a') + pyautogui.keyUp('ctrl') + + +class Qwiklabs(Gui): + JOIN_BTN_PERCENTAGE = (0.775, 0.183) + SIGN_IN_BTN_PERCENTAGE = (0.2125, 0.73) + EMAIL_TEXTBOX_PERCENTAGE = (0.5, 0.73) + COURSE_BTN_PERCENTAGE = (0.29, 0.45) + STARTLAB_BTN_PERCENTAGE = (0.125, 0.31) + CAPTCHA_BTN_PERCENTAGE = (0.075, 0.425) + EMAIL_COPY_BTN_PERCENTAGE = (0.3125, 0.7) + PASSWORD_COPY_BTN_PERCENTAGE = (0.3125, 0.82) + + def __init__(self, width, height): + Qwiklabs.JOIN_BTN=width*Qwiklabs.JOIN_BTN_PERCENTAGE[0], height*Qwiklabs.JOIN_BTN_PERCENTAGE[1] + Qwiklabs.SIGN_IN_BTN=width*Qwiklabs.SIGN_IN_BTN_PERCENTAGE[0], height*Qwiklabs.SIGN_IN_BTN_PERCENTAGE[1] + Qwiklabs.EMAIL_TEXTBOX=width*Qwiklabs.EMAIL_TEXTBOX_PERCENTAGE[0], height*Qwiklabs.EMAIL_TEXTBOX_PERCENTAGE[1] + Qwiklabs.COURSE_BTN=width*Qwiklabs.COURSE_BTN_PERCENTAGE[0], height*Qwiklabs.COURSE_BTN_PERCENTAGE[1] + Qwiklabs.STARTLAB_BTN=width*Qwiklabs.STARTLAB_BTN_PERCENTAGE[0], height*Qwiklabs.STARTLAB_BTN_PERCENTAGE[1] + Qwiklabs.CAPTCHA_BTN=width*Qwiklabs.CAPTCHA_BTN_PERCENTAGE[0], height*Qwiklabs.CAPTCHA_BTN_PERCENTAGE[1] + Qwiklabs.EMAIL_COPY_BTN=width*Qwiklabs.EMAIL_COPY_BTN_PERCENTAGE[0], height*Qwiklabs.EMAIL_COPY_BTN_PERCENTAGE[1] + Qwiklabs.PASSWORD_COPY_BTN=width*Qwiklabs.PASSWORD_COPY_BTN_PERCENTAGE[0], height*Qwiklabs.PASSWORD_COPY_BTN_PERCENTAGE[1] + +if __name__ == "__main__": + import time + import subprocess + import os + import pyautogui + import sys + import requests + pyautogui.FAILSAFE = False - + screenWidth, screenHeight = pyautogui.size() - ui = gui.Gui(screenWidth, screenHeight) + ui = Gui(screenWidth, screenHeight) - print("Screen is {} {}".format(screenWidth, screenHeight)) + # print("[QL_GetGAccount] Screen is {} {}".format(screenWidth, screenHeight)) - print("Accessing course on qwiklabs") + # print("[QL_GetGAccount] Accessing course on qwiklabs") # Head over to the course on qwiklabs.com - gui.Gui.chrome_gui.click_searchbar() + Gui.chrome_gui.click_searchbar() pyautogui.write("qwiklabs.com") pyautogui.press('/') pyautogui.write("focuses") @@ -27,7 +69,7 @@ def get_account(account_list): time.sleep(15) - print("Signing in") + # print("[QL_GetGAccount] Signing in") pyautogui.moveTo(0,0) # Click join button @@ -38,7 +80,7 @@ def get_account(account_list): # Move to the end of the page pyautogui.press('pgdn') - print("Moving from sign up to sign in") + # print("Moving from sign up to sign in") # switch to sign in button pyautogui.moveTo(ui.qwiklabs_gui.SIGN_IN_BTN[0], ui.qwiklabs_gui.SIGN_IN_BTN[1], 3, pyautogui.easeOutQuad) pyautogui.click(button='left') @@ -49,15 +91,20 @@ def get_account(account_list): pyautogui.click(button='left') time.sleep(2) - print("Inserting credentials") + # print("[QL_GetGAccount] Inserting credentials") # account; "mopopa1077@5sword.com", "hellogoodbye" # account = ("hemerey688@kibwot.com", "hellogoodbye") - account_email = account_list.request_new_account() + account_email = sys.argv[1] account = (account_email, "hellogoodbye") username = account[0] password = account[1] - first_part = username.split('@')[0] - second_part = username.split('@')[1] + + try: + first_part = username.split('@')[0] + second_part = username.split('@')[1] + except: + print(False) + exit() pyautogui.press('@') pyautogui.press('left') @@ -73,7 +120,7 @@ def get_account(account_list): # Start course time.sleep(5) - print("Starting the course") + # print("[QL_GetGAccount] Starting the course") pyautogui.moveTo(ui.qwiklabs_gui.STARTLAB_BTN[0], ui.qwiklabs_gui.STARTLAB_BTN[1], 3, pyautogui.easeOutQuad) pyautogui.click() @@ -87,21 +134,58 @@ def get_account(account_list): bashCommand = "copyq clipboard" # Copy username to clipboard time.sleep(20) - print("Copying email") + # print("Copying email") pyautogui.moveTo(ui.qwiklabs_gui.EMAIL_COPY_BTN[0], ui.qwiklabs_gui.EMAIL_COPY_BTN[1], 3, pyautogui.easeOutQuad) pyautogui.click() g_email = subprocess.check_output(['bash','-c', bashCommand]).decode('utf-8') # Copy password to clipboard time.sleep(5) - print("Copying password") + # print("Copying password") pyautogui.moveTo(ui.qwiklabs_gui.PASSWORD_COPY_BTN[0], ui.qwiklabs_gui.PASSWORD_COPY_BTN[1], 3, pyautogui.easeOutQuad) pyautogui.click() g_password = subprocess.check_output(['bash','-c', bashCommand]).decode('utf-8') + time.sleep(5) - # a possible way of finding out we haven't got the password, therefore the account was probably blocked - if not '@' in g_email: - account_list.mark_account_for_deletition(account_email) - return False + # a possible way of finding out we haven't got the password, therefore the account was probably blocked or there was a connection issue + if '@' in g_email: + print(g_email, g_password) + else: + # account_list.mark_account_for_deletition(account_email) + print(False) - return (g_email, g_password) \ No newline at end of file + + +def get_google_account(): + from utils import global_vars + import subprocess + + print("[QL_GetAccount] Getting new google account..." ) + account = global_vars.ql_list.request_new_account() + + res = subprocess.check_output(['bash','-c', "src/qwiklabs/get_account.sh {} {} ".format(str(global_vars.PROXY), account)]).decode('utf-8') + + if res is False: + res = bool(res) + # Maybe if we failed there was a connection issue, so ping qwiklabs.com to check + # If ping is successful the account is out of quota + + if global_vars.PROXY is False: + r = requests.get("https://qwiklabs.com", proxies=proxyDict) + else : + proxyDict = { + "socksVersion" : 5, + "socks" : global_vars.PROXY + } + + r = requests.get("https://qwiklabs.com", proxies=proxyDict) + + # ping was unsuccessful, delete the account + if r.stats_code == 200: + print("[QL_GetAccount] Something went wrong, trying again") + else: + ql_list.mark_account_for_deletition(account) + + + print("[QL_GetGAccount] {}".format(res)) + return res \ No newline at end of file diff --git a/src/qwiklabs/get_account.sh b/src/qwiklabs/get_account.sh index 9bf946d..53ccc3b 100755 --- a/src/qwiklabs/get_account.sh +++ b/src/qwiklabs/get_account.sh @@ -1,18 +1,22 @@ #!/bin/bash -#Start xephyr window -DISPLAY=:2 Xephyr -br -ac -noreset -screen 800x600 :2 & -# Start a copyq server, that will be used to copy the email and password of the obtained account from the clipboard of Xephyr -DISPLAY=:1 copyq & +d=":2" # Clear chrome profile rm -rf ./chrome-profile +DISPLAY=:2 kill -9 $(pidof /usr/bin/google-chrome-stable) > /dev/null 2> /dev/null #Start chrome -DISPLAY=:1 /usr/bin/google-chrome-stable --user-data-dir='./chrome-profile' --no-first-run & +if [ $1 == "False" ]; then + DISPLAY=$d /usr/bin/google-chrome-stable --user-data-dir='./chrome-profile' --no-first-run > /dev/null 2> /dev/null & + # echo "Starting chrome without proxy" +else + DISPLAY=$d /usr/bin/google-chrome-stable --user-data-dir='./chrome-profile' --no-first-run --proxy-server=socks5://$1 > /dev/null 2> /dev/null & + # echo "Starting chrome with proxy" +fi #Wait enough to let chrome start up sleep 5 #Now start the actual bot, we're in a safe environment -DISPLAY=:1 python get_account_from_qwiklabs.py \ No newline at end of file +DISPLAY=$d python src/qwiklabs/get_account.py $2 \ No newline at end of file diff --git a/src/utils/__pycache__/browser_manager.cpython-39.pyc b/src/utils/__pycache__/browser_manager.cpython-39.pyc index 257c40c..5f77960 100644 Binary files a/src/utils/__pycache__/browser_manager.cpython-39.pyc and b/src/utils/__pycache__/browser_manager.cpython-39.pyc differ diff --git a/src/utils/browser_manager.py b/src/utils/browser_manager.py index 83a579f..32f028e 100644 --- a/src/utils/browser_manager.py +++ b/src/utils/browser_manager.py @@ -14,6 +14,8 @@ import time import random import requests +from utils.global_vars import PROXY + def waitForElement(browser, by, selector, timeout=5, after_delay=0): try: return WebDriverWait(browser, timeout).until(EC.element_to_be_clickable((by, selector))) @@ -57,7 +59,7 @@ def expand_shadow_element(driver, element): # shadowRoot = driver.execute_script('return arguments[0].shadowRoot.children', element) # return shadowRoot -def start_browser(headless=False, proxy=False): +def start_browser(headless=False): # # change mac # # run_as_sudo('macchanger -r wlp3s0') @@ -70,8 +72,8 @@ def start_browser(headless=False, proxy=False): opts.add_argument('--enable-javascript') #enabling javascript is needed in order to not get recognized as a bot # opts.add_argument("user-agent={}".format(user_agent)) - if proxy is not False: - opts.add_argument(f'--proxy-server=socks5://'+proxy) + if PROXY is not False: + opts.add_argument(f'--proxy-server=socks5://'+PROXY) #Fire up chromedriver chromedriver = webdriver.Chrome(options=opts) diff --git a/src/utils/change_mac.sh b/src/utils/change_mac.sh old mode 100644 new mode 100755 diff --git a/src/utils/global_vars.py b/src/utils/global_vars.py new file mode 100644 index 0000000..9818afd --- /dev/null +++ b/src/utils/global_vars.py @@ -0,0 +1,4 @@ +from qwiklabs import account_list + +PROXY = False +ql_list = account_list.QL_AccountList('/home/emamaker/Documents/Projects/GColabAutomator/GColabAutomator-v2/src/qwiklabs_available_accounts.txt') \ No newline at end of file diff --git a/src/utils/gui.py b/src/utils/gui.py deleted file mode 100644 index 65614ed..0000000 --- a/src/utils/gui.py +++ /dev/null @@ -1,44 +0,0 @@ -''' -This classes holds the coordinates for all the elements that need to be clicked on the screen. -All the coordinates are kept as percentages of the screen resolution and are recalculated at runtime -''' -import pyautogui - -class Gui: - def __init__(self, width, height): - Gui.chrome_gui = Chrome(width, height) - Gui.qwiklabs_gui = Qwiklabs(width, height) - -class Chrome(Gui): - SEARCH_BAR_PERCENTAGE = (0.5, 0.1) - - def __init__(self, width, height): - Chrome.SEARCH_BAR=width*Chrome.SEARCH_BAR_PERCENTAGE[0], height*Chrome.SEARCH_BAR_PERCENTAGE[1] - - def click_searchbar(self): - pyautogui.moveTo(Chrome.SEARCH_BAR[0], Chrome.SEARCH_BAR[1]) - pyautogui.click() - pyautogui.keyDown('ctrl') - pyautogui.press('a') - pyautogui.keyUp('ctrl') - - -class Qwiklabs(Gui): - JOIN_BTN_PERCENTAGE = (0.775, 0.183) - SIGN_IN_BTN_PERCENTAGE = (0.2125, 0.73) - EMAIL_TEXTBOX_PERCENTAGE = (0.5, 0.73) - COURSE_BTN_PERCENTAGE = (0.29, 0.45) - STARTLAB_BTN_PERCENTAGE = (0.125, 0.31) - CAPTCHA_BTN_PERCENTAGE = (0.075, 0.425) - EMAIL_COPY_BTN_PERCENTAGE = (0.3125, 0.7) - PASSWORD_COPY_BTN_PERCENTAGE = (0.3125, 0.82) - - def __init__(self, width, height): - Qwiklabs.JOIN_BTN=width*Qwiklabs.JOIN_BTN_PERCENTAGE[0], height*Qwiklabs.JOIN_BTN_PERCENTAGE[1] - Qwiklabs.SIGN_IN_BTN=width*Qwiklabs.SIGN_IN_BTN_PERCENTAGE[0], height*Qwiklabs.SIGN_IN_BTN_PERCENTAGE[1] - Qwiklabs.EMAIL_TEXTBOX=width*Qwiklabs.EMAIL_TEXTBOX_PERCENTAGE[0], height*Qwiklabs.EMAIL_TEXTBOX_PERCENTAGE[1] - Qwiklabs.COURSE_BTN=width*Qwiklabs.COURSE_BTN_PERCENTAGE[0], height*Qwiklabs.COURSE_BTN_PERCENTAGE[1] - Qwiklabs.STARTLAB_BTN=width*Qwiklabs.STARTLAB_BTN_PERCENTAGE[0], height*Qwiklabs.STARTLAB_BTN_PERCENTAGE[1] - Qwiklabs.CAPTCHA_BTN=width*Qwiklabs.CAPTCHA_BTN_PERCENTAGE[0], height*Qwiklabs.CAPTCHA_BTN_PERCENTAGE[1] - Qwiklabs.EMAIL_COPY_BTN=width*Qwiklabs.EMAIL_COPY_BTN_PERCENTAGE[0], height*Qwiklabs.EMAIL_COPY_BTN_PERCENTAGE[1] - Qwiklabs.PASSWORD_COPY_BTN=width*Qwiklabs.PASSWORD_COPY_BTN_PERCENTAGE[0], height*Qwiklabs.PASSWORD_COPY_BTN_PERCENTAGE[1] diff --git a/src/utils/proxy.py b/src/utils/proxy.py new file mode 100644 index 0000000..e193dc1 --- /dev/null +++ b/src/utils/proxy.py @@ -0,0 +1,51 @@ +from ngrok import ngrok +from colab import colab +from colab.gists import Gists +from utils import global_vars +from qwiklabs import get_account + +import time + +class Proxy(): + def __init__(self): + Proxy.PROXY_COMBOS = [ + ( ('giangillo.rossi1@gmail.com', 'emamaker02'), Gists.PROXY1), + ( ('giangillo.rossi2@gmail.com', 'emamaker02'), Gists.PROXY2) + ] + Proxy.TIME_ELAPSED = 2400 #time that has to pass before changing account combo, in seconds + + self.account_combo_index = 0 + self.account_combo = Proxy.PROXY_COMBOS[self.account_combo_index] + self.last_time = time.time() + + self.start_new_proxy_session() + + def request_new_proxy(self): + print("[PROXY] A new proxy has been requested") + # then it's time to close the current gist+ngrok account and open another one + if time.time() - self.last_time > Proxy.TIME_ELAPSED: + print("[PROXY] Time for current account {} has expired".format(self.account_combo[0])) + self.ngrok.close_browser() + self.colab.quit() + + # it's not needed to manually close the colab session, just leave it decay on it's own + # but it's needed to close ngrok + self.account_combo_index = (self.account_combo_index+1) % len(Proxy.PROXY_COMBOS) + self.account_combo = Proxy.PROXY_COMBOS[self.account_combo_index] + print("[PROXY] Switching to new account {}".format(self.account_combo[1])) + + self.start_new_proxy_session() + else: + print("[PROXY] Refreshing existing proxy to get new ip") + #just refresh + self.colab.refresh_event.set() + + global_vars.PROXY = self.ngrok.get_proxy_ip() + print("[PROXY] Done! New proxy is: {} ".format(global_vars.PROXY)) + + def start_new_proxy_session(self): + self.colab = colab.ColabGist(self.account_combo[1], get_account.get_google_account()) + self.colab.run() #this launches a new thread + time.sleep(90) + + \ No newline at end of file