diff --git a/.gitignore b/.gitignore index ddc7b0c..0faebdf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ test.py +like.py venv/ __pycache__/ dist diff --git a/itd/client.py b/itd/client.py index 714f5cd..3a4b4e5 100644 --- a/itd/client.py +++ b/itd/client.py @@ -2,7 +2,7 @@ from uuid import UUID from _io import BufferedReader from typing import cast -from requests.exceptions import HTTPError, ConnectionError +from requests.exceptions import ConnectionError, HTTPError from itd.routes.users import get_user, update_profile, follow, unfollow, get_followers, get_following, update_privacy from itd.routes.etc import get_top_clans, get_who_to_follow, get_platform_status @@ -26,20 +26,18 @@ from itd.models.pagination import Pagination from itd.models.verification import Verification, VerificationStatus from itd.request import set_cookies -from itd.exceptions import NoCookie, NoAuthData, SamePassword, InvalidOldPassword, NotFound, ValidationError, UserBanned, PendingRequestExists, Forbidden, UsernameTaken +from itd.exceptions import NoCookie, NoAuthData, SamePassword, InvalidOldPassword, NotFound, ValidationError, UserBanned, PendingRequestExists, Forbidden, UsernameTaken, CantFollowYourself, Unauthorized def refresh_on_error(func): def wrapper(self, *args, **kwargs): - try: - return func(self, *args, **kwargs) - except HTTPError as e: - if '401' in str(e): + if self.cookies: + try: + return func(self, *args, **kwargs) + except (Unauthorized, ConnectionError, HTTPError): self.refresh_auth() return func(self, *args, **kwargs) - raise e - except ConnectionError: - self.refresh_auth() + else: return func(self, *args, **kwargs) return wrapper @@ -203,6 +201,7 @@ class Client: Raises: NotFound: Пользователь не найден + CantFollowYourself: Невозможно подписаться на самого себе Returns: int: Число подписчиков после подписки @@ -210,6 +209,8 @@ class Client: res = follow(self.token, username) if res.json().get('error', {}).get('code') == 'NOT_FOUND': raise NotFound('User') + if res.json().get('error', {}).get('code') == 'VALIDATION_ERROR' and res.status_code == 400: + raise CantFollowYourself() res.raise_for_status() return res.json()['followersCount'] diff --git a/itd/exceptions.py b/itd/exceptions.py index f1cc39f..1963ed9 100644 --- a/itd/exceptions.py +++ b/itd/exceptions.py @@ -7,14 +7,20 @@ class NoAuthData(Exception): return 'No auth data. Provide token or cookies' class InvalidCookie(Exception): + def __init__(self, code: str): + self.code = code def __str__(self): - return f'Invalid cookie data' + if self.code == 'SESSION_NOT_FOUND': + return f'Invalid cookie data: Session not found (incorrect refresh token)' + elif self.code == 'REFRESH_TOKEN_MISSING': + return f'Invalid cookie data: No refresh token' + # SESSION_REVOKED + return f'Invalid cookie data: Session revoked (logged out)' class InvalidToken(Exception): def __str__(self): return f'Invalid access token' - class SamePassword(Exception): def __str__(self): return 'Old and new password must not equals' @@ -58,4 +64,12 @@ class Forbidden(Exception): class UsernameTaken(Exception): def __str__(self): - return 'Username is already taken' \ No newline at end of file + return 'Username is already taken' + +class CantFollowYourself(Exception): + def __str__(self): + return 'Cannot follow yourself' + +class Unauthorized(Exception): + def __str__(self) -> str: + return 'Auth required - refresh token' \ No newline at end of file diff --git a/itd/request.py b/itd/request.py index 909ed31..ac4a2d7 100644 --- a/itd/request.py +++ b/itd/request.py @@ -3,7 +3,7 @@ from _io import BufferedReader from requests import Session from requests.exceptions import JSONDecodeError -from itd.exceptions import InvalidToken, InvalidCookie, RateLimitExceeded +from itd.exceptions import InvalidToken, InvalidCookie, RateLimitExceeded, Unauthorized s = Session() @@ -35,10 +35,13 @@ def fetch(token: str, method: str, url: str, params: dict = {}, files: dict[str, try: if res.json().get('error', {}).get('code') == 'RATE_LIMIT_EXCEEDED': raise RateLimitExceeded(res.json()['error'].get('retryAfter', 0)) + if res.json().get('error', {}).get('code') == 'UNAUTHORIZED': + raise Unauthorized() except JSONDecodeError: pass - print(res.text) + if not res.ok: + print(res.text) return res @@ -82,8 +85,10 @@ def auth_fetch(cookies: str, method: str, url: str, params: dict = {}, token: st try: if res.json().get('error', {}).get('code') == 'RATE_LIMIT_EXCEEDED': raise RateLimitExceeded(res.json()['error'].get('retryAfter', 0)) - if res.json().get('error', {}).get('code') in ('SESSION_NOT_FOUND', 'REFRESH_TOKEN_MISSING'): - raise InvalidCookie() + if res.json().get('error', {}).get('code') in ('SESSION_NOT_FOUND', 'REFRESH_TOKEN_MISSING', 'SESSION_REVOKED'): + raise InvalidCookie(res.json()['error']['code']) + if res.json().get('error', {}).get('code') == 'UNAUTHORIZED': + raise Unauthorized() except JSONDecodeError: pass