Добавлены докстринги

This commit is contained in:
Денис Семёнов 2025-06-20 17:23:51 +03:00
parent 1e4d22a2bc
commit e08e620b92
101 changed files with 2222 additions and 152 deletions

View File

@ -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.
:param message_id: ID сообщения
:return: Объект сообщения
"""
return await self.get_messages(
message_ids=[message_id]
)
async def get_me(self) -> User:
"""Получает информацию о текущем боте.
:return: Объект пользователя бота
"""
async def get_me(self):
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)

View File

@ -16,6 +16,14 @@ if TYPE_CHECKING:
class BaseConnection:
"""
Базовый класс для всех методов API.
Содержит общую логику выполнения запроса (например, сериализацию, отправку HTTP-запроса, обработку ответа).
Метод request() может быть переопределён в потомках при необходимости.
"""
API_URL = 'https://botapi.max.ru'
def __init__(self):
@ -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(

View File

@ -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 = {}

View File

@ -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)]

View File

@ -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

View File

@ -1,6 +1,14 @@
from enum import Enum
class ApiPath(str, Enum):
"""
Перечисление всех доступных API-эндпоинтов.
Используется для унифицированного указания путей при отправке запросов.
"""
ME = '/me'
CHATS = '/chats'
MESSAGES = '/messages'

View File

@ -1,6 +1,14 @@
from enum import Enum
class AttachmentType(str, Enum):
"""
Типы вложений, поддерживаемые в сообщениях.
Используется для указания типа содержимого при отправке или обработке вложений.
"""
IMAGE = 'image'
VIDEO = 'video'
AUDIO = 'audio'

View File

@ -2,6 +2,13 @@ from enum import Enum
class ButtonType(str, Enum):
"""
Типы кнопок, доступных в интерфейсе бота.
Определяют поведение при нажатии на кнопку в сообщении.
"""
REQUEST_CONTACT = 'request_contact'
CALLBACK = 'callback'
LINK = 'link'

View File

@ -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'

View File

@ -2,6 +2,13 @@ from enum import Enum
class ChatStatus(str, Enum):
"""
Статус чата относительно пользователя или системы.
Используется для отображения текущего состояния чата или определения доступных действий.
"""
ACTIVE = 'active'
REMOVED = 'removed'
LEFT = 'left'

View File

@ -2,5 +2,12 @@ from enum import Enum
class ChatType(str, Enum):
"""
Тип чата.
Используется для различения личных и групповых чатов.
"""
DIALOG = 'dialog'
CHAT = 'chat'

View File

@ -2,6 +2,13 @@ from enum import Enum
class HTTPMethod(str, Enum):
"""
HTTP-методы, поддерживаемые клиентом API.
Используются при выполнении запросов к серверу.
"""
POST = 'POST'
GET = 'GET'
PATCH = 'PATCH'

View File

@ -1,6 +1,14 @@
from enum import Enum
class Intent(str, Enum):
"""
Тип интента (намерения) кнопки.
Используется для стилизации и логической классификации пользовательских действий.
"""
DEFAULT = 'default'
POSITIVE = 'positive'
NEGATIVE = 'negative'

View File

@ -2,5 +2,12 @@ from enum import Enum
class MessageLinkType(str, Enum):
"""
Тип связи между сообщениями.
Используется для указания типа привязки: пересылка или ответ.
"""
FORWARD = 'forward'
REPLY = 'reply'

View File

@ -1,5 +1,13 @@
from enum import Enum
class ParseMode(str, Enum):
"""
Формат разметки текста сообщений.
Используется для указания способа интерпретации стилей (жирный, курсив, ссылки и т.д.).
"""
MARKDOWN = 'markdown'
HTML = 'html'

View File

@ -1,6 +1,14 @@
from enum import Enum
class SenderAction(str, Enum):
"""
Действия отправителя, отображаемые получателю в интерфейсе.
Используются для имитации активности (например, "печатает...") перед отправкой сообщения или медиа.
"""
TYPING_ON = 'typing_on'
SENDING_PHOTO = 'sending_photo'
SENDING_VIDEO = 'sending_video'

View File

@ -2,6 +2,13 @@ from enum import Enum
class TextStyle(Enum):
"""
Стили текста, применяемые в сообщениях.
Используются для форматирования и выделения частей текста в сообщении.
"""
UNDERLINE = 'underline'
STRONG = 'strong'
EMPHASIZED = 'emphasized'

View File

@ -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'

View File

@ -2,6 +2,13 @@ from enum import Enum
class UploadType(str, Enum):
"""
Типы загружаемых файлов.
Используются для указания категории контента при загрузке на сервер.
"""
IMAGE = 'image'
VIDEO = 'video'
AUDIO = 'audio'

View File

@ -10,6 +10,12 @@ from ..loggers import logger_dp
class Handler:
"""
Обработчик события.
Позволяет связать функцию-обработчик с типом обновления, состоянием и набором фильтров.
"""
def __init__(
self,
*args,
@ -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 = []

View File

@ -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
@ -16,6 +15,16 @@ if TYPE_CHECKING:
class AddAdminChat(BaseConnection):
"""
Класс для добавления списка администраторов в чат через API.
Args:
bot (Bot): Экземпляр бота, через который выполняется запрос.
chat_id (int): Идентификатор чата.
admins (List[ChatAdmin]): Список администраторов для добавления.
marker (int, optional): Маркер для пагинации или дополнительных настроек. По умолчанию None.
"""
def __init__(
self,
bot: 'Bot',
@ -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]

View File

@ -14,6 +14,15 @@ if TYPE_CHECKING:
class AddMembersChat(BaseConnection):
"""
Класс для добавления участников в чат через API.
Args:
bot (Bot): Экземпляр бота, через который выполняется запрос.
chat_id (int): Идентификатор целевого чата.
user_ids (List[int]): Список ID пользователей для добавления в чат.
"""
def __init__(
self,
bot: 'Bot',
@ -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

View File

@ -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

View File

@ -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,

View File

@ -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),

View File

@ -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

View File

@ -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,

View File

@ -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:

View File

@ -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 = {}

View File

@ -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),

View File

@ -15,6 +15,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-_]*'
def __init__(
@ -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],

View File

@ -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

View File

@ -14,6 +14,18 @@ if TYPE_CHECKING:
class GetListAdminChat(BaseConnection):
"""
Класс для получения списка администраторов чата через API.
Args:
bot (Bot): Экземпляр бота для выполнения запроса.
chat_id (int): Идентификатор чата.
Attributes:
bot (Bot): Экземпляр бота.
chat_id (int): Идентификатор чата.
"""
def __init__(
self,
bot: 'Bot',
@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -14,6 +14,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,
bot: 'Bot',
@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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',
@ -26,6 +32,13 @@ class GetVideo(BaseConnection):
async def request(self) -> Video:
"""
Выполняет GET-запрос для получения данных видео по токену.
Returns:
Video: Объект с информацией о видео.
"""
return await super().request(
method=HTTPMethod.GET,
path=ApiPath.VIDEOS.value + '/' + self.video_token,

View File

@ -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

View File

@ -1,5 +1,3 @@
from typing import TYPE_CHECKING
from .types.removed_admin import RemovedAdmin
@ -16,6 +14,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,
bot: 'Bot',
@ -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,

View File

@ -1,4 +1,4 @@
from typing import TYPE_CHECKING, List
from typing import TYPE_CHECKING
from .types.removed_member_chat import RemovedMemberChat
@ -14,6 +14,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,
bot: 'Bot',
@ -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

View File

@ -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

View File

@ -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()
params['callback_id'] = self.callback_id
"""
Выполняет POST-запрос для отправки callback-ответа.
json = {}
Возвращает результат отправки.
if self.message: json['message'] = self.message.model_dump()
if self.notification: json['notification'] = self.notification
Returns:
SendedCallback: Объект с результатом отправки callback.
"""
return await super().request(
method=HTTPMethod.POST,
path=ApiPath.ANSWERS,
model=SendedCallback,
params=params,
json=json
)
except Exception as e:
print(e)
...
params = self.bot.params.copy()
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
)

View File

@ -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': []}

View File

@ -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

View File

@ -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

View File

@ -3,5 +3,14 @@ from pydantic import BaseModel
class DeletedBotFromChat(BaseModel):
"""
Ответ API при удалении бота из чата.
Attributes:
success (bool): Статус успешности операции.
message (Optional[str]): Дополнительное сообщение или ошибка.
"""
success: bool
message: Optional[str] = None

View File

@ -3,5 +3,14 @@ from pydantic import BaseModel
class DeletedChat(BaseModel):
"""
Ответ API при удалении чата (?).
Attributes:
success (bool): Статус успешности операции.
message (Optional[str]): Дополнительное сообщение или ошибка.
"""
success: bool
message: Optional[str] = None

View File

@ -3,5 +3,14 @@ from pydantic import BaseModel
class DeletedMessage(BaseModel):
"""
Ответ API при удалении сообщения.
Attributes:
success (bool): Статус успешности операции.
message (Optional[str]): Дополнительное сообщение или ошибка.
"""
success: bool
message: Optional[str] = None

View File

@ -3,5 +3,14 @@ from pydantic import BaseModel
class DeletedPinMessage(BaseModel):
"""
Ответ API при удалении закрепленного в чате сообщения.
Attributes:
success (bool): Статус успешности операции.
message (Optional[str]): Дополнительное сообщение или ошибка.
"""
success: bool
message: Optional[str] = None

View File

@ -3,5 +3,14 @@ from pydantic import BaseModel
class EditedMessage(BaseModel):
"""
Ответ API при изменении сообщения.
Attributes:
success (bool): Статус успешности операции.
message (Optional[str]): Дополнительное сообщение или ошибка.
"""
success: bool
message: Optional[str] = None

View File

@ -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

View File

@ -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

View File

@ -5,4 +5,12 @@ from ...types.message import Message
class GettedPin(BaseModel):
"""
Ответ API с информацией о закреплённом сообщении.
Attributes:
message (Optional[Message]): Закреплённое сообщение, если оно есть.
"""
message: Optional[Message] = None

View File

@ -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

View File

@ -3,5 +3,14 @@ from pydantic import BaseModel
class PinnedMessage(BaseModel):
"""
Ответ API при добавлении списка администраторов в чат.
Attributes:
success (bool): Статус успешности операции.
message (Optional[str]): Дополнительное сообщение или ошибка.
"""
success: bool
message: Optional[str] = None

View File

@ -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

View File

@ -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

View File

@ -3,5 +3,14 @@ from pydantic import BaseModel
class SendedAction(BaseModel):
"""
Ответ API после выполнения действия.
Attributes:
success (bool): Статус успешности выполнения операции.
message (Optional[str]): Дополнительное сообщение или описание ошибки.
"""
success: bool
message: Optional[str] = None

View File

@ -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)

View File

@ -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

View File

@ -1,5 +0,0 @@
from pydantic import BaseModel
class UploadFileResponse(BaseModel):
...

View File

@ -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,

View File

@ -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

View File

@ -5,5 +5,14 @@ from ..attachment import ButtonsPayload
class AttachmentButton(BaseModel):
"""
Модель кнопки вложения для сообщения.
Attributes:
type: Тип кнопки, фиксированное значение 'inline_keyboard'
payload: Полезная нагрузка кнопки (массив рядов кнопок)
"""
type: Literal['inline_keyboard'] = 'inline_keyboard'
payload: ButtonsPayload

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -4,4 +4,12 @@ from .button import Button
class LinkButton(Button):
"""
Кнопка с внешней ссылкой.
Args:
url: Ссылка для перехода (должна содержать http/https)
"""
url: Optional[str] = None

View File

@ -2,4 +2,7 @@ from .button import Button
class RequestContact(Button):
"""
Кнопка с контактом.
"""
...

View File

@ -2,4 +2,12 @@ from .button import Button
class RequestGeoLocationButton(Button):
"""Кнопка запроса геолокации пользователя.
Attributes:
quick: Если True, запрашивает геолокацию без дополнительного
подтверждения пользователя (по умолчанию False)
"""
quick: bool = False

View File

@ -4,4 +4,12 @@ from .attachment import Attachment
class Contact(Attachment):
"""
Вложение с типом контакта.
Attributes:
type (Literal['contact']): Тип вложения, всегда 'contact'.
"""
type: Literal['contact'] = 'contact'

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -2,5 +2,14 @@ from pydantic import BaseModel
class Error(BaseModel):
"""
Модель ошибки.
Attributes:
code (int): Код ошибки.
raw (dict): Необработанные данные ошибки.
"""
code: int
raw: dict

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -4,6 +4,15 @@ from ...enums.update import UpdateType
class Update(BaseModel):
"""
Базовая модель обновления.
Attributes:
update_type (UpdateType): Тип обновления.
timestamp (int): Временная метка обновления.
"""
update_type: UpdateType
timestamp: int

View File

@ -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)

View File

@ -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)

View File

@ -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]

Some files were not shown because too many files have changed in this diff Show More