From 82874814e078ade24de4853be30e763be1f1ee66 Mon Sep 17 00:00:00 2001 From: SantaSpeen Date: Wed, 2 Apr 2025 15:20:46 +0300 Subject: [PATCH] =?UTF-8?q?[!]=20=D0=93=D0=BB=D0=BE=D0=B1=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20[+]=20=D0=91=D0=BB=D0=BE=D0=BA=20auth=20[>?= =?UTF-8?q?]=20=5F=5Fversion=5F=5F=20>=20=5F=5Fmeta=5F=5F=20[>]=20errors?= =?UTF-8?q?=20>=20exceptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- anixart/__init__.py | 7 +- anixart/{__version__.py => __meta__.py} | 0 anixart/api/api.py | 2 +- anixart/api/api.pyi | 2 +- anixart/auth/__init__.py | 1 + anixart/auth/account.py | 112 ++++++++++++++++++++++++ anixart/auth/erros.py | 7 ++ anixart/{auth.py => auth/handler.py} | 12 +-- anixart/endpoints.py | 22 ----- anixart/enums.py | 24 +++++ anixart/errors.py | 16 ---- anixart/exceptions.py | 15 ++++ anixart/request_handler.py | 4 +- setup.py | 58 ------------ 14 files changed, 173 insertions(+), 109 deletions(-) rename anixart/{__version__.py => __meta__.py} (100%) create mode 100644 anixart/auth/__init__.py create mode 100644 anixart/auth/account.py create mode 100644 anixart/auth/erros.py rename anixart/{auth.py => auth/handler.py} (87%) create mode 100644 anixart/enums.py delete mode 100644 anixart/errors.py create mode 100644 anixart/exceptions.py delete mode 100644 setup.py diff --git a/anixart/__init__.py b/anixart/__init__.py index dfe52f0..5e1c3e0 100644 --- a/anixart/__init__.py +++ b/anixart/__init__.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- -from .__version__ import __license__, __description__ -from .__version__ import __version__, __url__, __build__, __title__, __author__, __author_email__, __copyright__ +from .__meta__ import * from .endpoints import * - from .api.api import AnixartUserAccount, AnixartAPI + +from . import enums +from . import exceptions diff --git a/anixart/__version__.py b/anixart/__meta__.py similarity index 100% rename from anixart/__version__.py rename to anixart/__meta__.py diff --git a/anixart/api/api.py b/anixart/api/api.py index c21d310..88fbcf7 100644 --- a/anixart/api/api.py +++ b/anixart/api/api.py @@ -3,7 +3,7 @@ import logging import requests from ..auth import AnixartAuth -from ..errors import AnixartInitError, AnixartAPIRequestError +from ..exceptions import AnixartInitError, AnixartAPIRequestError from ..request_handler import AnixartRequestsHandler _log_name = "file:%-29s -> %s" % ("", "%s") diff --git a/anixart/api/api.pyi b/anixart/api/api.pyi index 44f106a..4e82064 100644 --- a/anixart/api/api.pyi +++ b/anixart/api/api.pyi @@ -12,7 +12,7 @@ class AnixartUserAccount: ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Usage: >>> user = AnixartUserAccount("login", "password", config_file="anixart_data.json") - >>> print(user.login) + >>> print(user.__login) Availible params: ~~~~~~~~~~~~~~~~~ * login -> Your anixart nick diff --git a/anixart/auth/__init__.py b/anixart/auth/__init__.py new file mode 100644 index 0000000..7f5464a --- /dev/null +++ b/anixart/auth/__init__.py @@ -0,0 +1 @@ +from .account import AnixartAccount, AnixartAccountToken diff --git a/anixart/auth/account.py b/anixart/auth/account.py new file mode 100644 index 0000000..00b3dab --- /dev/null +++ b/anixart/auth/account.py @@ -0,0 +1,112 @@ +import json +from pathlib import Path + +import requests + +from anixart.exceptions import AnixartInitError + + +class AnixartAccount: + def __init__(self, username: str, password: str): + self._username = username + self._password = password + if not isinstance(username, str) or not isinstance(password, str): + raise AnixartInitError("Auth data must be strings.") + + self._token = None + self._session = requests.Session() + + @property + def username(self): + return self._username + + @property + def session(self): + return self._session + + @property + def token(self): + return self._token + + def to_file(self, filename: str | Path): + """Save the account information to a file.""" + acc = AnixartAccountSaved.from_account(filename, self) + acc.save() + return acc + + @classmethod + def from_file(cls, filename: str | Path): + """Load the account information from a file.""" + acc = AnixartAccountSaved(filename) + acc.load() + return acc + + def login(self): + """Login to Anixart and return the token.""" + # TODO: Implement login logic here + + def __str__(self): + return f'AnixartAccount(login={self._username!r}, password={"*" * len(self._password)!r})' + + def __repr__(self): + return f"<{self}>" + +class AnixartAccountSaved(AnixartAccount): + + def __init__(self, account_file: str | Path = "anixart_account.json"): + super().__init__("", "") + self._file = Path(account_file) + + def save(self): + """Save the account information to a file.""" + data = { + "username": self._username, + "password": self._password, + "token": self._token + } + with open(self._file, 'w') as f: + json.dump(data, f, indent=4) + + def load(self): + """Load the account information from a file.""" + if not self._file.exists(): + raise AnixartInitError(f"Account file {self._file} does not exist.") + with open(self._file, 'r') as f: + data = json.load(f) + self._username = data.get("username") + self._password = data.get("password") + self._token = data.get("token") + if not self._username or not self._password: + raise AnixartInitError("Login and password must be provided in the account file.") + + @classmethod + def from_account(cls, account_file: str | Path, account: AnixartAccount): + c = cls(account_file) + c._username = account.username + c._password = account._password + c._token = account.token + return c + + def login(self): + """Login to Anixart using the saved credentials.""" + # Проверяем токен, если просрочен, то логинимся + # Если токен валиден, то просто дальше работаем + # TODO: Implement login logic here + pass + + def __str__(self): + return f'AnixartAccountSaved(account_file={self._file!r}")' + +class AnixartAccountToken(AnixartAccount): + + def __init__(self, token): + super().__init__("mradx", "") # Пасхалка) + self._token = token + + def login(self): + """Login to Anixart and return information about the tokens.""" + # TODO: Implement login logic here + pass + + def __str__(self): + return f'AnixartAccountToken(token={self._token!r}")' diff --git a/anixart/auth/erros.py b/anixart/auth/erros.py new file mode 100644 index 0000000..670357a --- /dev/null +++ b/anixart/auth/erros.py @@ -0,0 +1,7 @@ +from enum import IntEnum + + +class AnixartAuthError(IntEnum): + """ Error codes for AnixartApi authentication.""" + INCORRECT_LOGIN = 1 + INCORRECT_PASSWORD = 2 diff --git a/anixart/auth.py b/anixart/auth/handler.py similarity index 87% rename from anixart/auth.py rename to anixart/auth/handler.py index b245066..17a3d1e 100644 --- a/anixart/auth.py +++ b/anixart/auth/handler.py @@ -3,7 +3,7 @@ import logging import os.path from .endpoints import SING_IN, CHANGE_PASSWORD, PROFILE -from .errors import AnixartAuthError +from .exceptions import AnixartAuthError from .request_handler import AnixartRequestsHandler @@ -47,20 +47,20 @@ class AnixartAuth(AnixartRequestsHandler): uid = config.get("id") token = config.get("token") if not self.get(PROFILE.format(uid), {"token": token}).json().get("is_my_profile") or \ - self.user.login != config.get("login"): + self.user.__login != config.get("login"): logging.getLogger("anixart.api.AnixAPI").debug("Invalid config file. Re login.") else: self.user.id = uid - self.user.token = token + self.user.__token = token return config - payload = {"login": self.user.login, "password": self.user.password} + payload = {"login": self.user.__login, "password": self.user.__password} res = self.post(SING_IN, payload) ready = _parse_response(res) uid = ready["profile"]["id"] token = ready["profileToken"]["token"] self.user.id = uid - self.user.token = token - self._save_config({"id": uid, "token": token, "login": self.user.login}) + self.user.__token = token + self._save_config({"id": uid, "token": token, "login": self.user.__login}) return ready def change_password(self, old, new): diff --git a/anixart/endpoints.py b/anixart/endpoints.py index c12aaac..b20e1c0 100644 --- a/anixart/endpoints.py +++ b/anixart/endpoints.py @@ -1,27 +1,5 @@ # -*- coding: utf-8 -*- -class AnixartComment: - DISLIKE = 1 - LIKE = 2 - - -class AnixartProfileVotedSort: - LAST_FIRST = 1 - OLD_FIRST = 2 - STAR_5 = 3 - STAR_4 = 4 - STAR_3 = 5 - STAR_2 = 6 - STAR_1 = 7 - - -class AnixartLists: - WATCHING = 1 - IN_PLANS = 2 - WATCHED = 3 - POSTPONED = 4 - DROPPED = 5 - API_URL = "https://api.anixart.tv" diff --git a/anixart/enums.py b/anixart/enums.py new file mode 100644 index 0000000..190c7cb --- /dev/null +++ b/anixart/enums.py @@ -0,0 +1,24 @@ +from enum import IntEnum + + +class AnixartComment(IntEnum): + DISLIKE = 1 + LIKE = 2 + + +class AnixartProfileVotedSort(IntEnum): + LAST_FIRST = 1 + OLD_FIRST = 2 + STAR_5 = 3 + STAR_4 = 4 + STAR_3 = 5 + STAR_2 = 6 + STAR_1 = 7 + + +class AnixartLists(IntEnum): + WATCHING = 1 + IN_PLANS = 2 + WATCHED = 3 + POSTPONED = 4 + DROPPED = 5 diff --git a/anixart/errors.py b/anixart/errors.py deleted file mode 100644 index e93b52f..0000000 --- a/anixart/errors.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- - -class AnixartInitError(Exception): - pass - - -class AnixartAuthError(Exception): - pass - - -class AnixartAPIRequestError(Exception): - pass - - -class AnixartAPIError(Exception): - pass diff --git a/anixart/exceptions.py b/anixart/exceptions.py new file mode 100644 index 0000000..d9b0c2e --- /dev/null +++ b/anixart/exceptions.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- + +class AnixartBasError(Exception): ... + +# Init errors + +class AnixartInitError(AnixartBasError, TypeError): ... + +# API errors +class AnixartAPIError(AnixartBasError): ... + +class AnixartAuthError(AnixartAPIError): ... + +class AnixartAPIRequestError(AnixartAPIError): ... + diff --git a/anixart/request_handler.py b/anixart/request_handler.py index a1309a1..f28bc7a 100644 --- a/anixart/request_handler.py +++ b/anixart/request_handler.py @@ -4,9 +4,9 @@ import logging import requests -from .__version__ import __version__, __build__ +from .__meta__ import __version__, __build__ from .endpoints import API_URL -from .errors import AnixartAPIRequestError, AnixartAPIError +from .exceptions import AnixartAPIRequestError, AnixartAPIError _log_name = "file:%-28s -> %s" % ("", "%s") diff --git a/setup.py b/setup.py deleted file mode 100644 index 523285a..0000000 --- a/setup.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- - -import os -import sys - -from setuptools import setup - -here = os.path.abspath(os.path.dirname(__file__)) - -packages = ['anixart'] - -requires = ['requests'] - -# 'setup.py publish' shortcut. -if sys.argv[-1] == 'publish': - os.system('py -m build') - os.system('py -m twine upload --repository testpypi dist/*') - os.system('py -m twine upload --repository pypi dist/*') - sys.exit() - -about = {} -with open(os.path.join(here, 'anixart', '__version__.py'), 'r', encoding='utf-8') as f: - exec(f.read(), about) - -with open('README.md', 'r', encoding='utf-8') as f: - readme = f.read() - -setup( - name=about['__title__'], - version=about['__version__'], - description=about['__description__'], - long_description=readme, - long_description_content_type='text/markdown', - author=about['__author__'], - author_email=about['__author_email__'], - url=about['__url__'], - packages=packages, - package_data={'': ['LICENSE']}, - package_dir={'anixart': 'anixart'}, - include_package_data=True, - install_requires=requires, - license=about['__license__'], - classifiers=[ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Natural Language :: Russian", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", - "License :: Other/Proprietary License", - "Operating System :: OS Independent", - ], - project_urls={ - 'Documentation': 'https://anixart.readthedocs.io/', - 'Source': 'https://github.com/SantaSpeen/anixart', - }, - python_requires=">=3.7", -)