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 commitsmaster
parent
de3df999c8
commit
67429fa3bf
|
@ -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"]
|
|
@ -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()
|
|
|
@ -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
|
|
@ -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")
|
|
@ -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
|
|
@ -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()
|
|
@ -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]')
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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.
|
@ -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
|
|
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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.
Loading…
Reference in New Issue