feat: add cant follow yourself error

This commit is contained in:
firedotguy
2026-02-04 22:52:10 +03:00
parent ba78457de5
commit 2f026a32d7
4 changed files with 37 additions and 16 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
test.py test.py
like.py
venv/ venv/
__pycache__/ __pycache__/
dist dist

View File

@@ -2,7 +2,7 @@ from uuid import UUID
from _io import BufferedReader from _io import BufferedReader
from typing import cast 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.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 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.models.verification import Verification, VerificationStatus
from itd.request import set_cookies 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 refresh_on_error(func):
def wrapper(self, *args, **kwargs): def wrapper(self, *args, **kwargs):
try: if self.cookies:
return func(self, *args, **kwargs) try:
except HTTPError as e: return func(self, *args, **kwargs)
if '401' in str(e): except (Unauthorized, ConnectionError, HTTPError):
self.refresh_auth() self.refresh_auth()
return func(self, *args, **kwargs) return func(self, *args, **kwargs)
raise e else:
except ConnectionError:
self.refresh_auth()
return func(self, *args, **kwargs) return func(self, *args, **kwargs)
return wrapper return wrapper
@@ -203,6 +201,7 @@ class Client:
Raises: Raises:
NotFound: Пользователь не найден NotFound: Пользователь не найден
CantFollowYourself: Невозможно подписаться на самого себе
Returns: Returns:
int: Число подписчиков после подписки int: Число подписчиков после подписки
@@ -210,6 +209,8 @@ class Client:
res = follow(self.token, username) res = follow(self.token, username)
if res.json().get('error', {}).get('code') == 'NOT_FOUND': if res.json().get('error', {}).get('code') == 'NOT_FOUND':
raise NotFound('User') raise NotFound('User')
if res.json().get('error', {}).get('code') == 'VALIDATION_ERROR' and res.status_code == 400:
raise CantFollowYourself()
res.raise_for_status() res.raise_for_status()
return res.json()['followersCount'] return res.json()['followersCount']

View File

@@ -7,14 +7,20 @@ class NoAuthData(Exception):
return 'No auth data. Provide token or cookies' return 'No auth data. Provide token or cookies'
class InvalidCookie(Exception): class InvalidCookie(Exception):
def __init__(self, code: str):
self.code = code
def __str__(self): 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): class InvalidToken(Exception):
def __str__(self): def __str__(self):
return f'Invalid access token' return f'Invalid access token'
class SamePassword(Exception): class SamePassword(Exception):
def __str__(self): def __str__(self):
return 'Old and new password must not equals' return 'Old and new password must not equals'
@@ -59,3 +65,11 @@ class Forbidden(Exception):
class UsernameTaken(Exception): class UsernameTaken(Exception):
def __str__(self): def __str__(self):
return 'Username is already taken' 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'

View File

@@ -3,7 +3,7 @@ from _io import BufferedReader
from requests import Session from requests import Session
from requests.exceptions import JSONDecodeError from requests.exceptions import JSONDecodeError
from itd.exceptions import InvalidToken, InvalidCookie, RateLimitExceeded from itd.exceptions import InvalidToken, InvalidCookie, RateLimitExceeded, Unauthorized
s = Session() s = Session()
@@ -35,10 +35,13 @@ def fetch(token: str, method: str, url: str, params: dict = {}, files: dict[str,
try: try:
if res.json().get('error', {}).get('code') == 'RATE_LIMIT_EXCEEDED': if res.json().get('error', {}).get('code') == 'RATE_LIMIT_EXCEEDED':
raise RateLimitExceeded(res.json()['error'].get('retryAfter', 0)) raise RateLimitExceeded(res.json()['error'].get('retryAfter', 0))
if res.json().get('error', {}).get('code') == 'UNAUTHORIZED':
raise Unauthorized()
except JSONDecodeError: except JSONDecodeError:
pass pass
print(res.text) if not res.ok:
print(res.text)
return res return res
@@ -82,8 +85,10 @@ def auth_fetch(cookies: str, method: str, url: str, params: dict = {}, token: st
try: try:
if res.json().get('error', {}).get('code') == 'RATE_LIMIT_EXCEEDED': if res.json().get('error', {}).get('code') == 'RATE_LIMIT_EXCEEDED':
raise RateLimitExceeded(res.json()['error'].get('retryAfter', 0)) raise RateLimitExceeded(res.json()['error'].get('retryAfter', 0))
if res.json().get('error', {}).get('code') in ('SESSION_NOT_FOUND', 'REFRESH_TOKEN_MISSING'): if res.json().get('error', {}).get('code') in ('SESSION_NOT_FOUND', 'REFRESH_TOKEN_MISSING', 'SESSION_REVOKED'):
raise InvalidCookie() raise InvalidCookie(res.json()['error']['code'])
if res.json().get('error', {}).get('code') == 'UNAUTHORIZED':
raise Unauthorized()
except JSONDecodeError: except JSONDecodeError:
pass pass