automator: put inside own folder and convert to docker compose
parent
bef53a1d36
commit
de3df999c8
|
@ -0,0 +1,11 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM python:3.10-bullseye
|
||||
WORKDIR .
|
||||
COPY . .
|
||||
#RUN pip3 install --upgrade pip
|
||||
#RUN pip3 install -r requirements.txt
|
||||
|
||||
#CMD [ "./colab_automator.sh"]
|
||||
#CMD ["python3", "-u", "main.py"]
|
||||
CMD ["python3", "-u", "account_server_test.py"]
|
|
@ -0,0 +1,16 @@
|
|||
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,12 @@
|
|||
services:
|
||||
bot:
|
||||
build: .
|
||||
volumes:
|
||||
- ./code:/code
|
||||
- ./account_data:/account_data
|
||||
networks:
|
||||
- qwaccountserver_default
|
||||
|
||||
networks:
|
||||
qwaccountserver_default:
|
||||
external: true
|
|
@ -210,8 +210,9 @@ def get_google_account():
|
|||
# Assumes the account server is already running on localhost:12345
|
||||
def socket_request_new_account():
|
||||
import socket
|
||||
from utils import global_vars
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(("localhost", 12345))
|
||||
s.connect((global_vars.QWACCOUNTSERVER_HOSTNAME_DOCKER, 12345)) #ip
|
||||
s.send(b"givacc")
|
||||
account = s.recv(1024).decode("utf-8")
|
||||
s.close()
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
#sudo docker compose up
|
||||
sudo docker compose up --build --scale 1
|
|
@ -3,4 +3,5 @@ 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"
|
||||
# TEST_QWIKLABS_ACCOUNT = "i3z8qtab@xojxe.com"
|
||||
QWACCOUNTSERVER_HOSTNAME_DOCKER = "server" #using hostname, much simpler
|
BIN
chromedriver
BIN
chromedriver
Binary file not shown.
|
@ -1,14 +0,0 @@
|
|||
06prgzamm96@esiix.com
|
||||
jhv8mtemi@esiix.com
|
||||
6bgfngq6@yoggm.com
|
||||
fohxil@xojxe.com
|
||||
b4d0o0y5pg@esiix.com
|
||||
i3z8qtab@xojxe.com
|
||||
l5wbup@1secmail.com
|
||||
ryysw0@1secmail.net
|
||||
m5l7868ar@wwjmp.com
|
||||
ue8oqa0lf0j@1secmail.net
|
||||
17k2l9@1secmail.com
|
||||
c5xm6j@1secmail.net
|
||||
mud0ud@esiix.com
|
||||
t788egrvdp@wwjmp.com
|
Binary file not shown.
Binary file not shown.
|
@ -1,98 +0,0 @@
|
|||
''' This file needs to be run outside of the GShellAutomator script
|
||||
Starts a TCP server on localhost, to which GSA asks for accounts and reports problems
|
||||
Command list:
|
||||
givacc: Client is requesting a qwiklabs account to use. Take one from the available list and return it, then put it in the suspended list
|
||||
remacc: Client reported the account is not working anymore, and it needs to be delete (TODO: make this script test is the account is really unusable)
|
||||
'''
|
||||
|
||||
import time
|
||||
import json
|
||||
import socket
|
||||
import random
|
||||
import threading
|
||||
|
||||
from multiprocessing import Process, Manager
|
||||
|
||||
def handle_clients(available_list, suspended_dict, todelete_list):
|
||||
while True:
|
||||
(clientsocket, address) = socket.accept()
|
||||
command = clientsocket.recv(1024).decode("utf-8").split("|")
|
||||
|
||||
if command[0] != "":
|
||||
if command[0] == "givacc":
|
||||
account_valid = False
|
||||
while not account_valid:
|
||||
account = available_list[random.randint(0, len(available_list)-1)]
|
||||
if (not account in suspended_dict.keys() ) and (not account in todelete_list):
|
||||
account_valid = True
|
||||
suspended_dict[account] = time.time()
|
||||
|
||||
clientsocket.send(account.encode("utf-8"))
|
||||
|
||||
print("[AccountServer] Received a request for a new account, choose", account)
|
||||
|
||||
elif command[0] == "remacc":
|
||||
del suspended_dict[command[1]]
|
||||
todelete_list.append(command[1])
|
||||
clientsocket.close()
|
||||
|
||||
print("[AccountServer] Received a request to delete", account, "adding to list!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
socket.bind(("localhost", 12345))
|
||||
socket.listen(5)
|
||||
|
||||
with Manager() as manager:
|
||||
available = open('src/qwiklabs/account_server/qwiklabs_available_accounts.txt', 'r+')
|
||||
suspended = open('src/qwiklabs/account_server/qwiklabs_suspended.txt', 'r+')
|
||||
todelete = open('src/qwiklabs/account_server/qwiklabs_todelete.txt', 'r+')
|
||||
|
||||
# create the list from the files
|
||||
available_list = manager.list([line.strip() for line in available.readlines()])
|
||||
try:
|
||||
suspended_dict = manager.dict(json.loads(suspended.read()))
|
||||
except:
|
||||
suspended_dict = manager.dict({})
|
||||
|
||||
todelete_list = manager.list([line.strip() for line in todelete.readlines()])
|
||||
|
||||
p = Process(target=handle_clients, args=(available_list, suspended_dict, todelete_list))
|
||||
p.start()
|
||||
|
||||
last_update_time = time.time()
|
||||
while True:
|
||||
|
||||
tounsuspend = []
|
||||
for account in suspended_dict:
|
||||
if time.time()-suspended_dict[account] > 3600: #time is stored in seconds, so this is 3600 after an hour os first being suspened
|
||||
tounsuspend.append(account)
|
||||
print("Unsuspend", account, "as enough time as passed")
|
||||
|
||||
for account in tounsuspend:
|
||||
del suspended_dict[account]
|
||||
|
||||
#update list
|
||||
if time.time() - last_update_time > 5:
|
||||
last_update_time = time.time()
|
||||
#print("Cyclic update of files")
|
||||
|
||||
available = open('src/qwiklabs/account_server/qwiklabs_available_accounts.txt', 'r+')
|
||||
suspended = open('src/qwiklabs/account_server/qwiklabs_suspended.txt', 'r+')
|
||||
todelete = open('src/qwiklabs/account_server/qwiklabs_todelete.txt', 'r+')
|
||||
|
||||
#clear files, update with data loaded from the program
|
||||
available.truncate(0)
|
||||
suspended.truncate(0)
|
||||
todelete.truncate(0)
|
||||
|
||||
#put data in there
|
||||
available.writelines([(l + "\n") for l in available_list])
|
||||
suspended.write(json.dumps(dict(suspended_dict)))
|
||||
todelete.writelines([(l + "\n") for l in todelete_list])
|
||||
|
||||
#close files for it to take effect
|
||||
available.close()
|
||||
suspended.close()
|
||||
todelete.close()
|
|
@ -1,13 +0,0 @@
|
|||
import socket
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(("localhost", 12345))
|
||||
s.send(b"givacc")
|
||||
print(s.recv(1024))
|
||||
s.close()
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(("localhost", 12345))
|
||||
s.send(b"remacc|06prgzamm96@esiix.com")
|
||||
print(s.recv(1024))
|
||||
s.close()
|
|
@ -1,14 +0,0 @@
|
|||
06prgzamm96@esiix.com
|
||||
jhv8mtemi@esiix.com
|
||||
6bgfngq6@yoggm.com
|
||||
fohxil@xojxe.com
|
||||
b4d0o0y5pg@esiix.com
|
||||
i3z8qtab@xojxe.com
|
||||
l5wbup@1secmail.com
|
||||
ryysw0@1secmail.net
|
||||
m5l7868ar@wwjmp.com
|
||||
ue8oqa0lf0j@1secmail.net
|
||||
17k2l9@1secmail.com
|
||||
c5xm6j@1secmail.net
|
||||
mud0ud@esiix.com
|
||||
t788egrvdp@wwjmp.com
|
|
@ -1 +0,0 @@
|
|||
{}
|
|
@ -1 +0,0 @@
|
|||
06prgzamm96@esiix.com
|
|
@ -1,193 +0,0 @@
|
|||
from utils import browser_manager
|
||||
from selenium.webdriver.common.by import By
|
||||
import time
|
||||
from selenium.webdriver.common.alert import Alert, Command
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
import requests
|
||||
|
||||
import os
|
||||
import urllib
|
||||
|
||||
# recaptcha libraries
|
||||
import pydub
|
||||
import speech_recognition as sr
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from utils.global_vars import PROXY
|
||||
|
||||
class QL_CreateAccount:
|
||||
|
||||
def create_account(self):
|
||||
self.info = RandomNameGenerator(self.proxy).get_person_info()
|
||||
|
||||
self.driver = browser_manager.start_browser()
|
||||
self.temp_mail = TempMail()
|
||||
|
||||
self.temp_mail_address = self.temp_mail.get_new_temp_mail()
|
||||
|
||||
self.sign_up()
|
||||
self.accept_eula()
|
||||
|
||||
print("Account created!".format(self.info, self.temp_mail_address))
|
||||
|
||||
def sign_up(self):
|
||||
print("[+] Creating a new account for with mail [{}:{}]".format(self.info, self.temp_mail_address))
|
||||
|
||||
self.driver.get("https://www.qwiklabs.com/users/sign_up")
|
||||
time.sleep(1.5)
|
||||
|
||||
#accept goddamn cookies
|
||||
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[2]/div/button')
|
||||
time.sleep(2)
|
||||
|
||||
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_first_name", self.info[0], after_delay=1.5)
|
||||
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_last_name", self.info[1], after_delay=1.5)
|
||||
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_email", self.temp_mail_address, after_delay=1.5)
|
||||
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_company_name", self.info[2], after_delay=1.5)
|
||||
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_password", "hellogoodbye", after_delay=1.5)
|
||||
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_password_confirmation", "hellogoodbye", after_delay=1.5)
|
||||
time.sleep(10)
|
||||
|
||||
self.resolve_captcha('/html/body/div[1]/div[1]/div[2]/form[2]/div[8]/div/div/iframe', "recaptcha-checkbox", "/html/body/div[4]/div[4]", "recaptcha-audio-button")
|
||||
|
||||
time.sleep(5)
|
||||
self.driver.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/form[2]/div[9]/button').click()
|
||||
|
||||
def resolve_captcha(self, frame1_xpath, checkbox_classname, frame2_container_xpath, audio_id):
|
||||
# switch to recaptcha frame
|
||||
# frames = self.driver.find_elements_by_tag_name("iframe")
|
||||
# self.driver.switch_to.frame(frames[0])
|
||||
self.driver.switch_to.frame(self.driver.find_element_by_xpath(frame1_xpath))
|
||||
|
||||
browser_manager.delay(self.driver)
|
||||
|
||||
# click on checkbox to activate recaptcha
|
||||
self.driver.find_element_by_class_name(checkbox_classname).click()
|
||||
|
||||
# switch to recaptcha audio control frame
|
||||
self.driver.switch_to.default_content()
|
||||
frame2_container = browser_manager.waitForElement(self.driver, By.XPATH, frame2_container_xpath)
|
||||
|
||||
# Sometimes the captcha gets accepted right away
|
||||
if frame2_container is False:
|
||||
return
|
||||
|
||||
frames = frame2_container.find_elements_by_tag_name("iframe")
|
||||
self.driver.switch_to.frame(frames[0])
|
||||
browser_manager.delay(self.driver)
|
||||
|
||||
# click on audio challenge
|
||||
self.driver.find_element_by_id(audio_id).click()
|
||||
|
||||
# switch to recaptcha audio challenge frame
|
||||
self.driver.switch_to.default_content()
|
||||
frames = self.driver.find_elements_by_tag_name("iframe")
|
||||
self.driver.switch_to.frame(frames[-1])
|
||||
browser_manager.delay(self.driver)
|
||||
|
||||
# get the mp3 audio file
|
||||
src = self.driver.find_element_by_id("audio-source").get_attribute("src")
|
||||
print("[INFO] Audio src: %s" % src)
|
||||
|
||||
# download the mp3 audio file from the source
|
||||
urllib.request.urlretrieve(src, os.path.normpath(os.getcwd() + "\\sample.mp3"))
|
||||
browser_manager.delay(self.driver)
|
||||
|
||||
# load downloaded mp3 audio file as .wav
|
||||
try:
|
||||
sound = pydub.AudioSegment.from_mp3(os.path.normpath(os.getcwd() + "\\sample.mp3"))
|
||||
sound.export(os.path.normpath(os.getcwd() + "\\sample.wav"), format="wav")
|
||||
sample_audio = sr.AudioFile(os.path.normpath(os.getcwd() + "\\sample.wav"))
|
||||
except Exception:
|
||||
print("[ERR] Please run program as administrator or download ffmpeg manually, "
|
||||
"http://blog.gregzaal.com/how-to-install-ffmpeg-on-windows/")
|
||||
|
||||
# translate audio to text with google voice recognition
|
||||
r = sr.Recognizer()
|
||||
with sample_audio as source:
|
||||
audio = r.record(source)
|
||||
key = r.recognize_google(audio)
|
||||
print("[INFO] Recaptcha Passcode: %s" % key)
|
||||
|
||||
# key in results and submit
|
||||
self.driver.find_element_by_id("audio-response").send_keys(key.lower())
|
||||
self.driver.find_element_by_id("audio-response").send_keys(Keys.ENTER)
|
||||
self.driver.switch_to.default_content()
|
||||
browser_manager.delay(self.driver)
|
||||
# self.driver.find_element_by_id("recaptcha-verify-button").click()
|
||||
# browser_manager.delay(self.driver)
|
||||
|
||||
def accept_eula(self):
|
||||
self.driver.get(self.temp_mail.get_confirmation_link())
|
||||
|
||||
time.sleep(5)
|
||||
|
||||
#insert password
|
||||
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_password", "hellogoodbye", after_delay=1.5)
|
||||
browser_manager.clickButton(self.driver, By.XPATH, "/html/body/div[2]/div[1]/div[2]/form/div[4]/button")
|
||||
time.sleep(10)
|
||||
|
||||
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[2]/div/button')
|
||||
time.sleep(2)
|
||||
|
||||
self.resolve_captcha('/html/body/div[1]/form/div/div/div/div/div/iframe', "recaptcha-checkbox", "/html/body/div[4]/div[4]", "recaptcha-audio-button")
|
||||
time.sleep(5)
|
||||
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[1]/form/input[5]')
|
||||
|
||||
time.sleep(1000)
|
||||
|
||||
class RandomNameGenerator():
|
||||
def __init__(self):
|
||||
self.proxyDict = {
|
||||
"socks" : PROXY,
|
||||
"socksVersion" : 5
|
||||
}
|
||||
|
||||
def get_person_info(self):
|
||||
if PROXY:
|
||||
r = requests.get('https://randomuser.me/api', proxies=self.proxyDict)
|
||||
else:
|
||||
r = requests.get('https://randomuser.me/api')
|
||||
|
||||
firstname = r.json()['results'][0]['name']['first']
|
||||
lastname = r.json()['results'][0]['name']['last']
|
||||
#use city as company
|
||||
company = r.json()['results'][0]['location']['city']
|
||||
return (firstname, lastname, company)
|
||||
|
||||
# get a temp mail from https://www.1secmail.com/api/ and handle it using requests
|
||||
class TempMail:
|
||||
def __init__(self):
|
||||
self.proxyDict = {
|
||||
"socks" : PROXY,
|
||||
"socksVersion" : 5
|
||||
}
|
||||
|
||||
# Open a new tab, head over to temp-mail.org, click the delete button and get a new temp mail
|
||||
def get_new_temp_mail(self):
|
||||
self.email = requests.get('https://www.1secmail.com/api/v1/?action=genRandomMailbox', proxies=self.proxyDict).json()[0]
|
||||
return self.email
|
||||
|
||||
# Wait for qwiklabs confirmation email to arrive, click it
|
||||
def get_confirmation_link(self):
|
||||
arrived = False
|
||||
while arrived == False:
|
||||
print('Waiting for confirmation email')
|
||||
fetched_msg = requests.get('https://www.1secmail.com/api/v1/?action=getMessages&login=' + self.email.split('@')[0] + '&domain='+self.email.split('@')[1], proxies=self.proxyDict)
|
||||
arrived = fetched_msg.text != '[]'
|
||||
time.sleep(2)
|
||||
|
||||
print('Email arrived')
|
||||
msg_id = fetched_msg.json()[0]['id']
|
||||
email = requests.get('https://www.1secmail.com/api/v1/?action=readMessage&login=' + self.email.split('@')[0] + '&domain='+self.email.split('@')[1] + '&id=' + str(msg_id))
|
||||
body = email.json()['body']
|
||||
|
||||
soup = BeautifulSoup(body, 'html.parser')
|
||||
|
||||
a = ""
|
||||
for link in soup.find_all('a'):
|
||||
if 'confirmation' in link.get('href'):
|
||||
a = link.get('href')
|
||||
print("Here's the confirmation link " + a)
|
||||
|
||||
return a
|
|
@ -1,72 +0,0 @@
|
|||
from utils import browser_manager
|
||||
from selenium.webdriver.common.by import By
|
||||
import time
|
||||
from selenium.webdriver.common.alert import Alert
|
||||
from selenium.webdriver.common.alert import Command
|
||||
|
||||
class QL_DeleteAccount:
|
||||
def __init__(self, account):
|
||||
self.account = account
|
||||
|
||||
def delete_account(self):
|
||||
self.driver = browser_manager.start_browser()
|
||||
self.sign_in()
|
||||
self.delete()
|
||||
|
||||
def sign_in(self):
|
||||
print("[+] Signing in using account [{}:{}]".format(self.account[0], self.account[1]))
|
||||
|
||||
self.driver.get("https://www.qwiklabs.com/users/sign_in")
|
||||
time.sleep(1.5)
|
||||
|
||||
#accept goddamn cookies
|
||||
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[2]/div/button')
|
||||
time.sleep(2)
|
||||
|
||||
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_email", self.account[0])
|
||||
time.sleep(1.5)
|
||||
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_password", self.account[1])
|
||||
time.sleep(1.5)
|
||||
browser_manager.clickButton(self.driver, By.CSS_SELECTOR, "#new_user > div.form-actions > button")
|
||||
time.sleep(5)
|
||||
|
||||
def delete(self):
|
||||
|
||||
# Click on profile icon, it's under a shadow-dom element
|
||||
root1 = self.driver.find_element_by_css_selector("#my_account")
|
||||
shadow = browser_manager.expand_shadow_element(self.driver, root1)
|
||||
profile = shadow.find_element_by_css_selector('.ql-icon-button')
|
||||
profile.click()
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
# head over to settings
|
||||
settings = self.driver.find_element_by_css_selector('#settings')
|
||||
settings.click()
|
||||
time.sleep(2)
|
||||
|
||||
#accept goddamn cookies
|
||||
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[2]/div/button')
|
||||
time.sleep(2)
|
||||
|
||||
# select 'security' tab
|
||||
root1 = browser_manager.waitForElement(self.driver, By.XPATH, '/html/body/ql-drawer-container/ql-drawer/ql-sidenav/ql-sidenav-item[4]')
|
||||
shadow = browser_manager.expand_shadow_element(self.driver, root1)
|
||||
root1.click()
|
||||
time.sleep(2)
|
||||
|
||||
# button = shadow.find_element_by_css_selector('.sidenav-item')
|
||||
# button.click()
|
||||
|
||||
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/ql-drawer-container/ql-drawer-content/main/div[3]/div[2]/div/a')
|
||||
time.sleep(5)
|
||||
|
||||
#delete history
|
||||
browser_manager.clickButton(self.driver, By.CSS_SELECTOR, '#delete_account_history_are_you_sure > div > div > div > a:nth-child(2)')
|
||||
time.sleep(8)
|
||||
|
||||
# finally accept the deletition of the account
|
||||
al = self.driver.switch_to.alert
|
||||
al.accept()
|
||||
|
||||
print("Account {} deleted!".format(self.account))
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue