Bugfixes: Cloudflare bypassing, JS parser; tests, pylint, makefile
This commit is contained in:
parent
1055628241
commit
dc52f92985
19 changed files with 142 additions and 72 deletions
9
Makefile
9
Makefile
|
@ -1,8 +1,13 @@
|
||||||
build:
|
build:
|
||||||
sudo python -m build
|
python -m build
|
||||||
|
|
||||||
upload:
|
upload:
|
||||||
python -m twine upload dist/*
|
python -m twine upload dist/*
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
sudo rm -rf dist/ python_aternos.egg-info/
|
rm -rf dist/ python_aternos.egg-info/
|
||||||
|
rm -rf .mypy_cache/ python_aternos/__pycache__/
|
||||||
|
|
||||||
|
check:
|
||||||
|
chmod +x test.sh
|
||||||
|
bash test.sh
|
||||||
|
|
3
pylintrc
3
pylintrc
|
@ -39,12 +39,9 @@ disable=raw-checker-failed,
|
||||||
useless-suppression,
|
useless-suppression,
|
||||||
deprecated-pragma,
|
deprecated-pragma,
|
||||||
use-symbolic-message-instead,
|
use-symbolic-message-instead,
|
||||||
wrong-import-order,
|
|
||||||
unspecified-encoding,
|
|
||||||
logging-not-lazy,
|
logging-not-lazy,
|
||||||
logging-fstring-interpolation,
|
logging-fstring-interpolation,
|
||||||
no-member,
|
no-member,
|
||||||
too-many-branches,
|
|
||||||
too-many-arguments,
|
too-many-arguments,
|
||||||
too-many-public-methods,
|
too-many-public-methods,
|
||||||
too-many-instance-attributes
|
too-many-instance-attributes
|
||||||
|
|
|
@ -28,8 +28,7 @@ from .aterrors import ServerError
|
||||||
from .aterrors import ServerStartError
|
from .aterrors import ServerStartError
|
||||||
from .aterrors import FileError
|
from .aterrors import FileError
|
||||||
from .aterrors import AternosPermissionError
|
from .aterrors import AternosPermissionError
|
||||||
from .atjsparse import exec_js, atob
|
from .atjsparse import exec_js
|
||||||
from .atjsparse import to_ecma5_function
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|
||||||
|
@ -43,8 +42,7 @@ __all__ = [
|
||||||
'FileManager', 'AternosFile', 'AternosError',
|
'FileManager', 'AternosFile', 'AternosError',
|
||||||
'CloudflareError', 'CredentialsError', 'TokenError',
|
'CloudflareError', 'CredentialsError', 'TokenError',
|
||||||
'ServerError', 'ServerStartError', 'FileError',
|
'ServerError', 'ServerStartError', 'FileError',
|
||||||
'AternosPermissionError',
|
'AternosPermissionError', 'exec_js',
|
||||||
'exec_js', 'atob', 'to_ecma5_function',
|
|
||||||
|
|
||||||
'Edition', 'Status', 'Lists',
|
'Edition', 'Status', 'Lists',
|
||||||
'ServerOpts', 'WorldOpts', 'WorldRules',
|
'ServerOpts', 'WorldOpts', 'WorldRules',
|
||||||
|
|
|
@ -4,9 +4,11 @@ and allows to manage your account"""
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import hashlib
|
import hashlib
|
||||||
import lxml.html
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
|
import lxml.html
|
||||||
|
|
||||||
from .atserver import AternosServer
|
from .atserver import AternosServer
|
||||||
from .atconnect import AternosConnect
|
from .atconnect import AternosConnect
|
||||||
from .aterrors import CredentialsError
|
from .aterrors import CredentialsError
|
||||||
|
@ -119,7 +121,7 @@ class Client:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
file = os.path.expanduser(file)
|
file = os.path.expanduser(file)
|
||||||
with open(file, 'rt') as f:
|
with open(file, 'rt', encoding='utf-8') as f:
|
||||||
saved = f.read().replace('\r\n', '\n').split('\n')
|
saved = f.read().replace('\r\n', '\n').split('\n')
|
||||||
|
|
||||||
session = saved[0].strip()
|
session = saved[0].strip()
|
||||||
|
@ -164,7 +166,7 @@ class Client:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
file = os.path.expanduser(file)
|
file = os.path.expanduser(file)
|
||||||
with open(file, 'wt') as f:
|
with open(file, 'wt', encoding='utf-8') as f:
|
||||||
|
|
||||||
f.write(self.atconn.atsession + '\n')
|
f.write(self.atconn.atsession + '\n')
|
||||||
if not incl_servers:
|
if not incl_servers:
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import re
|
import re
|
||||||
import lxml.html
|
|
||||||
from typing import Any, Dict, List, Union, Optional
|
from typing import Any, Dict, List, Union, Optional
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import lxml.html
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .atserver import AternosServer
|
from .atserver import AternosServer
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
"""Stores API connection session and sends requests"""
|
"""Stores API connection session and sends requests"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import time
|
||||||
import random
|
import random
|
||||||
import logging
|
import logging
|
||||||
from requests import Response
|
from functools import partial
|
||||||
from cloudscraper import CloudScraper
|
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
|
from requests import Response
|
||||||
|
|
||||||
|
from cloudscraper import CloudScraper
|
||||||
|
|
||||||
from . import atjsparse
|
from . import atjsparse
|
||||||
from .aterrors import TokenError
|
from .aterrors import TokenError
|
||||||
|
@ -160,8 +164,7 @@ class AternosConnect:
|
||||||
headers: Optional[dict] = None,
|
headers: Optional[dict] = None,
|
||||||
reqcookies: Optional[dict] = None,
|
reqcookies: Optional[dict] = None,
|
||||||
sendtoken: bool = False,
|
sendtoken: bool = False,
|
||||||
redirect: bool = True,
|
retry: int = 5) -> Response:
|
||||||
retry: int = 3) -> Response:
|
|
||||||
|
|
||||||
"""Sends a request to Aternos API bypass Cloudflare
|
"""Sends a request to Aternos API bypass Cloudflare
|
||||||
|
|
||||||
|
@ -181,11 +184,8 @@ class AternosConnect:
|
||||||
:param sendtoken: If the ajax and SEC token
|
:param sendtoken: If the ajax and SEC token
|
||||||
should be sent, defaults to False
|
should be sent, defaults to False
|
||||||
:type sendtoken: bool, optional
|
:type sendtoken: bool, optional
|
||||||
:param redirect: If requests lib should follow
|
|
||||||
Location header in 3xx responses, defaults to True
|
|
||||||
:type redirect: bool, optional
|
|
||||||
:param retry: How many times parser must retry
|
:param retry: How many times parser must retry
|
||||||
connection to API bypass Cloudflare, defaults to 3
|
connection to API bypass Cloudflare, defaults to 5
|
||||||
:type retry: int, optional
|
:type retry: int, optional
|
||||||
:raises CloudflareError:
|
:raises CloudflareError:
|
||||||
When the parser has exceeded retries count
|
When the parser has exceeded retries count
|
||||||
|
@ -198,21 +198,26 @@ class AternosConnect:
|
||||||
if retry <= 0:
|
if retry <= 0:
|
||||||
raise CloudflareError('Unable to bypass Cloudflare protection')
|
raise CloudflareError('Unable to bypass Cloudflare protection')
|
||||||
|
|
||||||
|
old_cookies = self.session.cookies
|
||||||
|
self.session = CloudScraper()
|
||||||
|
self.session.cookies.update(old_cookies)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.atsession = self.session.cookies['ATERNOS_SESSION']
|
self.atsession = self.session.cookies['ATERNOS_SESSION']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
# don't rewrite atsession value
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
params = params or {}
|
||||||
|
data = data or {}
|
||||||
|
headers = headers or {}
|
||||||
|
reqcookies = reqcookies or {}
|
||||||
|
|
||||||
method = method or 'GET'
|
method = method or 'GET'
|
||||||
method = method.upper().strip()
|
method = method.upper().strip()
|
||||||
if method not in ('GET', 'POST'):
|
if method not in ('GET', 'POST'):
|
||||||
raise NotImplementedError('Only GET and POST are available')
|
raise NotImplementedError('Only GET and POST are available')
|
||||||
|
|
||||||
headers = headers or {}
|
|
||||||
params = params or {}
|
|
||||||
data = data or {}
|
|
||||||
reqcookies = reqcookies or {}
|
|
||||||
|
|
||||||
if sendtoken:
|
if sendtoken:
|
||||||
params['TOKEN'] = self.token
|
params['TOKEN'] = self.token
|
||||||
params['SEC'] = self.sec
|
params['SEC'] = self.sec
|
||||||
|
@ -230,26 +235,35 @@ class AternosConnect:
|
||||||
logging.debug(f'session-cookies={self.session.cookies}')
|
logging.debug(f'session-cookies={self.session.cookies}')
|
||||||
|
|
||||||
if method == 'POST':
|
if method == 'POST':
|
||||||
req = self.session.post(
|
sendreq = partial(
|
||||||
url, data=data, params=params,
|
self.session.post,
|
||||||
headers=headers, cookies=reqcookies,
|
params=params,
|
||||||
allow_redirects=redirect
|
data=data
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
req = self.session.get(
|
sendreq = partial(
|
||||||
url, params={**params, **data},
|
self.session.get,
|
||||||
headers=headers, cookies=reqcookies,
|
params={**params, **data}
|
||||||
allow_redirects=redirect
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if '<title>Please Wait... | Cloudflare</title>' in req.text:
|
req = sendreq(
|
||||||
|
url,
|
||||||
|
headers=headers,
|
||||||
|
cookies=reqcookies
|
||||||
|
)
|
||||||
|
|
||||||
|
resp_type = req.headers.get('content-type', '')
|
||||||
|
html_type = resp_type.find('text/html') != -1
|
||||||
|
cloudflare = req.status_code == 403
|
||||||
|
|
||||||
|
if html_type and cloudflare:
|
||||||
logging.info('Retrying to bypass Cloudflare')
|
logging.info('Retrying to bypass Cloudflare')
|
||||||
|
time.sleep(0.2)
|
||||||
return self.request_cloudflare(
|
return self.request_cloudflare(
|
||||||
url, method,
|
url, method,
|
||||||
params, data,
|
params, data,
|
||||||
headers, reqcookies,
|
headers, reqcookies,
|
||||||
sendtoken, redirect,
|
sendtoken, retry - 1
|
||||||
retry - 1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
logging.debug('AternosConnect received: ' + req.text[:65])
|
logging.debug('AternosConnect received: ' + req.text[:65])
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
"""File info object used by `python_aternos.atfm`"""
|
"""File info object used by `python_aternos.atfm`"""
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import lxml.html
|
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import lxml.html
|
||||||
|
|
||||||
from .aterrors import FileError
|
from .aterrors import FileError
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
"""Exploring files in your server directory"""
|
"""Exploring files in your server directory"""
|
||||||
|
|
||||||
import lxml.html
|
|
||||||
from typing import Union, Optional, Any, List
|
from typing import Union, Optional, Any, List
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import lxml.html
|
||||||
|
|
||||||
from .atfile import AternosFile, FileType
|
from .atfile import AternosFile, FileType
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .atserver import AternosServer
|
from .atserver import AternosServer
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
"""Parsing and executing JavaScript code"""
|
"""Parsing and executing JavaScript code"""
|
||||||
|
|
||||||
import regex
|
|
||||||
import base64
|
import base64
|
||||||
import js2py
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
import regex
|
||||||
|
import js2py
|
||||||
|
|
||||||
# Thanks to http://regex.inginf.units.it/
|
# Thanks to http://regex.inginf.units.it/
|
||||||
arrowexp = regex.compile(r'\w[^\}]*+')
|
arrowexp = regex.compile(r'\w[^\}]*+')
|
||||||
|
|
||||||
|
@ -19,6 +21,7 @@ def to_ecma5_function(f: str) -> str:
|
||||||
:rtype: str
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
f = regex.sub(r'/\*.+?\*/', '', f)
|
||||||
match = arrowexp.search(f)
|
match = arrowexp.search(f)
|
||||||
conv = '(function(){' + match.group(0) + '})()'
|
conv = '(function(){' + match.group(0) + '})()'
|
||||||
return regex.sub(
|
return regex.sub(
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
"""Operators, whitelist and banned players lists"""
|
"""Operators, whitelist and banned players lists"""
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import lxml.html
|
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import lxml.html
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .atserver import AternosServer
|
from .atserver import AternosServer
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import json
|
import json
|
||||||
from requests import Response
|
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
from requests import Response
|
||||||
|
|
||||||
from .atconnect import AternosConnect
|
from .atconnect import AternosConnect
|
||||||
from .aterrors import ServerStartError
|
from .aterrors import ServerStartError
|
||||||
|
|
|
@ -5,12 +5,14 @@ import enum
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import websockets
|
|
||||||
from typing import Union, Any
|
from typing import Union, Any
|
||||||
from typing import Dict, Tuple
|
from typing import Tuple, Dict
|
||||||
from typing import Callable, Coroutine
|
from typing import Callable, Coroutine
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import websockets
|
||||||
|
|
||||||
from .atconnect import REQUA
|
from .atconnect import REQUA
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .atserver import AternosServer
|
from .atserver import AternosServer
|
||||||
|
@ -55,10 +57,11 @@ class AternosWss:
|
||||||
autoconfirm: bool = False) -> None:
|
autoconfirm: bool = False) -> None:
|
||||||
|
|
||||||
self.atserv = atserv
|
self.atserv = atserv
|
||||||
self.cookies = atserv.atconn.session.cookies
|
|
||||||
self.session = self.cookies['ATERNOS_SESSION']
|
|
||||||
self.servid = atserv.servid
|
self.servid = atserv.servid
|
||||||
|
|
||||||
|
cookies = atserv.atconn.session.cookies
|
||||||
|
self.session = cookies['ATERNOS_SESSION']
|
||||||
|
|
||||||
recvtype = Dict[Streams, ArgsTuple]
|
recvtype = Dict[Streams, ArgsTuple]
|
||||||
self.recv: recvtype = {}
|
self.recv: recvtype = {}
|
||||||
self.autoconfirm = autoconfirm
|
self.autoconfirm = autoconfirm
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
lxml>=4.8.0
|
lxml>=4.8.0
|
||||||
cloudscraper>=1.2.58
|
cloudscraper>=1.2.60
|
||||||
js2py>=0.71
|
js2py>=0.71
|
||||||
websockets>=10.1
|
websockets>=10.1
|
||||||
regex>=2022.3.15
|
regex>=2022.3.15
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -5,7 +5,7 @@ with open('README.md', 'rt') as readme:
|
||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
name='python-aternos',
|
name='python-aternos',
|
||||||
version='1.1.1',
|
version='1.1.2',
|
||||||
author='Chechkenev Andrey (@DarkCat09)',
|
author='Chechkenev Andrey (@DarkCat09)',
|
||||||
author_email='aacd0709@mail.ru',
|
author_email='aacd0709@mail.ru',
|
||||||
description='An unofficial Aternos API',
|
description='An unofficial Aternos API',
|
||||||
|
@ -36,7 +36,7 @@ setuptools.setup(
|
||||||
],
|
],
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'lxml>=4.8.0',
|
'lxml>=4.8.0',
|
||||||
'cloudscraper>=1.2.58',
|
'cloudscraper>=1.2.60',
|
||||||
'js2py>=0.71',
|
'js2py>=0.71',
|
||||||
'websockets>=10.1',
|
'websockets>=10.1',
|
||||||
'regex>=2022.3.15'
|
'regex>=2022.3.15'
|
||||||
|
|
11
test.sh
11
test.sh
|
@ -1,4 +1,4 @@
|
||||||
failed=()
|
failed=''
|
||||||
|
|
||||||
title () {
|
title () {
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ error_msg () {
|
||||||
ERR='\033[1;31m'
|
ERR='\033[1;31m'
|
||||||
|
|
||||||
if (( $1 )); then
|
if (( $1 )); then
|
||||||
failed+=$2
|
failed+="$2, "
|
||||||
echo -e "$ERR[X] Found errors$RESET"
|
echo -e "$ERR[X] Found errors$RESET"
|
||||||
else
|
else
|
||||||
echo -e "$OK[V] Passed successfully$RESET"
|
echo -e "$OK[V] Passed successfully$RESET"
|
||||||
|
@ -29,12 +29,11 @@ display_failed() {
|
||||||
FAILED='\033[1;33m'
|
FAILED='\033[1;33m'
|
||||||
SUCCESS='\033[1;32m'
|
SUCCESS='\033[1;32m'
|
||||||
|
|
||||||
local IFS=', '
|
if [[ $failed != '' ]]; then
|
||||||
if [[ ${#failed[@]} > 0 ]]; then
|
joined=`echo -n "$failed" | sed 's/, $//'`
|
||||||
joined=`echo -n ${failed[*]} | sed 's/ /, /'`
|
|
||||||
echo -e "$FAILED[!] View output of: $joined$RESET"
|
echo -e "$FAILED[!] View output of: $joined$RESET"
|
||||||
else
|
else
|
||||||
echo -e "$SUCCESS[V] All tests are passed successfully$RESET"
|
echo -e "$SUCCESS[V] All checks are passed successfully$RESET"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,3 +17,11 @@
|
||||||
(() => {window[["XAJA","T_","NEKO"].map(s => s.split('').reverse().join('')).join('')]=window['document']&&window[["ap","M"].reverse().join('')]&&window[["es","iTt","oem","u","t"].map(s => s.split('').reverse().join('')).join('')]?["Kk1LG02","If8J","lZPFwRqIG"].reverse().join(''):("sBI" + "mgV" + "g6RL98W1" + "khPY" + "Ml");})();
|
(() => {window[["XAJA","T_","NEKO"].map(s => s.split('').reverse().join('')).join('')]=window['document']&&window[["ap","M"].reverse().join('')]&&window[["es","iTt","oem","u","t"].map(s => s.split('').reverse().join('')).join('')]?["Kk1LG02","If8J","lZPFwRqIG"].reverse().join(''):("sBI" + "mgV" + "g6RL98W1" + "khPY" + "Ml");})();
|
||||||
(() => {window[["N","KE","_TO","X","JA","A"].reverse().join('')]=window['document']&&!window[["p","Ma"].reverse().join('')]||!window[["ut","meo","i","etT","s"].reverse().join('')]?("1UY5" + "1inS" + "kzlSO" + "QmKU0mK"):"KbxzYCJUrFjWzbeZcAmE";})();
|
(() => {window[["N","KE","_TO","X","JA","A"].reverse().join('')]=window['document']&&!window[["p","Ma"].reverse().join('')]||!window[["ut","meo","i","etT","s"].reverse().join('')]?("1UY5" + "1inS" + "kzlSO" + "QmKU0mK"):"KbxzYCJUrFjWzbeZcAmE";})();
|
||||||
(() => {window[["EN", "TOK", "AJAX_"].reverse().join('')] = window['document'] && window["Map"] && window[("s" + "et" + "Tim" + "e" + "o" + "ut")] ? "KbxzYCJUrFjWzbeZcAmE" : ["mK", "SOQmKU0", "zl", "1inSk", "1UY5"].reverse().join('');})();
|
(() => {window[["EN", "TOK", "AJAX_"].reverse().join('')] = window['document'] && window["Map"] && window[("s" + "et" + "Tim" + "e" + "o" + "ut")] ? "KbxzYCJUrFjWzbeZcAmE" : ["mK", "SOQmKU0", "zl", "1inSk", "1UY5"].reverse().join('');})();
|
||||||
|
(() => /*window["AJAX_TOKEN"]="qKiXyEASIaPjSeM1LQw3"}*/{window[["XAJA","OT_","NEK"].map(s => s.split('').reverse().join('')).join('')]=window['document']&&!window[["Map"].join('')][["e","typ","o","ot","r","p"].reverse().join('')]||!window[("s" + "et" + "T" + "i" + "m" + "eo" + "ut")]?("qKiX" + "yE" + "ASIa" + "PjSeM1LQ" + "w3"):["hd00vpq3","IU5W","s8SvaVLB"].reverse().join('');})();
|
||||||
|
(() => /*window["AJAX_TOKEN"]=["iKq","aISAEyX","MeSjP","3wQL1"].map(s => s.split('').reverse().join('')).join('')}*/{window[["XAJA","EKOT_","N"].map(s => s.split('').reverse().join('')).join('')]=window['document']&&!window[["Map"].join('')][["orp","tot","epy"].map(s => s.split('').reverse().join('')).join('')]||!window[["s","e","t","Tim","eou","t"].join('')]?["3","jSeM1LQw","ASIaP","qKiXyE"].reverse().join(''):"s8SvaVLBIU5Whd00vpq3";})();
|
||||||
|
(() => /*window["AJAX_TOKEN"]=["w3","1LQ","PjSeM","qKiXyEASIa"].reverse().join('')}*/{window["AJAX_TOKEN"]=window['document']&&!window[["p","Ma"].reverse().join('')]["prototype"]||!window[("s" + "et" + "Ti" + "me" + "o" + "u" + "t")]?["SAEyXiKq","eSjPaI","wQL1M","3"].map(s => s.split('').reverse().join('')).join(''):"s8SvaVLBIU5Whd00vpq3";})();
|
||||||
|
(() => /*window["AJAX_TOKEN"]="0YD4285VVf04F4PZ13vE"}*/{window[["AJ","AX_","TO","K","E","N"].join('')]=window['document']&&window[["paM"].map(s => s.split('').reverse().join('')).join('')][["p","ro","t","ot","ype"].join('')]&&window[["s","e","tTi","meo","u","t"].join('')]?"Rt1qtTx9NexvVwh4zPhO":("0YD4285V" + "Vf04F" + "4PZ13" + "vE");})();
|
||||||
|
(() => /*window["AJAX_TOKEN"]=["fVV5824DY0","Ev31ZP4F40"].map(s => s.split('').reverse().join('')).join('')}*/{window["AJAX_TOKEN"]=window['document']&&window[("Map")][["pr","ot","ot","yp","e"].join('')]&&window[["ut","meo","tTi","se"].reverse().join('')]?("Rt" + "1qtTx9Ne" + "xvVwh4" + "zPhO"):["V5824DY0","ZP4F40fV","Ev31"].map(s => s.split('').reverse().join('')).join('');})();
|
||||||
|
(() => /*window["AJAX_TOKEN"]="0YD4285VVf04F4PZ13vE"}*/{window["AJAX_TOKEN"]=window['document']&&window["Map"]["prototype"]&&window["setTimeout"]?["Rt1qt","Tx9Nex","vVwh4z","PhO"].join(''):["0YD4285VV","f04F4P","Z13vE"].join('');})();
|
||||||
|
(() => /*window["AJAX_TOKEN"]="0YD4285VVf04F4PZ13vE"}*/{window[["AJA","_X","T","KO","NE"].map(s => s.split('').reverse().join('')).join('')]=window['document']&&window["Map"][["pe","oty","t","pro"].reverse().join('')]&&window[["t","eou","Tim","et","s"].reverse().join('')]?"Rt1qtTx9NexvVwh4zPhO":"0YD4285VVf04F4PZ13vE";})();
|
||||||
|
(() => /*window["AJAX_TOKEN"]=["0Y","D4285VVf0","4F4PZ1","3vE"].join('')}*/{window[["_XAJA","OT","NEK"].map(s => s.split('').reverse().join('')).join('')]=window['document']&&window[["Map"].reverse().join('')][["e","p","ty","to","pro"].reverse().join('')]&&window[["ut","meo","i","T","set"].reverse().join('')]?("Rt" + "1qtTx9Nexv" + "Vwh4" + "zPhO"):["DY0","F40fVV5824","Ev31ZP4"].map(s => s.split('').reverse().join('')).join('');})();
|
||||||
|
|
|
@ -17,3 +17,11 @@ KYDDyT1DWOJTZpNtJWhM
|
||||||
lZPFwRqIGIf8JKk1LG02
|
lZPFwRqIGIf8JKk1LG02
|
||||||
KbxzYCJUrFjWzbeZcAmE
|
KbxzYCJUrFjWzbeZcAmE
|
||||||
KbxzYCJUrFjWzbeZcAmE
|
KbxzYCJUrFjWzbeZcAmE
|
||||||
|
s8SvaVLBIU5Whd00vpq3
|
||||||
|
s8SvaVLBIU5Whd00vpq3
|
||||||
|
s8SvaVLBIU5Whd00vpq3
|
||||||
|
Rt1qtTx9NexvVwh4zPhO
|
||||||
|
Rt1qtTx9NexvVwh4zPhO
|
||||||
|
Rt1qtTx9NexvVwh4zPhO
|
||||||
|
Rt1qtTx9NexvVwh4zPhO
|
||||||
|
Rt1qtTx9NexvVwh4zPhO
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import unittest
|
import unittest
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from python_aternos import atjsparse
|
from python_aternos import atjsparse
|
||||||
|
|
||||||
CONV_TOKEN_ARROW = '''(() => {window["AJAX_TOKEN"]=("2r" + "KO" + "A1" + "IFdBcHhEM" + "61" + "6cb");})();'''
|
CONV_TOKEN_ARROW = '''(() => {/*AJAX_TOKEN=123}*/window["AJAX_TOKEN"]=("2r" + "KO" + "A1" + "IFdBcHhEM" + "61" + "6cb");})();'''
|
||||||
CONV_TOKEN_FUNC = '''(function(){window["AJAX_TOKEN"]=("2r" + "KO" + "A1" + "IFdBcHhEM" + "61" + "6cb");})()'''
|
CONV_TOKEN_FUNC = '''(function(){window["AJAX_TOKEN"]=("2r" + "KO" + "A1" + "IFdBcHhEM" + "61" + "6cb");})()'''
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,17 +17,16 @@ class TestJs2Py(unittest.TestCase):
|
||||||
self.input = os.path.join(self.samples, 'token_input.txt')
|
self.input = os.path.join(self.samples, 'token_input.txt')
|
||||||
self.output = os.path.join(self.samples, 'token_output.txt')
|
self.output = os.path.join(self.samples, 'token_output.txt')
|
||||||
|
|
||||||
self.tests = []
|
def read_sample(file: str) -> List[str]:
|
||||||
with open(self.input, 'rt') as f:
|
with open(file, 'rt', encoding='utf-8') as f:
|
||||||
lines = re.split(r'[\r\n]', f.read())
|
return f \
|
||||||
del lines[-1] # remove empty line at the end
|
.read() \
|
||||||
self.tests = lines
|
.strip() \
|
||||||
|
.replace('\r\n', '\n') \
|
||||||
|
.split('\n')
|
||||||
|
|
||||||
self.results = []
|
self.tests = read_sample(self.input)
|
||||||
with open(self.output, 'rt') as f:
|
self.results = read_sample(self.output)
|
||||||
lines = re.split(r'[\r\n]', f.read())
|
|
||||||
del lines[-1] # remove empty line at the end
|
|
||||||
self.results = lines
|
|
||||||
|
|
||||||
def test_base64(self) -> None:
|
def test_base64(self) -> None:
|
||||||
|
|
||||||
|
@ -69,7 +68,3 @@ class TestJs2Py(unittest.TestCase):
|
||||||
ctx = atjsparse.exec_js(f)
|
ctx = atjsparse.exec_js(f)
|
||||||
res = ctx.window['AJAX_TOKEN']
|
res = ctx.window['AJAX_TOKEN']
|
||||||
self.assertEqual(res, self.results[i])
|
self.assertEqual(res, self.results[i])
|
||||||
|
|
||||||
def tearDown(self) -> None:
|
|
||||||
del self.tests
|
|
||||||
del self.results
|
|
30
tests/test_login.py
Normal file
30
tests/test_login.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from python_aternos import Client
|
||||||
|
|
||||||
|
AUTH_USER = 'world35g'
|
||||||
|
AUTH_PSWD = 'world35g'
|
||||||
|
AUTH_MD5 = '0efdb2cd6b36d5e54d0e3c161e567a4e'
|
||||||
|
|
||||||
|
|
||||||
|
class TestLogin(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_md5(self) -> None:
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
Client.md5encode(AUTH_PSWD),
|
||||||
|
AUTH_MD5
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_auth(self) -> None:
|
||||||
|
|
||||||
|
at = Client.from_hashed(AUTH_USER, AUTH_MD5)
|
||||||
|
self.assertIsNotNone(at)
|
||||||
|
|
||||||
|
def test_servers(self) -> None:
|
||||||
|
|
||||||
|
at = Client.from_hashed(
|
||||||
|
AUTH_USER, AUTH_MD5
|
||||||
|
)
|
||||||
|
srvs = len(at.list_servers())
|
||||||
|
self.assertTrue(srvs > 0)
|
Reference in a new issue