mirror of
https://github.com/SantaSpeen/anixart.git
synced 2025-07-01 23:47:00 +00:00
* Перетащил файлы из прошлого проекта
- Поменял нейминиги - Оптимизировал `request_handler.py` - Оптимизировал `errors.py` - Оптимизировал `auth.py` - Оптимизировал `api/api.py` - Добавил `api/api.pyi` * Добавил пример: `/examples/auth.py` * Обновил зависимости
This commit is contained in:
parent
c6bfda72df
commit
a6f1655449
@ -0,0 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from .__version__ import __license__, __description__
|
||||
from .__version__ import __version__, __url__, __build__, __title__, __author__, __author_email__, __copyright__
|
||||
|
||||
from .endpoints import *
|
||||
|
||||
from .api.api import AnixartUserAccount, AnixartAPI
|
@ -3,8 +3,8 @@
|
||||
__title__ = 'anixart'
|
||||
__description__ = 'Wrapper for using the Anixart API.'
|
||||
__url__ = 'https://github.com/SantaSpeen/anixart'
|
||||
__version__ = '0.1.0'
|
||||
__build__ = 1
|
||||
__version__ = '0.2.1'
|
||||
__build__ = 3
|
||||
__author__ = 'SantaSpeen'
|
||||
__author_email__ = 'SantaSpeen@gmail.com'
|
||||
__license__ = "FPA"
|
||||
|
78
anixart/api/api.py
Normal file
78
anixart/api/api.py
Normal file
@ -0,0 +1,78 @@
|
||||
import logging
|
||||
|
||||
import requests
|
||||
|
||||
from ..auth import AnixartAuth
|
||||
from ..errors import AnixartInitError, AnixartAPIRequestError
|
||||
from ..request_handler import AnixartRequestsHandler
|
||||
|
||||
_log_name = "file:%-29s -> %s" % ("<anixart.api:%-4i>", "%s")
|
||||
|
||||
|
||||
class AnixartUserAccount:
|
||||
def __init__(self, login, password, config_file="anixart_data.json", **kwargs):
|
||||
self.kwargs = kwargs
|
||||
log_level = logging.CRITICAL
|
||||
log_format = '[%(name)-43s] %(levelname)-5s: %(message)s'
|
||||
if kwargs.get("loglevel") is not None:
|
||||
log_level = kwargs.get("loglevel")
|
||||
if kwargs.get("logformat") is not None:
|
||||
log_format = kwargs.get("logformat")
|
||||
logging.basicConfig(level=log_level, format=log_format)
|
||||
init_log = logging.getLogger("anixart.api.AnixUserAccount")
|
||||
init_log.debug(_log_name, 23, "__init__ - INIT")
|
||||
self.login = login
|
||||
self.password = password
|
||||
if not isinstance(login, str) or not isinstance(password, str):
|
||||
raise AnixartInitError("Use normal auth data. In string.")
|
||||
self.token = None
|
||||
self.id = None
|
||||
self.config_file = config_file
|
||||
self.session = requests.Session()
|
||||
init_log.debug(_log_name, 32, f"{str(self)}")
|
||||
init_log.debug(_log_name, 33, "__init__() - OK")
|
||||
|
||||
def __str__(self):
|
||||
return f'AnixartUserAccount(login="{self.login}", password="{self.password}", ' \
|
||||
f'config_file="{self.config_file}", kwargs="{self.kwargs}")'
|
||||
|
||||
def get_login(self):
|
||||
return self.login
|
||||
|
||||
def get_password(self):
|
||||
return self.password
|
||||
|
||||
def get_token(self):
|
||||
return self.token
|
||||
|
||||
def get_id(self):
|
||||
return self.id
|
||||
|
||||
|
||||
class AnixartAPI:
|
||||
|
||||
def __init__(self, user: AnixartUserAccount):
|
||||
init_log = logging.getLogger("anixart.api.AnixartAPI")
|
||||
init_log.debug(_log_name, 56, "__init__ - INIT")
|
||||
if not isinstance(user, AnixartUserAccount):
|
||||
init_log.critical('Use anixart.api.AnixartUserAccount for user.')
|
||||
raise AnixartInitError('Use class "AnixartUserAccount" for user.')
|
||||
self.auth = AnixartAuth(user)
|
||||
if user.token is None or user.id is None:
|
||||
init_log.debug(_log_name, 62, "Singing in..")
|
||||
self.auth.sing_in()
|
||||
self.user = user
|
||||
init_log.debug(_log_name, 65, "__init__ - OK.")
|
||||
self.http_handler = AnixartRequestsHandler(user.token, user.session)
|
||||
|
||||
def __str__(self):
|
||||
return f'AnixAPI({self.user})'
|
||||
|
||||
def execute(self, http_method, endpoint, **kwargs):
|
||||
http_method = http_method.upper()
|
||||
if http_method == "GET":
|
||||
return self.http_handler.get(endpoint, **kwargs)
|
||||
elif http_method == "POST":
|
||||
return self.http_handler.post(endpoint, **kwargs)
|
||||
else:
|
||||
raise AnixartAPIRequestError("Allow only GET and POST requests.")
|
65
anixart/api/api.pyi
Normal file
65
anixart/api/api.pyi
Normal file
@ -0,0 +1,65 @@
|
||||
import requests
|
||||
|
||||
from ..auth import AnixartAuth
|
||||
from ..request_handler import AnixartRequestsHandler
|
||||
|
||||
|
||||
class AnixartUserAccount:
|
||||
def __init__(self, login, password, config_file="anixart_data.json", **kwargs):
|
||||
"""
|
||||
Info:
|
||||
Anixart login class object.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Usage:
|
||||
>>> user = AnixartUserAccount("login", "password", config_file="anixart_data.json")
|
||||
>>> print(user.login)
|
||||
Availible params:
|
||||
~~~~~~~~~~~~~~~~~
|
||||
* login -> Your anixart nick
|
||||
* password -> Your anixart password
|
||||
* need_reg -> If you need new account, set True
|
||||
* mail -> Real email for registration.
|
||||
* config_file -> Patch to anixart login cache
|
||||
:param login: Your anixart nick
|
||||
:param password: Anixart password
|
||||
:param need_reg: If you need new account, set True
|
||||
:param email: Real email for registration
|
||||
:param config_file: Patch to anixart login cache
|
||||
:type login: str
|
||||
:type password: str
|
||||
:type need_reg: bool
|
||||
:type email: str
|
||||
:type config_file: str
|
||||
:return: :class:`AnixUserAccount <anixart.api.AnixUserAccount>` object
|
||||
"""
|
||||
self.kwargs: dict = kwargs
|
||||
self.login: str = login
|
||||
self.password: str = password
|
||||
self.config_file: str = config_file
|
||||
self.token: str = None
|
||||
self.id: int = None
|
||||
self.session: requests.Session = requests.Session()
|
||||
|
||||
def __str__(self) -> str: ...
|
||||
def get_login(self) -> str: ...
|
||||
def get_password(self) -> str: ...
|
||||
def get_token(self) -> str: ...
|
||||
def get_id(self) -> int: ...
|
||||
|
||||
class AnixartAPI:
|
||||
def __init__(self, user: AnixartUserAccount):
|
||||
"""
|
||||
Info:
|
||||
Anixart API class object.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Usage:
|
||||
>>> user = AnixartUserAccount("login", "password", config_file="anixart_data.json")
|
||||
>>> anix = AnixartAPI(user)
|
||||
:param user: :class:`AnixUserAccount <anixart.api.AnixUserAccount>` object
|
||||
:return: :class:`AnixAPIRequests <anixart.api.AnixAPIRequests>` object
|
||||
"""
|
||||
self.auth = AnixartAuth(user)
|
||||
self.user = user
|
||||
self.http_handler = AnixartRequestsHandler(user.token, user.session)
|
||||
def __str__(self) -> str: ...
|
||||
def execute(self, http_method: str, endpoint: str) -> requests.Request: ...
|
67
anixart/auth.py
Normal file
67
anixart/auth.py
Normal file
@ -0,0 +1,67 @@
|
||||
import json
|
||||
import logging
|
||||
import os.path
|
||||
|
||||
from .endpoints import SING_IN, CHANGE_PASSWORD, PROFILE
|
||||
from .errors import AnixartAuthError
|
||||
from .request_handler import AnixartRequestsHandler
|
||||
|
||||
|
||||
def _parse_response(data):
|
||||
ready = data.json()
|
||||
ready.update({"status_code": data.status_code})
|
||||
code = ready['code']
|
||||
if code != 0:
|
||||
if code == 2:
|
||||
raise AnixartAuthError("Incorrect login.")
|
||||
if code == 3:
|
||||
raise AnixartAuthError("Incorrect password.")
|
||||
print("\n\n" + data.text + "\n\n")
|
||||
raise AnixartAuthError("Unknown auth error.")
|
||||
return ready
|
||||
|
||||
|
||||
class AnixartAuth(AnixartRequestsHandler):
|
||||
|
||||
def __init__(self, user):
|
||||
super(AnixartAuth, self).__init__(None, user.session, "anixart.auth.AnixAuth")
|
||||
self.user = user
|
||||
self.filename = user.config_file
|
||||
|
||||
def _save_config(self, data):
|
||||
with open(self.filename, "w") as f:
|
||||
json.dump(data, f)
|
||||
return data
|
||||
|
||||
def _open_config(self):
|
||||
if os.path.isfile(self.filename):
|
||||
with open(self.filename, "r") as read_file:
|
||||
data = json.load(read_file)
|
||||
return data
|
||||
else:
|
||||
return None
|
||||
|
||||
def sing_in(self):
|
||||
config = self._open_config()
|
||||
if config:
|
||||
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"):
|
||||
logging.getLogger("anixart.api.AnixAPI").debug("Invalid config file. Re login.")
|
||||
else:
|
||||
self.user.id = uid
|
||||
self.user.token = token
|
||||
return config
|
||||
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})
|
||||
return ready
|
||||
|
||||
def change_password(self, old, new):
|
||||
return self.get(CHANGE_PASSWORD, {"current": old, "new": new, "token": self.user.token})
|
16
anixart/errors.py
Normal file
16
anixart/errors.py
Normal file
@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
class AnixartInitError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class AnixartAuthError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class AnixartAPIRequestError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class AnixartAPIError(Exception):
|
||||
pass
|
91
anixart/request_handler.py
Normal file
91
anixart/request_handler.py
Normal file
@ -0,0 +1,91 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
import requests
|
||||
|
||||
from .__version__ import __version__, __build__
|
||||
from .endpoints import API_URL
|
||||
from .errors import AnixartAPIRequestError, AnixartAPIError
|
||||
_log_name = "file:%-28s -> %s" % ("<Anixart.request_handler:%-3i>", "%s")
|
||||
|
||||
|
||||
def _parse_res_code(res, payload, http_method, http_headers):
|
||||
json = res.json()
|
||||
error = json.get("error")
|
||||
code = json.get("code")
|
||||
if res.status_code >= 400:
|
||||
raise AnixartAPIRequestError(f"\n\nAnixartPyAPIWrapper: ERROR\n"
|
||||
f"Send this info to author: https://t.me/SantaSpeen\n"
|
||||
f"URL: {http_method} {res.url}\n"
|
||||
f"Status code: {res.status_code}\n"
|
||||
f"Res headers: {res.headers}\n"
|
||||
f"Req headers: {http_headers}\n"
|
||||
f"Server res: {json}\n"
|
||||
f"Client req: {payload}\n")
|
||||
if error:
|
||||
raise AnixartAPIRequestError(f"Internal server error: {error}; Payload: {payload}")
|
||||
if code:
|
||||
if code == 0:
|
||||
return
|
||||
else:
|
||||
raise AnixartAPIError(f"AnixartAPI send error code: {code}; Json: {json}")
|
||||
|
||||
|
||||
class AnixartRequestsHandler:
|
||||
|
||||
def __init__(self, token: str = None, session: requests.Session = None,
|
||||
_log_class="Anixart.request_handler.AnixartRequestsHandler"):
|
||||
self.__log = logging.getLogger(_log_class)
|
||||
self.__log.debug(_log_name, 44, f"__init__ - INIT from {self}")
|
||||
if session:
|
||||
self.__session = session
|
||||
else:
|
||||
self.__log.debug(_log_name, 48, "Create new session.")
|
||||
self.__session = requests.Session()
|
||||
self.__session.headers = {
|
||||
'User-Agent': f'AnixartPyAPIWrapper/{__version__}-{__build__}'
|
||||
f' (Linux; Android 12; SantaSpeen AnixartPyAPIWrapper Build/{__build__})'}
|
||||
self.__token = token
|
||||
|
||||
def post(self, method: str, payload: dict = None, is_json: bool = False, **kwargs):
|
||||
if payload is None:
|
||||
payload = {}
|
||||
url = API_URL + method
|
||||
if payload.get("token") is None:
|
||||
if self.__token is not None:
|
||||
payload.update({"token": self.__token})
|
||||
url += "?token=" + self.__token
|
||||
else:
|
||||
token = kwargs.get("token")
|
||||
if token is not None:
|
||||
payload.update({"token": token})
|
||||
url += "?token=" + token
|
||||
kwargs = {"url": url}
|
||||
if is_json:
|
||||
self.__session.headers.update({"Content-Type": "application/json; charset=UTF-8"})
|
||||
self.__session.headers.update({"Content-Length": str(len(str(payload)))})
|
||||
kwargs.update({"json": payload})
|
||||
else:
|
||||
kwargs.update({"data": payload})
|
||||
self.__log.debug(_log_name, 79, f"{'json' if is_json else ''} POST {method}; {payload}")
|
||||
res = self.__session.post(**kwargs)
|
||||
_parse_res_code(res, payload, "POST", self.__session.headers)
|
||||
self.__session.headers["Content-Type"] = ""
|
||||
self.__session.headers["Content-Length"] = ""
|
||||
return res
|
||||
|
||||
def get(self, method: str, payload: dict = None, **kwargs):
|
||||
if payload is None:
|
||||
payload = {}
|
||||
if payload.get("token") is None:
|
||||
if self.__token is not None:
|
||||
payload.update({"token": self.__token})
|
||||
else:
|
||||
token = kwargs.get("token")
|
||||
if token is not None:
|
||||
payload.update({"token": token})
|
||||
self.__log.debug(_log_name, 101, f"GET {method}; {payload}")
|
||||
res = self.__session.get(API_URL + method, params=payload)
|
||||
_parse_res_code(res, payload, "GET", self.__session.headers)
|
||||
return res
|
@ -2,6 +2,32 @@
|
||||
|
||||
## Anixart API Wrapper
|
||||
|
||||
### 28.09.2022
|
||||
#### Version: 0.2.1, Build: 3
|
||||
|
||||
##### Changes:
|
||||
|
||||
* Перетащил файлы из прошлого проекта
|
||||
- Поменял нейминиги
|
||||
- Оптимизировал `request_handler.py`
|
||||
- Оптимизировал `errors.py`
|
||||
- Оптимизировал `auth.py`
|
||||
- Оптимизировал `api/api.py`
|
||||
- Добавил `api/api.pyi`
|
||||
* Добавил пример: `/examples/auth.py`
|
||||
* Обновил зависимости
|
||||
|
||||
##### TODOs:
|
||||
|
||||
* Метод `AnixartAPI.execute()` пересобрать и сделать нормальный хандлер запроса.
|
||||
|
||||
_Из прошлых версий_
|
||||
|
||||
* Проверить эндпоинты через чарлес
|
||||
- Задокументировать методы
|
||||
- Выявить и удалить не рабочие
|
||||
- Выявить и удалить не используемые
|
||||
|
||||
### 27.09.2022
|
||||
[//]: # ( Да, я не билдил, это не ошибка )
|
||||
#### Version: 0.1.0, Build: 1
|
||||
|
@ -0,0 +1,9 @@
|
||||
from anixart import AnixartAPI, AnixartUserAccount, PROFILE
|
||||
|
||||
user = AnixartUserAccount("SantaSpeen", "I_H@ve_Very_Secret_P@ssw0rd!")
|
||||
anix = AnixartAPI(user)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
me = anix.execute("GET", PROFILE.format(user.id))
|
||||
print(me.json())
|
@ -0,0 +1 @@
|
||||
requests~=2.28.1
|
Loading…
x
Reference in New Issue
Block a user