diff --git a/connect_test.py b/connect_test.py
new file mode 100644
index 0000000..38ac8ad
--- /dev/null
+++ b/connect_test.py
@@ -0,0 +1,11 @@
+from python_aternos import Client as AternosClient
+
+aternos = AternosClient('', password='')
+
+srvs = aternos.servers
+
+print(srvs)
+
+s = srvs[0]
+
+s.start()
diff --git a/python_aternos/atconnect.py b/python_aternos/atconnect.py
index 38cf54b..d349244 100644
--- a/python_aternos/atconnect.py
+++ b/python_aternos/atconnect.py
@@ -8,141 +8,187 @@ from typing import Optional, Union
from . import aterrors
+#TEST
+from py_mini_racer import MiniRacer
+import base64
+
+presettings = """
+let window = {1: null, 2: null, AJAX_TOKEN: null};
+let i = 1;
+function __log() { return {win_var: window["AJAX_TOKEN"], 1: window[1], 2: window[2]} };
+function atob(arg) {window[i++] = arg;};
+"""
+postsettings = """__log();"""
+
+
REQGET = 0
REQPOST = 1
REQUA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Goanna/4.8 Firefox/68.0 PaleMoon/29.4.0.2'
class AternosConnect:
- def __init__(self) -> None:
+ def __init__(self) -> None:
- pass
+ pass
- def parse_token(self, response:Optional[Union[str,bytes]]=None) -> str:
+ def parse_token(self, response:Optional[Union[str,bytes]]=None) -> str:
- if response == None:
- loginpage = self.request_cloudflare(
- f'https://aternos.org/go/', REQGET
- ).content
- pagetree = lxml.html.fromstring(loginpage)
- else:
- pagetree = lxml.html.fromstring(response)
+ if response == None:
+ loginpage = self.request_cloudflare(
+ f'https://aternos.org/go/', REQGET
+ ).content
+ pagetree = lxml.html.fromstring(loginpage)
+ else:
+ pagetree = lxml.html.fromstring(response)
- try:
- pagehead = pagetree.head
- self.token = re.search(
- r'const\s+AJAX_TOKEN\s*=\s*["\'](\w+)["\']',
- pagehead.text_content()
- )[1]
- except (IndexError, TypeError):
- raise aterrors.AternosCredentialsError(
- 'Unable to parse TOKEN from the page'
- )
+ try:
+ # fetch text
+ pagehead = pagetree.head
+ text = pagehead.text_content()
+ #print(text)
- return self.token
+ #search
+ token_js_func = text[
+ text.index("const COOKIE_PREFIX = \"ATERNOS\";") +
+ len("const COOKIE_PREFIX = \"ATERNOS\";") :
+ text.index("(function(i,s,o,g,r,a,m)")
+ ].strip()
+ print(token_js_func)
- def generate_sec(self) -> str:
- randkey = self.generate_aternos_rand()
- randval = self.generate_aternos_rand()
- self.sec = f'{randkey}:{randval}'
- self.session.cookies.set(
- f'ATERNOS_SEC_{randkey}', randval,
- domain='aternos.org'
- )
+ # run js
+ ctx = MiniRacer()
+ result = ctx.eval(presettings + token_js_func)
+ result = ctx.call('__log')
+
+ print(result)
+
+ if 'win_var' in result and result['win_var']:
+ result = result['win_var']
+ elif '1' in result and ('2' in result and not result['2']):
+ result = base64.standard_b64decode(result['1'])
+ else:
+ result = base64.standard_b64decode(result['2'])
- return self.sec
- def generate_aternos_rand(self, randlen:int=16) -> str:
+ print(result)
+ self.token = result
+
+ """
+ self.token = re.search(
+ r'const\s+AJAX_TOKEN\s*=\s*["\'](\w+)["\']',
+ text
+ )[1]
+ """
+ except (IndexError, TypeError):
+ raise aterrors.AternosCredentialsError(
+ 'Unable to parse TOKEN from the page'
+ )
- rand_arr = []
- for i in range(randlen+1):
- rand_arr.append('')
+ return self.token
- rand_alphanum = \
- self.convert_num(random.random(),36) + \
- '00000000000000000'
- return (rand_alphanum[2:18].join(rand_arr)[:randlen])
+ def generate_sec(self) -> str:
- def convert_num(self, num:Union[int,float], base:int) -> str:
+ randkey = self.generate_aternos_rand()
+ randval = self.generate_aternos_rand()
+ self.sec = f'{randkey}:{randval}'
+ self.session.cookies.set(
+ f'ATERNOS_SEC_{randkey}', randval,
+ domain='aternos.org'
+ )
- result = ''
- while num > 0:
- result = str(num % base) + result
- num //= base
- return result
+ return self.sec
- def request_cloudflare(
- self, url:str, method:int,
- retries:int=10,
- params:Optional[dict]=None,
- data:Optional[dict]=None,
- headers:Optional[dict]=None,
- reqcookies:Optional[dict]=None,
- sendtoken:bool=False) -> Response:
+ def generate_aternos_rand(self, randlen:int=16) -> str:
- cftitle = '
Please Wait... | Cloudflare'
+ rand_arr = []
+ for i in range(randlen+1):
+ rand_arr.append('')
- if sendtoken:
- if params == None:
- params = {}
- params['SEC'] = self.sec
- params['TOKEN'] = self.token
+ rand_alphanum = \
+ self.convert_num(random.random(),36) + \
+ '00000000000000000'
+ return (rand_alphanum[2:18].join(rand_arr)[:randlen])
- if headers == None:
- headers = {}
- headers['User-Agent'] = REQUA
+ def convert_num(self, num:Union[int,float], base:int) -> str:
- try:
- cookies = self.session.cookies
- except AttributeError:
- cookies = None
+ result = ''
+ while num > 0:
+ result = str(num % base) + result
+ num //= base
+ return result
- self.session = CloudScraper()
- if cookies != None:
- self.session.cookies = cookies
+ def request_cloudflare(
+ self, url:str, method:int,
+ retries:int=10,
+ params:Optional[dict]=None,
+ data:Optional[dict]=None,
+ headers:Optional[dict]=None,
+ reqcookies:Optional[dict]=None,
+ sendtoken:bool=False) -> Response:
- if method == REQPOST:
- req = self.session.post(
- url,
- data=data,
- headers=headers,
- cookies=reqcookies
- )
- else:
- req = self.session.get(
- url,
- params=params,
- headers=headers,
- cookies=reqcookies
- )
+ cftitle = 'Please Wait... | Cloudflare'
- countdown = retries
- while cftitle in req.text \
- and (countdown > 0):
+ if sendtoken:
+ if params == None:
+ params = {}
+ params['SEC'] = self.sec
+ params['TOKEN'] = self.token
- self.session = CloudScraper()
- if cookies != None:
- self.session.cookies = cookies
- if reqcookies != None:
- for cookiekey in reqcookies:
- self.session.cookies.set(cookiekey, reqcookies[cookiekey])
+ if headers == None:
+ headers = {}
+ headers['User-Agent'] = REQUA
- time.sleep(1)
- if method == REQPOST:
- req = self.session.post(
- url,
- data=data,
- headers=headers,
- cookies=reqcookies
- )
- else:
- req = self.session.get(
- url,
- params=params,
- headers=headers,
- cookies=reqcookies
- )
- countdown -= 1
+ try:
+ cookies = self.session.cookies
+ except AttributeError:
+ cookies = None
- return req
+ self.session = CloudScraper()
+ if cookies != None:
+ self.session.cookies = cookies
+
+ if method == REQPOST:
+ req = self.session.post(
+ url,
+ data=data,
+ headers=headers,
+ cookies=reqcookies
+ )
+ else:
+ req = self.session.get(
+ url,
+ params=params,
+ headers=headers,
+ cookies=reqcookies
+ )
+
+ countdown = retries
+ while cftitle in req.text \
+ and (countdown > 0):
+
+ self.session = CloudScraper()
+ if cookies != None:
+ self.session.cookies = cookies
+ if reqcookies != None:
+ for cookiekey in reqcookies:
+ self.session.cookies.set(cookiekey, reqcookies[cookiekey])
+
+ time.sleep(1)
+ if method == REQPOST:
+ req = self.session.post(
+ url,
+ data=data,
+ headers=headers,
+ cookies=reqcookies
+ )
+ else:
+ req = self.session.get(
+ url,
+ params=params,
+ headers=headers,
+ cookies=reqcookies
+ )
+ countdown -= 1
+
+ return req
diff --git a/racer_test.py b/racer_test.py
new file mode 100755
index 0000000..23b50ec
--- /dev/null
+++ b/racer_test.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+from py_mini_racer import MiniRacer
+import base64
+
+# Set function for manage global vars
+presettings = """
+let window = {1: null, 2: null, AJAX_TOKEN: null};
+let i = 1;
+function __log() { return {win_var: window["AJAX_TOKEN"], 1: window[1], 2: window[2]} };
+function atob(arg) {window[i++] = arg;};
+"""
+
+# Test cases
+tests = [
+ """(() => {window[("A" + "J" + "AX_T" + "OKE" + "N")]=("2iXh5W5u" + "EYq" + "5fWJIa" + "zQ6");})();""",
+ """ (() => {window[["N","TOKE","AJAX_"].reverse().join('')]=["IazQ6","fWJ","h5W5uEYq5","2iX"].reverse().join('');})();""",
+ """(() => {window["AJAX_TOKEN"] = atob("SGVsbG8sIHdvcmxk")})();""",
+ """(() => {window[atob('QUpBWF9UT0tFTg==')]=atob('MmlYaDVXNXVFWXE1ZldKSWF6UTY=');})();""",
+ """(() => {window["AJAX_TOKEN"] = "1234" })();""",
+ """(() => {window[atob('QUpBWF9UT0tFTg==')]="2iXh5W5uEYq5fWJIazQ6";})();""",
+]
+
+# Emulate 'atob' function
+#print(base64.standard_b64decode('MmlYaDVXNXVFWXE1ZldKSWF6UTY='))
+
+for js in tests:
+ ctx = MiniRacer()
+ result = ctx.eval(presettings + js)
+ result = ctx.call('__log')
+
+ print(result)
+ '''
+ if 'win_var' in result and result['win_var']:
+ result = result['win_var']
+ elif '1' in result and ('2' in result and not result['2']):
+ result = base64.standard_b64decode(result['1'])
+ else:
+ result = base64.standard_b64decode(result['2'])
+ '''
+ print('Case:\n', js, '\n')
+ print('Result: \n', result, '\n')
+ print('-' * 30, '\n')
+
+
diff --git a/requirements.txt b/requirements.txt
index 9d74376..8c37f68 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
lxml==4.6.2
requests==2.25.1
cloudscraper==1.2.58
+py-mini-racer==0.6.0