From e08e620b92c6e47830258a177ff8e8b0d6f0772f Mon Sep 17 00:00:00 2001 From: Denis Date: Fri, 20 Jun 2025 17:23:51 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B4=D0=BE=D0=BA=D1=81=D1=82=D1=80=D0=B8=D0=BD?= =?UTF-8?q?=D0=B3=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- maxapi/bot.py | 389 ++++++++++++++++-- maxapi/connection/base.py | 35 +- maxapi/context/__init__.py | 56 ++- maxapi/context/state_machine.py | 18 + maxapi/dispatcher.py | 66 ++- maxapi/enums/api_path.py | 8 + maxapi/enums/attachment.py | 8 + maxapi/enums/button_type.py | 7 + maxapi/enums/chat_permission.py | 7 + maxapi/enums/chat_status.py | 7 + maxapi/enums/chat_type.py | 7 + maxapi/enums/http_method.py | 7 + maxapi/enums/intent.py | 8 + maxapi/enums/message_link_type.py | 7 + maxapi/enums/parse_mode.py | 8 + maxapi/enums/sender_action.py | 8 + maxapi/enums/text_style.py | 7 + maxapi/enums/update.py | 9 + maxapi/enums/upload_type.py | 7 + maxapi/filters/handler.py | 18 + maxapi/methods/add_admin_chat.py | 21 +- maxapi/methods/add_members_chat.py | 19 + maxapi/methods/change_info.py | 19 + maxapi/methods/delete_bot_from_chat.py | 19 +- maxapi/methods/delete_chat.py | 17 + maxapi/methods/delete_message.py | 19 + maxapi/methods/delete_pin_message.py | 18 + maxapi/methods/edit_chat.py | 28 +- maxapi/methods/edit_message.py | 26 ++ maxapi/methods/get_chat_by_id.py | 16 + maxapi/methods/get_chat_by_link.py | 20 + maxapi/methods/get_chats.py | 25 +- maxapi/methods/get_list_admin_chat.py | 20 + maxapi/methods/get_me.py | 20 +- maxapi/methods/get_me_from_chat.py | 23 +- maxapi/methods/get_members_chat.py | 28 ++ maxapi/methods/get_messages.py | 33 +- maxapi/methods/get_pinned_message.py | 22 +- maxapi/methods/get_updates.py | 33 +- maxapi/methods/get_upload_url.py | 21 + maxapi/methods/get_video.py | 23 +- maxapi/methods/pin_message.py | 33 +- maxapi/methods/remove_admin.py | 26 +- maxapi/methods/remove_member_chat.py | 28 +- maxapi/methods/send_action.py | 32 +- maxapi/methods/send_callback.py | 63 ++- maxapi/methods/send_message.py | 44 +- maxapi/methods/types/added_admin_chat.py | 13 +- maxapi/methods/types/added_members_chat.py | 13 +- maxapi/methods/types/deleted_bot_from_chat.py | 9 + maxapi/methods/types/deleted_chat.py | 9 + maxapi/methods/types/deleted_message.py | 9 + maxapi/methods/types/deleted_pin_message.py | 9 + maxapi/methods/types/edited_message.py | 9 + .../methods/types/getted_list_admin_chat.py | 9 + maxapi/methods/types/getted_members_chat.py | 9 + maxapi/methods/types/getted_pineed_message.py | 8 + maxapi/methods/types/getted_upload_url.py | 4 +- maxapi/methods/types/pinned_message.py | 9 + maxapi/methods/types/removed_admin.py | 11 +- maxapi/methods/types/removed_member_chat.py | 13 +- maxapi/methods/types/sended_action.py | 9 + maxapi/methods/types/sended_callback.py | 10 + maxapi/methods/types/sended_message.py | 9 +- maxapi/methods/types/upload_file_response.py | 5 - maxapi/types/attachments/attachment.py | 57 ++- maxapi/types/attachments/audio.py | 9 + .../attachments/buttons/attachment_button.py | 9 + maxapi/types/attachments/buttons/button.py | 10 +- .../attachments/buttons/callback_button.py | 13 +- .../types/attachments/buttons/chat_button.py | 11 + .../types/attachments/buttons/link_button.py | 8 + .../attachments/buttons/request_contact.py | 3 + .../buttons/request_geo_location_button.py | 8 + maxapi/types/attachments/contact.py | 8 + maxapi/types/attachments/file.py | 10 + maxapi/types/attachments/image.py | 18 + maxapi/types/attachments/location.py | 10 + maxapi/types/attachments/share.py | 11 + maxapi/types/attachments/sticker.py | 10 + maxapi/types/attachments/upload.py | 19 +- maxapi/types/attachments/video.py | 37 ++ maxapi/types/callback.py | 11 + maxapi/types/chats.py | 63 +++ maxapi/types/command.py | 27 +- maxapi/types/errors.py | 9 + maxapi/types/input_media.py | 28 ++ maxapi/types/message.py | 161 +++++++- maxapi/types/updates/bot_added.py | 11 + maxapi/types/updates/bot_removed.py | 11 + maxapi/types/updates/bot_started.py | 12 + maxapi/types/updates/chat_title_changed.py | 12 + maxapi/types/updates/message_callback.py | 55 ++- maxapi/types/updates/message_created.py | 21 +- maxapi/types/updates/message_edited.py | 19 + maxapi/types/updates/message_removed.py | 19 + maxapi/types/updates/update.py | 9 + maxapi/types/updates/user_added.py | 20 + maxapi/types/updates/user_removed.py | 20 + maxapi/types/users.py | 27 ++ maxapi/utils/inline_keyboard.py | 38 +- 101 files changed, 2222 insertions(+), 152 deletions(-) delete mode 100644 maxapi/methods/types/upload_file_response.py diff --git a/maxapi/bot.py b/maxapi/bot.py index 4f1164a..d63f113 100644 --- a/maxapi/bot.py +++ b/maxapi/bot.py @@ -35,19 +35,51 @@ from .enums.upload_type import UploadType from .types.attachments.attachment import Attachment from .types.attachments.image import PhotoAttachmentRequestPayload -from .types.message import NewMessageLink -from .types.users import ChatAdmin +from .types.message import Messages, NewMessageLink +from .types.users import ChatAdmin, User from .types.command import BotCommand from .connection.base import BaseConnection if TYPE_CHECKING: from .types.message import Message + from .methods.types.added_admin_chat import AddedListAdminChat + from .methods.types.added_members_chat import AddedMembersChat + from .methods.types.deleted_bot_from_chat import DeletedBotFromChat + from .methods.types.deleted_chat import DeletedChat + from .methods.types.deleted_message import DeletedMessage + from .methods.types.deleted_pin_message import DeletedPinMessage + from .methods.types.edited_message import EditedMessage + from .methods.types.getted_list_admin_chat import GettedListAdminChat + from .methods.types.getted_members_chat import GettedMembersChat + from .methods.types.getted_pineed_message import GettedPin + from .methods.types.getted_upload_url import GettedUploadUrl + from .methods.types.pinned_message import PinnedMessage + from .methods.types.removed_admin import RemovedAdmin + from .methods.types.removed_member_chat import RemovedMemberChat + from .methods.types.sended_action import SendedAction + from .methods.types.sended_callback import SendedCallback + from .methods.types.sended_message import SendedMessage + from maxapi.types.attachments.video import Video + from maxapi.types.chats import Chat, ChatMember, Chats + from maxapi.types.updates import UpdateUnion class Bot(BaseConnection): + + """Основной класс для работы с API бота. + + Предоставляет методы для взаимодействия с чатами, сообщениями, + пользователями и другими функциями бота. + """ def __init__(self, token: str): + + """Инициализирует экземпляр бота с указанным токеном. + + :param token: Токен доступа к API бота + """ + super().__init__() self.bot = self @@ -66,7 +98,22 @@ class Bot(BaseConnection): link: NewMessageLink = None, notify: bool = True, parse_mode: ParseMode = None - ): + ) -> SendedMessage: + + """Отправляет сообщение в чат или пользователю. + + :param chat_id: ID чата для отправки (обязателен, если не указан user_id) + :param user_id: ID пользователя для отправки (обязателен, если не указан chat_id) + :param disable_link_preview: Отключить предпросмотр ссылок (по умолчанию False) + :param text: Текст сообщения + :param attachments: Список вложений к сообщению + :param link: Данные ссылки сообщения + :param notify: Отправлять уведомление получателю (по умолчанию True) + :param parse_mode: Режим форматирования текста + + :return: Объект отправленного сообщения + """ + return await SendMessage( bot=self, chat_id=chat_id, @@ -83,7 +130,16 @@ class Bot(BaseConnection): self, chat_id: int = None, action: SenderAction = SenderAction.TYPING_ON - ): + ) -> SendedAction: + + """Отправляет действие в чат (например, "печатает"). + + :param chat_id: ID чата для отправки действия + :param action: Тип действия (по умолчанию SenderAction.TYPING_ON) + + :return: Результат отправки действия + """ + return await SendAction( bot=self, chat_id=chat_id, @@ -98,7 +154,20 @@ class Bot(BaseConnection): link: NewMessageLink = None, notify: bool = True, parse_mode: ParseMode = None - ): + ) -> EditedMessage: + + """Редактирует существующее сообщение. + + :param message_id: ID сообщения для редактирования + :param text: Новый текст сообщения + :param attachments: Новые вложения + :param link: Новая ссылка сообщения + :param notify: Уведомлять получателя об изменении (по умолчанию True) + :param parse_mode: Режим форматирования текста + + :return: Объект отредактированного сообщения + """ + return await EditMessage( bot=self, message_id=message_id, @@ -112,7 +181,15 @@ class Bot(BaseConnection): async def delete_message( self, message_id: str - ): + ) -> DeletedMessage: + + """Удаляет сообщение. + + :param message_id: ID сообщения для удаления + + :return: Результат удаления сообщения + """ + return await DeleteMessage( bot=self, message_id=message_id, @@ -121,7 +198,15 @@ class Bot(BaseConnection): async def delete_chat( self, chat_id: int - ): + ) -> DeletedChat: + + """Удаляет чат. + + :param chat_id: ID чата для удаления + + :return: Результат удаления чата + """ + return await DeleteChat( bot=self, chat_id=chat_id, @@ -134,7 +219,19 @@ class Bot(BaseConnection): from_time: datetime | int = None, to_time: datetime | int = None, count: int = 50, - ): + ) -> Messages: + + """Получает сообщения из чата. + + :param chat_id: ID чата (обязателен, если не указаны message_ids) + :param message_ids: Список ID сообщений для получения + :param from_time: Время начала периода (datetime или timestamp) + :param to_time: Время конца периода (datetime или timestamp) + :param count: Количество сообщений (по умолчанию 50) + + :return: Список сообщений + """ + return await GetMessages( bot=self, chat_id=chat_id, @@ -144,14 +241,47 @@ class Bot(BaseConnection): count=count ).request() - async def get_message(self, message_id: str): - return await self.get_messages(message_ids=[message_id]) + async def get_message( + self, + message_id: str + ) -> Messages: + + """Получает одно сообщение по ID. - async def get_me(self): + :param message_id: ID сообщения + + :return: Объект сообщения + """ + + return await self.get_messages( + message_ids=[message_id] + ) + + async def get_me(self) -> User: + + """Получает информацию о текущем боте. + + :return: Объект пользователя бота + """ + return await GetMe(self).request() - async def get_pin_message(self, chat_id: int): - return await GetPinnedMessage(bot=self, chat_id=chat_id).request() + async def get_pin_message( + self, + chat_id: int + ) -> GettedPin: + + """Получает закрепленное сообщение в чате. + + :param chat_id: ID чата + + :return: Закрепленное сообщение + """ + + return await GetPinnedMessage( + bot=self, + chat_id=chat_id + ).request() async def change_info( self, @@ -159,7 +289,17 @@ class Bot(BaseConnection): description: str = None, commands: List[BotCommand] = None, photo: Dict[str, Any] = None - ): + ) -> User: + + """Изменяет информацию о боте. + + :param name: Новое имя бота + :param description: Новое описание бота + :param commands: Список команд бота + :param photo: Данные фотографии бота + + :return: Обновленная информация о боте + """ return await ChangeInfo( bot=self, @@ -173,18 +313,48 @@ class Bot(BaseConnection): self, count: int = 50, marker: int = None - ): + ) -> Chats: + + """Получает список чатов бота. + + :param count: Количество чатов (по умолчанию 50) + :param marker: Маркер для пагинации + + :return: Список чатов + """ + return await GetChats( bot=self, count=count, marker=marker ).request() - async def get_chat_by_link(self, link: str): - """под вопросом""" + async def get_chat_by_link( + self, + link: str + ) -> Chat: + + """Получает чат по ссылке. + + :param link: Ссылка на чат + + :return: Объект чата + """ + return await GetChatByLink(bot=self, link=link).request() - async def get_chat_by_id(self, id: int): + async def get_chat_by_id( + self, + id: int + ) -> Chat: + + """Получает чат по ID. + + :param id: ID чата + + :return: Объект чата + """ + return await GetChatById(bot=self, id=id).request() async def edit_chat( @@ -194,7 +364,19 @@ class Bot(BaseConnection): title: str = None, pin: str = None, notify: bool = True, - ): + ) -> Chat: + + """Редактирует параметры чата. + + :param chat_id: ID чата + :param icon: Данные иконки чата + :param title: Новый заголовок чата + :param pin: ID сообщения для закрепления + :param notify: Уведомлять участников (по умолчанию True) + + :return: Обновленный объект чата + """ + return await EditChat( bot=self, chat_id=chat_id, @@ -204,15 +386,39 @@ class Bot(BaseConnection): notify=notify ).request() - async def get_video(self, video_token: str): - return await GetVideo(bot=self, video_token=video_token).request() + async def get_video( + self, + video_token: str + ) -> Video: + + """Получает видео по токену. + + :param video_token: Токен видео + + :return: Объект видео + """ + + return await GetVideo( + bot=self, + video_token=video_token + ).request() async def send_callback( self, callback_id: str, message: 'Message' = None, notification: str = None - ): + ) -> SendedCallback: + + """Отправляет callback ответ. + + :param callback_id: ID callback + :param message: Сообщение для отправки + :param notification: Текст уведомления + + :return: Результат отправки callback + """ + return await SendCallback( bot=self, callback_id=callback_id, @@ -225,7 +431,17 @@ class Bot(BaseConnection): chat_id: int, message_id: str, notify: bool = True - ): + ) -> PinnedMessage: + + """Закрепляет сообщение в чате. + + :param chat_id: ID чата + :param message_id: ID сообщения + :param notify: Уведомлять участников (по умолчанию True) + + :return: Закрепленное сообщение + """ + return await PinMessage( bot=self, chat_id=chat_id, @@ -236,7 +452,15 @@ class Bot(BaseConnection): async def delete_pin_message( self, chat_id: int, - ): + ) -> DeletedPinMessage: + + """Удаляет закрепленное сообщение в чате. + + :param chat_id: ID чата + + :return: Результат удаления + """ + return await DeletePinMessage( bot=self, chat_id=chat_id, @@ -245,7 +469,15 @@ class Bot(BaseConnection): async def get_me_from_chat( self, chat_id: int, - ): + ) -> ChatMember: + + """Получает информацию о боте в конкретном чате. + + :param chat_id: ID чата + + :return: Информация о боте в чате + """ + return await GetMeFromChat( bot=self, chat_id=chat_id, @@ -254,7 +486,15 @@ class Bot(BaseConnection): async def delete_me_from_chat( self, chat_id: int, - ): + ) -> DeletedBotFromChat: + + """Удаляет бота из чата. + + :param chat_id: ID чата + + :return: Результат удаления + """ + return await DeleteMeFromMessage( bot=self, chat_id=chat_id, @@ -263,7 +503,15 @@ class Bot(BaseConnection): async def get_list_admin_chat( self, chat_id: int, - ): + ) -> GettedListAdminChat: + + """Получает список администраторов чата. + + :param chat_id: ID чата + + :return: Список администраторов + """ + return await GetListAdminChat( bot=self, chat_id=chat_id, @@ -274,7 +522,17 @@ class Bot(BaseConnection): chat_id: int, admins: List[ChatAdmin], marker: int = None - ): + ) -> AddedListAdminChat: + + """Добавляет администраторов в чат. + + :param chat_id: ID чата + :param admins: Список администраторов + :param marker: Маркер для пагинации + + :return: Результат добавления + """ + return await AddAdminChat( bot=self, chat_id=chat_id, @@ -286,7 +544,16 @@ class Bot(BaseConnection): self, chat_id: int, user_id: int - ): + ) -> RemovedAdmin: + + """Удаляет администратора из чата. + + :param chat_id: ID чата + :param user_id: ID пользователя + + :return: Результат удаления + """ + return await RemoveAdmin( bot=self, chat_id=chat_id, @@ -299,7 +566,18 @@ class Bot(BaseConnection): user_ids: List[int] = None, marker: int = None, count: int = None, - ): + ) -> GettedMembersChat: + + """Получает участников чата. + + :param chat_id: ID чата + :param user_ids: Фильтр по ID пользователей + :param marker: Маркер для пагинации + :param count: Количество участников + + :return: Список участников + """ + return await GetMembersChat( bot=self, chat_id=chat_id, @@ -312,7 +590,16 @@ class Bot(BaseConnection): self, chat_id: int, user_ids: List[str], - ): + ) -> AddedMembersChat: + + """Добавляет участников в чат. + + :param chat_id: ID чата + :param user_ids: Список ID пользователей + + :return: Результат добавления + """ + return await AddMembersChat( bot=self, chat_id=chat_id, @@ -324,7 +611,17 @@ class Bot(BaseConnection): chat_id: int, user_id: int, block: bool = False, - ): + ) -> RemovedMemberChat: + + """Исключает участника из чата. + + :param chat_id: ID чата + :param user_id: ID пользователя + :param block: Блокировать пользователя (по умолчанию False) + + :return: Результат исключения + """ + return await RemoveMemberChat( bot=self, chat_id=chat_id, @@ -334,7 +631,13 @@ class Bot(BaseConnection): async def get_updates( self, - ): + ) -> UpdateUnion: + + """Получает обновления для бота. + + :return: Список обновлений + """ + return await GetUpdates( bot=self, ).request() @@ -342,7 +645,15 @@ class Bot(BaseConnection): async def get_upload_url( self, type: UploadType - ): + ) -> GettedUploadUrl: + + """Получает URL для загрузки файлов. + + :param type: Тип загружаемого файла + + :return: URL для загрузки + """ + return await GetUploadURL( bot=self, type=type @@ -351,7 +662,15 @@ class Bot(BaseConnection): async def set_my_commands( self, *commands: BotCommand - ): + ) -> User: + + """Устанавливает список команд бота. + + :param commands: Список команд + + :return: Обновленная информация о боте + """ + return await ChangeInfo( bot=self, commands=list(commands) diff --git a/maxapi/connection/base.py b/maxapi/connection/base.py index f4a2227..7b09db7 100644 --- a/maxapi/connection/base.py +++ b/maxapi/connection/base.py @@ -15,6 +15,14 @@ if TYPE_CHECKING: class BaseConnection: + + """ + Базовый класс для всех методов API. + + Содержит общую логику выполнения запроса (например, сериализацию, отправку HTTP-запроса, обработку ответа). + + Метод request() может быть переопределён в потомках при необходимости. + """ API_URL = 'https://botapi.max.ru' @@ -31,6 +39,21 @@ class BaseConnection: **kwargs ): + """ + Выполняет HTTP-запрос к API, используя указанные параметры. + + :param method: HTTP-метод запроса (GET, POST и т.д.) + :param path: Путь к конечной точке API + :param model: Pydantic-модель, в которую будет десериализован ответ (если is_return_raw=False) + :param is_return_raw: Если True — вернуть "сырое" тело ответа, иначе — результат десериализации в model + :param kwargs: Дополнительные параметры (например, query, headers, json) + + :return: + - Объект model (если is_return_raw=False и model задан) + + - dict (если is_return_raw=True) + """ + if not self.bot.session: self.bot.session = aiohttp.ClientSession(self.bot.API_URL) @@ -71,11 +94,21 @@ class BaseConnection: path: str, type: UploadType ): + """ + Загружает файл на указанный URL. + + :param url: Конечная точка загрузки файла + :param path: Путь к локальному файлу + :param type: Тип файла (video, image, audio, file) + + :return: Сырой .text() ответ от сервера после загрузки файла + """ + with open(path, 'rb') as f: file_data = f.read() basename = os.path.basename(path) - name, ext = os.path.splitext(basename) + _, ext = os.path.splitext(basename) form = aiohttp.FormData() form.add_field( diff --git a/maxapi/context/__init__.py b/maxapi/context/__init__.py index 9aa6640..3792748 100644 --- a/maxapi/context/__init__.py +++ b/maxapi/context/__init__.py @@ -2,10 +2,19 @@ import asyncio from typing import Any, Dict -from ..context.state_machine import State, StatesGroup +from ..context.state_machine import State class MemoryContext: + + """ + Контекст хранения данных пользователя с блокировками. + + Args: + chat_id (int): Идентификатор чата + user_id (int): Идентификатор пользователя + """ + def __init__(self, chat_id: int, user_id: int): self.chat_id = chat_id self.user_id = user_id @@ -14,26 +23,71 @@ class MemoryContext: self._lock = asyncio.Lock() async def get_data(self) -> dict[str, Any]: + + """ + Возвращает текущий контекст данных. + + Returns: + Словарь с данными контекста + """ + async with self._lock: return self._context async def set_data(self, data: dict[str, Any]): + + """ + Полностью заменяет контекст данных. + + Args: + data: Новый словарь контекста + """ + async with self._lock: self._context = data async def update_data(self, **kwargs): + + """ + Обновляет контекст данных новыми значениями. + + Args: + **kwargs: Пары ключ-значение для обновления + """ + async with self._lock: self._context.update(kwargs) async def set_state(self, state: State | str = None): + + """ + Устанавливает новое состояние. + + Args: + state: Новое состояние или None для сброса + """ + async with self._lock: self._state = state async def get_state(self): + + """ + Возвращает текущее состояние. + + Returns: + Текущее состояние или None + """ + async with self._lock: return self._state async def clear(self): + + """ + Очищает контекст и сбрасывает состояние. + """ + async with self._lock: self._state = None self._context = {} diff --git a/maxapi/context/state_machine.py b/maxapi/context/state_machine.py index a69399d..a221810 100644 --- a/maxapi/context/state_machine.py +++ b/maxapi/context/state_machine.py @@ -1,4 +1,10 @@ class State: + """ + Представляет отдельное состояние в FSM-группе. + + При использовании внутри StatesGroup, автоматически присваивает уникальное имя в формате 'ИмяКласса:имя_поля'. + """ + def __init__(self): self.name = None @@ -10,7 +16,19 @@ class State: class StatesGroup: + """ + Базовый класс для описания группы состояний FSM. + + Атрибуты должны быть экземплярами State. Метод `states()` возвращает список всех состояний в виде строк. + """ + @classmethod def states(cls) -> list[str]: + """ + Получить список всех состояний в формате 'ИмяКласса:имя_состояния'. + + :return: Список строковых представлений состояний + """ + return [str(getattr(cls, attr)) for attr in dir(cls) if isinstance(getattr(cls, attr), State)] \ No newline at end of file diff --git a/maxapi/dispatcher.py b/maxapi/dispatcher.py index 65246e2..f79c2db 100644 --- a/maxapi/dispatcher.py +++ b/maxapi/dispatcher.py @@ -3,7 +3,7 @@ from typing import Callable, List from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from uvicorn import Config, Server -from aiohttp import ClientConnectorDNSError +from aiohttp import ClientConnectorError from .filters.handler import Handler @@ -24,6 +24,12 @@ app = FastAPI() class Dispatcher: + + """Основной класс для обработки событий бота. + + Обеспечивает работу с вебхуком и поллингом, управляет обработчиками событий. + """ + def __init__(self): self.event_handlers: List[Handler] = [] self.contexts: List[MemoryContext] = [] @@ -44,15 +50,36 @@ class Dispatcher: self.on_started = Event(update_type=UpdateType.ON_STARTED, router=self) async def check_me(self): + + """Проверяет и логирует информацию о боте.""" + me = await self.bot.get_me() logger_dp.info(f'Бот: @{me.username} id={me.user_id}') def include_routers(self, *routers: 'Router'): + + """Добавляет обработчики из роутеров. + + Args: + *routers: Роутеры для включения + """ + for router in routers: for event in router.event_handlers: self.event_handlers.append(event) - def get_memory_context(self, chat_id: int, user_id: int): + def __get_memory_context(self, chat_id: int, user_id: int): + + """Возвращает или создает контекст для чата и пользователя. + + Args: + chat_id: ID чата + user_id: ID пользователя + + Returns: + Существующий или новый контекст + """ + for ctx in self.contexts: if ctx.chat_id == chat_id and ctx.user_id == user_id: return ctx @@ -62,6 +89,13 @@ class Dispatcher: return new_ctx async def handle(self, event_object: UpdateUnion): + + """Обрабатывает событие. + + Args: + event_object: Объект события для обработки + """ + is_handled = False for handler in self.event_handlers: @@ -75,7 +109,7 @@ class Dispatcher: ids = event_object.get_ids() - memory_context = self.get_memory_context(*ids) + memory_context = self.__get_memory_context(*ids) if not handler.state == await memory_context.get_state() \ and handler.state: @@ -100,6 +134,13 @@ class Dispatcher: logger_dp.info(f'Проигнорировано: {event_object.update_type} | chat_id: {ids[0]}, user_id: {ids[1]}') async def start_polling(self, bot: Bot): + + """Запускает поллинг обновлений. + + Args: + bot: Экземпляр бота + """ + self.bot = bot await self.check_me() @@ -128,12 +169,21 @@ class Dispatcher: await self.handle(event) except Exception as e: logger_dp.error(f"Ошибка при обработке события: {event.update_type}: {e}") - except ClientConnectorDNSError: + except ClientConnectorError: logger_dp.error(f'Ошибка подключения: {e}') except Exception as e: logger_dp.error(f'Общая ошибка при обработке событий: {e}') - async def handle_webhook(self, bot: Bot, host: str = 'localhost', port: int = 8080): + async def handle_webhook(self, bot: Bot, host: str = '0.0.0.0', port: int = 8080): + + """Запускает вебхук сервер. + + Args: + bot: Экземпляр бота + host: Хост для сервера + port: Порт для сервера + """ + self.bot = bot await self.check_me() @@ -164,11 +214,17 @@ class Dispatcher: class Router(Dispatcher): + + """Роутер для группировки обработчиков событий.""" + def __init__(self): super().__init__() class Event: + + """Декоратор для регистрации обработчиков событий.""" + def __init__(self, update_type: UpdateType, router: Dispatcher | Router): self.update_type = update_type self.router = router diff --git a/maxapi/enums/api_path.py b/maxapi/enums/api_path.py index a02ca94..742e858 100644 --- a/maxapi/enums/api_path.py +++ b/maxapi/enums/api_path.py @@ -1,6 +1,14 @@ from enum import Enum + class ApiPath(str, Enum): + + """ + Перечисление всех доступных API-эндпоинтов. + + Используется для унифицированного указания путей при отправке запросов. + """ + ME = '/me' CHATS = '/chats' MESSAGES = '/messages' diff --git a/maxapi/enums/attachment.py b/maxapi/enums/attachment.py index 00614d2..d1d796d 100644 --- a/maxapi/enums/attachment.py +++ b/maxapi/enums/attachment.py @@ -1,6 +1,14 @@ from enum import Enum + class AttachmentType(str, Enum): + + """ + Типы вложений, поддерживаемые в сообщениях. + + Используется для указания типа содержимого при отправке или обработке вложений. + """ + IMAGE = 'image' VIDEO = 'video' AUDIO = 'audio' diff --git a/maxapi/enums/button_type.py b/maxapi/enums/button_type.py index 2b8d809..743f5f8 100644 --- a/maxapi/enums/button_type.py +++ b/maxapi/enums/button_type.py @@ -2,6 +2,13 @@ from enum import Enum class ButtonType(str, Enum): + + """ + Типы кнопок, доступных в интерфейсе бота. + + Определяют поведение при нажатии на кнопку в сообщении. + """ + REQUEST_CONTACT = 'request_contact' CALLBACK = 'callback' LINK = 'link' diff --git a/maxapi/enums/chat_permission.py b/maxapi/enums/chat_permission.py index 3b8dc1c..6e0f4d1 100644 --- a/maxapi/enums/chat_permission.py +++ b/maxapi/enums/chat_permission.py @@ -2,6 +2,13 @@ from enum import Enum class ChatPermission(str, Enum): + + """ + Права доступа пользователя в чате. + + Используются для управления разрешениями при добавлении участников или изменении настроек чата. + """ + READ_ALL_MESSAGES = 'read_all_messages' ADD_REMOVE_MEMBERS = 'add_remove_members' ADD_ADMINS = 'add_admins' diff --git a/maxapi/enums/chat_status.py b/maxapi/enums/chat_status.py index bcf73a6..a4a5318 100644 --- a/maxapi/enums/chat_status.py +++ b/maxapi/enums/chat_status.py @@ -2,6 +2,13 @@ from enum import Enum class ChatStatus(str, Enum): + + """ + Статус чата относительно пользователя или системы. + + Используется для отображения текущего состояния чата или определения доступных действий. + """ + ACTIVE = 'active' REMOVED = 'removed' LEFT = 'left' diff --git a/maxapi/enums/chat_type.py b/maxapi/enums/chat_type.py index 9d1c19f..5571a17 100644 --- a/maxapi/enums/chat_type.py +++ b/maxapi/enums/chat_type.py @@ -2,5 +2,12 @@ from enum import Enum class ChatType(str, Enum): + + """ + Тип чата. + + Используется для различения личных и групповых чатов. + """ + DIALOG = 'dialog' CHAT = 'chat' \ No newline at end of file diff --git a/maxapi/enums/http_method.py b/maxapi/enums/http_method.py index 068aa5f..08d296f 100644 --- a/maxapi/enums/http_method.py +++ b/maxapi/enums/http_method.py @@ -2,6 +2,13 @@ from enum import Enum class HTTPMethod(str, Enum): + + """ + HTTP-методы, поддерживаемые клиентом API. + + Используются при выполнении запросов к серверу. + """ + POST = 'POST' GET = 'GET' PATCH = 'PATCH' diff --git a/maxapi/enums/intent.py b/maxapi/enums/intent.py index 2ae81f4..424e1e1 100644 --- a/maxapi/enums/intent.py +++ b/maxapi/enums/intent.py @@ -1,6 +1,14 @@ from enum import Enum + class Intent(str, Enum): + + """ + Тип интента (намерения) кнопки. + + Используется для стилизации и логической классификации пользовательских действий. + """ + DEFAULT = 'default' POSITIVE = 'positive' NEGATIVE = 'negative' \ No newline at end of file diff --git a/maxapi/enums/message_link_type.py b/maxapi/enums/message_link_type.py index f5bfd50..9046127 100644 --- a/maxapi/enums/message_link_type.py +++ b/maxapi/enums/message_link_type.py @@ -2,5 +2,12 @@ from enum import Enum class MessageLinkType(str, Enum): + + """ + Тип связи между сообщениями. + + Используется для указания типа привязки: пересылка или ответ. + """ + FORWARD = 'forward' REPLY = 'reply' \ No newline at end of file diff --git a/maxapi/enums/parse_mode.py b/maxapi/enums/parse_mode.py index e7ff9da..d6df136 100644 --- a/maxapi/enums/parse_mode.py +++ b/maxapi/enums/parse_mode.py @@ -1,5 +1,13 @@ from enum import Enum + class ParseMode(str, Enum): + + """ + Формат разметки текста сообщений. + + Используется для указания способа интерпретации стилей (жирный, курсив, ссылки и т.д.). + """ + MARKDOWN = 'markdown' HTML = 'html' \ No newline at end of file diff --git a/maxapi/enums/sender_action.py b/maxapi/enums/sender_action.py index f661ce3..b41773f 100644 --- a/maxapi/enums/sender_action.py +++ b/maxapi/enums/sender_action.py @@ -1,6 +1,14 @@ from enum import Enum + class SenderAction(str, Enum): + + """ + Действия отправителя, отображаемые получателю в интерфейсе. + + Используются для имитации активности (например, "печатает...") перед отправкой сообщения или медиа. + """ + TYPING_ON = 'typing_on' SENDING_PHOTO = 'sending_photo' SENDING_VIDEO = 'sending_video' diff --git a/maxapi/enums/text_style.py b/maxapi/enums/text_style.py index d349454..aba2a0f 100644 --- a/maxapi/enums/text_style.py +++ b/maxapi/enums/text_style.py @@ -2,6 +2,13 @@ from enum import Enum class TextStyle(Enum): + + """ + Стили текста, применяемые в сообщениях. + + Используются для форматирования и выделения частей текста в сообщении. + """ + UNDERLINE = 'underline' STRONG = 'strong' EMPHASIZED = 'emphasized' diff --git a/maxapi/enums/update.py b/maxapi/enums/update.py index 38755f7..86d1875 100644 --- a/maxapi/enums/update.py +++ b/maxapi/enums/update.py @@ -1,6 +1,14 @@ from enum import Enum + class UpdateType(str, Enum): + + """ + Типы обновлений (ивентов) от API. + + Используются для обработки различных событий в боте или чате. + """ + MESSAGE_CREATED = 'message_created' BOT_ADDED = 'bot_added' BOT_REMOVED = 'bot_removed' @@ -13,4 +21,5 @@ class UpdateType(str, Enum): USER_ADDED = 'user_added' USER_REMOVED = 'user_removed' + # Для начинки диспатчера ON_STARTED = 'on_started' \ No newline at end of file diff --git a/maxapi/enums/upload_type.py b/maxapi/enums/upload_type.py index 55e4a03..d9a34ba 100644 --- a/maxapi/enums/upload_type.py +++ b/maxapi/enums/upload_type.py @@ -2,6 +2,13 @@ from enum import Enum class UploadType(str, Enum): + + """ + Типы загружаемых файлов. + + Используются для указания категории контента при загрузке на сервер. + """ + IMAGE = 'image' VIDEO = 'video' AUDIO = 'audio' diff --git a/maxapi/filters/handler.py b/maxapi/filters/handler.py index 751ee50..ab0533b 100644 --- a/maxapi/filters/handler.py +++ b/maxapi/filters/handler.py @@ -9,6 +9,12 @@ from ..loggers import logger_dp class Handler: + + """ + Обработчик события. + + Позволяет связать функцию-обработчик с типом обновления, состоянием и набором фильтров. + """ def __init__( self, @@ -18,6 +24,18 @@ class Handler: **kwargs ): + """ + Инициализация обработчика. + + :param args: Список фильтров и состояний, в том числе: + - MagicFilter — фильтр события, + - State — состояние FSM, + - Command — команда для фильтрации по началу текста сообщения. + :param func_event: Функция-обработчик события + :param update_type: Тип обновления (события), на которое подписан обработчик + :param kwargs: Дополнительные параметры (не используются) + """ + self.func_event = func_event self.update_type = update_type self.filters = [] diff --git a/maxapi/methods/add_admin_chat.py b/maxapi/methods/add_admin_chat.py index 83e2b43..b0bb2cf 100644 --- a/maxapi/methods/add_admin_chat.py +++ b/maxapi/methods/add_admin_chat.py @@ -1,7 +1,6 @@ from typing import TYPE_CHECKING, List from .types.added_admin_chat import AddedListAdminChat - from ..types.users import ChatAdmin from ..enums.http_method import HTTPMethod @@ -15,6 +14,16 @@ if TYPE_CHECKING: class AddAdminChat(BaseConnection): + + """ + Класс для добавления списка администраторов в чат через API. + + Args: + bot (Bot): Экземпляр бота, через который выполняется запрос. + chat_id (int): Идентификатор чата. + admins (List[ChatAdmin]): Список администраторов для добавления. + marker (int, optional): Маркер для пагинации или дополнительных настроек. По умолчанию None. + """ def __init__( self, @@ -29,6 +38,16 @@ class AddAdminChat(BaseConnection): self.marker = marker async def request(self) -> AddedListAdminChat: + + """ + Выполняет HTTP POST запрос для добавления администраторов в чат. + + Формирует JSON с данными администраторов и отправляет запрос на соответствующий API-эндпоинт. + + Returns: + AddedListAdminChat: Результат операции с информацией об успешности. + """ + json = {} json['admins'] = [admin.model_dump() for admin in self.admins] diff --git a/maxapi/methods/add_members_chat.py b/maxapi/methods/add_members_chat.py index 902b4ef..1bd7c8a 100644 --- a/maxapi/methods/add_members_chat.py +++ b/maxapi/methods/add_members_chat.py @@ -13,6 +13,15 @@ if TYPE_CHECKING: class AddMembersChat(BaseConnection): + + """ + Класс для добавления участников в чат через API. + + Args: + bot (Bot): Экземпляр бота, через который выполняется запрос. + chat_id (int): Идентификатор целевого чата. + user_ids (List[int]): Список ID пользователей для добавления в чат. + """ def __init__( self, @@ -26,6 +35,16 @@ class AddMembersChat(BaseConnection): self.user_ids = user_ids async def request(self) -> AddedMembersChat: + + """ + Отправляет POST-запрос на добавление пользователей в чат. + + Формирует JSON с ID пользователей и вызывает базовый метод запроса. + + Returns: + AddedMembersChat: Результат операции с информацией об успешности добавления. + """ + json = {} json['user_ids'] = self.user_ids diff --git a/maxapi/methods/change_info.py b/maxapi/methods/change_info.py index 1417ea8..13b61a7 100644 --- a/maxapi/methods/change_info.py +++ b/maxapi/methods/change_info.py @@ -14,6 +14,18 @@ if TYPE_CHECKING: class ChangeInfo(BaseConnection): + + """ + Класс для изменения информации о боте. + + Args: + bot (Bot): Объект бота + name (str, optional): Новое имя бота + description (str, optional): Новое описание + commands (List[BotCommand], optional): Список команд + photo (Dict[str, Any], optional): Данные фото + """ + def __init__( self, bot: 'Bot', @@ -29,6 +41,13 @@ class ChangeInfo(BaseConnection): self.photo = photo async def request(self) -> User: + + """Отправляет запрос на изменение информации о боте. + + Returns: + User: Объект с обновленными данными бота + """ + json = {} if self.name: json['name'] = self.name diff --git a/maxapi/methods/delete_bot_from_chat.py b/maxapi/methods/delete_bot_from_chat.py index 3b09300..6c475d0 100644 --- a/maxapi/methods/delete_bot_from_chat.py +++ b/maxapi/methods/delete_bot_from_chat.py @@ -1,10 +1,10 @@ from typing import TYPE_CHECKING from ..methods.types.deleted_bot_from_chat import DeletedBotFromChat -from ..methods.types.deleted_message import DeletedMessage from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath + from ..connection.base import BaseConnection @@ -13,6 +13,15 @@ if TYPE_CHECKING: class DeleteMeFromMessage(BaseConnection): + + """ + Класс для удаления бота из участников указанного чата. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата, из которого нужно удалить бота. + """ + def __init__( self, bot: 'Bot', @@ -22,6 +31,14 @@ class DeleteMeFromMessage(BaseConnection): self.chat_id = chat_id async def request(self) -> DeletedBotFromChat: + + """ + Отправляет DELETE-запрос для удаления бота из чата. + + Returns: + DeletedBotFromChat: Результат операции удаления. + """ + return await super().request( method=HTTPMethod.DELETE, path=ApiPath.CHATS + '/' + str(self.chat_id) + ApiPath.MEMBERS + ApiPath.ME, diff --git a/maxapi/methods/delete_chat.py b/maxapi/methods/delete_chat.py index cd15cd9..10b9107 100644 --- a/maxapi/methods/delete_chat.py +++ b/maxapi/methods/delete_chat.py @@ -12,6 +12,15 @@ if TYPE_CHECKING: class DeleteChat(BaseConnection): + + """ + Класс для удаления чата через API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата, который необходимо удалить. + """ + def __init__( self, bot: 'Bot', @@ -21,6 +30,14 @@ class DeleteChat(BaseConnection): self.chat_id = chat_id async def request(self) -> DeletedChat: + + """ + Отправляет DELETE-запрос для удаления указанного чата. + + Returns: + DeletedChat: Результат операции удаления чата. + """ + return await super().request( method=HTTPMethod.DELETE, path=ApiPath.CHATS.value + '/' + str(self.chat_id), diff --git a/maxapi/methods/delete_message.py b/maxapi/methods/delete_message.py index e7f0be4..bb56776 100644 --- a/maxapi/methods/delete_message.py +++ b/maxapi/methods/delete_message.py @@ -12,6 +12,15 @@ if TYPE_CHECKING: class DeleteMessage(BaseConnection): + + """ + Класс для удаления сообщения через API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + message_id (str): Идентификатор сообщения, которое нужно удалить. + """ + def __init__( self, bot: 'Bot', @@ -21,6 +30,16 @@ class DeleteMessage(BaseConnection): self.message_id = message_id async def request(self) -> DeletedMessage: + + """ + Выполняет DELETE-запрос для удаления сообщения. + + Использует параметр message_id для идентификации сообщения. + + Returns: + DeletedMessage: Результат операции удаления сообщения. + """ + params = self.bot.params.copy() params['message_id'] = self.message_id diff --git a/maxapi/methods/delete_pin_message.py b/maxapi/methods/delete_pin_message.py index 04c8b96..dc7276f 100644 --- a/maxapi/methods/delete_pin_message.py +++ b/maxapi/methods/delete_pin_message.py @@ -4,6 +4,7 @@ from ..methods.types.deleted_pin_message import DeletedPinMessage from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath + from ..connection.base import BaseConnection @@ -12,6 +13,15 @@ if TYPE_CHECKING: class DeletePinMessage(BaseConnection): + + """ + Класс для удаления закреплённого сообщения в чате через API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (str): Идентификатор чата, из которого нужно удалить закреплённое сообщение. + """ + def __init__( self, bot: 'Bot', @@ -21,6 +31,14 @@ class DeletePinMessage(BaseConnection): self.chat_id = chat_id async def request(self) -> DeletedPinMessage: + + """ + Выполняет DELETE-запрос для удаления закреплённого сообщения. + + Returns: + DeletedPinMessage: Результат операции удаления закреплённого сообщения. + """ + return await super().request( method=HTTPMethod.DELETE, path=ApiPath.CHATS + '/' + str(self.chat_id) + ApiPath.PIN, diff --git a/maxapi/methods/edit_chat.py b/maxapi/methods/edit_chat.py index fc1319b..a8e4da9 100644 --- a/maxapi/methods/edit_chat.py +++ b/maxapi/methods/edit_chat.py @@ -1,12 +1,11 @@ from logging import getLogger -from typing import Any, Dict, List, TYPE_CHECKING +from typing import TYPE_CHECKING from collections import Counter from ..types.attachments.image import PhotoAttachmentRequestPayload from ..types.chats import Chat -from ..types.command import Command from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath @@ -21,6 +20,19 @@ if TYPE_CHECKING: class EditChat(BaseConnection): + + """ + Класс для редактирования информации о чате через API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата для редактирования. + icon (PhotoAttachmentRequestPayload, optional): Новый значок (иконка) чата. + title (str, optional): Новое название чата. + pin (str, optional): Идентификатор закреплённого сообщения. + notify (bool, optional): Включение или отключение уведомлений (по умолчанию True). + """ + def __init__( self, bot: 'Bot', @@ -38,6 +50,18 @@ class EditChat(BaseConnection): self.notify = notify async def request(self) -> Chat: + + """ + Выполняет PATCH-запрос для обновления параметров чата. + + Валидация: + - Проверяется, что в `icon` атрибуты модели взаимоисключающие (в модели должно быть ровно 2 поля с None). + - Если условие не выполнено, логируется ошибка и запрос не отправляется. + + Returns: + Chat: Обновлённый объект чата. + """ + json = {} if self.icon: diff --git a/maxapi/methods/edit_message.py b/maxapi/methods/edit_message.py index e7674f4..b7fd29e 100644 --- a/maxapi/methods/edit_message.py +++ b/maxapi/methods/edit_message.py @@ -3,9 +3,11 @@ from typing import List, TYPE_CHECKING from .types.edited_message import EditedMessage from ..types.message import NewMessageLink from ..types.attachments.attachment import Attachment + from ..enums.parse_mode import ParseMode from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath + from ..connection.base import BaseConnection @@ -14,6 +16,20 @@ if TYPE_CHECKING: class EditMessage(BaseConnection): + + """ + Класс для редактирования существующего сообщения через API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + message_id (str): Идентификатор сообщения для редактирования. + text (str, optional): Новый текст сообщения. + attachments (List[Attachment], optional): Список вложений для сообщения. + link (NewMessageLink, optional): Связь с другим сообщением (ответ или пересылка). + notify (bool, optional): Отправлять ли уведомление о сообщении (по умолчанию True). + parse_mode (ParseMode, optional): Формат разметки текста (markdown, html и т.д.). + """ + def __init__( self, bot: 'Bot', @@ -33,6 +49,16 @@ class EditMessage(BaseConnection): self.parse_mode = parse_mode async def request(self) -> EditedMessage: + + """ + Выполняет PUT-запрос для обновления сообщения. + + Формирует тело запроса на основе переданных параметров и отправляет запрос к API. + + Returns: + EditedMessage: Обновлённое сообщение. + """ + params = self.bot.params.copy() json = {} diff --git a/maxapi/methods/get_chat_by_id.py b/maxapi/methods/get_chat_by_id.py index 98e8fe5..7b41c0a 100644 --- a/maxapi/methods/get_chat_by_id.py +++ b/maxapi/methods/get_chat_by_id.py @@ -14,6 +14,14 @@ if TYPE_CHECKING: class GetChatById(BaseConnection): + """ + Класс для получения информации о чате по его идентификатору. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + id (int): Идентификатор чата. + """ + def __init__( self, bot: 'Bot', @@ -23,6 +31,14 @@ class GetChatById(BaseConnection): self.id = id async def request(self) -> Chat: + + """ + Выполняет GET-запрос для получения данных чата. + + Returns: + Chat: Объект чата с полной информацией. + """ + return await super().request( method=HTTPMethod.GET, path=ApiPath.CHATS.value + '/' + str(self.id), diff --git a/maxapi/methods/get_chat_by_link.py b/maxapi/methods/get_chat_by_link.py index 2f6c901..264a575 100644 --- a/maxapi/methods/get_chat_by_link.py +++ b/maxapi/methods/get_chat_by_link.py @@ -14,6 +14,18 @@ if TYPE_CHECKING: class GetChatByLink(BaseConnection): + + """ + Класс для получения информации о чате по ссылке. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + link (str): Ссылка на чат (с содержанием @ или без). + + Attributes: + link (list[str]): Список валидных частей ссылки. + PATTERN_LINK (str): Регулярное выражение для парсинга ссылки. + """ PATTERN_LINK = r'@?[a-zA-Z]+[a-zA-Z0-9-_]*' @@ -29,6 +41,14 @@ class GetChatByLink(BaseConnection): return async def request(self) -> Chat: + + """ + Выполняет GET-запрос для получения данных чата по ссылке. + + Returns: + Chat: Объект с информацией о чате. + """ + return await super().request( method=HTTPMethod.GET, path=ApiPath.CHATS.value + '/' + self.link[-1], diff --git a/maxapi/methods/get_chats.py b/maxapi/methods/get_chats.py index 9382ef5..84858e0 100644 --- a/maxapi/methods/get_chats.py +++ b/maxapi/methods/get_chats.py @@ -1,5 +1,3 @@ - - from typing import TYPE_CHECKING from ..types.chats import Chats @@ -15,6 +13,21 @@ if TYPE_CHECKING: class GetChats(BaseConnection): + + """ + Класс для получения списка чатов через API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + count (int, optional): Максимальное количество чатов для получения. По умолчанию 50. + marker (int, optional): Маркер для постраничной навигации. По умолчанию None. + + Attributes: + bot (Bot): Экземпляр бота. + count (int): Количество чатов для запроса. + marker (int | None): Маркер для пагинации. + """ + def __init__( self, bot: 'Bot', @@ -26,6 +39,14 @@ class GetChats(BaseConnection): self.marker = marker async def request(self) -> Chats: + + """ + Выполняет GET-запрос для получения списка чатов. + + Returns: + Chats: Объект с данными по списку чатов. + """ + params = self.bot.params.copy() params['count'] = self.count diff --git a/maxapi/methods/get_list_admin_chat.py b/maxapi/methods/get_list_admin_chat.py index 8072cbb..ad2509f 100644 --- a/maxapi/methods/get_list_admin_chat.py +++ b/maxapi/methods/get_list_admin_chat.py @@ -13,6 +13,18 @@ if TYPE_CHECKING: class GetListAdminChat(BaseConnection): + + """ + Класс для получения списка администраторов чата через API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата. + + Attributes: + bot (Bot): Экземпляр бота. + chat_id (int): Идентификатор чата. + """ def __init__( self, @@ -23,6 +35,14 @@ class GetListAdminChat(BaseConnection): self.chat_id = chat_id async def request(self) -> GettedListAdminChat: + + """ + Выполняет GET-запрос для получения списка администраторов указанного чата. + + Returns: + GettedListAdminChat: Объект с информацией о администраторах чата. + """ + return await super().request( method=HTTPMethod.GET, path=ApiPath.CHATS.value + '/' + str(self.chat_id) + ApiPath.MEMBERS + ApiPath.ADMINS, diff --git a/maxapi/methods/get_me.py b/maxapi/methods/get_me.py index cf44ccd..87b75af 100644 --- a/maxapi/methods/get_me.py +++ b/maxapi/methods/get_me.py @@ -1,9 +1,5 @@ - - from typing import TYPE_CHECKING -from ..types.chats import Chats - from ..types.users import User from ..enums.http_method import HTTPMethod @@ -17,10 +13,26 @@ if TYPE_CHECKING: class GetMe(BaseConnection): + + """ + Класс для получения информации о боте. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + """ + def __init__(self, bot: 'Bot'): self.bot = bot async def request(self) -> User: + + """ + Выполняет GET-запрос для получения данных о боте. + + Returns: + User: Объект пользователя с полной информацией. + """ + return await super().request( method=HTTPMethod.GET, path=ApiPath.ME, diff --git a/maxapi/methods/get_me_from_chat.py b/maxapi/methods/get_me_from_chat.py index 9d2316a..7710c42 100644 --- a/maxapi/methods/get_me_from_chat.py +++ b/maxapi/methods/get_me_from_chat.py @@ -1,5 +1,3 @@ - - from typing import TYPE_CHECKING from ..types.chats import ChatMember @@ -15,6 +13,19 @@ if TYPE_CHECKING: class GetMeFromChat(BaseConnection): + + """ + Класс для получения информации о текущем боте в конкретном чате. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата. + + Attributes: + bot (Bot): Экземпляр бота. + chat_id (int): Идентификатор чата. + """ + def __init__( self, bot: 'Bot', @@ -24,6 +35,14 @@ class GetMeFromChat(BaseConnection): self.chat_id = chat_id async def request(self) -> ChatMember: + + """ + Выполняет GET-запрос для получения информации о боте в указанном чате. + + Returns: + ChatMember: Информация о боте как участнике чата. + """ + return await super().request( method=HTTPMethod.GET, path=ApiPath.CHATS + '/' + str(self.chat_id) + ApiPath.MEMBERS + ApiPath.ME, diff --git a/maxapi/methods/get_members_chat.py b/maxapi/methods/get_members_chat.py index c814c2d..9ebb21f 100644 --- a/maxapi/methods/get_members_chat.py +++ b/maxapi/methods/get_members_chat.py @@ -13,6 +13,24 @@ if TYPE_CHECKING: class GetMembersChat(BaseConnection): + + """ + Класс для получения списка участников чата через API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата. + user_ids (List[str], optional): Список ID пользователей для фильтрации. По умолчанию None. + marker (int, optional): Маркер для пагинации (начальная позиция). По умолчанию None. + count (int, optional): Максимальное количество участников для получения. По умолчанию None. + + Attributes: + bot (Bot): Экземпляр бота. + chat_id (int): Идентификатор чата. + user_ids (List[str] | None): Список ID пользователей для фильтра. + marker (int | None): Позиция для пагинации. + count (int | None): Максимальное количество участников. + """ def __init__( self, @@ -30,6 +48,16 @@ class GetMembersChat(BaseConnection): self.count = count async def request(self) -> GettedMembersChat: + + """ + Выполняет GET-запрос для получения участников чата с опциональной фильтрацией. + + Формирует параметры запроса с учётом фильтров и передаёт их базовому методу. + + Returns: + GettedMembersChat: Объект с данными по участникам чата. + """ + params = self.bot.params.copy() if self.user_ids: params['user_ids'] = ','.join(self.user_ids) diff --git a/maxapi/methods/get_messages.py b/maxapi/methods/get_messages.py index 801075c..0c55db4 100644 --- a/maxapi/methods/get_messages.py +++ b/maxapi/methods/get_messages.py @@ -1,5 +1,3 @@ - - from datetime import datetime from typing import TYPE_CHECKING, List @@ -14,6 +12,27 @@ if TYPE_CHECKING: class GetMessages(BaseConnection): + + """ + Класс для получения сообщений из чата через API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата. + message_ids (List[str], optional): Список идентификаторов сообщений для выборки. По умолчанию None. + from_time (datetime | int, optional): Временная метка начала выборки сообщений (timestamp или datetime). По умолчанию None. + to_time (datetime | int, optional): Временная метка конца выборки сообщений (timestamp или datetime). По умолчанию None. + count (int, optional): Максимальное количество сообщений для получения. По умолчанию 50. + + Attributes: + bot (Bot): Экземпляр бота. + chat_id (int): Идентификатор чата. + message_ids (List[str] | None): Фильтр по идентификаторам сообщений. + from_time (datetime | int | None): Начальная временная метка. + to_time (datetime | int | None): Конечная временная метка. + count (int): Максимальное число сообщений. + """ + def __init__( self, bot: 'Bot', @@ -31,6 +50,16 @@ class GetMessages(BaseConnection): self.count = count async def request(self) -> Messages: + + """ + Выполняет GET-запрос для получения сообщений с учётом параметров фильтрации. + + Преобразует datetime в UNIX timestamp при необходимости. + + Returns: + Messages: Объект с полученными сообщениями. + """ + params = self.bot.params.copy() if self.chat_id: params['chat_id'] = self.chat_id diff --git a/maxapi/methods/get_pinned_message.py b/maxapi/methods/get_pinned_message.py index 3fbb292..bdc5f5e 100644 --- a/maxapi/methods/get_pinned_message.py +++ b/maxapi/methods/get_pinned_message.py @@ -1,7 +1,4 @@ - - -from datetime import datetime -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING from .types.getted_pineed_message import GettedPin @@ -15,6 +12,15 @@ if TYPE_CHECKING: class GetPinnedMessage(BaseConnection): + + """ + Класс для получения закреплённого сообщения в указанном чате. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата. + """ + def __init__( self, bot: 'Bot', @@ -24,6 +30,14 @@ class GetPinnedMessage(BaseConnection): self.chat_id = chat_id async def request(self) -> GettedPin: + + """ + Выполняет GET-запрос для получения закреплённого сообщения. + + Returns: + GettedPin: Объект с информацией о закреплённом сообщении. + """ + return await super().request( method=HTTPMethod.GET, path=ApiPath.CHATS + '/' + str(self.chat_id) + ApiPath.PIN, diff --git a/maxapi/methods/get_updates.py b/maxapi/methods/get_updates.py index ffab79e..71ba546 100644 --- a/maxapi/methods/get_updates.py +++ b/maxapi/methods/get_updates.py @@ -1,16 +1,10 @@ - - -from datetime import datetime -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING from ..types.updates import UpdateUnion -from ..methods.types.getted_updates import process_update_request - - -from ..types.message import Messages from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath + from ..connection.base import BaseConnection @@ -19,6 +13,19 @@ if TYPE_CHECKING: class GetUpdates(BaseConnection): + + """ + Класс для получения обновлений (updates) из API. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + limit (int, optional): Максимальное количество обновлений для получения. По умолчанию 100. + + Attributes: + bot (Bot): Экземпляр бота. + limit (int): Лимит на количество обновлений. + """ + def __init__( self, bot: 'Bot', @@ -28,6 +35,16 @@ class GetUpdates(BaseConnection): self.limit = limit async def request(self) -> UpdateUnion: + + """ + Выполняет GET-запрос для получения обновлений с указанным лимитом. + + Возвращает необработанный JSON с обновлениями. + + Returns: + UpdateUnion: Объединённый тип данных обновлений. + """ + params = self.bot.params.copy() params['limit'] = self.limit diff --git a/maxapi/methods/get_upload_url.py b/maxapi/methods/get_upload_url.py index 2ebffd9..674bb0b 100644 --- a/maxapi/methods/get_upload_url.py +++ b/maxapi/methods/get_upload_url.py @@ -3,9 +3,11 @@ from typing import TYPE_CHECKING from ..methods.types.getted_upload_url import GettedUploadUrl + from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath from ..enums.upload_type import UploadType + from ..connection.base import BaseConnection @@ -14,6 +16,15 @@ if TYPE_CHECKING: class GetUploadURL(BaseConnection): + + """ + Класс для получения URL загрузки файла определённого типа. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + type (UploadType): Тип загружаемого файла (например, image, video и т.д.). + """ + def __init__( self, bot: 'Bot', @@ -23,6 +34,16 @@ class GetUploadURL(BaseConnection): self.type = type async def request(self) -> GettedUploadUrl: + + """ + Выполняет POST-запрос для получения URL загрузки файла. + + Возвращает объект с данными URL. + + Returns: + GettedUploadUrl: Результат с URL для загрузки. + """ + params = self.bot.params.copy() params['type'] = self.type.value diff --git a/maxapi/methods/get_video.py b/maxapi/methods/get_video.py index 4548eea..04d2aef 100644 --- a/maxapi/methods/get_video.py +++ b/maxapi/methods/get_video.py @@ -1,13 +1,10 @@ -from typing import List, TYPE_CHECKING +from typing import TYPE_CHECKING from ..types.attachments.video import Video -from .types.edited_message import EditedMessage -from ..types.message import NewMessageLink -from ..types.attachments.attachment import Attachment -from ..enums.parse_mode import ParseMode from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath + from ..connection.base import BaseConnection @@ -16,6 +13,15 @@ if TYPE_CHECKING: class GetVideo(BaseConnection): + + """ + Класс для получения информации о видео по его токену. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + video_token (str): Токен видео для запроса. + """ + def __init__( self, bot: 'Bot', @@ -25,6 +31,13 @@ class GetVideo(BaseConnection): self.video_token = video_token async def request(self) -> Video: + + """ + Выполняет GET-запрос для получения данных видео по токену. + + Returns: + Video: Объект с информацией о видео. + """ return await super().request( method=HTTPMethod.GET, diff --git a/maxapi/methods/pin_message.py b/maxapi/methods/pin_message.py index cb181f5..60d82f7 100644 --- a/maxapi/methods/pin_message.py +++ b/maxapi/methods/pin_message.py @@ -1,12 +1,10 @@ - - -from datetime import datetime -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING from .types.pinned_message import PinnedMessage from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath + from ..connection.base import BaseConnection @@ -15,6 +13,23 @@ if TYPE_CHECKING: class PinMessage(BaseConnection): + + """ + Класс для закрепления сообщения в чате. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата, в котором закрепляется сообщение. + message_id (str): Идентификатор сообщения для закрепления. + notify (bool, optional): Отправлять ли уведомление о закреплении (по умолчанию True). + + Attributes: + bot (Bot): Экземпляр бота. + chat_id (int): Идентификатор чата. + message_id (str): Идентификатор закрепляемого сообщения. + notify (bool): Флаг отправки уведомления. + """ + def __init__( self, bot: 'Bot', @@ -28,6 +43,16 @@ class PinMessage(BaseConnection): self.notify = notify async def request(self) -> PinnedMessage: + + """ + Выполняет PUT-запрос для закрепления сообщения в чате. + + Формирует тело запроса с ID сообщения и флагом уведомления. + + Returns: + PinnedMessage: Объект с информацией о закреплённом сообщении. + """ + json = {} json['message_id'] = self.message_id diff --git a/maxapi/methods/remove_admin.py b/maxapi/methods/remove_admin.py index 9cbbd9c..b180cd9 100644 --- a/maxapi/methods/remove_admin.py +++ b/maxapi/methods/remove_admin.py @@ -1,5 +1,3 @@ - - from typing import TYPE_CHECKING from .types.removed_admin import RemovedAdmin @@ -15,6 +13,20 @@ if TYPE_CHECKING: class RemoveAdmin(BaseConnection): + + """ + Класс для отмены прав администратора в чате. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата. + user_id (int): Идентификатор пользователя. + + Attributes: + bot (Bot): Экземпляр бота. + chat_id (int): Идентификатор чата. + user_id (int): Идентификатор пользователя. + """ def __init__( self, @@ -27,9 +39,17 @@ class RemoveAdmin(BaseConnection): self.user_id = user_id async def request(self) -> RemovedAdmin: + + """ + Выполняет DELETE-запрос для отмены прав администратора в чате. + + Returns: + RemovedAdmin: Объект с результатом отмены прав администратора. + """ + return await super().request( method=HTTPMethod.DELETE, - path=ApiPath.CHATS.value + '/' + str(self.chat_id) + \ + path=ApiPath.CHATS + '/' + str(self.chat_id) + \ ApiPath.MEMBERS + ApiPath.ADMINS + '/' + str(self.user_id), model=RemovedAdmin, params=self.bot.params, diff --git a/maxapi/methods/remove_member_chat.py b/maxapi/methods/remove_member_chat.py index 1033bc4..48b00c0 100644 --- a/maxapi/methods/remove_member_chat.py +++ b/maxapi/methods/remove_member_chat.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING from .types.removed_member_chat import RemovedMemberChat @@ -13,6 +13,22 @@ if TYPE_CHECKING: class RemoveMemberChat(BaseConnection): + + """ + Класс для удаления участника из чата с опцией блокировки. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int): Идентификатор чата. + user_id (int): Идентификатор пользователя, которого необходимо удалить. + block (bool, optional): Блокировать пользователя после удаления. По умолчанию False. + + Attributes: + bot (Bot): Экземпляр бота. + chat_id (int): Идентификатор чата. + user_id (int): Идентификатор пользователя. + block (bool): Флаг блокировки пользователя. + """ def __init__( self, @@ -28,6 +44,16 @@ class RemoveMemberChat(BaseConnection): self.block = block async def request(self) -> RemovedMemberChat: + + """ + Выполняет DELETE-запрос для удаления пользователя из чата. + + Параметр `block` определяет, будет ли пользователь заблокирован после удаления. + + Returns: + RemovedMemberChat: Результат удаления участника. + """ + params = self.bot.params.copy() params['chat_id'] = self.chat_id diff --git a/maxapi/methods/send_action.py b/maxapi/methods/send_action.py index a8e46bb..04718b5 100644 --- a/maxapi/methods/send_action.py +++ b/maxapi/methods/send_action.py @@ -1,16 +1,13 @@ -from typing import List, TYPE_CHECKING +from typing import TYPE_CHECKING -from ..enums.sender_action import SenderAction from ..methods.types.sended_action import SendedAction -from .types.sended_message import SendedMessage -from ..types.message import NewMessageLink -from ..types.attachments.attachment import Attachment -from ..enums.parse_mode import ParseMode +from ..enums.sender_action import SenderAction from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath + from ..connection.base import BaseConnection @@ -19,6 +16,21 @@ if TYPE_CHECKING: class SendAction(BaseConnection): + + """ + Класс для отправки действия пользователя (например, индикатора печати) в чат. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int | None): Идентификатор чата. Если None, действие не отправляется. + action (SenderAction, optional): Тип действия. По умолчанию SenderAction.TYPING_ON. + + Attributes: + bot (Bot): Экземпляр бота. + chat_id (int | None): Идентификатор чата. + action (SenderAction): Тип действия. + """ + def __init__( self, bot: 'Bot', @@ -30,6 +42,14 @@ class SendAction(BaseConnection): self.action = action async def request(self) -> SendedAction: + + """ + Выполняет POST-запрос для отправки действия в указанный чат. + + Returns: + SendedAction: Результат выполнения запроса. + """ + json = {} json['action'] = self.action.value diff --git a/maxapi/methods/send_callback.py b/maxapi/methods/send_callback.py index 9e0b065..5ecb025 100644 --- a/maxapi/methods/send_callback.py +++ b/maxapi/methods/send_callback.py @@ -1,14 +1,12 @@ -from typing import List, TYPE_CHECKING +from typing import TYPE_CHECKING from ..methods.types.sended_callback import SendedCallback -from .types.sended_message import SendedMessage -from ..types.attachments.attachment import Attachment -from ..enums.parse_mode import ParseMode from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath + from ..connection.base import BaseConnection @@ -18,6 +16,23 @@ if TYPE_CHECKING: class SendCallback(BaseConnection): + + """ + Класс для отправки callback-ответа с опциональным сообщением и уведомлением. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + callback_id (str): Идентификатор callback. + message (Message, optional): Сообщение для отправки в ответе. + notification (str, optional): Текст уведомления. + + Attributes: + bot (Bot): Экземпляр бота. + callback_id (str): Идентификатор callback. + message (Message | None): Сообщение для отправки. + notification (str | None): Текст уведомления. + """ + def __init__( self, bot: 'Bot', @@ -31,23 +46,29 @@ class SendCallback(BaseConnection): self.notification = notification async def request(self) -> SendedCallback: - try: - params = self.bot.params.copy() + + """ + Выполняет POST-запрос для отправки callback-ответа. - params['callback_id'] = self.callback_id + Возвращает результат отправки. - json = {} - - if self.message: json['message'] = self.message.model_dump() - if self.notification: json['notification'] = self.notification + Returns: + SendedCallback: Объект с результатом отправки callback. + """ + + params = self.bot.params.copy() - return await super().request( - method=HTTPMethod.POST, - path=ApiPath.ANSWERS, - model=SendedCallback, - params=params, - json=json - ) - except Exception as e: - print(e) - ... \ No newline at end of file + params['callback_id'] = self.callback_id + + json = {} + + if self.message: json['message'] = self.message.model_dump() + if self.notification: json['notification'] = self.notification + + return await super().request( + method=HTTPMethod.POST, + path=ApiPath.ANSWERS, + model=SendedCallback, + params=params, + json=json + ) \ No newline at end of file diff --git a/maxapi/methods/send_message.py b/maxapi/methods/send_message.py index 1716e2a..db73b39 100644 --- a/maxapi/methods/send_message.py +++ b/maxapi/methods/send_message.py @@ -5,18 +5,19 @@ from typing import List, TYPE_CHECKING from json import loads as json_loads -from ..enums.upload_type import UploadType - +from .types.sended_message import SendedMessage from ..types.attachments.upload import AttachmentPayload, AttachmentUpload from ..types.errors import Error -from .types.sended_message import SendedMessage from ..types.message import NewMessageLink from ..types.input_media import InputMedia from ..types.attachments.attachment import Attachment + +from ..enums.upload_type import UploadType from ..enums.parse_mode import ParseMode from ..enums.http_method import HTTPMethod from ..enums.api_path import ApiPath from ..connection.base import BaseConnection + from ..loggers import logger_bot @@ -29,6 +30,22 @@ class UploadResponse: class SendMessage(BaseConnection): + + """ + Класс для отправки сообщения в чат или пользователю с поддержкой вложений и форматирования. + + Args: + bot (Bot): Экземпляр бота для выполнения запроса. + chat_id (int, optional): Идентификатор чата, куда отправлять сообщение. + user_id (int, optional): Идентификатор пользователя, если нужно отправить личное сообщение. + disable_link_preview (bool, optional): Отключить предпросмотр ссылок. По умолчанию False. + text (str, optional): Текст сообщения. + attachments (List[Attachment | InputMedia], optional): Список вложений к сообщению. + link (NewMessageLink, optional): Связь с другим сообщением (например, ответ или пересылка). + notify (bool, optional): Отправлять ли уведомление о сообщении. По умолчанию True. + parse_mode (ParseMode, optional): Режим разбора текста (например, Markdown, HTML). + """ + def __init__( self, bot: 'Bot', @@ -55,6 +72,17 @@ class SendMessage(BaseConnection): self, att: InputMedia ): + + """ + Загружает файл вложения и формирует объект AttachmentUpload. + + Args: + att (InputMedia): Объект вложения для загрузки. + + Returns: + AttachmentUpload: Загруженное вложение с токеном. + """ + upload = await self.bot.get_upload_url(att.type) upload_file_response = await self.upload_file( @@ -83,6 +111,16 @@ class SendMessage(BaseConnection): ) async def request(self) -> SendedMessage: + + """ + Отправляет сообщение с вложениями (если есть), с обработкой задержки готовности вложений. + + Возвращает результат отправки или ошибку. + + Возвращаемое значение: + SendedMessage или Error + """ + params = self.bot.params.copy() json = {'attachments': []} diff --git a/maxapi/methods/types/added_admin_chat.py b/maxapi/methods/types/added_admin_chat.py index 0329d67..88161a2 100644 --- a/maxapi/methods/types/added_admin_chat.py +++ b/maxapi/methods/types/added_admin_chat.py @@ -1,9 +1,16 @@ -from typing import List, Optional +from typing import Optional from pydantic import BaseModel -from ...types.chats import ChatMember - class AddedListAdminChat(BaseModel): + + """ + Ответ API при добавлении списка администраторов в чат. + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или ошибка. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/added_members_chat.py b/maxapi/methods/types/added_members_chat.py index 2fa52c8..54bfcd8 100644 --- a/maxapi/methods/types/added_members_chat.py +++ b/maxapi/methods/types/added_members_chat.py @@ -1,9 +1,16 @@ -from typing import List, Optional +from typing import Optional from pydantic import BaseModel -from ...types.chats import ChatMember - class AddedMembersChat(BaseModel): + + """ + Ответ API при добавлении списка пользователей в чат. + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или ошибка. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/deleted_bot_from_chat.py b/maxapi/methods/types/deleted_bot_from_chat.py index 19b8f09..568e0ae 100644 --- a/maxapi/methods/types/deleted_bot_from_chat.py +++ b/maxapi/methods/types/deleted_bot_from_chat.py @@ -3,5 +3,14 @@ from pydantic import BaseModel class DeletedBotFromChat(BaseModel): + + """ + Ответ API при удалении бота из чата. + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или ошибка. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/deleted_chat.py b/maxapi/methods/types/deleted_chat.py index 0855cd0..e1b60a7 100644 --- a/maxapi/methods/types/deleted_chat.py +++ b/maxapi/methods/types/deleted_chat.py @@ -3,5 +3,14 @@ from pydantic import BaseModel class DeletedChat(BaseModel): + + """ + Ответ API при удалении чата (?). + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или ошибка. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/deleted_message.py b/maxapi/methods/types/deleted_message.py index fa53861..4c396a4 100644 --- a/maxapi/methods/types/deleted_message.py +++ b/maxapi/methods/types/deleted_message.py @@ -3,5 +3,14 @@ from pydantic import BaseModel class DeletedMessage(BaseModel): + + """ + Ответ API при удалении сообщения. + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или ошибка. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/deleted_pin_message.py b/maxapi/methods/types/deleted_pin_message.py index c781714..22afc0f 100644 --- a/maxapi/methods/types/deleted_pin_message.py +++ b/maxapi/methods/types/deleted_pin_message.py @@ -3,5 +3,14 @@ from pydantic import BaseModel class DeletedPinMessage(BaseModel): + + """ + Ответ API при удалении закрепленного в чате сообщения. + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или ошибка. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/edited_message.py b/maxapi/methods/types/edited_message.py index 8aa82a5..57bc773 100644 --- a/maxapi/methods/types/edited_message.py +++ b/maxapi/methods/types/edited_message.py @@ -3,5 +3,14 @@ from pydantic import BaseModel class EditedMessage(BaseModel): + + """ + Ответ API при изменении сообщения. + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или ошибка. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/getted_list_admin_chat.py b/maxapi/methods/types/getted_list_admin_chat.py index f71bb32..9f7b708 100644 --- a/maxapi/methods/types/getted_list_admin_chat.py +++ b/maxapi/methods/types/getted_list_admin_chat.py @@ -5,5 +5,14 @@ from ...types.chats import ChatMember class GettedListAdminChat(BaseModel): + + """ + Ответ API с полученным списком администраторов чата. + + Attributes: + members (List[ChatMember]): Список участников с правами администратора. + marker (Optional[int]): Маркер для постраничной навигации (если есть). + """ + members: List[ChatMember] marker: Optional[int] = None \ No newline at end of file diff --git a/maxapi/methods/types/getted_members_chat.py b/maxapi/methods/types/getted_members_chat.py index d11fc9b..8438e38 100644 --- a/maxapi/methods/types/getted_members_chat.py +++ b/maxapi/methods/types/getted_members_chat.py @@ -5,5 +5,14 @@ from ...types.chats import ChatMember class GettedMembersChat(BaseModel): + + """ + Ответ API с полученным списком участников чата. + + Attributes: + members (List[ChatMember]): Список участников с правами администратора. + marker (Optional[int]): Маркер для постраничной навигации (если есть). + """ + members: List[ChatMember] marker: Optional[int] = None \ No newline at end of file diff --git a/maxapi/methods/types/getted_pineed_message.py b/maxapi/methods/types/getted_pineed_message.py index 261e398..2e5dbb3 100644 --- a/maxapi/methods/types/getted_pineed_message.py +++ b/maxapi/methods/types/getted_pineed_message.py @@ -5,4 +5,12 @@ from ...types.message import Message class GettedPin(BaseModel): + + """ + Ответ API с информацией о закреплённом сообщении. + + Attributes: + message (Optional[Message]): Закреплённое сообщение, если оно есть. + """ + message: Optional[Message] = None \ No newline at end of file diff --git a/maxapi/methods/types/getted_upload_url.py b/maxapi/methods/types/getted_upload_url.py index 3f1756b..13d7a20 100644 --- a/maxapi/methods/types/getted_upload_url.py +++ b/maxapi/methods/types/getted_upload_url.py @@ -1,8 +1,6 @@ -from typing import Any, Optional +from typing import Optional from pydantic import BaseModel -from ...types.message import Message - class GettedUploadUrl(BaseModel): url: Optional[str] = None diff --git a/maxapi/methods/types/pinned_message.py b/maxapi/methods/types/pinned_message.py index e8859cb..b336c05 100644 --- a/maxapi/methods/types/pinned_message.py +++ b/maxapi/methods/types/pinned_message.py @@ -3,5 +3,14 @@ from pydantic import BaseModel class PinnedMessage(BaseModel): + + """ + Ответ API при добавлении списка администраторов в чат. + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или ошибка. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/removed_admin.py b/maxapi/methods/types/removed_admin.py index 44fe8c3..2d296d0 100644 --- a/maxapi/methods/types/removed_admin.py +++ b/maxapi/methods/types/removed_admin.py @@ -1,7 +1,16 @@ -from typing import List, Optional +from typing import Optional from pydantic import BaseModel class RemovedAdmin(BaseModel): + + """ + Ответ API при отмене прав администратора у пользователя в чате + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или ошибка. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/removed_member_chat.py b/maxapi/methods/types/removed_member_chat.py index 5dd4d59..476d8bd 100644 --- a/maxapi/methods/types/removed_member_chat.py +++ b/maxapi/methods/types/removed_member_chat.py @@ -1,9 +1,16 @@ -from typing import List, Optional +from typing import Optional from pydantic import BaseModel -from ...types.chats import ChatMember - class RemovedMemberChat(BaseModel): + + """ + Ответ API при удалении участника из чата. + + Attributes: + success (bool): Статус успешности операции. + message (Optional[str]): Дополнительное сообщение или описание ошибки. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/sended_action.py b/maxapi/methods/types/sended_action.py index 4d4c2c8..4b59814 100644 --- a/maxapi/methods/types/sended_action.py +++ b/maxapi/methods/types/sended_action.py @@ -3,5 +3,14 @@ from pydantic import BaseModel class SendedAction(BaseModel): + + """ + Ответ API после выполнения действия. + + Attributes: + success (bool): Статус успешности выполнения операции. + message (Optional[str]): Дополнительное сообщение или описание ошибки. + """ + success: bool message: Optional[str] = None \ No newline at end of file diff --git a/maxapi/methods/types/sended_callback.py b/maxapi/methods/types/sended_callback.py index 674c08b..5dd940e 100644 --- a/maxapi/methods/types/sended_callback.py +++ b/maxapi/methods/types/sended_callback.py @@ -6,6 +6,16 @@ if TYPE_CHECKING: class SendedCallback(BaseModel): + + """ + Ответ API после выполнения callback-действия. + + Attributes: + success (bool): Статус успешности выполнения callback. + message (Optional[str]): Дополнительное сообщение или описание ошибки. + bot (Optional[Bot]): Внутреннее поле для хранения ссылки на экземпляр бота (не сериализуется). + """ + success: bool message: Optional[str] = None bot: Optional[Any] = Field(default=None, exclude=True) diff --git a/maxapi/methods/types/sended_message.py b/maxapi/methods/types/sended_message.py index f013211..f540cf8 100644 --- a/maxapi/methods/types/sended_message.py +++ b/maxapi/methods/types/sended_message.py @@ -1,8 +1,15 @@ -from typing import Any from pydantic import BaseModel from ...types.message import Message class SendedMessage(BaseModel): + + """ + Ответ API с отправленным сообщением. + + Attributes: + message (Message): Объект отправленного сообщения. + """ + message: Message \ No newline at end of file diff --git a/maxapi/methods/types/upload_file_response.py b/maxapi/methods/types/upload_file_response.py deleted file mode 100644 index 9765910..0000000 --- a/maxapi/methods/types/upload_file_response.py +++ /dev/null @@ -1,5 +0,0 @@ -from pydantic import BaseModel - - -class UploadFileResponse(BaseModel): - ... \ No newline at end of file diff --git a/maxapi/types/attachments/attachment.py b/maxapi/types/attachments/attachment.py index 0475fdb..879cf8f 100644 --- a/maxapi/types/attachments/attachment.py +++ b/maxapi/types/attachments/attachment.py @@ -5,37 +5,90 @@ from ...types.attachments.upload import AttachmentUpload from ...types.attachments.buttons import InlineButtonUnion from ...types.users import User -from ...enums.attachment import AttachmentType -AttachmentUnion = [] +from ...enums.attachment import AttachmentType class StickerAttachmentPayload(BaseModel): + + """ + Данные для вложения типа стикер. + + Attributes: + url (str): URL стикера. + code (str): Код стикера. + """ + url: str code: str class PhotoAttachmentPayload(BaseModel): + + """ + Данные для фото-вложения. + + Attributes: + photo_id (int): Идентификатор фотографии. + token (str): Токен для доступа к фото. + url (str): URL фотографии. + """ + photo_id: int token: str url: str class OtherAttachmentPayload(BaseModel): + + """ + Данные для общих типов вложений (файлы и т.п.). + + Attributes: + url (str): URL вложения. + token (Optional[str]): Опциональный токен доступа. + """ + url: str token: Optional[str] = None class ContactAttachmentPayload(BaseModel): + + """ + Данные для контакта. + + Attributes: + vcf_info (Optional[str]): Информация в формате vcf. + max_info (Optional[User]): Дополнительная информация о пользователе. + """ + vcf_info: Optional[str] = None max_info: Optional[User] = None class ButtonsPayload(BaseModel): + + """ + Данные для вложения с кнопками. + + Attributes: + buttons (List[List[InlineButtonUnion]]): Двумерный список inline-кнопок. + """ + buttons: List[List[InlineButtonUnion]] class Attachment(BaseModel): + + """ + Универсальный класс вложения с типом и полезной нагрузкой. + + Attributes: + type (AttachmentType): Тип вложения. + payload (Optional[Union[...] ]): Полезная нагрузка, зависит от типа вложения. + """ + type: AttachmentType payload: Optional[Union[ AttachmentUpload, diff --git a/maxapi/types/attachments/audio.py b/maxapi/types/attachments/audio.py index 84955ce..b981bcd 100644 --- a/maxapi/types/attachments/audio.py +++ b/maxapi/types/attachments/audio.py @@ -4,5 +4,14 @@ from .attachment import Attachment class Audio(Attachment): + + """ + Вложение с типом аудио. + + Attributes: + type (Literal['audio']): Тип вложения, всегда 'audio'. + transcription (Optional[str]): Транскрипция аудио (если есть). + """ + type: Literal['audio'] = 'audio' transcription: Optional[str] = None \ No newline at end of file diff --git a/maxapi/types/attachments/buttons/attachment_button.py b/maxapi/types/attachments/buttons/attachment_button.py index 7d9658c..ea213cf 100644 --- a/maxapi/types/attachments/buttons/attachment_button.py +++ b/maxapi/types/attachments/buttons/attachment_button.py @@ -5,5 +5,14 @@ from ..attachment import ButtonsPayload class AttachmentButton(BaseModel): + + """ + Модель кнопки вложения для сообщения. + + Attributes: + type: Тип кнопки, фиксированное значение 'inline_keyboard' + payload: Полезная нагрузка кнопки (массив рядов кнопок) + """ + type: Literal['inline_keyboard'] = 'inline_keyboard' payload: ButtonsPayload \ No newline at end of file diff --git a/maxapi/types/attachments/buttons/button.py b/maxapi/types/attachments/buttons/button.py index 18732c3..28da649 100644 --- a/maxapi/types/attachments/buttons/button.py +++ b/maxapi/types/attachments/buttons/button.py @@ -1,10 +1,18 @@ -from typing import Literal from pydantic import BaseModel from ....enums.button_type import ButtonType class Button(BaseModel): + + """ + Базовая модель кнопки для сообщений. + + Attributes: + type: Тип кнопки (определяет её поведение и функционал) + text: Текст, отображаемый на кнопке (1-64 символа) + """ + type: ButtonType text: str diff --git a/maxapi/types/attachments/buttons/callback_button.py b/maxapi/types/attachments/buttons/callback_button.py index bd1a35d..6f71c66 100644 --- a/maxapi/types/attachments/buttons/callback_button.py +++ b/maxapi/types/attachments/buttons/callback_button.py @@ -1,12 +1,23 @@ from typing import Optional from ....enums.button_type import ButtonType - from ....enums.intent import Intent + from .button import Button class CallbackButton(Button): + + """ + Кнопка с callback-действием. + + Attributes: + type: Тип кнопки (фиксированное значение ButtonType.CALLBACK) + text: Текст, отображаемый на кнопке (наследуется от Button) + payload: Дополнительные данные (до 256 символов), передаваемые при нажатии + intent: Намерение кнопки (визуальный стиль и поведение) + """ + type: ButtonType = ButtonType.CALLBACK payload: Optional[str] = None intent: Intent = Intent.DEFAULT \ No newline at end of file diff --git a/maxapi/types/attachments/buttons/chat_button.py b/maxapi/types/attachments/buttons/chat_button.py index 82934e3..4f40610 100644 --- a/maxapi/types/attachments/buttons/chat_button.py +++ b/maxapi/types/attachments/buttons/chat_button.py @@ -4,6 +4,17 @@ from .button import Button class ChatButton(Button): + + """ + Attributes: + type: Тип кнопки (наследуется от Button) + text: Текст кнопки (наследуется от Button) + chat_title: Название чата (до 128 символов) + chat_description: Описание чата (до 256 символов) + start_payload: Данные, передаваемые при старте чата (до 512 символов) + uuid: Уникальный идентификатор чата + """ + chat_title: Optional[str] = None chat_description: Optional[str] = None start_payload: Optional[str] = None diff --git a/maxapi/types/attachments/buttons/link_button.py b/maxapi/types/attachments/buttons/link_button.py index f364c93..99a86f2 100644 --- a/maxapi/types/attachments/buttons/link_button.py +++ b/maxapi/types/attachments/buttons/link_button.py @@ -4,4 +4,12 @@ from .button import Button class LinkButton(Button): + + """ + Кнопка с внешней ссылкой. + + Args: + url: Ссылка для перехода (должна содержать http/https) + """ + url: Optional[str] = None \ No newline at end of file diff --git a/maxapi/types/attachments/buttons/request_contact.py b/maxapi/types/attachments/buttons/request_contact.py index 140d4ed..2c8af5d 100644 --- a/maxapi/types/attachments/buttons/request_contact.py +++ b/maxapi/types/attachments/buttons/request_contact.py @@ -2,4 +2,7 @@ from .button import Button class RequestContact(Button): + """ + Кнопка с контактом. + """ ... \ No newline at end of file diff --git a/maxapi/types/attachments/buttons/request_geo_location_button.py b/maxapi/types/attachments/buttons/request_geo_location_button.py index d63ccde..bc64e55 100644 --- a/maxapi/types/attachments/buttons/request_geo_location_button.py +++ b/maxapi/types/attachments/buttons/request_geo_location_button.py @@ -2,4 +2,12 @@ from .button import Button class RequestGeoLocationButton(Button): + + """Кнопка запроса геолокации пользователя. + + Attributes: + quick: Если True, запрашивает геолокацию без дополнительного + подтверждения пользователя (по умолчанию False) + """ + quick: bool = False \ No newline at end of file diff --git a/maxapi/types/attachments/contact.py b/maxapi/types/attachments/contact.py index 9e6026d..18e74f1 100644 --- a/maxapi/types/attachments/contact.py +++ b/maxapi/types/attachments/contact.py @@ -4,4 +4,12 @@ from .attachment import Attachment class Contact(Attachment): + + """ + Вложение с типом контакта. + + Attributes: + type (Literal['contact']): Тип вложения, всегда 'contact'. + """ + type: Literal['contact'] = 'contact' \ No newline at end of file diff --git a/maxapi/types/attachments/file.py b/maxapi/types/attachments/file.py index 99a38b1..02a7d0b 100644 --- a/maxapi/types/attachments/file.py +++ b/maxapi/types/attachments/file.py @@ -4,6 +4,16 @@ from .attachment import Attachment class File(Attachment): + + """ + Вложение с типом файла. + + Attributes: + type (Literal['file']): Тип вложения, всегда 'file'. + filename (Optional[str]): Имя файла. + size (Optional[int]): Размер файла в байтах. + """ + type: Literal['file'] = 'file' filename: Optional[str] = None size: Optional[int] = None \ No newline at end of file diff --git a/maxapi/types/attachments/image.py b/maxapi/types/attachments/image.py index ce7475c..acfdcb1 100644 --- a/maxapi/types/attachments/image.py +++ b/maxapi/types/attachments/image.py @@ -5,10 +5,28 @@ from .attachment import Attachment class PhotoAttachmentRequestPayload(BaseModel): + + """ + Полезная нагрузка для запроса фото-вложения. + + Attributes: + url (Optional[str]): URL изображения. + token (Optional[str]): Токен доступа к изображению. + photos (Optional[str]): Дополнительные данные о фотографиях. + """ + url: Optional[str] = None token: Optional[str] = None photos: Optional[str] = None class Image(Attachment): + + """ + Вложение с типом изображения. + + Attributes: + type (Literal['image']): Тип вложения, всегда 'image'. + """ + type: Literal['image'] = 'image' \ No newline at end of file diff --git a/maxapi/types/attachments/location.py b/maxapi/types/attachments/location.py index 5ffd7fc..b501ef4 100644 --- a/maxapi/types/attachments/location.py +++ b/maxapi/types/attachments/location.py @@ -4,6 +4,16 @@ from .attachment import Attachment class Location(Attachment): + + """ + Вложение с типом геолокации. + + Attributes: + type (Literal['location']): Тип вложения, всегда 'location'. + latitude (Optional[float]): Широта. + longitude (Optional[float]): Долгота. + """ + type: Literal['location'] = 'location' latitude: Optional[float] = None longitude: Optional[float] = None \ No newline at end of file diff --git a/maxapi/types/attachments/share.py b/maxapi/types/attachments/share.py index 1b050e6..4f6e19c 100644 --- a/maxapi/types/attachments/share.py +++ b/maxapi/types/attachments/share.py @@ -4,6 +4,17 @@ from .attachment import Attachment class Share(Attachment): + + """ + Вложение с типом "share" (поделиться). + + Attributes: + type (Literal['share']): Тип вложения, всегда 'share'. + title (Optional[str]): Заголовок для шаринга. + description (Optional[str]): Описание. + image_url (Optional[str]): URL изображения для предпросмотра. + """ + type: Literal['share'] = 'share' title: Optional[str] = None description: Optional[str] = None diff --git a/maxapi/types/attachments/sticker.py b/maxapi/types/attachments/sticker.py index 29b1509..a2278de 100644 --- a/maxapi/types/attachments/sticker.py +++ b/maxapi/types/attachments/sticker.py @@ -4,6 +4,16 @@ from .attachment import Attachment class Sticker(Attachment): + + """ + Вложение с типом стикера. + + Attributes: + type (Literal['sticker']): Тип вложения, всегда 'sticker'. + width (Optional[int]): Ширина стикера в пикселях. + height (Optional[int]): Высота стикера в пикселях. + """ + type: Literal['sticker'] = 'sticker' width: Optional[int] = None height: Optional[int] = None \ No newline at end of file diff --git a/maxapi/types/attachments/upload.py b/maxapi/types/attachments/upload.py index 165b298..f6ce7cd 100644 --- a/maxapi/types/attachments/upload.py +++ b/maxapi/types/attachments/upload.py @@ -1,14 +1,29 @@ - - from pydantic import BaseModel from ...enums.upload_type import UploadType class AttachmentPayload(BaseModel): + + """ + Полезная нагрузка вложения с токеном. + + Attributes: + token (str): Токен для доступа или идентификации вложения. + """ + token: str class AttachmentUpload(BaseModel): + + """ + Вложение с полезной нагрузкой для загрузки на сервера MAX. + + Attributes: + type (UploadType): Тип вложения (например, image, video, audio). + payload (AttachmentPayload): Полезная нагрузка с токеном. + """ + type: UploadType payload: AttachmentPayload \ No newline at end of file diff --git a/maxapi/types/attachments/video.py b/maxapi/types/attachments/video.py index d9d9fde..6a19508 100644 --- a/maxapi/types/attachments/video.py +++ b/maxapi/types/attachments/video.py @@ -8,6 +8,20 @@ if TYPE_CHECKING: class VideoUrl(BaseModel): + + """ + URLs различных разрешений видео. + + Attributes: + mp4_1080 (Optional[str]): URL видео в 1080p. + mp4_720 (Optional[str]): URL видео в 720p. + mp4_480 (Optional[str]): URL видео в 480p. + mp4_360 (Optional[str]): URL видео в 360p. + mp4_240 (Optional[str]): URL видео в 240p. + mp4_144 (Optional[str]): URL видео в 144p. + hls (Optional[str]): URL HLS потока. + """ + mp4_1080: Optional[str] = None mp4_720: Optional[str] = None mp4_480: Optional[str] = None @@ -18,10 +32,33 @@ class VideoUrl(BaseModel): class VideoThumbnail(BaseModel): + + """ + Миниатюра видео. + + Attributes: + url (str): URL миниатюры. + """ + url: str class Video(Attachment): + + """ + Вложение с типом видео. + + Attributes: + type (Optional[Literal['video']]): Тип вложения, всегда 'video'. + token (Optional[str]): Токен видео. + urls (Optional[VideoUrl]): URLs видео разных разрешений. + thumbnail (VideoThumbnail): Миниатюра видео. + width (Optional[int]): Ширина видео. + height (Optional[int]): Высота видео. + duration (Optional[int]): Продолжительность видео в секундах. + bot (Optional[Any]): Ссылка на экземпляр бота, не сериализуется. + """ + type: Optional[Literal['video']] = 'video' token: Optional[str] = None urls: Optional[VideoUrl] = None diff --git a/maxapi/types/callback.py b/maxapi/types/callback.py index bfb74fc..8df267b 100644 --- a/maxapi/types/callback.py +++ b/maxapi/types/callback.py @@ -5,6 +5,17 @@ from ..types.users import User class Callback(BaseModel): + + """ + Модель callback-запроса. + + Attributes: + timestamp (int): Временная метка callback. + callback_id (str): Уникальный идентификатор callback. + payload (Optional[str]): Дополнительные данные callback. Может быть None. + user (User): Объект пользователя, инициировавшего callback. + """ + timestamp: int callback_id: str payload: Optional[str] = None diff --git a/maxapi/types/chats.py b/maxapi/types/chats.py index d163a53..aed9c8c 100644 --- a/maxapi/types/chats.py +++ b/maxapi/types/chats.py @@ -11,10 +11,41 @@ from ..types.message import Message class Icon(BaseModel): + + """ + Модель иконки чата. + + Attributes: + url (str): URL-адрес иконки. + """ + url: str class Chat(BaseModel): + + """ + Модель чата. + + Attributes: + chat_id (int): Уникальный идентификатор чата. + type (ChatType): Тип чата. + status (ChatStatus): Статус чата. + title (Optional[str]): Название чата. + icon (Optional[Icon]): Иконка чата. Может быть None. + last_event_time (int): Временная метка последнего события в чате. + participants_count (int): Количество участников чата. + owner_id (Optional[int]): Идентификатор владельца чата. + participants (Optional[Dict[str, datetime]]): Словарь участников с временными метками. Может быть None. + is_public (bool): Флаг публичности чата. + link (Optional[str]): Ссылка на чат. Может быть None. + description (Optional[str]): Описание чата. Может быть None. + dialog_with_user (Optional[User]): Пользователь, с которым ведется диалог. Может быть None. + messages_count (Optional[int]): Количество сообщений в чате. Может быть None. + chat_message_id (Optional[str]): Идентификатор сообщения чата. Может быть None. + pinned_message (Optional[Message]): Закрепленное сообщение. Может быть None. + """ + chat_id: int type: ChatType status: ChatStatus @@ -35,6 +66,17 @@ class Chat(BaseModel): @field_validator('participants', mode='before') @classmethod def convert_timestamps(cls, value: Dict[str, int]) -> Dict[str, datetime]: + + """ + Преобразует временные метки участников из миллисекунд в объекты datetime. + + Args: + value (Dict[str, int]): Словарь с временными метками в миллисекундах. + + Returns: + Dict[str, datetime]: Словарь с временными метками в формате datetime. + """ + return { key: datetime.fromtimestamp(ts / 1000) for key, ts in value.items() @@ -45,11 +87,32 @@ class Chat(BaseModel): class Chats(BaseModel): + + """ + Модель списка чатов. + + Attributes: + chats (List[Chat]): Список чатов. По умолчанию пустой. + marker (Optional[int]): Маркер для пагинации. Может быть None. + """ + chats: List[Chat] = [] marker: Optional[int] = None class ChatMember(User): + + """ + Модель участника чата. + + Attributes: + last_access_time (Optional[int]): Время последнего доступа. Может быть None. + is_owner (Optional[bool]): Флаг владельца чата. Может быть None. + is_admin (Optional[bool]): Флаг администратора чата. Может быть None. + join_time (Optional[int]): Время присоединения к чату. Может быть None. + permissions (Optional[List[ChatPermission]]): Список разрешений участника. Может быть None. + """ + last_access_time: Optional[int] = None is_owner: Optional[bool] = None is_admin: Optional[bool] = None diff --git a/maxapi/types/command.py b/maxapi/types/command.py index f40fe48..e04559b 100644 --- a/maxapi/types/command.py +++ b/maxapi/types/command.py @@ -1,18 +1,43 @@ - from typing import Optional from pydantic import BaseModel class Command: + + """ + Класс для представления команды бота. + + Attributes: + text (str): Текст команды без префикса. + prefix (str): Префикс команды. По умолчанию '/'. + """ + def __init__(self, text: str, prefix: str = '/'): self.text = text self.prefix = prefix @property def command(self): + + """ + Возвращает полную команду с префиксом. + + Returns: + str: Команда, состоящая из префикса и текста. + """ + return self.prefix + self.text class BotCommand(BaseModel): + + """ + Модель команды бота для сериализации. + + Attributes: + name (str): Название команды. + description (Optional[str]): Описание команды. Может быть None. + """ + name: str description: Optional[str] = None \ No newline at end of file diff --git a/maxapi/types/errors.py b/maxapi/types/errors.py index 69f2e5a..9ef687f 100644 --- a/maxapi/types/errors.py +++ b/maxapi/types/errors.py @@ -2,5 +2,14 @@ from pydantic import BaseModel class Error(BaseModel): + + """ + Модель ошибки. + + Attributes: + code (int): Код ошибки. + raw (dict): Необработанные данные ошибки. + """ + code: int raw: dict \ No newline at end of file diff --git a/maxapi/types/input_media.py b/maxapi/types/input_media.py index c04b12e..602fdef 100644 --- a/maxapi/types/input_media.py +++ b/maxapi/types/input_media.py @@ -4,11 +4,39 @@ from ..enums.upload_type import UploadType class InputMedia: + + """ + Класс для представления медиафайла. + + Attributes: + path (str): Путь к файлу. + type (UploadType): Тип файла, определенный на основе MIME-типа. + """ + def __init__(self, path: str): + + """ + Инициализирует объект медиафайла. + + Args: + path (str): Путь к файлу. + """ + self.path = path self.type = self.__detect_file_type(path) def __detect_file_type(self, path: str) -> UploadType: + + """ + Определяет тип файла на основе его MIME-типа. + + Args: + path (str): Путь к файлу. + + Returns: + UploadType: Тип файла (VIDEO, IMAGE, AUDIO или FILE). + """ + mime_type, _ = mimetypes.guess_type(path) if mime_type is None: diff --git a/maxapi/types/message.py b/maxapi/types/message.py index 11584a6..3717720 100644 --- a/maxapi/types/message.py +++ b/maxapi/types/message.py @@ -3,19 +3,21 @@ from __future__ import annotations from pydantic import BaseModel, Field from typing import Any, Optional, List, Union, TYPE_CHECKING -from ..enums.parse_mode import ParseMode -from ..types.attachments.attachment import Attachment -from ..types.attachments.share import Share -from .attachments.buttons.attachment_button import AttachmentButton from ..enums.text_style import TextStyle +from ..enums.parse_mode import ParseMode from ..enums.chat_type import ChatType from ..enums.message_link_type import MessageLinkType + +from .attachments.attachment import Attachment +from .attachments.share import Share +from .attachments.buttons.attachment_button import AttachmentButton from .attachments.sticker import Sticker from .attachments.file import File from .attachments.image import Image from .attachments.video import Video from .attachments.audio import Audio -from ..types.users import User + +from .users import User if TYPE_CHECKING: @@ -23,6 +25,16 @@ if TYPE_CHECKING: class MarkupElement(BaseModel): + + """ + Модель элемента разметки текста. + + Attributes: + type (TextStyle): Тип разметки. + from_ (int): Начальная позиция разметки в тексте. + length (int): Длина разметки. + """ + type: TextStyle from_: int = Field(..., alias='from') length: int @@ -32,16 +44,47 @@ class MarkupElement(BaseModel): class MarkupLink(MarkupElement): + + """ + Модель разметки ссылки. + + Attributes: + url (Optional[str]): URL ссылки. Может быть None. + """ + url: Optional[str] = None class Recipient(BaseModel): - user_id: Optional[int] = None # Для пользователя - chat_id: Optional[int] = None # Для чата - chat_type: ChatType # Тип получателя (диалог или чат) + + """ + Модель получателя сообщения. + + Attributes: + user_id (Optional[int]): Идентификатор пользователя. Может быть None. + chat_id (Optional[int]): Идентификатор чата. Может быть None. + chat_type (ChatType): Тип получателя (диалог или чат). + """ + + user_id: Optional[int] = None + chat_id: Optional[int] = None + chat_type: ChatType class MessageBody(BaseModel): + + """ + Модель тела сообщения. + + Attributes: + mid (str): Уникальный идентификатор сообщения. + seq (int): Порядковый номер сообщения. + text (str): Текст сообщения. Может быть None. + attachments (Optional[List[Union[AttachmentButton, Audio, Video, File, Image, Sticker, Share]]]): + Список вложений. По умолчанию пустой. + markup (Optional[List[Union[MarkupLink, MarkupElement]]]): Список элементов разметки. По умолчанию пустой. + """ + mid: str seq: int text: str = None @@ -69,10 +112,29 @@ class MessageBody(BaseModel): class MessageStat(BaseModel): + + """ + Модель статистики сообщения. + + Attributes: + views (int): Количество просмотров сообщения. + """ + views: int class LinkedMessage(BaseModel): + + """ + Модель связанного сообщения. + + Attributes: + type (MessageLinkType): Тип связи. + sender (User): Отправитель связанного сообщения. + chat_id (Optional[int]): Идентификатор чата. Может быть None. + message (MessageBody): Тело связанного сообщения. + """ + type: MessageLinkType sender: User chat_id: Optional[int] = None @@ -80,6 +142,21 @@ class LinkedMessage(BaseModel): class Message(BaseModel): + + """ + Модель сообщения. + + Attributes: + sender (User): Отправитель сообщения. + recipient (Recipient): Получатель сообщения. + timestamp (int): Временная метка сообщения. + link (Optional[LinkedMessage]): Связанное сообщение. Может быть None. + body (Optional[MessageBody]): Тело сообщения. Может быть None. + stat (Optional[MessageStat]): Статистика сообщения. Может быть None. + url (Optional[str]): URL сообщения. Может быть None. + bot (Optional[Bot]): Объект бота, исключается из сериализации. + """ + sender: User recipient: Recipient timestamp: int @@ -100,6 +177,22 @@ class Message(BaseModel): notify: bool = True, parse_mode: ParseMode = None ): + + """ + Отправляет ответное сообщение. + + Args: + text (str, optional): Текст ответа. Может быть None. + disable_link_preview (bool): Отключить предпросмотр ссылок. По умолчанию False. + attachments (List[Attachment], optional): Список вложений. Может быть None. + link (NewMessageLink, optional): Связь с другим сообщением. Может быть None. + notify (bool): Флаг отправки уведомления. По умолчанию True. + parse_mode (ParseMode, optional): Режим форматирования текста. Может быть None. + + Returns: + Any: Результат выполнения метода send_message бота. + """ + return await self.bot.send_message( chat_id=self.recipient.chat_id, user_id=self.recipient.user_id, @@ -119,6 +212,21 @@ class Message(BaseModel): notify: bool = True, parse_mode: ParseMode = None ): + + """ + Редактирует текущее сообщение. + + Args: + text (str, optional): Новый текст сообщения. Может быть None. + attachments (List[Attachment], optional): Новые вложения. Может быть None. + link (NewMessageLink, optional): Новая связь с сообщением. Может быть None. + notify (bool): Флаг отправки уведомления. По умолчанию True. + parse_mode (ParseMode, optional): Режим форматирования текста. Может быть None. + + Returns: + Any: Результат выполнения метода edit_message бота. + """ + return await self.bot.edit_message( message_id=self.body.mid, text=text, @@ -129,11 +237,30 @@ class Message(BaseModel): ) async def delete(self): + + """ + Удаляет текущее сообщение. + + Returns: + Any: Результат выполнения метода delete_message бота. + """ + return await self.bot.delete_message( message_id=self.body.mid, ) async def pin(self, notify: bool = True): + + """ + Закрепляет текущее сообщение в чате. + + Args: + notify (bool): Флаг отправки уведомления. По умолчанию True. + + Returns: + Any: Результат выполнения метода pin_message бота. + """ + return await self.bot.pin_message( chat_id=self.recipient.chat_id, message_id=self.body.mid, @@ -142,6 +269,15 @@ class Message(BaseModel): class Messages(BaseModel): + + """ + Модель списка сообщений. + + Attributes: + messages (List[Message]): Список сообщений. + bot (Optional[Bot]): Объект бота, исключается из сериализации. + """ + messages: List[Message] bot: Optional[Any] = Field(default=None, exclude=True) @@ -150,5 +286,14 @@ class Messages(BaseModel): class NewMessageLink(BaseModel): + + """ + Модель ссылки на новое сообщение. + + Attributes: + type (MessageLinkType): Тип связи. + mid (str): Идентификатор сообщения. + """ + type: MessageLinkType mid: str \ No newline at end of file diff --git a/maxapi/types/updates/bot_added.py b/maxapi/types/updates/bot_added.py index b2cbd0e..ab44185 100644 --- a/maxapi/types/updates/bot_added.py +++ b/maxapi/types/updates/bot_added.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any, Optional from pydantic import Field from .update import Update + from ...types.users import User if TYPE_CHECKING: @@ -10,6 +11,16 @@ if TYPE_CHECKING: class BotAdded(Update): + + """ + Обновление, сигнализирующее о добавлении бота в чат. + + Attributes: + chat_id (Optional[int]): Идентификатор чата, куда добавлен бот. + user (User): Объект пользователя-бота. + bot (Optional[Any]): Ссылка на экземпляр бота, не сериализуется. + """ + chat_id: Optional[int] = None user: User bot: Optional[Any] = Field(default=None, exclude=True) diff --git a/maxapi/types/updates/bot_removed.py b/maxapi/types/updates/bot_removed.py index 604691f..c25ca3c 100644 --- a/maxapi/types/updates/bot_removed.py +++ b/maxapi/types/updates/bot_removed.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any, Optional from pydantic import Field from .update import Update + from ...types.users import User if TYPE_CHECKING: @@ -10,6 +11,16 @@ if TYPE_CHECKING: class BotRemoved(Update): + + """ + Обновление, сигнализирующее об удалении бота из чата. + + Attributes: + chat_id (Optional[int]): Идентификатор чата, из которого удалён бот. + user (User): Объект пользователя-бота. + bot (Optional[Any]): Ссылка на экземпляр бота, не сериализуется. + """ + chat_id: Optional[int] = None user: User bot: Optional[Any] = Field(default=None, exclude=True) diff --git a/maxapi/types/updates/bot_started.py b/maxapi/types/updates/bot_started.py index 85051ec..f72ebbb 100644 --- a/maxapi/types/updates/bot_started.py +++ b/maxapi/types/updates/bot_started.py @@ -10,6 +10,18 @@ if TYPE_CHECKING: class BotStarted(Update): + + """ + Обновление, сигнализирующее о первом старте бота. + + Attributes: + chat_id (Optional[int]): Идентификатор чата. + user (User): Пользователь (бот). + user_locale (Optional[str]): Локаль пользователя. + payload (Optional[str]): Дополнительные данные. + bot (Optional[Any]): Ссылка на экземпляр бота, не сериализуется. + """ + chat_id: Optional[int] = None user: User user_locale: Optional[str] = None diff --git a/maxapi/types/updates/chat_title_changed.py b/maxapi/types/updates/chat_title_changed.py index 9fe8baf..6ecb864 100644 --- a/maxapi/types/updates/chat_title_changed.py +++ b/maxapi/types/updates/chat_title_changed.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any, Optional from pydantic import Field from .update import Update + from ...types.users import User if TYPE_CHECKING: @@ -10,6 +11,17 @@ if TYPE_CHECKING: class ChatTitleChanged(Update): + + """ + Обновление, сигнализирующее об изменении названия чата. + + Attributes: + chat_id (Optional[int]): Идентификатор чата. + user (User): Пользователь, совершивший изменение. + title (Optional[str]): Новое название чата. + bot (Optional[Any]): Ссылка на экземпляр бота, не сериализуется. + """ + chat_id: Optional[int] = None user: User title: Optional[str] = None diff --git a/maxapi/types/updates/message_callback.py b/maxapi/types/updates/message_callback.py index c4af974..e0ad559 100644 --- a/maxapi/types/updates/message_callback.py +++ b/maxapi/types/updates/message_callback.py @@ -3,12 +3,14 @@ from typing import Any, List, Optional, TYPE_CHECKING, Union from pydantic import BaseModel, Field from .update import Update + +from ...enums.parse_mode import ParseMode + +from ...types.message import NewMessageLink +from ...types.attachments.share import Share from ...types.callback import Callback from ...types.message import Message -from ...enums.parse_mode import ParseMode -from ...types.message import NewMessageLink -from ...types.attachments.share import Share from ..attachments.buttons.attachment_button import AttachmentButton from ..attachments.sticker import Sticker from ..attachments.file import File @@ -22,6 +24,19 @@ if TYPE_CHECKING: class MessageForCallback(BaseModel): + + """ + Модель сообщения для ответа на callback-запрос. + + Attributes: + text (Optional[str]): Текст сообщения. + attachments (Optional[List[Union[AttachmentButton, Audio, Video, File, Image, Sticker, Share]]]): + Список вложений. + link (Optional[NewMessageLink]): Связь с другим сообщением. + notify (Optional[bool]): Отправлять ли уведомление. + format (Optional[ParseMode]): Режим разбора текста. + """ + text: Optional[str] = None attachments: Optional[ List[ @@ -42,6 +57,17 @@ class MessageForCallback(BaseModel): class MessageCallback(Update): + + """ + Обновление с callback-событием сообщения. + + Attributes: + message (Message): Сообщение, на которое пришёл callback. + user_locale (Optional[str]): Локаль пользователя. + callback (Callback): Объект callback. + bot (Optional[Any]): Экземпляр бота, не сериализуется. + """ + message: Message user_locale: Optional[str] = None callback: Callback @@ -51,6 +77,14 @@ class MessageCallback(Update): bot: Optional[Bot] def get_ids(self): + + """ + Возвращает кортеж идентификаторов (chat_id, user_id). + + Returns: + tuple[Optional[int], int]: Идентификаторы чата и пользователя. + """ + return (self.message.recipient.chat_id, self.callback.user.user_id) async def answer( @@ -61,6 +95,21 @@ class MessageCallback(Update): notify: bool = True, format: ParseMode = None, ): + + """ + Отправляет ответ на callback с возможностью изменить текст, вложения и параметры уведомления. + + Args: + notification (str): Текст уведомления. + new_text (Optional[str]): Новый текст сообщения. + link (Optional[NewMessageLink]): Связь с другим сообщением. + notify (bool): Отправлять ли уведомление. + format (Optional[ParseMode]): Режим разбора текста. + + Returns: + Результат вызова send_callback бота. + """ + message = MessageForCallback() message.text = new_text diff --git a/maxapi/types/updates/message_created.py b/maxapi/types/updates/message_created.py index 02c265b..f94cc6d 100644 --- a/maxapi/types/updates/message_created.py +++ b/maxapi/types/updates/message_created.py @@ -1,9 +1,10 @@ from __future__ import annotations -from typing import Any, Optional, TYPE_CHECKING, ForwardRef +from typing import Any, Optional, TYPE_CHECKING from pydantic import Field from .update import Update + from ...types.message import Message if TYPE_CHECKING: @@ -11,6 +12,16 @@ if TYPE_CHECKING: class MessageCreated(Update): + + """ + Обновление, сигнализирующее о создании нового сообщения. + + Attributes: + message (Message): Объект сообщения. + user_locale (Optional[str]): Локаль пользователя. + bot (Optional[Any]): Экземпляр бота, не сериализуется. + """ + message: Message user_locale: Optional[str] = None bot: Optional[Any] = Field(default=None, exclude=True) @@ -19,4 +30,12 @@ class MessageCreated(Update): bot: Optional[Bot] def get_ids(self): + + """ + Возвращает кортеж идентификаторов (chat_id, user_id). + + Returns: + tuple[Optional[int], int]: Идентификатор чата и пользователя. + """ + return (self.message.recipient.chat_id, self.message.sender.user_id) \ No newline at end of file diff --git a/maxapi/types/updates/message_edited.py b/maxapi/types/updates/message_edited.py index 137f9d1..0a728f1 100644 --- a/maxapi/types/updates/message_edited.py +++ b/maxapi/types/updates/message_edited.py @@ -1,7 +1,9 @@ from typing import TYPE_CHECKING, Any, Optional from pydantic import Field + from .update import Update + from ...types.message import Message if TYPE_CHECKING: @@ -9,6 +11,15 @@ if TYPE_CHECKING: class MessageEdited(Update): + + """ + Обновление, сигнализирующее об изменении сообщения. + + Attributes: + message (Message): Объект измененного сообщения. + bot (Optional[Any]): Экземпляр бота, не сериализуется. + """ + message: Message bot: Optional[Any] = Field(default=None, exclude=True) @@ -16,4 +27,12 @@ class MessageEdited(Update): bot: Optional[Bot] def get_ids(self): + + """ + Возвращает кортеж идентификаторов (chat_id, user_id). + + Returns: + Tuple[Optional[int], Optional[int]]: Идентификаторы чата и пользователя. + """ + return (self.message.recipient.chat_id, self.message.recipient.user_id) \ No newline at end of file diff --git a/maxapi/types/updates/message_removed.py b/maxapi/types/updates/message_removed.py index 6c822a9..83f32b3 100644 --- a/maxapi/types/updates/message_removed.py +++ b/maxapi/types/updates/message_removed.py @@ -9,6 +9,17 @@ if TYPE_CHECKING: class MessageRemoved(Update): + + """ + Класс для обработки события удаления сообщения в чате. + + Attributes: + message_id (Optional[str]): Идентификатор удаленного сообщения. Может быть None. + chat_id (Optional[int]): Идентификатор чата. Может быть None. + user_id (Optional[int]): Идентификатор пользователя. Может быть None. + bot (Optional[Bot]): Объект бота, исключается из сериализации. + """ + message_id: Optional[str] = None chat_id: Optional[int] = None user_id: Optional[int] = None @@ -18,4 +29,12 @@ class MessageRemoved(Update): bot: Optional[Bot] def get_ids(self): + + """ + Возвращает кортеж идентификаторов (chat_id, user_id). + + Returns: + Tuple[Optional[int], Optional[int]]: Идентификаторы чата и пользователя. + """ + return (self.chat_id, self.user_id) \ No newline at end of file diff --git a/maxapi/types/updates/update.py b/maxapi/types/updates/update.py index c600837..caa986b 100644 --- a/maxapi/types/updates/update.py +++ b/maxapi/types/updates/update.py @@ -4,6 +4,15 @@ from ...enums.update import UpdateType class Update(BaseModel): + + """ + Базовая модель обновления. + + Attributes: + update_type (UpdateType): Тип обновления. + timestamp (int): Временная метка обновления. + """ + update_type: UpdateType timestamp: int diff --git a/maxapi/types/updates/user_added.py b/maxapi/types/updates/user_added.py index 887d755..d5ae547 100644 --- a/maxapi/types/updates/user_added.py +++ b/maxapi/types/updates/user_added.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any, Optional from pydantic import Field from .update import Update + from ...types.users import User @@ -11,6 +12,17 @@ if TYPE_CHECKING: class UserAdded(Update): + + """ + Класс для обработки события добавления пользователя в чат. + + Attributes: + inviter_id (Optional[int]): Идентификатор пользователя, добавившего нового участника. Может быть None. + chat_id (Optional[int]): Идентификатор чата. Может быть None. + user (User): Объект пользователя, добавленного в чат. + bot (Optional[Bot]): Объект бота, исключается из сериализации. + """ + inviter_id: Optional[int] = None chat_id: Optional[int] = None user: User @@ -20,4 +32,12 @@ class UserAdded(Update): bot: Optional[Bot] def get_ids(self): + + """ + Возвращает кортеж идентификаторов (chat_id, user_id). + + Returns: + Tuple[Optional[int], Optional[int]]: Идентификаторы чата и пользователя. + """ + return (self.chat_id, self.inviter_id) \ No newline at end of file diff --git a/maxapi/types/updates/user_removed.py b/maxapi/types/updates/user_removed.py index c201acf..6a218d2 100644 --- a/maxapi/types/updates/user_removed.py +++ b/maxapi/types/updates/user_removed.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any, Optional from pydantic import Field from .update import Update + from ...types.users import User if TYPE_CHECKING: @@ -10,6 +11,17 @@ if TYPE_CHECKING: class UserRemoved(Update): + + """ + Класс для обработки события удаления пользователя из чата. + + Attributes: + admin_id (Optional[int]): Идентификатор администратора, удалившего пользователя. Может быть None. + chat_id (Optional[int]): Идентификатор чата. Может быть None. + user (User): Объект пользователя, удаленного из чата. + bot (Optional[Bot]): Объект бота, исключается из сериализации. + """ + admin_id: Optional[int] = None chat_id: Optional[int] = None user: User @@ -19,4 +31,12 @@ class UserRemoved(Update): bot: Optional[Bot] def get_ids(self): + + """ + Возвращает кортеж идентификаторов (chat_id, user_id). + + Returns: + Tuple[Optional[int], Optional[int]]: Идентификаторы чата и пользователя. + """ + return (self.chat_id, self.admin_id) \ No newline at end of file diff --git a/maxapi/types/users.py b/maxapi/types/users.py index 28569e4..b1c78d3 100644 --- a/maxapi/types/users.py +++ b/maxapi/types/users.py @@ -3,10 +3,28 @@ from typing import List, Optional from datetime import datetime from ..enums.chat_permission import ChatPermission + from ..types.command import BotCommand class User(BaseModel): + + """ + Модель пользователя. + + Attributes: + user_id (int): Уникальный идентификатор пользователя. + first_name (str): Имя пользователя. + last_name (Optional[str]): Фамилия пользователя. Может быть None. + username (Optional[str]): Имя пользователя (ник). Может быть None. + is_bot (bool): Флаг, указывающий, является ли пользователь ботом. + last_activity_time (int): Временная метка последней активности. + description (Optional[str]): Описание пользователя. Может быть None. + avatar_url (Optional[str]): URL аватара пользователя. Может быть None. + full_avatar_url (Optional[str]): URL полного аватара пользователя. Может быть None. + commands (Optional[List[BotCommand]]): Список команд бота. Может быть None. + """ + user_id: int first_name: str last_name: Optional[str] = None @@ -25,5 +43,14 @@ class User(BaseModel): class ChatAdmin(BaseModel): + + """ + Модель администратора чата. + + Attributes: + user_id (int): Уникальный идентификатор администратора. + permissions (List[ChatPermission]): Список разрешений администратора. + """ + user_id: int permissions: List[ChatPermission] \ No newline at end of file diff --git a/maxapi/utils/inline_keyboard.py b/maxapi/utils/inline_keyboard.py index aeee4a1..1335e77 100644 --- a/maxapi/utils/inline_keyboard.py +++ b/maxapi/utils/inline_keyboard.py @@ -1,15 +1,47 @@ +from maxapi.types.attachments.buttons import InlineButtonUnion from ..enums.attachment import AttachmentType from ..types.attachments.attachment import Attachment, ButtonsPayload class InlineKeyboardBuilder: - def __init__(self): - self.payload = [] + + """Конструктор инлайн-клавиатур. - def row(self, *buttons): + Позволяет удобно собирать кнопки в ряды и формировать из них клавиатуру + для отправки в сообщениях. + """ + + def __init__(self): + self.payload = [[]] + + def row(self, *buttons: InlineButtonUnion): + + """Добавить новый ряд кнопок в клавиатуру. + + Args: + *buttons: Произвольное количество кнопок для добавления в ряд. + """ + self.payload.append([*buttons]) + + def add(self, button: InlineButtonUnion): + + """Добавить кнопку в последний ряд клавиатуры. + + Args: + button: Кнопка для добавления. + """ + + self.payload[-1].append(button) def as_markup(self): + + """Собрать клавиатуру в объект для отправки. + + Returns: + Объект вложения с типом INLINE_KEYBOARD. + """ + return Attachment( type=AttachmentType.INLINE_KEYBOARD, payload=ButtonsPayload(