qwiklabs: use a server on localhost:12345 to manage new qw account requests
this allows to scale the automator using multiple instances of the script running separetely (e.g. in docker containers) but using a single server for accounts to prevent conficts between different instancesmaster
parent
b83e8449e3
commit
5fb1d0edde
|
@ -1,7 +1,7 @@
|
|||
import subprocess
|
||||
from utils import global_vars
|
||||
import time
|
||||
from qwiklabs import get_account
|
||||
from qwiklabs import get_google_account
|
||||
from shell import shell
|
||||
from shell.gists.gists import UserBot
|
||||
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
# There is a more efficient way of doing this, but i don't want to think about it rn
|
||||
import time
|
||||
import random
|
||||
# from qwiklabs import create_account, delete_account
|
||||
|
||||
class QL_AccountList():
|
||||
|
||||
def __init__(self, account_list):
|
||||
QL_AccountList.SUSPEND_TIME = 3600 #in seconds
|
||||
QL_AccountList.ACTION_WAIT_TIME = 1200 #in seconds
|
||||
|
||||
self.account_list = account_list
|
||||
self.suspended_list = {}
|
||||
self.to_delete = []
|
||||
self.last_action_time = time.time()
|
||||
self.last_action = 0 #0 added, 1 removed
|
||||
print("[QL_AccountList] New account list created! Using list from file: {} " .format(account_list))
|
||||
|
||||
def request_new_account(self):
|
||||
with open(self.account_list, 'r') as accounts:
|
||||
accounts_lines = []
|
||||
#needed to strip down of \n
|
||||
for line in accounts.readlines():
|
||||
accounts_lines.append(line.rstrip())
|
||||
|
||||
while True:
|
||||
account = accounts_lines[random.randint(0, len(accounts_lines)-1)]
|
||||
if self.is_account_valid(account):
|
||||
print("[QL_AccountList] A new account has been requested! choosen {}".format(account))
|
||||
|
||||
self.suspend_account(account)
|
||||
return account
|
||||
|
||||
def suspend_account(self, account):
|
||||
print("[QL_AccountList] Account {} will be suspended for the next {} seconds".format(account, QL_AccountList.SUSPEND_TIME))
|
||||
self.suspended_list[account] = int(time.time())
|
||||
|
||||
def is_account_suspended(self, account):
|
||||
return account in self.suspended_list.keys()
|
||||
|
||||
def is_account_valid(self, account):
|
||||
return (not self.is_account_suspended(account)) and (not account in self.to_delete)
|
||||
|
||||
def mark_account_for_deletition(self):
|
||||
print("[QL_AccountList] Account {} has been marked for deletition".format(account))
|
||||
self.to_delete.append(account)
|
||||
|
||||
def update_account_list(self):
|
||||
# Try to reintegrate suspended accounts
|
||||
to_delete = []
|
||||
for account in self.suspended_list.keys():
|
||||
if time.time() - self.suspended_list[account] > QL_AccountList.SUSPEND_TIME:
|
||||
to_delete.append(account)
|
||||
|
||||
for d in to_delete:
|
||||
del self.suspended_list[d]
|
||||
|
||||
# if time.time() - self.last_action_time > QL_AccountList.ACTION_WAIT_TIME:
|
||||
# # TODO: add the requesting of a proxy when doing these actions
|
||||
|
||||
# if last_action == 0:
|
||||
# # removed an account from the "to delete" lsit
|
||||
# delete_account.QL_DeleteAccount(False, to_delete[random.randint(0, len(to_delete)-1)])
|
||||
# else:
|
||||
# # otherwise create a new account
|
||||
# create_account.QL_CreateAccount(False)
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
''' 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()
|
|
@ -0,0 +1,13 @@
|
|||
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()
|
|
@ -0,0 +1,14 @@
|
|||
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
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1 @@
|
|||
06prgzamm96@esiix.com
|
|
@ -19,4 +19,4 @@ fi
|
|||
sleep 5
|
||||
|
||||
#Now start the actual bot, we're in a safe environment
|
||||
DISPLAY=:2 python src/qwiklabs/get_account.py $2
|
||||
DISPLAY=:2 python src/qwiklabs/get_google_account.py $2
|
|
@ -177,7 +177,7 @@ def get_google_account():
|
|||
|
||||
if global_vars.TEST_QWIKLABS_ACCOUNT is False:
|
||||
print("[QL_GetAccount] Using TEST Qwiklabs account to get it")
|
||||
account = global_vars.ql_list.request_new_account()
|
||||
account = socket_request_new_account()
|
||||
|
||||
subprocess.call(['bash','-c', "src/qwiklabs/get_account.sh {} {} ".format(str(global_vars.PROXY), account)])
|
||||
else:
|
||||
|
@ -207,44 +207,12 @@ def get_google_account():
|
|||
|
||||
return email, password, gshell_link, driver
|
||||
|
||||
# def get_google_account():
|
||||
# from utils import global_vars
|
||||
# import subprocess
|
||||
|
||||
# if not global_vars.TEST_ACCOUNT:
|
||||
# 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 == 'False' or 'False' in res:
|
||||
# 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")
|
||||
# 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")
|
||||
# return get_google_account()
|
||||
# else:
|
||||
# global_vars.account_list.mark_account_for_deletition(account)
|
||||
|
||||
# else:
|
||||
# res = tuple(res.rsplit())
|
||||
|
||||
# print("[QL_GetGAccount] {}".format(res))
|
||||
# return res
|
||||
|
||||
# else:
|
||||
# print("[QL_GetAccount] Using Test Account {}".format(global_vars.TEST_ACCOUNT) )
|
||||
# return global_vars.TEST_ACCOUNT
|
||||
|
||||
# Assumes the account server is already running on localhost:12345
|
||||
def socket_request_new_account():
|
||||
import socket
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(("localhost", 12345))
|
||||
s.send(b"givacc")
|
||||
account = s.recv(1024).decode("utf-8")
|
||||
s.close()
|
||||
return account
|
|
@ -8,7 +8,7 @@ Specs:
|
|||
'''
|
||||
# text.get_attribute("value") return the text content of a text field
|
||||
|
||||
from qwiklabs.get_account import get_google_account
|
||||
from qwiklabs.get_google_account import get_google_account
|
||||
from utils import global_vars, browser_manager
|
||||
|
||||
import random
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
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')
|
||||
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"
|
Loading…
Reference in New Issue