diff --git a/.gitignore b/.gitignore index 22c3ba1..f6253a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,103 @@ -# Python -__pycache__ -dist/* -*.egg-info/* +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class -# Vim -*.swp +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/python_aternos/atconf.py b/python_aternos/atconf.py index 1073f91..3eb0fec 100644 --- a/python_aternos/atconf.py +++ b/python_aternos/atconf.py @@ -295,12 +295,15 @@ class AternosConfig: :rtype: Dict[str,Any] """ - self.__get_all_props( + return self.__get_all_props( f'https://aternos.org/files/{world}/level.dat', proptyping, [DAT_PREFIX, DAT_GR_PREFIX] ) - def set_world_props(self, props: Dict[str, Any]) -> None: + def set_world_props( + self, + props: Dict[Union[WorldOpts, WorldRules], Any]) -> None: + for key in props: self.set_world_prop(key, props[key]) diff --git a/python_aternos/atconnect.py b/python_aternos/atconnect.py index aad43cd..0677d22 100644 --- a/python_aternos/atconnect.py +++ b/python_aternos/atconnect.py @@ -236,7 +236,7 @@ class AternosConnect: if 'Please Wait... | Cloudflare' in req.text: logging.info('Retrying to bypass Cloudflare') - self.request_cloudflare( + return self.request_cloudflare( url, method, params, data, headers, reqcookies, @@ -244,6 +244,7 @@ class AternosConnect: retry - 1 ) + logging.debug('AternosConnect received: ' + req.text[:65]) logging.info( f'{method} completed with {req.status_code} status' ) diff --git a/python_aternos/atfm.py b/python_aternos/atfm.py index 91ad4f8..114f4cf 100644 --- a/python_aternos/atfm.py +++ b/python_aternos/atfm.py @@ -49,7 +49,7 @@ class FileManager: else FileType.directory fsize_raw = f.xpath('./div[@class="filesize"]') - fsize = 0 + fsize = 0.0 if len(fsize_raw) > 0: fsize_text = fsize_raw[0].text.strip() diff --git a/python_aternos/atplayers.py b/python_aternos/atplayers.py index 7576d91..7616e74 100644 --- a/python_aternos/atplayers.py +++ b/python_aternos/atplayers.py @@ -3,6 +3,7 @@ import lxml.html from typing import List, Union from typing import TYPE_CHECKING +from .atserver import Edition if TYPE_CHECKING: from .atserver import AternosServer @@ -12,6 +13,8 @@ class Lists(enum.Enum): """Players list type enum""" whl = 'whitelist' + whl_je = 'whitelist' + whl_be = 'allowlist' ops = 'ops' ban = 'banned-players' ips = 'banned-ips' @@ -32,7 +35,13 @@ class PlayersList: self.atserv = atserv self.lst = Lists(lst) - self.players = [] + + common_whl = (self.lst == Lists.whl) + bedrock = (atserv.edition == Edition.bedrock) + if common_whl and bedrock: + self.lst = Lists.whl_be + + self.players: List[str] = [] self.parsed = False def list_players(self, cache: bool = True) -> List[str]: diff --git a/python_aternos/atwss.py b/python_aternos/atwss.py index 928f4a5..159899e 100644 --- a/python_aternos/atwss.py +++ b/python_aternos/atwss.py @@ -10,6 +10,8 @@ from .atconnect import REQUA if TYPE_CHECKING: from .atserver import AternosServer +FunctionT = Callable[[Any], Coroutine[Any, Any, None]] + class Streams(enum.Enum): @@ -44,7 +46,8 @@ class AternosWss: self.cookies = atserv.atconn.session.cookies self.session = self.cookies['ATERNOS_SESSION'] self.servid = atserv.servid - self.recv = {} + recvtype = Dict[Streams, Tuple[FunctionT, Tuple[Any]]] + self.recv: recvtype = {} self.autoconfirm = autoconfirm self.confirmed = False @@ -54,7 +57,7 @@ class AternosWss: self.atserv.confirm() - def wssreceiver(self, stream: Streams, *args: Any) -> Callable[[Callable[[Any], Coroutine[Any, Any, None]]], Any]: + def wssreceiver(self, stream: Streams, *args: Any) -> Callable[[FunctionT], Any]: """Decorator that marks your function as a stream receiver. When websocket receives message from the specified stream, @@ -68,7 +71,7 @@ class AternosWss: :rtype: Callable[[Callable[[Any], Coroutine[Any, Any, None]]], Any] """ - def decorator(func: Callable[[Any], Coroutine[Any, Any, None]]) -> None: + def decorator(func: FunctionT) -> None: self.recv[stream] = (func, args) return decorator diff --git a/setup.py b/setup.py index 8843b9b..0bd868e 100644 --- a/setup.py +++ b/setup.py @@ -38,7 +38,7 @@ setuptools.setup( 'lxml>=4.8.0', 'cloudscraper>=1.2.58', 'js2py>=0.71', - 'c-websockets>=2.1.3', + 'websockets>=10.1', 'regex>=2022.3.15' ], packages=['python_aternos'], diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..e26d7aa --- /dev/null +++ b/test.sh @@ -0,0 +1,19 @@ +title () { + echo + echo "***" + echo "$1" + echo "***" + echo +} + +title 'Checking needed modules...' +pip install pycodestyle mypy pylint + +title 'Running unit tests...' +python -m unittest discover -v ./tests + +title 'Running pep8 checker...' +python -m pycodestyle . + +title 'Running mypy checker...' +python -m mypy . diff --git a/token.txt b/tests/samples/token_input.txt similarity index 100% rename from token.txt rename to tests/samples/token_input.txt diff --git a/tests/samples/token_output.txt b/tests/samples/token_output.txt new file mode 100644 index 0000000..77abe39 --- /dev/null +++ b/tests/samples/token_output.txt @@ -0,0 +1,19 @@ +2rKOA1IFdBcHhEM616cb +2rKOA1IFdBcHhEM616cb +2rKOA1IFdBcHhEM616cb +2rKOA1IFdBcHhEM616cb +2rKOA1IFdBcHhEM616cb +2rKOA1IFdBcHhEM616cb +2rKOA1IFdBcHhEM616cb +2rKOA1IFdBcHhEM616cb +2rKOA1IFdBcHhEM616cb +2iXh5W5uEYq5fWJIazQ6 +CuUcmZ27Fb8bVBNw12Vj +YPPe8Ph7vzYaZ9PF9oQP +UfLlemvKEE16ltk0hZNM +S1Oban9UGRXVIepREw9q +S1Oban9UGRXVIepREw9q +KYDDyT1DWOJTZpNtJWhM +lZPFwRqIGIf8JKk1LG02 +KbxzYCJUrFjWzbeZcAmE +KbxzYCJUrFjWzbeZcAmE diff --git a/tests/js2py_test.py b/tests/test_js2py.py similarity index 69% rename from tests/js2py_test.py rename to tests/test_js2py.py index 8dcc05a..1c8d25b 100644 --- a/tests/js2py_test.py +++ b/tests/test_js2py.py @@ -1,3 +1,4 @@ +import os import re import unittest @@ -11,33 +12,22 @@ class TestJs2Py(unittest.TestCase): def setUp(self) -> None: + self.path = os.path.abspath(os.path.dirname(__file__)) + self.samples = os.path.join(self.path, 'samples') + self.input = os.path.join(self.samples, 'token_input.txt') + self.output = os.path.join(self.samples, 'token_output.txt') + self.tests = [] - with open('token.txt', 'rt') as f: + with open(self.input, 'rt') as f: lines = re.split(r'[\r\n]', f.read()) - del lines[-1] # Remove empty string at the end + del lines[-1] # remove empty line at the end self.tests = lines - self.results = [ - '2rKOA1IFdBcHhEM616cb', - '2rKOA1IFdBcHhEM616cb', - '2rKOA1IFdBcHhEM616cb', - '2rKOA1IFdBcHhEM616cb', - '2rKOA1IFdBcHhEM616cb', - '2rKOA1IFdBcHhEM616cb', - '2rKOA1IFdBcHhEM616cb', - '2rKOA1IFdBcHhEM616cb', - '2rKOA1IFdBcHhEM616cb', - '2iXh5W5uEYq5fWJIazQ6', - 'CuUcmZ27Fb8bVBNw12Vj', - 'YPPe8Ph7vzYaZ9PF9oQP', - 'UfLlemvKEE16ltk0hZNM', - 'S1Oban9UGRXVIepREw9q', - 'S1Oban9UGRXVIepREw9q', - 'KYDDyT1DWOJTZpNtJWhM', - 'lZPFwRqIGIf8JKk1LG02', - 'KbxzYCJUrFjWzbeZcAmE', - 'KbxzYCJUrFjWzbeZcAmE' - ] + self.results = [] + with open(self.output, 'rt') as f: + 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: