[SQUASHED] Use of Global Vars, fix bash scripts to properly use Xephyr
parent
68b0560e7d
commit
66d0617299
|
@ -1,4 +1,5 @@
|
||||||
__pycache__/
|
**/__pycache__/
|
||||||
chrome-profile/
|
chrome-profile/
|
||||||
misc/
|
misc/
|
||||||
chromedriver
|
chromedriver
|
||||||
|
bash-test.sh
|
|
@ -1,5 +1,3 @@
|
||||||
# '!' before an email address means it still needs to be activated. Password is 'hellogoodbye' when not specified
|
|
||||||
|
|
||||||
06prgzamm96@esiix.com
|
06prgzamm96@esiix.com
|
||||||
jhv8mtemi@esiix.com
|
jhv8mtemi@esiix.com
|
||||||
6bgfngq6@yoggm.com
|
6bgfngq6@yoggm.com
|
||||||
|
@ -7,13 +5,10 @@ fohxil@xojxe.com
|
||||||
b4d0o0y5pg@esiix.com
|
b4d0o0y5pg@esiix.com
|
||||||
i3z8qtab@xojxe.com
|
i3z8qtab@xojxe.com
|
||||||
l5wbup@1secmail.com
|
l5wbup@1secmail.com
|
||||||
|
ryysw0@1secmail.net
|
||||||
! ryysw0@1secmail.net
|
m5l7868ar@wwjmp.com
|
||||||
! m5l7868ar@wwjmp.com
|
ue8oqa0lf0j@1secmail.net
|
||||||
! m5i8g3@1secmail.com
|
17k2l9@1secmail.com
|
||||||
! ue8oqa0lf0j@1secmail.net
|
c5xm6j@1secmail.net
|
||||||
! 17k2l9@1secmail.com
|
mud0ud@esiix.com
|
||||||
! 08hyvaejbr@xojxe.com
|
t788egrvdp@wwjmp.com
|
||||||
! c5xm6j@1secmail.net
|
|
||||||
! mud0ud@esiix.com
|
|
||||||
! t788egrvdp@wwjmp.com
|
|
Binary file not shown.
|
@ -2,7 +2,9 @@ from utils import browser_manager
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
import time
|
import time
|
||||||
from threading import Thread
|
from threading import Thread, Event
|
||||||
|
|
||||||
|
from utils.global_vars import PROXY
|
||||||
|
|
||||||
class ColabGist(Thread):
|
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
|
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.url = url
|
||||||
self.account = account
|
self.account = account
|
||||||
self.minutes = minutes
|
self.minutes = minutes
|
||||||
self.backend = backend
|
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):
|
def run(self):
|
||||||
self.run_colab()
|
self.run_colab()
|
||||||
|
|
||||||
def run_colab(self):
|
def run_colab(self):
|
||||||
|
print("[ColabGist {}] Starting the gist".format(self.url))
|
||||||
self.start_browser()
|
self.start_browser()
|
||||||
self.start_session()
|
self.start_session()
|
||||||
|
|
||||||
def sign_in(self):
|
def sign_in(self):
|
||||||
|
print("[ColabGist {}] Signing in...".format(self.url))
|
||||||
|
|
||||||
try:
|
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
|
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")
|
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
|
# Run the desired Colab notebook. Logging into Google account by profile is mandatory
|
||||||
def start_session(self):
|
def start_session(self):
|
||||||
if not self.sign_in():
|
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.driver.quit()
|
||||||
self.run_colab()
|
self.run_colab()
|
||||||
return
|
return
|
||||||
|
|
||||||
self.driver.get(self.url)
|
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.CSS_SELECTOR, "#runtime-menu-button")
|
||||||
|
|
||||||
browser_manager.clickButton(self.driver, By.XPATH, '//*[@id=":24"]')
|
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")
|
browser_manager.clickButton(self.driver, By.CSS_SELECTOR, "#ok")
|
||||||
time.sleep(1.5)
|
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():
|
def terminate_session():
|
||||||
# Terminate the session
|
# Terminate the session
|
||||||
|
@ -125,8 +138,15 @@ class ColabGist(Thread):
|
||||||
time.sleep(60)
|
time.sleep(60)
|
||||||
|
|
||||||
def start_browser(self):
|
def start_browser(self):
|
||||||
self.driver=browser_manager.start_browser(self.proxy)
|
self.driver=browser_manager.start_browser()
|
||||||
|
|
||||||
def stop_browser(self):
|
def stop_browser(self):
|
||||||
# Close browser
|
# Close browser
|
||||||
self.driver.quit()
|
self.driver.quit()
|
||||||
|
|
||||||
|
def actual_quit(self):
|
||||||
|
self.terminate_session()
|
||||||
|
self.stop_browser()
|
||||||
|
|
||||||
|
def quit(self):
|
||||||
|
self.stop_event.set()
|
|
@ -9,8 +9,12 @@ pip install -r requirements.txt
|
||||||
|
|
||||||
#Start xephyr window
|
#Start xephyr window
|
||||||
Xephyr -br -ac -noreset -screen 1280x720 :1 &
|
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
|
# 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
|
#Now start the actual bot, we're in a safe environment
|
||||||
DISPLAY=:1 python get_account_from_qwiklabs.py
|
DISPLAY=:1 python src/main.py
|
13
src/main.py
13
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("[MAIN] Entering main script!")
|
||||||
print(ql_list.request_new_account())
|
|
||||||
|
|
||||||
|
p = proxy.Proxy()
|
||||||
while True:
|
while True:
|
||||||
ql_list.update_account_list()
|
p.request_new_proxy()
|
||||||
print(ql_list.suspended_list)
|
print(global_vars.PROXY)
|
||||||
|
|
||||||
|
time.sleep(30)
|
Binary file not shown.
|
@ -8,25 +8,9 @@ from selenium.webdriver.common.by import By
|
||||||
import time
|
import time
|
||||||
from colab import colab
|
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:
|
class Ngrok:
|
||||||
|
|
||||||
def __init__(self, account):
|
def __init__(self, account):
|
||||||
Ngrok.ACCOUNTS = [
|
|
||||||
('giangillo.rossi1@gmail.com', 'emamaker02')
|
|
||||||
('giangillo.rossi2@gmail.com', 'emamaker02')
|
|
||||||
]
|
|
||||||
self.account = account
|
self.account = account
|
||||||
|
|
||||||
def start_browser(self):
|
def start_browser(self):
|
||||||
|
|
Binary file not shown.
|
@ -1,7 +1,7 @@
|
||||||
# There is a more efficient way of doing this, but i don't want to think about it rn
|
# There is a more efficient way of doing this, but i don't want to think about it rn
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
from qwiklabs import create_account, delete_account
|
# from qwiklabs import create_account, delete_account
|
||||||
|
|
||||||
class QL_AccountList():
|
class QL_AccountList():
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ class QL_AccountList():
|
||||||
self.to_delete = []
|
self.to_delete = []
|
||||||
self.last_action_time = time.time()
|
self.last_action_time = time.time()
|
||||||
self.last_action = 0 #0 added, 1 removed
|
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):
|
def request_new_account(self):
|
||||||
with open(self.account_list, 'r') as accounts:
|
with open(self.account_list, 'r') as accounts:
|
||||||
|
@ -25,10 +26,13 @@ class QL_AccountList():
|
||||||
while True:
|
while True:
|
||||||
account = accounts_lines[random.randint(0, len(accounts_lines)-1)]
|
account = accounts_lines[random.randint(0, len(accounts_lines)-1)]
|
||||||
if self.is_account_valid(account):
|
if self.is_account_valid(account):
|
||||||
|
print("[QL_AccountList] A new account has been requested! choosen {}".format(account))
|
||||||
|
|
||||||
self.suspend_account(account)
|
self.suspend_account(account)
|
||||||
return account
|
return account
|
||||||
|
|
||||||
def suspend_account(self, 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())
|
self.suspended_list[account] = int(time.time())
|
||||||
|
|
||||||
def is_account_suspended(self, account):
|
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)
|
return (not self.is_account_suspended(account)) and (not account in self.to_delete)
|
||||||
|
|
||||||
def mark_account_for_deletition(self):
|
def mark_account_for_deletition(self):
|
||||||
|
print("[QL_AccountList] Account {} has been marked for deletition".format(account))
|
||||||
self.to_delete.append(account)
|
self.to_delete.append(account)
|
||||||
|
|
||||||
def update_account_list(self):
|
def update_account_list(self):
|
||||||
|
@ -50,13 +55,13 @@ class QL_AccountList():
|
||||||
for d in to_delete:
|
for d in to_delete:
|
||||||
del self.suspended_list[d]
|
del self.suspended_list[d]
|
||||||
|
|
||||||
if time.time() - self.last_action_time > QL_AccountList.ACTION_WAIT_TIME:
|
# if time.time() - self.last_action_time > QL_AccountList.ACTION_WAIT_TIME:
|
||||||
# TODO: add the requesting of a proxy when doing these actions
|
# # TODO: add the requesting of a proxy when doing these actions
|
||||||
|
|
||||||
if last_action == 0:
|
# if last_action == 0:
|
||||||
# removed an account from the "to delete" lsit
|
# # removed an account from the "to delete" lsit
|
||||||
delete_account.QL_DeleteAccount(False, to_delete[random.randint(0, len(to_delete)-1)])
|
# delete_account.QL_DeleteAccount(False, to_delete[random.randint(0, len(to_delete)-1)])
|
||||||
else:
|
# else:
|
||||||
# otherwise create a new account
|
# # otherwise create a new account
|
||||||
create_account.QL_CreateAccount(False)
|
# create_account.QL_CreateAccount(False)
|
||||||
|
|
||||||
|
|
|
@ -13,16 +13,15 @@ import pydub
|
||||||
import speech_recognition as sr
|
import speech_recognition as sr
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
from utils.global_vars import PROXY
|
||||||
|
|
||||||
class QL_CreateAccount:
|
class QL_CreateAccount:
|
||||||
def __init__(self, proxy=False):
|
|
||||||
self.proxy = proxy
|
|
||||||
|
|
||||||
def create_account(self):
|
def create_account(self):
|
||||||
self.info = RandomNameGenerator(self.proxy).get_person_info()
|
self.info = RandomNameGenerator(self.proxy).get_person_info()
|
||||||
|
|
||||||
self.driver = browser_manager.start_browser(self.proxy)
|
self.driver = browser_manager.start_browser()
|
||||||
self.temp_mail = TempMail(self.proxy)
|
self.temp_mail = TempMail()
|
||||||
|
|
||||||
self.temp_mail_address = self.temp_mail.get_new_temp_mail()
|
self.temp_mail_address = self.temp_mail.get_new_temp_mail()
|
||||||
|
|
||||||
|
@ -141,15 +140,14 @@ class QL_CreateAccount:
|
||||||
|
|
||||||
|
|
||||||
class RandomNameGenerator():
|
class RandomNameGenerator():
|
||||||
def __init__(self, proxy=False):
|
def __init__(self):
|
||||||
self.proxy = proxy
|
|
||||||
self.proxyDict = {
|
self.proxyDict = {
|
||||||
"socks" : proxy,
|
"socks" : PROXY,
|
||||||
"socksVersion" : 5
|
"socksVersion" : 5
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_person_info(self):
|
def get_person_info(self):
|
||||||
if self.proxy:
|
if PROXY:
|
||||||
r = requests.get('https://randomuser.me/api', proxies=self.proxyDict)
|
r = requests.get('https://randomuser.me/api', proxies=self.proxyDict)
|
||||||
else:
|
else:
|
||||||
r = requests.get('https://randomuser.me/api')
|
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
|
# get a temp mail from https://www.1secmail.com/api/ and handle it using requests
|
||||||
class TempMail:
|
class TempMail:
|
||||||
def __init__(self, proxy=False):
|
def __init__(self):
|
||||||
self.proxy = proxy
|
|
||||||
self.proxyDict = {
|
self.proxyDict = {
|
||||||
"socks" : proxy,
|
"socks" : PROXY,
|
||||||
"socksVersion" : 5
|
"socksVersion" : 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,11 @@ from selenium.webdriver.common.alert import Alert
|
||||||
from selenium.webdriver.common.alert import Command
|
from selenium.webdriver.common.alert import Command
|
||||||
|
|
||||||
class QL_DeleteAccount:
|
class QL_DeleteAccount:
|
||||||
def __init__(self, proxy, account):
|
def __init__(self, account):
|
||||||
self.proxy = proxy
|
|
||||||
self.account = account
|
self.account = account
|
||||||
|
|
||||||
def delete_account(self):
|
def delete_account(self):
|
||||||
self.driver = browser_manager.start_browser(self.proxy)
|
self.driver = browser_manager.start_browser()
|
||||||
self.sign_in()
|
self.sign_in()
|
||||||
self.delete()
|
self.delete()
|
||||||
|
|
||||||
|
|
|
@ -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
|
pyautogui.FAILSAFE = False
|
||||||
|
|
||||||
screenWidth, screenHeight = pyautogui.size()
|
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
|
# Head over to the course on qwiklabs.com
|
||||||
gui.Gui.chrome_gui.click_searchbar()
|
Gui.chrome_gui.click_searchbar()
|
||||||
pyautogui.write("qwiklabs.com")
|
pyautogui.write("qwiklabs.com")
|
||||||
pyautogui.press('/')
|
pyautogui.press('/')
|
||||||
pyautogui.write("focuses")
|
pyautogui.write("focuses")
|
||||||
|
@ -27,7 +69,7 @@ def get_account(account_list):
|
||||||
|
|
||||||
time.sleep(15)
|
time.sleep(15)
|
||||||
|
|
||||||
print("Signing in")
|
# print("[QL_GetGAccount] Signing in")
|
||||||
pyautogui.moveTo(0,0)
|
pyautogui.moveTo(0,0)
|
||||||
|
|
||||||
# Click join button
|
# Click join button
|
||||||
|
@ -38,7 +80,7 @@ def get_account(account_list):
|
||||||
# Move to the end of the page
|
# Move to the end of the page
|
||||||
pyautogui.press('pgdn')
|
pyautogui.press('pgdn')
|
||||||
|
|
||||||
print("Moving from sign up to sign in")
|
# print("Moving from sign up to sign in")
|
||||||
# switch to sign in button
|
# 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.moveTo(ui.qwiklabs_gui.SIGN_IN_BTN[0], ui.qwiklabs_gui.SIGN_IN_BTN[1], 3, pyautogui.easeOutQuad)
|
||||||
pyautogui.click(button='left')
|
pyautogui.click(button='left')
|
||||||
|
@ -49,15 +91,20 @@ def get_account(account_list):
|
||||||
pyautogui.click(button='left')
|
pyautogui.click(button='left')
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
print("Inserting credentials")
|
# print("[QL_GetGAccount] Inserting credentials")
|
||||||
# account; "mopopa1077@5sword.com", "hellogoodbye"
|
# account; "mopopa1077@5sword.com", "hellogoodbye"
|
||||||
# account = ("hemerey688@kibwot.com", "hellogoodbye")
|
# account = ("hemerey688@kibwot.com", "hellogoodbye")
|
||||||
account_email = account_list.request_new_account()
|
account_email = sys.argv[1]
|
||||||
account = (account_email, "hellogoodbye")
|
account = (account_email, "hellogoodbye")
|
||||||
username = account[0]
|
username = account[0]
|
||||||
password = account[1]
|
password = account[1]
|
||||||
|
|
||||||
|
try:
|
||||||
first_part = username.split('@')[0]
|
first_part = username.split('@')[0]
|
||||||
second_part = username.split('@')[1]
|
second_part = username.split('@')[1]
|
||||||
|
except:
|
||||||
|
print(False)
|
||||||
|
exit()
|
||||||
|
|
||||||
pyautogui.press('@')
|
pyautogui.press('@')
|
||||||
pyautogui.press('left')
|
pyautogui.press('left')
|
||||||
|
@ -73,7 +120,7 @@ def get_account(account_list):
|
||||||
|
|
||||||
# Start course
|
# Start course
|
||||||
time.sleep(5)
|
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.moveTo(ui.qwiklabs_gui.STARTLAB_BTN[0], ui.qwiklabs_gui.STARTLAB_BTN[1], 3, pyautogui.easeOutQuad)
|
||||||
pyautogui.click()
|
pyautogui.click()
|
||||||
|
|
||||||
|
@ -87,21 +134,58 @@ def get_account(account_list):
|
||||||
bashCommand = "copyq clipboard"
|
bashCommand = "copyq clipboard"
|
||||||
# Copy username to clipboard
|
# Copy username to clipboard
|
||||||
time.sleep(20)
|
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.moveTo(ui.qwiklabs_gui.EMAIL_COPY_BTN[0], ui.qwiklabs_gui.EMAIL_COPY_BTN[1], 3, pyautogui.easeOutQuad)
|
||||||
pyautogui.click()
|
pyautogui.click()
|
||||||
g_email = subprocess.check_output(['bash','-c', bashCommand]).decode('utf-8')
|
g_email = subprocess.check_output(['bash','-c', bashCommand]).decode('utf-8')
|
||||||
|
|
||||||
# Copy password to clipboard
|
# Copy password to clipboard
|
||||||
time.sleep(5)
|
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.moveTo(ui.qwiklabs_gui.PASSWORD_COPY_BTN[0], ui.qwiklabs_gui.PASSWORD_COPY_BTN[1], 3, pyautogui.easeOutQuad)
|
||||||
pyautogui.click()
|
pyautogui.click()
|
||||||
g_password = subprocess.check_output(['bash','-c', bashCommand]).decode('utf-8')
|
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
|
# 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 not '@' in g_email:
|
if '@' in g_email:
|
||||||
account_list.mark_account_for_deletition(account_email)
|
print(g_email, g_password)
|
||||||
return False
|
else:
|
||||||
|
# account_list.mark_account_for_deletition(account_email)
|
||||||
|
print(False)
|
||||||
|
|
||||||
return (g_email, g_password)
|
|
||||||
|
|
||||||
|
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
|
|
@ -1,18 +1,22 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
#Start xephyr window
|
d=":2"
|
||||||
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 &
|
|
||||||
|
|
||||||
# Clear chrome profile
|
# Clear chrome profile
|
||||||
rm -rf ./chrome-profile
|
rm -rf ./chrome-profile
|
||||||
|
DISPLAY=:2 kill -9 $(pidof /usr/bin/google-chrome-stable) > /dev/null 2> /dev/null
|
||||||
|
|
||||||
#Start chrome
|
#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
|
#Wait enough to let chrome start up
|
||||||
sleep 5
|
sleep 5
|
||||||
|
|
||||||
#Now start the actual bot, we're in a safe environment
|
#Now start the actual bot, we're in a safe environment
|
||||||
DISPLAY=:1 python get_account_from_qwiklabs.py
|
DISPLAY=$d python src/qwiklabs/get_account.py $2
|
Binary file not shown.
|
@ -14,6 +14,8 @@ import time
|
||||||
import random
|
import random
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from utils.global_vars import PROXY
|
||||||
|
|
||||||
def waitForElement(browser, by, selector, timeout=5, after_delay=0):
|
def waitForElement(browser, by, selector, timeout=5, after_delay=0):
|
||||||
try:
|
try:
|
||||||
return WebDriverWait(browser, timeout).until(EC.element_to_be_clickable((by, selector)))
|
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)
|
# shadowRoot = driver.execute_script('return arguments[0].shadowRoot.children', element)
|
||||||
# return shadowRoot
|
# return shadowRoot
|
||||||
|
|
||||||
def start_browser(headless=False, proxy=False):
|
def start_browser(headless=False):
|
||||||
# # change mac
|
# # change mac
|
||||||
# # run_as_sudo('macchanger -r wlp3s0')
|
# # 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('--enable-javascript') #enabling javascript is needed in order to not get recognized as a bot
|
||||||
# opts.add_argument("user-agent={}".format(user_agent))
|
# opts.add_argument("user-agent={}".format(user_agent))
|
||||||
if proxy is not False:
|
if PROXY is not False:
|
||||||
opts.add_argument(f'--proxy-server=socks5://'+proxy)
|
opts.add_argument(f'--proxy-server=socks5://'+PROXY)
|
||||||
|
|
||||||
#Fire up chromedriver
|
#Fire up chromedriver
|
||||||
chromedriver = webdriver.Chrome(options=opts)
|
chromedriver = webdriver.Chrome(options=opts)
|
||||||
|
|
|
@ -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')
|
|
@ -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]
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue