diff --git a/src/classes/baseprocessor.py b/src/classes/baseprocessor.py index c23ce7e..07d5a72 100644 --- a/src/classes/baseprocessor.py +++ b/src/classes/baseprocessor.py @@ -1,10 +1,12 @@ import logging + from common.config import ServerConfig -from common.static import Static -from common.tools import Tools +from common.opcodes import Opcodes from common.proto_tcp import MobileProto from common.proto_web import WebProto -from common.opcodes import Opcodes +from common.static import Static +from common.tools import Tools + class BaseProcessor: def __init__(self, db_pool=None, clients=None, send_event=None, type="socket"): @@ -21,7 +23,7 @@ def __init__(self, db_pool=None, clients=None, send_event=None, type="socket"): self.event = send_event self.logger = logging.getLogger(__name__) - self.type = type + self.type = "mobile" if type == "socket" else type if type == "socket": self.proto = MobileProto() @@ -31,23 +33,26 @@ def __init__(self, db_pool=None, clients=None, send_event=None, type="socket"): async def _send(self, writer, packet): try: # Если объектом является вебсокет, то используем функцию send для отправки - if hasattr(writer, 'send'): + if hasattr(writer, "send"): await writer.send(packet) - else: # В ином случае отправляем как в обычный сокет + else: # В ином случае отправляем как в обычный сокет writer.write(packet) await writer.drain() except Exception: pass async def _send_error(self, seq, opcode, error_type, writer): - payload = self.static.ERROR_TYPES.get(error_type, { - "localizedMessage": "Неизвестная ошибка", - "error": "unknown.error", - "message": "Unknown error", - "title": "Неизвестная ошибка" - }) + payload = self.static.ERROR_TYPES.get( + error_type, + { + "localizedMessage": "Неизвестная ошибка", + "error": "unknown.error", + "message": "Unknown error", + "title": "Неизвестная ошибка", + }, + ) packet = self.proto.pack_packet( cmd=self.proto.CMD_ERR, seq=seq, opcode=opcode, payload=payload ) - await self._send(writer, packet) \ No newline at end of file + await self._send(writer, packet) diff --git a/src/common/config.py b/src/common/config.py index dc14fa9..a0dea08 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -50,4 +50,4 @@ def __init__(self): origins = [x.strip() for x in os.getenv("origins", "").split(",") if x.strip()] if os.getenv("origins") else None ### sms шлюз - sms_gateway_url = os.getenv("sms_gateway_url") or "http://127.0.0.1/sms-gateway" \ No newline at end of file + sms_gateway_url = os.getenv("sms_gateway_url", "") diff --git a/src/common/tools.py b/src/common/tools.py index cb63c28..6f3ea6a 100644 --- a/src/common/tools.py +++ b/src/common/tools.py @@ -96,10 +96,12 @@ def generate_chat( """Генерация чата""" # Генерируем список участников if isinstance(participants, dict): - result_participants = {str(k): v for k, v in participants.items()} + result_participants = { + int(k): int(v) if v is not None else 0 for k, v in participants.items() + } else: # assume list - result_participants = {str(participant): 0 for participant in participants} + result_participants = {int(participant): 0 for participant in participants} result = None @@ -125,7 +127,14 @@ def generate_chat( # Возвращаем return result - async def generate_chats(self, chatIds, db_pool, senderId, include_favourites=True, protocol_type='mobile'): + async def generate_chats( + self, + chatIds, + db_pool, + senderId, + include_favourites=True, + protocol_type="mobile", + ): """Генерирует чаты для отдачи клиенту""" # Готовый список с чатами chats = [] @@ -188,12 +197,14 @@ async def generate_chats(self, chatIds, db_pool, senderId, include_favourites=Tr ) # Получаем ID предыдущего сообщения для избранного (чат ID = senderId) - prevMessageId = await self.get_previous_message_id(senderId, db_pool, protocol_type=protocol_type) + prevMessageId = await self.get_previous_message_id( + senderId, db_pool, protocol_type=protocol_type + ) # Хардкодим в лист чатов избранное chats.append( self.generate_chat( - chatId if protocol_type == 'mobile' else str(chatId), + chatId if protocol_type == "mobile" else str(chatId), senderId, "DIALOG", participants, @@ -241,7 +252,7 @@ async def insert_message( # Возвращаем айдишки return int(message_id), int(last_message_id), message_time - async def get_last_message(self, chatId, db_pool, protocol_type='mobile'): + async def get_last_message(self, chatId, db_pool, protocol_type="mobile"): """Получение последнего сообщения в чате""" async with db_pool.acquire() as db_connection: async with db_connection.cursor() as cursor: @@ -259,7 +270,9 @@ async def get_last_message(self, chatId, db_pool, protocol_type='mobile'): # Собираем сообщение message = { - "id": row.get("id") if protocol_type == 'mobile' else str(row.get('id')), + "id": row.get("id") + if protocol_type == "mobile" + else str(row.get("id")), "time": int(row.get("time")), "type": row.get("type"), "sender": row.get("sender"), @@ -273,7 +286,7 @@ async def get_last_message(self, chatId, db_pool, protocol_type='mobile'): # Возвращаем return message, int(row.get("time")) - async def get_previous_message_id(self, chatId, db_pool, protocol_type='mobile'): + async def get_previous_message_id(self, chatId, db_pool, protocol_type="mobile"): """Получение ID предыдущего сообщения (второго с конца) в чате.""" async with db_pool.acquire() as db_connection: async with db_connection.cursor() as cursor: @@ -285,10 +298,14 @@ async def get_previous_message_id(self, chatId, db_pool, protocol_type='mobile') # Если результат есть, возвращаем его if row: - return row.get("id") if protocol_type == 'mobile' else str(row.get('id')) + return ( + row.get("id") + if protocol_type == "mobile" + else str(row.get("id")) + ) # В ином случае возвращаем 0 - return 0 if protocol_type == 'mobile' else "0" + return 0 if protocol_type == "mobile" else "0" async def get_participant_last_activity(self, chatId, participant_ids, db_pool): """Возвращает словарь {participant_id: last_activity_time} для участников чата.""" @@ -310,11 +327,11 @@ async def get_participant_last_activity(self, chatId, participant_ids, db_pool): rows = await cursor.fetchall() # Собираем список участников без времени последней активности в чате - result = {str(pid): 0 for pid in participant_ids} + result = {int(pid): 0 for pid in participant_ids} # Обновляем для каждого участника время последней активности в чате for row in rows: - sender = str(row["sender"]) + sender = int(row["sender"]) last_time = row["last_time"] if last_time is not None: result[sender] = int(last_time) @@ -330,7 +347,7 @@ async def get_chat_participants(self, chatId, db_pool): (chatId,), ) rows = await cursor.fetchall() - return [row["user_id"] for row in rows] + return [int(row["user_id"]) for row in rows] async def auth_required(self, userPhone, coro, *args): if userPhone: diff --git a/src/main.py b/src/main.py index 68c72c6..212a82f 100644 --- a/src/main.py +++ b/src/main.py @@ -12,6 +12,70 @@ server_config = ServerConfig() +class SQLiteCursorCompat: + def __init__(self, connection): + self.connection = connection + self.cursor = None + + async def __aenter__(self): + self.cursor = await self.connection.cursor() + return self + + async def __aexit__(self, exc_type, exc, tb): + if self.cursor is not None: + await self.cursor.close() + self.cursor = None + + @property + def lastrowid(self): + return None if self.cursor is None else self.cursor.lastrowid + + def _normalize_query(self, query): + return query.replace("%s", "?").replace( + "UNIX_TIMESTAMP()", "CAST(strftime('%s','now') AS INTEGER)" + ) + + async def execute(self, query, params=()): + normalized_query = self._normalize_query(query) + if params is None: + params = () + elif not isinstance(params, (tuple, list, dict)): + params = (params,) + await self.cursor.execute(normalized_query, params) + + async def fetchone(self): + row = await self.cursor.fetchone() + if row is None: + return None + return dict(row) + + async def fetchall(self): + rows = await self.cursor.fetchall() + return [dict(row) for row in rows] + + +class SQLiteConnectionCompat: + def __init__(self, connection): + self.connection = connection + + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc, tb): + return False + + def cursor(self): + return SQLiteCursorCompat(self.connection) + + +class SQLitePoolCompat: + def __init__(self, connection): + self.connection = connection + + def acquire(self): + return SQLiteConnectionCompat(self.connection) + + async def init_db(): """Инициализация базы данных""" @@ -32,8 +96,9 @@ async def init_db(): elif server_config.db_type == "sqlite": import aiosqlite - raw_db = await aiosqlite.connect(server_config.db_file) - db["acquire"] = lambda: raw_db + raw_db = await aiosqlite.connect(server_config.db_file, isolation_level=None) + raw_db.row_factory = aiosqlite.Row + db = SQLitePoolCompat(raw_db) # Возвращаем return db diff --git a/src/oneme/processors/auth.py b/src/oneme/processors/auth.py index c2c70bf..80d2e21 100644 --- a/src/oneme/processors/auth.py +++ b/src/oneme/processors/auth.py @@ -1,22 +1,31 @@ +import hashlib import json +import logging import secrets -import hashlib import time -import logging + import pydantic + from classes.baseprocessor import BaseProcessor +from common.sms import send_sms_code +from oneme.config import OnemeConfig from oneme.models import ( - RequestCodePayloadModel, - VerifyCodePayloadModel, AuthConfirmRegisterPayloadModel, LoginPayloadModel, + RequestCodePayloadModel, + VerifyCodePayloadModel, ) -from oneme.config import OnemeConfig -from common.sms import send_sms_code class AuthProcessors(BaseProcessor): - def __init__(self, db_pool=None, clients=None, send_event=None, telegram_bot=None, type="socket"): + def __init__( + self, + db_pool=None, + clients=None, + send_event=None, + telegram_bot=None, + type="socket", + ): super().__init__(db_pool, clients, send_event, type) self.server_config = OnemeConfig().SERVER_CONFIG self.telegram_bot = telegram_bot @@ -27,7 +36,9 @@ async def auth_request(self, payload, seq, writer): RequestCodePayloadModel.model_validate(payload) except pydantic.ValidationError as error: self.logger.error(f"Возникли ошибки при валидации пакета: {error}") - await self._send_error(seq, self.opcodes.AUTH_REQUEST, self.error_types.INVALID_PAYLOAD, writer) + await self._send_error( + seq, self.opcodes.AUTH_REQUEST, self.error_types.INVALID_PAYLOAD, writer + ) return # Извлекаем телефон из пакета @@ -49,13 +60,16 @@ async def auth_request(self, payload, seq, writer): user = await cursor.fetchone() # Получаем код через SMS шлюз или генерируем локально (безопасность прежде всего) + local_fallback_code = False if self.config.sms_gateway_url: code = await send_sms_code(self.config.sms_gateway_url, phone) if code is None: code = str(secrets.randbelow(900000) + 100000) + local_fallback_code = True else: code = str(secrets.randbelow(900000) + 100000) + local_fallback_code = True # Хешируем code_hash = hashlib.sha256(code.encode()).hexdigest() @@ -68,18 +82,35 @@ async def auth_request(self, payload, seq, writer): # Сохраняем токен await cursor.execute( "INSERT INTO auth_tokens (phone, token_hash, code_hash, expires) VALUES (%s, %s, %s, %s)", - (phone, token_hash, code_hash, expires,) + ( + phone, + token_hash, + code_hash, + expires, + ), ) - # Если тг бот включен, и тг привязан к аккаунту - отправляем туда сообщение - if not self.config.sms_gateway_url and self.telegram_bot and user.get("telegram_id"): - await self.telegram_bot.send_code(chat_id=int(user.get("telegram_id")), phone=phone, code=code) + # Если код был сгенерирован локально, а тг привязан к аккаунту - отправляем туда сообщение + if ( + local_fallback_code + and self.telegram_bot + and user.get("telegram_id") + ): + await self.telegram_bot.send_code( + chat_id=int(user.get("telegram_id")), phone=phone, code=code + ) else: # Пользователь не найден - сохраняем токен со state='register' # чтобы после верификации кода направить на экран регистрации await cursor.execute( "INSERT INTO auth_tokens (phone, token_hash, code_hash, expires, state) VALUES (%s, %s, %s, %s, %s)", - (phone, token_hash, code_hash, expires, "register",) + ( + phone, + token_hash, + code_hash, + expires, + "register", + ), ) # Данные пакета @@ -88,12 +119,15 @@ async def auth_request(self, payload, seq, writer): "codeLength": 6, "requestMaxDuration": 60000, "requestCountLeft": 10, - "altActionDuration": 60000 + "altActionDuration": 60000, } # Собираем пакет packet = self.proto.pack_packet( - cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.AUTH_REQUEST, payload=payload + cmd=self.proto.CMD_OK, + seq=seq, + opcode=self.opcodes.AUTH_REQUEST, + payload=payload, ) # Отправляем @@ -106,7 +140,9 @@ async def auth(self, payload, seq, writer, deviceType, deviceName): VerifyCodePayloadModel.model_validate(payload) except pydantic.ValidationError as error: self.logger.error(f"Возникли ошибки при валидации пакета: {error}") - await self._send_error(seq, self.opcodes.AUTH, self.error_types.INVALID_PAYLOAD, writer) + await self._send_error( + seq, self.opcodes.AUTH, self.error_types.INVALID_PAYLOAD, writer + ) return # Извлекаем данные из пакета @@ -127,18 +163,22 @@ async def auth(self, payload, seq, writer, deviceType, deviceName): # Ищем токен await cursor.execute( "SELECT * FROM auth_tokens WHERE token_hash = %s AND expires > UNIX_TIMESTAMP()", - (hashed_token,) + (hashed_token,), ) stored_token = await cursor.fetchone() # Если токен просрочен, или его нет - отправляем ошибку if stored_token is None: - await self._send_error(seq, self.opcodes.AUTH, self.error_types.CODE_EXPIRED, writer) + await self._send_error( + seq, self.opcodes.AUTH, self.error_types.CODE_EXPIRED, writer + ) return # Проверяем код if stored_token.get("code_hash") != hashed_code: - await self._send_error(seq, self.opcodes.AUTH, self.error_types.INVALID_CODE, writer) + await self._send_error( + seq, self.opcodes.AUTH, self.error_types.INVALID_CODE, writer + ) return # Если это новый пользователь - переводим токен в state='verified' @@ -146,48 +186,60 @@ async def auth(self, payload, seq, writer, deviceType, deviceName): if stored_token.get("state") == "register": await cursor.execute( "UPDATE auth_tokens SET state = %s WHERE token_hash = %s", - ("verified", hashed_token,) + ( + "verified", + hashed_token, + ), ) packet = self.proto.pack_packet( - cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.AUTH, + cmd=self.proto.CMD_OK, + seq=seq, + opcode=self.opcodes.AUTH, payload={ - "tokenAttrs": { - "REGISTER": { - "token": token - } - }, - "presetAvatars": [] - } + "tokenAttrs": {"REGISTER": {"token": token}}, + "presetAvatars": [], + }, ) await self._send(writer, packet) return # Ищем аккаунт - await cursor.execute("SELECT * FROM users WHERE phone = %s", (stored_token.get("phone"),)) + await cursor.execute( + "SELECT * FROM users WHERE phone = %s", (stored_token.get("phone"),) + ) account = await cursor.fetchone() # Удаляем токен - await cursor.execute("DELETE FROM auth_tokens WHERE token_hash = %s", (hashed_token,)) + await cursor.execute( + "DELETE FROM auth_tokens WHERE token_hash = %s", (hashed_token,) + ) # Создаем сессию await cursor.execute( "INSERT INTO tokens (phone, token_hash, device_type, device_name, location, time) VALUES (%s, %s, %s, %s, %s, %s)", - (stored_token.get("phone"), hashed_login, deviceType, deviceName, "Little Saint James Island", int(time.time()),) # весь покрытый зеленью, абсолютно весь, остров невезения в океане есть + ( + stored_token.get("phone"), + hashed_login, + deviceType, + deviceName, + "Little Saint James Island", + int(time.time()), + ), # весь покрытый зеленью, абсолютно весь, остров невезения в океане есть ) # Генерируем профиль # Аватарка с биографией - photoId = None if not account.get("avatar_id") else int(account.get("avatar_id")) + photoId = ( + None if not account.get("avatar_id") else int(account.get("avatar_id")) + ) avatar_url = None if not photoId else self.config.avatar_base_url + photoId - description = None if not account.get("description") else account.get("description") + description = ( + None if not account.get("description") else account.get("description") + ) # Собираем данные пакета payload = { - "tokenAttrs": { - "LOGIN": { - "token": login - } - }, + "tokenAttrs": {"LOGIN": {"token": login}}, "profile": self.tools.generate_profile( id=account.get("id"), phone=int(account.get("phone")), @@ -201,8 +253,8 @@ async def auth(self, payload, seq, writer, deviceType, deviceName): accountStatus=int(account.get("accountstatus")), profileOptions=json.loads(account.get("profileoptions")), includeProfileOptions=True, - username=account.get("username") - ) + username=account.get("username"), + ), } # Создаем пакет @@ -220,7 +272,9 @@ async def auth_confirm(self, payload, seq, writer, deviceType, deviceName): AuthConfirmRegisterPayloadModel.model_validate(payload) except pydantic.ValidationError as error: self.logger.error(f"Возникли ошибки при валидации пакета: {error}") - await self._send_error(seq, self.opcodes.AUTH_CONFIRM, self.error_types.INVALID_PAYLOAD, writer) + await self._send_error( + seq, self.opcodes.AUTH_CONFIRM, self.error_types.INVALID_PAYLOAD, writer + ) return # Извлекаем данные из пакета @@ -240,13 +294,21 @@ async def auth_confirm(self, payload, seq, writer, deviceType, deviceName): # Ищем токен - он должен быть в state='verified' await cursor.execute( "SELECT * FROM auth_tokens WHERE token_hash = %s AND expires > UNIX_TIMESTAMP() AND state = %s", - (hashed_token, "verified",) + ( + hashed_token, + "verified", + ), ) stored_token = await cursor.fetchone() # Если токен не найден или просрочен - отправляем ошибку if stored_token is None: - await self._send_error(seq, self.opcodes.AUTH_CONFIRM, self.error_types.CODE_EXPIRED, writer) + await self._send_error( + seq, + self.opcodes.AUTH_CONFIRM, + self.error_types.CODE_EXPIRED, + writer, + ) return phone = stored_token.get("phone") @@ -254,7 +316,12 @@ async def auth_confirm(self, payload, seq, writer, deviceType, deviceName): # Проверяем что пользователь с таким телефоном ещё не существует await cursor.execute("SELECT id FROM users WHERE phone = %s", (phone,)) if await cursor.fetchone(): - await self._send_error(seq, self.opcodes.AUTH_CONFIRM, self.error_types.INVALID_PAYLOAD, writer) + await self._send_error( + seq, + self.opcodes.AUTH_CONFIRM, + self.error_types.INVALID_PAYLOAD, + writer, + ) return now_ms = int(time.time() * 1000) @@ -269,10 +336,18 @@ async def auth_confirm(self, payload, seq, writer, deviceType, deviceName): VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """, ( - self.tools.generate_id(), phone, None, first_name, last_name, None, - json.dumps([]), json.dumps(["TT", "ONEME"]), - 0, str(now_ms), str(now_s), - ) + self.tools.generate_id(), + phone, + None, + first_name, + last_name, + None, + json.dumps([]), + json.dumps(["TT", "ONEME"]), + 0, + str(now_ms), + str(now_s), + ), ) user_id = cursor.lastrowid @@ -290,16 +365,25 @@ async def auth_confirm(self, payload, seq, writer, deviceType, deviceName): json.dumps(self.static.USER_FOLDERS), json.dumps(self.static.USER_SETTINGS), json.dumps({}), - ) + ), ) # Удаляем токен - await cursor.execute("DELETE FROM auth_tokens WHERE token_hash = %s", (hashed_token,)) + await cursor.execute( + "DELETE FROM auth_tokens WHERE token_hash = %s", (hashed_token,) + ) # Создаем сессию await cursor.execute( "INSERT INTO tokens (phone, token_hash, device_type, device_name, location, time) VALUES (%s, %s, %s, %s, %s, %s)", - (phone, hashed_login, deviceType or "ANDROID", deviceName or "Unknown", "Little Saint James Island", now_s,) + ( + phone, + hashed_login, + deviceType or "ANDROID", + deviceName or "Unknown", + "Little Saint James Island", + now_s, + ), ) # Генерируем профиль @@ -316,7 +400,7 @@ async def auth_confirm(self, payload, seq, writer, deviceType, deviceName): accountStatus=0, profileOptions=[], includeProfileOptions=True, - username=None + username=None, ) # Собираем данные пакета @@ -324,17 +408,22 @@ async def auth_confirm(self, payload, seq, writer, deviceType, deviceName): "userToken": "0", "profile": profile, "tokenType": "LOGIN", - "token": login + "token": login, } # Создаем пакет packet = self.proto.pack_packet( - cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.AUTH_CONFIRM, payload=payload + cmd=self.proto.CMD_OK, + seq=seq, + opcode=self.opcodes.AUTH_CONFIRM, + payload=payload, ) # Отправляем await self._send(writer, packet) - self.logger.info(f"Новый пользователь зарегистрирован: phone={phone} id={user_id} name={first_name} {last_name}") + self.logger.info( + f"Новый пользователь зарегистрирован: phone={phone} id={user_id} name={first_name} {last_name}" + ) async def login(self, payload, seq, writer): """Обработчик авторизации клиента на сервере""" @@ -343,9 +432,11 @@ async def login(self, payload, seq, writer): LoginPayloadModel.model_validate(payload) except pydantic.ValidationError as error: self.logger.error(f"Возникли ошибки при валидации пакета: {error}") - await self._send_error(seq, self.opcodes.LOGIN, self.error_types.INVALID_PAYLOAD, writer) + await self._send_error( + seq, self.opcodes.LOGIN, self.error_types.INVALID_PAYLOAD, writer + ) return - + # Чаты, где состоит пользователь chats = [] @@ -358,33 +449,40 @@ async def login(self, payload, seq, writer): # Ищем токен в бд async with self.db_pool.acquire() as conn: async with conn.cursor() as cursor: - await cursor.execute("SELECT * FROM tokens WHERE token_hash = %s", (hashed_token,)) + await cursor.execute( + "SELECT * FROM tokens WHERE token_hash = %s", (hashed_token,) + ) token_data = await cursor.fetchone() # Если токен не найден, отправляем ошибку if token_data is None: - await self._send_error(seq, self.opcodes.LOGIN, self.error_types.INVALID_TOKEN, writer) + await self._send_error( + seq, self.opcodes.LOGIN, self.error_types.INVALID_TOKEN, writer + ) return # Ищем аккаунт пользователя в бд - await cursor.execute("SELECT * FROM users WHERE phone = %s", (token_data.get("phone"),)) + await cursor.execute( + "SELECT * FROM users WHERE phone = %s", (token_data.get("phone"),) + ) user = await cursor.fetchone() # Ищем данные пользователя в бд - await cursor.execute("SELECT * FROM user_data WHERE phone = %s", (token_data.get("phone"),)) + await cursor.execute( + "SELECT * FROM user_data WHERE phone = %s", + (token_data.get("phone"),), + ) user_data = await cursor.fetchone() # Ищем все чаты, где состоит пользователь await cursor.execute( - "SELECT * FROM chat_participants WHERE user_id = %s", - (user.get('id')) + "SELECT * FROM chat_participants WHERE user_id = %s", + (user.get("id")), ) user_chats = await cursor.fetchall() for chat in user_chats: - chats.append( - chat.get("chat_id") - ) + chats.append(chat.get("chat_id")) # Аватарка с биографией photoId = None if not user.get("avatar_id") else int(user.get("avatar_id")) @@ -405,7 +503,7 @@ async def login(self, payload, seq, writer): accountStatus=int(user.get("accountstatus")), profileOptions=json.loads(user.get("profileoptions")), includeProfileOptions=True, - username=user.get("username") + username=user.get("username"), ) chats = await self.tools.generate_chats( @@ -422,11 +520,11 @@ async def login(self, payload, seq, writer): "presence": {}, "config": { "server": self.server_config, - "user": json.loads(user_data.get("user_config")) + "user": json.loads(user_data.get("user_config")), }, "token": token, "videoChatHistory": False, - "time": int(time.time() * 1000) + "time": int(time.time() * 1000), } # Собираем пакет @@ -443,12 +541,14 @@ async def logout(self, seq, writer, hashedToken): # Удаляем токен из бд async with self.db_pool.acquire() as conn: async with conn.cursor() as cursor: - await cursor.execute("DELETE FROM tokens WHERE token_hash = %s", (hashedToken,)) - + await cursor.execute( + "DELETE FROM tokens WHERE token_hash = %s", (hashedToken,) + ) + # Создаем пакет response = self.proto.pack_packet( cmd=self.proto.CMD_OK, seq=seq, opcode=self.opcodes.LOGOUT, payload=None ) # Отправляем - await self._send(writer, response) \ No newline at end of file + await self._send(writer, response) diff --git a/src/telegrambot/bot.py b/src/telegrambot/bot.py index 26de5c8..4914159 100644 --- a/src/telegrambot/bot.py +++ b/src/telegrambot/bot.py @@ -60,7 +60,7 @@ async def handle_register(self, message: Message): tg_id = str(message.from_user.id) # Проверка ID на наличие в белом списке - if tg_id not in self.whitelist_ids: + if self.whitelist_ids and tg_id not in self.whitelist_ids: await message.answer( self.get_bot_message(self.msg_types.ID_NOT_WHITELISTED) )