Automator: various bug&fixes

- disable access to QWAccountServer until it gets fixed
- Adapt hardcoded directories to docker-compose folder structure
- Rewrite PyAutoGUI bot to use absolute coordinates instead of relatives, and switch from chrome to firefox as it has less popus
- Simplify code in some parts (i.e shell access to google account, rewrite shell scripts)
- Change elements selectors and xpath to accomodate changes in the website
- Use Context Managers when using sockets
- Rewrite Docker scripts to use entrypoint and bind mounts
- Clear requirements from old, unneeded captcha stuff

This project is a mess, I know, I promise I will make better commits
master
EmaMaker 2022-01-21 19:11:20 +01:00
parent de3df999c8
commit 67429fa3bf
37 changed files with 166 additions and 199 deletions

View File

@ -1,11 +1,36 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM python:3.10-bullseye FROM ubuntu:20.04
WORKDIR .
COPY . .
#RUN pip3 install --upgrade pip
#RUN pip3 install -r requirements.txt
#CMD [ "./colab_automator.sh"] RUN useradd user -m -p hellogoodbye
#CMD ["python3", "-u", "main.py"]
CMD ["python3", "-u", "account_server_test.py"] WORKDIR /home/user/
COPY requirements.txt requirements.txt
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Rome
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get update -y
RUN apt-get install -y firefox nano net-tools tigervnc-standalone-server x11vnc xorg xserver-xephyr xterm xvfb python3 python3-pip wget unzip python3-tk python3-dev
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN apt-get install -y ./google-chrome-stable_current_amd64.deb
RUN wget https://chromedriver.storage.googleapis.com/97.0.4692.71/chromedriver_linux64.zip
RUN unzip chromedriver_linux64.zip
RUN chmod +x chromedriver
RUN mv chromedriver /usr/bin/
RUN wget https://github.com/mozilla/geckodriver/releases/download/v0.30.0/geckodriver-v0.30.0-linux64.tar.gz
RUN tar -xvzf geckodriver*
RUN chmod +x geckodriver
run mv geckodriver /usr/bin
USER user
RUN pip3 install --upgrade pip
RUN pip3 install -r requirements.txt
ENTRYPOINT ["/bin/bash", "/home/user/colab_automator.sh"]
#ENTRYPOINT ["ls", "-la", "/code"]

View File

@ -1,16 +0,0 @@
import socket
acc = ""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(("server", 12345))
s.send(b"givacc")
acc = s.recv(1024)
print(acc)
s.close()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(("server", 12345))
s.send(b"remacc|t788egrvdp@wwjmp.com")
print(s.recv(1024))
s.close()

View File

@ -0,0 +1,23 @@
#!/bin/bash
d=":1"
#Start chrome
#if [ $1 == "False" ]; then
echo "Starting the script now!"
#DISPLAY=:1 /usr/bin/google-chrome-stable --user-data-dir='./chrome-profile' --no-first-run --make-default-browser > /dev/null 2> /dev/null &
DISPLAY=:1 /usr/bin/firefox &
# 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=$d python3 /home/user/code/qwiklabs/get_google_account.py $2
# python3 /code/qwiklabs/get_google_account.py $2

View File

@ -1,43 +1,3 @@
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__": if __name__ == "__main__":
import time import time
import subprocess import subprocess
@ -46,16 +6,24 @@ if __name__ == "__main__":
import sys import sys
import requests import requests
JOIN_BTN = (564, 120)
SIGN_IN_BTN = (140, 360)
EMAIL_TEXTBOX = (340, 115)
STARTLAB_BTN = (110, 200)
CAPTCHA_BTN = (75, 255)
SEARCH_BAR = (385, 60)
# EMAIL_COPY_BTN = (0.3125, 0.7)
# PASSWORD_COPY_BTN = (0.3125, 0.82)
pyautogui.FAILSAFE = False pyautogui.FAILSAFE = False
screenWidth, screenHeight = pyautogui.size() pyautogui.moveTo(SEARCH_BAR[0], SEARCH_BAR[1])
ui = Gui(screenWidth, screenHeight) pyautogui.click()
pyautogui.keyDown('ctrl')
pyautogui.press('a')
pyautogui.keyUp('ctrl')
# print("[QL_GetGAccount] Screen is {} {}".format(screenWidth, screenHeight))
# print("[QL_GetGAccount] Accessing course on qwiklabs")
# Head over to the course on qwiklabs.com
Gui.chrome_gui.click_searchbar()
pyautogui.write("qwiklabs.com") pyautogui.write("qwiklabs.com")
pyautogui.press('/') pyautogui.press('/')
pyautogui.write("focuses") pyautogui.write("focuses")
@ -73,28 +41,26 @@ if __name__ == "__main__":
pyautogui.moveTo(0,0) pyautogui.moveTo(0,0)
# Click join button # Click join button
pyautogui.moveTo(ui.qwiklabs_gui.JOIN_BTN[0], ui.qwiklabs_gui.JOIN_BTN[1], 3, pyautogui.easeOutQuad) pyautogui.moveTo(JOIN_BTN[0], JOIN_BTN[1], 3, pyautogui.easeOutQuad)
pyautogui.click(button='left') pyautogui.click(button='left')
time.sleep(5) time.sleep(5)
# Move to the end of the page # Move to the end of the page
pyautogui.press('pgdn') 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(SIGN_IN_BTN[0], SIGN_IN_BTN[1], 3, pyautogui.easeOutQuad)
pyautogui.click(button='left') pyautogui.click(button='left')
time.sleep(5) time.sleep(5)
pyautogui.press('pgdn')
# switch to email textbox, the rest is done via kbd # switch to email textbox, the rest is done via kbd
pyautogui.moveTo(ui.qwiklabs_gui.EMAIL_TEXTBOX[0], ui.qwiklabs_gui.EMAIL_TEXTBOX[1], 3, pyautogui.easeOutQuad) pyautogui.moveTo(EMAIL_TEXTBOX[0], EMAIL_TEXTBOX[1], 3, pyautogui.easeOutQuad)
pyautogui.click(button='left') pyautogui.click(button='left')
time.sleep(2) time.sleep(2)
# print("[QL_GetGAccount] Inserting credentials")
# account; "mopopa1077@5sword.com", "hellogoodbye"
# account = ("hemerey688@kibwot.com", "hellogoodbye")
account_email = sys.argv[1] account_email = sys.argv[1]
account = (account_email, "hellogoodbye") account = (account_email, "hellogoodbye")
username = account[0] username = account[0]
@ -118,17 +84,16 @@ if __name__ == "__main__":
time.sleep(10) time.sleep(10)
# Start course # Start course
time.sleep(5) time.sleep(5)
# print("[QL_GetGAccount] 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(STARTLAB_BTN[0], STARTLAB_BTN[1], 3, pyautogui.easeOutQuad)
pyautogui.click() pyautogui.click()
# Accept captcha - sometimes they don't even ask for actual verification # Accept captcha - sometimes they don't even ask for actual verification
time.sleep(5) time.sleep(5)
# print("Accepting captcha (not needed really)") # print("Accepting captcha (not needed really)")
pyautogui.moveTo(ui.qwiklabs_gui.CAPTCHA_BTN[0], ui.qwiklabs_gui.CAPTCHA_BTN[1], 3, pyautogui.easeOutQuad) pyautogui.moveTo(CAPTCHA_BTN[0], CAPTCHA_BTN[1], 3, pyautogui.easeOutQuad)
pyautogui.click() pyautogui.click()
@ -139,14 +104,14 @@ if __name__ == "__main__":
# # 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(EMAIL_COPY_BTN[0], 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(PASSWORD_COPY_BTN[0], 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) # time.sleep(5)
@ -176,26 +141,44 @@ def get_google_account():
#TODO: Handle failure in getting the account #TODO: Handle failure in getting the account
if global_vars.TEST_QWIKLABS_ACCOUNT is False: if global_vars.TEST_QWIKLABS_ACCOUNT is False:
print("[QL_GetAccount] Using TEST Qwiklabs account to get it") print("[QL_GetAccount] Using Qwiklabs account to get it. Launching pyautogui bot to get a new qwiklabs account")
account = socket_request_new_account() account = socket_request_new_account()
print("[QL_GetAccount] Will use account", account)
subprocess.call(['bash','-c', "src/qwiklabs/get_account.sh {} {} ".format(str(global_vars.PROXY), account)]) subprocess.call(['bash','-c', "/home/user/code/qwiklabs/get_account.sh {} {} ".format(str(global_vars.PROXY), account)])
else: else:
print("[QL_GetAccount] Using Qwiklabs test account") print("[QL_GetAccount] Using Qwiklabs TEST account")
account = global_vars.TEST_QWIKLABS_ACCOUNT account = global_vars.TEST_QWIKLABS_ACCOUNT
driver = start_browser() driver = start_browser()
driver.get("https://www.qwiklabs.com/focuses/2794?catalog_rank=%7B%22rank%22%3A2%2C%22num_filters%22%3A0%2C%22has_search%22%3Atrue%7D&parent=catalog&search_id=12598152") driver.get("https://www.qwiklabs.com/focuses/2794?catalog_rank=%7B%22rank%22%3A2%2C%22num_filters%22%3A0%2C%22has_search%22%3Atrue%7D&parent=catalog&search_id=12598152")
time.sleep(5) time.sleep(5)
clickButton(driver, By.XPATH, '/html/body/div[1]/div[1]/ql-toolbar/div[2]/a[2]') #clickButton(driver, By.XPATH, '/html/body/div[1]/div[1]/ql-toolbar/div[2]/a[2]')
driver.get("https://www.qwiklabs.com/users/sign_in")
time.sleep(5) time.sleep(5)
inputText(driver, By.CSS_SELECTOR, "#user_email", account) inputText(driver, By.CSS_SELECTOR, "#user_email", account)
inputText(driver, By.CSS_SELECTOR, "#user_password", "hellogoodbye" + '\n') inputText(driver, By.CSS_SELECTOR, "#user_password", "hellogoodbye" + '\n')
time.sleep(5) time.sleep(5)
# in case undetected chromedriver will ever work
# driver.get("https://www.qwiklabs.com/focuses/2794?catalog_rank=%7B%22rank%22%3A2%2C%22num_filters%22%3A0%2C%22has_search%22%3Atrue%7D&parent=catalog&search_id=12598152")
# # uncover shadow DOM
# shadowRoot = browser_manager.expand_shadow_element(driver, driver.find_element_by_xpath("/html/body/main/div/ql-drawer-container/ql-drawer-content/ql-drawer-container/ql-drawer-content/ql-lab-control-panel"))
# # start lab
# shadowRoot[0].find_element_by_css_selector("#lab-control-button").click()
# # switch to captcha frame
# frame = driver.find_element_by_xpath("/html/body/main/div/ql-drawer-container/ql-drawer-content/ql-drawer-container/ql-drawer-content/ql-lab-control-panel/div/div/div/div/iframe")
# driver.switch_to.frame(frame)
# #click captcha, shouldn't need resolve with undetected chromedriver
# driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[1]/div/div/span/div[1]").click()
try:
panel = driver.find_element_by_xpath('/html/body/main/div/ql-drawer-container/ql-drawer-content/ql-drawer-container/ql-drawer-content/ql-lab-control-panel')
except:
panel = driver.find_element_by_xpath('/html/body/main/div/ql-drawer-container/ql-drawer-content/ql-drawer-container/ql-drawer[1]/ql-lab-control-panel') panel = driver.find_element_by_xpath('/html/body/main/div/ql-drawer-container/ql-drawer-content/ql-drawer-container/ql-drawer[1]/ql-lab-control-panel')
details = panel.get_attribute('labdetails') details = panel.get_attribute('labdetails')
details_json = json.loads(details) details_json = json.loads(details)
@ -211,7 +194,7 @@ def get_google_account():
def socket_request_new_account(): def socket_request_new_account():
import socket import socket
from utils import global_vars from utils import global_vars
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((global_vars.QWACCOUNTSERVER_HOSTNAME_DOCKER, 12345)) #ip s.connect((global_vars.QWACCOUNTSERVER_HOSTNAME_DOCKER, 12345)) #ip
s.send(b"givacc") s.send(b"givacc")
account = s.recv(1024).decode("utf-8") account = s.recv(1024).decode("utf-8")

View File

@ -0,0 +1,4 @@
.60. DEBIAN_FRONTEND=noninteractive sudo apt-get install -y xorg xserver-xephyr
.45. DEBIAN_FRONTEND=noninteractive sudo apt-get install -y firefox-esr tigervnc-standalone-server curlftpfs python3 python3-pip
# no view-only password
.2. clear

View File

@ -8,8 +8,8 @@ class UserBot (Gist):
def execute(self, shell): def execute(self, shell):
# prepare for userbot, without enabling ephimeral files will be there next reboot # prepare for userbot, without enabling ephimeral files will be there next reboot
shell.execute_script_from_local("./src/shell/gists/scripts/clear_homedir.sh") shell.execute_script_from_local("/home/user/code/shell/gists/scripts/clear_homedir.sh")
shell.execute_script_from_local("./src/shell/gists/scripts/prepare_environment_ubuntu.sh") shell.execute_script_from_local("/home/user/code/shell/gists/scripts/prepare_environment_ubuntu.sh")
i = 1 i = 1
@ -18,18 +18,18 @@ class UserBot (Gist):
i += 1 i += 1
#clean home dir, just in case #clean home dir, just in case
shell.execute_script_from_local("./src/shell/gists/scripts/clear_homedir.sh") shell.execute_script_from_local("/home/user/code/shell/gists/scripts/clear_homedir.sh")
#download bot #download bot
shell.execute_command("wget https://gist.githubusercontent.com/EmaMaker/86d49a9b6b2a66e6299ec4cd9fd8de12/raw/b26b9328a1ee06d34124eee86ff024ae92e0bbf8/userbot.py") shell.execute_command("wget https://gist.githubusercontent.com/EmaMaker/86d49a9b6b2a66e6299ec4cd9fd8de12/raw/b26b9328a1ee06d34124eee86ff024ae92e0bbf8/userbot.py")
#prepare python #prepare python
shell.execute_script_from_local("./src/shell/gists/scripts/prepare_python_environment.sh") shell.execute_script_from_local("/home/user/code/shell/gists/scripts/prepare_python_environment.sh")
#the userbot.py script is executing chromedriver in headless mode, so vnc isn't actually needed #the userbot.py script is executing chromedriver in headless mode, so vnc isn't actually needed
shell.execute_script_from_local("./src/shell/gists/scripts/start_vnc_server.sh") shell.execute_script_from_local("/home/user/code/shell/gists/scripts/start_vnc_server.sh")
# now execute userbot. Probably there will be some time between end of execution and start of reboot # now execute userbot. Probably there will be some time between end of execution and start of reboot
shell.execute_script_from_local("./src/shell/gists/scripts/userbot_script.sh") shell.execute_script_from_local("/home/user/code/shell/gists/scripts/userbot_script.sh")
# reboot the machine to get a clean one with a new ip and mac # reboot the machine to get a clean one with a new ip and mac
shell.reboot() shell.reboot()

View File

@ -37,26 +37,7 @@ class Shell():
print("[GCShell] No account was available, can't start!") print("[GCShell] No account was available, can't start!")
return return
# If using a test account, use the provided gsc link
if global_vars.TEST_ACCOUNT is False:
while (browser_manager.waitForElement(self.driver, By.XPATH, '/html/body/main/div/ql-drawer-container/ql-drawer-content/ql-drawer-container/ql-drawer[1]/ql-lab-control-panel') is False):
print("[GCShell] Page not ready, waiting...")
# get the shadow_dom element and click it
panel = self.driver.find_element_by_xpath('/html/body/main/div/ql-drawer-container/ql-drawer-content/ql-drawer-container/ql-drawer[1]/ql-lab-control-panel')
shadow1 = browser_manager.expand_shadow_element(self.driver, panel)
open_shell = shadow1.find_element_by_css_selector('div:nth-child(2) > div > ql-button')
print("[GCShell] Opening shell")
open_shell.click()
time.sleep(5)
# Now switch to the second tab
self.driver.switch_to.window(self.driver.window_handles[1]) #apparently clicking in selenium doesn't switch window
else:
print("[GCShell] Using Google Test Account")
self.driver.get(self.gcs_link) self.driver.get(self.gcs_link)
time.sleep(5) time.sleep(5)
oldPage = False oldPage = False
@ -102,6 +83,11 @@ class Shell():
time.sleep(5) time.sleep(5)
# Bypass "OHNOES! :( Your ancient browser broke our internetz. Want to see how bad?"
browser_manager.clickButton(self.driver, By.CSS_SELECTOR, '#bypassBtn')
time.sleep(10)
# Now we are in GCP. We need to accept some stuff (country, terms of use) # Now we are in GCP. We need to accept some stuff (country, terms of use)
# The form accepts keyboard input and anticipates it proposing a country. Make up a random string, send it. It will be out country # The form accepts keyboard input and anticipates it proposing a country. Make up a random string, send it. It will be out country
@ -115,7 +101,8 @@ class Shell():
#country += '\n' #country += '\n'
# print(country) # print(country)
browser_manager.inputText(self.driver, By.XPATH, '/html/body/div[3]/div[3]/div/mat-dialog-container/xap-deferred-loader-outlet/ng-component/mat-dialog-content/form/cfc-tos-checkboxes/form/div[1]/cfc-loader/div/mat-form-field/div/div[1]/div[3]/ace-select', country, interval=0, after_delay=2) #browser_manager.inputText(self.driver, By.XPATH, '/html/body/div[3]/div[3]/div/mat-dialog-container/xap-deferred-loader-outlet/ng-component/mat-dialog-content/form/cfc-tos-checkboxes/form/div[1]/cfc-loader/div/mat-form-field/div/div[1]/div[3]/ace-select', country, interval=0, after_delay=2)
browser_manager.inputText(self.driver, By.CSS_SELECTOR, '#cfc-select-0', country, interval=0, after_delay=2)
#accept terms of use #accept terms of use
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[3]/div[3]/div/mat-dialog-container/xap-deferred-loader-outlet/ng-component/mat-dialog-content/form/cfc-tos-checkboxes/form/div[2]/mat-checkbox/label/span[1]') browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[3]/div[3]/div/mat-dialog-container/xap-deferred-loader-outlet/ng-component/mat-dialog-content/form/cfc-tos-checkboxes/form/div[2]/mat-checkbox/label/span[1]')

View File

@ -1,6 +1,6 @@
# from sudo import run_as_sudo # from sudo import run_as_sudo
import undetected_chromedriver as uc #import undetected_chromedriver as uc
uc.install() #uc.install()
from selenium import webdriver from selenium import webdriver
@ -62,15 +62,15 @@ def select_shadow_element_by_css_selector(browser, selector):
return element return element
# Another lifesaver: https://stackoverflow.com/questions/37384458/how-to-handle-elements-inside-shadow-dom-from-selenium # Another lifesaver: https://stackoverflow.com/questions/37384458/how-to-handle-elements-inside-shadow-dom-from-selenium
def expand_shadow_element(driver, element): # def expand_shadow_element(driver, element):
shadow_root = driver.execute_script('return arguments[0].shadowRoot', element) # shadow_root = driver.execute_script('return arguments[0].shadowRoot', element)
return shadow_root # return shadow_root
# This variant works on firefox https://stackoverflow.com/questions/67133483/accessing-shadowroot-via-selenium-in-firefox-returns-javascriptexception-cyclic # This variant works on firefox https://stackoverflow.com/questions/67133483/accessing-shadowroot-via-selenium-in-firefox-returns-javascriptexception-cyclic
# def expand_shadow_element(driver, element): def expand_shadow_element(driver, element):
# # return a list of elements # return a list of elements
# 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): def start_browser(headless=False):
# # change mac # # change mac
@ -83,6 +83,7 @@ def start_browser(headless=False):
if headless is True: if headless is True:
opts.headless = True opts.headless = True
opts.add_argument('--no-sandbox')
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
user_agent = random_user_agent() user_agent = random_user_agent()
opts.add_argument("user-agent={}".format(user_agent)) opts.add_argument("user-agent={}".format(user_agent))
@ -92,7 +93,7 @@ def start_browser(headless=False):
print("[Browser_Manager] Starting new browser. Proxy: {} | UserAgent {}".format(PROXY, user_agent)) print("[Browser_Manager] Starting new browser. Proxy: {} | UserAgent {}".format(PROXY, user_agent))
#Fire up chromedriver #Fire up chromedriver
chromedriver = webdriver.Chrome(executable_path='./chromedriver', options=opts) chromedriver = webdriver.Chrome(options=opts)
time.sleep(3) time.sleep(3)
return chromedriver return chromedriver

View File

@ -0,0 +1,12 @@
PROXY = False
TEST_ACCOUNT = False
# email, password, gcloud shell link
TEST_ACCOUNT = ('student-00-b4498c222118@qwiklabs.net', '6SEjFzM6UN9V', 'https://accounts.google.com/AddSession?service=accountsettings&sarp=1&continue=https%3A%2F%2Fconsole.cloud.google.com%2Fhome%2Fdashboard%3Fproject%3Dqwiklabs-gcp-00-9cd596adba87#Email=student-00-b4498c222118@qwiklabs.net')
TEST_QWIKLABS_ACCOUNT = False
TEST_QWIKLABS_ACCOUNT = "l5wbup@1secmail.com"
QWACCOUNTSERVER_HOSTNAME_DOCKER = "server" #using hostname, much simpler
FILES_BASE_DIR="/home/user"

View File

@ -1,29 +1,13 @@
#!/bin/bash #!/bin/bash
# kill -9 $(pidof python) Xvfb -screen 0 1280x720x16 -ac &
source venv/bin/activate #switch to virtual env
# install and update requirements
pip install -r requirements.txt > /dev/null 2> /dev/null
#Start xephyr window
echo "[*] Starting Xephyr on :1"
Xephyr -br -ac -noreset -screen 1280x720 :1 > /dev/null 2> /dev/null &
sleep 5 sleep 5
echo "[*] Starting Xephyr on :2, contained inside :1" env DISPLAY=:0.0 x11vnc -noxrecord -noxfixes -noxdamage -forever -display :0 > /dev/null 2> /dev/null &
DISPLAY=:1 Xephyr -br -ac -noreset -screen 800x600 :2 > /dev/null 2> /dev/null&
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
#echo "[*] Starting copyq server on :2"
#DISPLAY=:2 copyq > /dev/null 2> /dev/null&
#set the kbd layout to the same of :0, otherwise sometimes we get mismatched letters touch /home/user/.Xauthority
#setxkbmap -display :0 -print | xkbcomp - :1 > /dev/null 2> /dev/null& DISPLAY=:0 Xephyr -screen 800x600 :1 &
# xkbcomp :0 :1
# xkbcomp :0 :2
sleep 2 sleep 2
echo "[*] Now starting the actual script" echo "[*] Now starting the actual script"
#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 src/main.py DISPLAY=:0 python3 -u /home/user/code/main.py

View File

@ -1,12 +1,13 @@
services: services:
bot: bot:
container_name: bot
build: . build: .
volumes: volumes:
- ./code:/code - ./code:/home/user/code
- ./account_data:/account_data - ./colab_automator.sh:/home/user/colab_automator.sh
networks: environment:
- qwaccountserver_default - DISPLAY=1
- TZ=Europe/Rome
networks: ports:
qwaccountserver_default: - "5900:5900"
external: true - "5901:5901"

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,22 +0,0 @@
#!/bin/bash
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
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=:2 python src/qwiklabs/get_google_account.py $2

View File

@ -1,6 +1,6 @@
pyautogui pyautogui
requests requests
undetected-chromedriver #undetected-chromedriver
selenium==3.141.0 selenium==3.141.0
urllib3==1.26.5 urllib3==1.26.5
SpeechRecognition==3.8.1 SpeechRecognition==3.8.1

Binary file not shown.

View File

@ -1,8 +0,0 @@
.30. sudo apt-get install -y xorg xserver-xephyr
.2.8
.30.41
.30.51
.30.1
.45. sudo apt-get install -y firefox-esr tigervnc-standalone-server curlftpfs python3 python3-pip
# no view-only password
.2. clear

Binary file not shown.

2
Automator/start.sh Normal file → Executable file
View File

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/bash
#sudo docker compose up #sudo docker compose up
sudo docker compose up --build --scale 1 sudo docker compose up --build

Binary file not shown.

View File

@ -1,7 +0,0 @@
PROXY = False
TEST_ACCOUNT = False
# email, password, gcloud shell link
# TEST_ACCOUNT = ('student-01-474fc01a4ea5@qwiklabs.net', 'PkR9NJR4ms5D', 'https://accounts.google.com/AddSession?service=accountsettings&sarp=1&continue=https%3A%2F%2Fconsole.cloud.google.com%2Fhome%2Fdashboard%3Fproject%3Dqwiklabs-gcp-03-676b378e29e0#Email=student-01-474fc01a4ea5@qwiklabs.net')
TEST_QWIKLABS_ACCOUNT = False
# TEST_QWIKLABS_ACCOUNT = "i3z8qtab@xojxe.com"
QWACCOUNTSERVER_HOSTNAME_DOCKER = "server" #using hostname, much simpler

Binary file not shown.