Переход на Google Style Docstring
This commit is contained in:
		
							
								
								
									
										884
									
								
								maxapi/bot.py
									
									
									
									
									
								
							
							
						
						
									
										884
									
								
								maxapi/bot.py
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,10 +1,27 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from aiohttp import ClientTimeout
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DefaultConnectionProperties:
 | 
			
		||||
    
 | 
			
		||||
    '''
 | 
			
		||||
    Класс для хранения параметров соединения по умолчанию для aiohttp-клиента.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        timeout (int): Таймаут всего соединения в секундах (по умолчанию 5 * 30).
 | 
			
		||||
        sock_connect (int): Таймаут установки TCP-соединения в секундах (по умолчанию 30).
 | 
			
		||||
        **kwargs: Дополнительные параметры, которые будут сохранены как есть.
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        timeout (ClientTimeout): Экземпляр aiohttp.ClientTimeout с заданными параметрами.
 | 
			
		||||
        kwargs (dict): Дополнительные параметры.
 | 
			
		||||
    '''
 | 
			
		||||
 | 
			
		||||
    def __init__(self, timeout: int = 5 * 30, sock_connect: int = 30, **kwargs):
 | 
			
		||||
        '''
 | 
			
		||||
        Инициализация параметров соединения.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            timeout (int): Таймаут всего соединения в секундах.
 | 
			
		||||
            sock_connect (int): Таймаут установки TCP-соединения в секундах.
 | 
			
		||||
            **kwargs: Дополнительные параметры.
 | 
			
		||||
        '''
 | 
			
		||||
        self.timeout = ClientTimeout(total=timeout, sock_connect=sock_connect)
 | 
			
		||||
        self.kwargs = kwargs
 | 
			
		||||
        self.kwargs = kwargs
 | 
			
		||||
 
 | 
			
		||||
@@ -30,9 +30,7 @@ class BaseConnection:
 | 
			
		||||
    """
 | 
			
		||||
    Базовый класс для всех методов API.
 | 
			
		||||
 | 
			
		||||
    Содержит общую логику выполнения запроса (например, сериализацию, отправку HTTP-запроса, обработку ответа).
 | 
			
		||||
 | 
			
		||||
    Метод request() может быть переопределён в потомках при необходимости.
 | 
			
		||||
    Содержит общую логику выполнения запроса (сериализация, отправка HTTP-запроса, обработка ответа).
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    API_URL = 'https://botapi.max.ru'
 | 
			
		||||
@@ -41,53 +39,67 @@ class BaseConnection:
 | 
			
		||||
    AFTER_MEDIA_INPUT_DELAY = 2.0
 | 
			
		||||
 | 
			
		||||
    def __init__(self) -> None:
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Инициализация BaseConnection.
 | 
			
		||||
 | 
			
		||||
        Атрибуты:
 | 
			
		||||
            bot (Optional[Bot]): Экземпляр бота.
 | 
			
		||||
            session (Optional[ClientSession]): aiohttp-сессия.
 | 
			
		||||
            after_input_media_delay (float): Задержка после ввода медиа.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.bot: Optional[Bot] = None
 | 
			
		||||
        self.session: Optional[ClientSession] = None
 | 
			
		||||
        self.after_input_media_delay: float = self.AFTER_MEDIA_INPUT_DELAY
 | 
			
		||||
 | 
			
		||||
    async def request(
 | 
			
		||||
            self,
 | 
			
		||||
            method: HTTPMethod,
 | 
			
		||||
            path: ApiPath | str,
 | 
			
		||||
            model: BaseModel | Any = None,
 | 
			
		||||
            is_return_raw: bool = False,
 | 
			
		||||
            **kwargs
 | 
			
		||||
        ):
 | 
			
		||||
        self,
 | 
			
		||||
        method: HTTPMethod,
 | 
			
		||||
        path: ApiPath | str,
 | 
			
		||||
        model: BaseModel | Any = None,
 | 
			
		||||
        is_return_raw: bool = False,
 | 
			
		||||
        **kwargs
 | 
			
		||||
    ):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Выполняет HTTP-запрос к API, используя указанные параметры.
 | 
			
		||||
        Выполняет 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)
 | 
			
		||||
        Args:
 | 
			
		||||
            method (HTTPMethod): HTTP-метод (GET, POST и т.д.).
 | 
			
		||||
            path (ApiPath | str): Путь до конечной точки.
 | 
			
		||||
            model (BaseModel | Any, optional): Pydantic-модель для десериализации ответа, если is_return_raw=False.
 | 
			
		||||
            is_return_raw (bool, optional): Если True — вернуть сырой ответ, иначе — результат десериализации.
 | 
			
		||||
            **kwargs: Дополнительные параметры (query, headers, json).
 | 
			
		||||
 | 
			
		||||
        :return:
 | 
			
		||||
            - Объект model (если is_return_raw=False и model задан)
 | 
			
		||||
            
 | 
			
		||||
            - dict (если is_return_raw=True)
 | 
			
		||||
        Returns:
 | 
			
		||||
            model | dict | Error: Объект модели, dict или ошибка.
 | 
			
		||||
 | 
			
		||||
        Raises:
 | 
			
		||||
            RuntimeError: Если бот не инициализирован.
 | 
			
		||||
            MaxConnection: Ошибка соединения.
 | 
			
		||||
            InvalidToken: Ошибка авторизации (401).
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        if self.bot is None:
 | 
			
		||||
            raise RuntimeError('Bot не инициализирован')
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        if not self.bot.session:
 | 
			
		||||
            self.bot.session = ClientSession(
 | 
			
		||||
                base_url=self.bot.API_URL, 
 | 
			
		||||
                timeout=self.bot.default_connection.timeout, 
 | 
			
		||||
                base_url=self.bot.API_URL,
 | 
			
		||||
                timeout=self.bot.default_connection.timeout,
 | 
			
		||||
                **self.bot.default_connection.kwargs
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            r = await self.bot.session.request(
 | 
			
		||||
                method=method.value, 
 | 
			
		||||
                url=path.value if isinstance(path, ApiPath) else path, 
 | 
			
		||||
                method=method.value,
 | 
			
		||||
                url=path.value if isinstance(path, ApiPath) else path,
 | 
			
		||||
                **kwargs
 | 
			
		||||
            )
 | 
			
		||||
        except ClientConnectionError as e:
 | 
			
		||||
            raise MaxConnection(f'Ошибка при отправке запроса: {e}')
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        if r.status == 401:
 | 
			
		||||
            await self.bot.session.close()
 | 
			
		||||
            raise InvalidToken('Неверный токен!')
 | 
			
		||||
@@ -97,38 +109,41 @@ class BaseConnection:
 | 
			
		||||
            error = Error(code=r.status, raw=raw)
 | 
			
		||||
            logger_bot.error(error)
 | 
			
		||||
            return error
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        raw = await r.json()
 | 
			
		||||
 | 
			
		||||
        if is_return_raw: 
 | 
			
		||||
        if is_return_raw:
 | 
			
		||||
            return raw
 | 
			
		||||
 | 
			
		||||
        model = model(**raw) # type: ignore
 | 
			
		||||
        
 | 
			
		||||
        model = model(**raw)  # type: ignore
 | 
			
		||||
 | 
			
		||||
        if hasattr(model, 'message'):
 | 
			
		||||
            attr = getattr(model, 'message')
 | 
			
		||||
            if hasattr(attr, 'bot'):
 | 
			
		||||
                attr.bot = self.bot
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        if hasattr(model, 'bot'):
 | 
			
		||||
            model.bot = self.bot
 | 
			
		||||
 | 
			
		||||
        return model
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    async def upload_file(
 | 
			
		||||
            self,
 | 
			
		||||
            url: str,
 | 
			
		||||
            path: str,
 | 
			
		||||
            type: UploadType
 | 
			
		||||
        self,
 | 
			
		||||
        url: str,
 | 
			
		||||
        path: str,
 | 
			
		||||
        type: UploadType
 | 
			
		||||
    ):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Загружает файл на указанный URL.
 | 
			
		||||
        Загружает файл на сервер.
 | 
			
		||||
 | 
			
		||||
        :param url: Конечная точка загрузки файла
 | 
			
		||||
        :param path: Путь к локальному файлу
 | 
			
		||||
        :param type: Тип файла (video, image, audio, file)
 | 
			
		||||
        Args:
 | 
			
		||||
            url (str): URL загрузки.
 | 
			
		||||
            path (str): Путь к файлу.
 | 
			
		||||
            type (UploadType): Тип файла.
 | 
			
		||||
 | 
			
		||||
        :return: Сырой .text() ответ от сервера после загрузки файла
 | 
			
		||||
        Returns:
 | 
			
		||||
            str: Сырой .text() ответ от сервера.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        async with aiofiles.open(path, 'rb') as f:
 | 
			
		||||
@@ -147,12 +162,12 @@ class BaseConnection:
 | 
			
		||||
 | 
			
		||||
        async with ClientSession() as session:
 | 
			
		||||
            response = await session.post(
 | 
			
		||||
                url=url, 
 | 
			
		||||
                url=url,
 | 
			
		||||
                data=form
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            return await response.text()
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    async def upload_file_buffer(
 | 
			
		||||
        self,
 | 
			
		||||
        filename: str,
 | 
			
		||||
@@ -160,16 +175,20 @@ class BaseConnection:
 | 
			
		||||
        buffer: bytes,
 | 
			
		||||
        type: UploadType
 | 
			
		||||
    ):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Загружает файл из буфера.
 | 
			
		||||
 | 
			
		||||
        :param url: Конечная точка загрузки файла
 | 
			
		||||
        :param buffer: Буфер (bytes)
 | 
			
		||||
        :param type: Тип файла (video, image, audio, file)
 | 
			
		||||
        Args:
 | 
			
		||||
            filename (str): Имя файла.
 | 
			
		||||
            url (str): URL загрузки.
 | 
			
		||||
            buffer (bytes): Буфер данных.
 | 
			
		||||
            type (UploadType): Тип файла.
 | 
			
		||||
 | 
			
		||||
        :return: Сырой .text() ответ от сервера после загрузки файла
 | 
			
		||||
        Returns:
 | 
			
		||||
            str: Сырой .text() ответ от сервера.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        try:
 | 
			
		||||
            matches = puremagic.magic_string(buffer[:4096])
 | 
			
		||||
            if matches:
 | 
			
		||||
@@ -194,36 +213,7 @@ class BaseConnection:
 | 
			
		||||
 | 
			
		||||
        async with ClientSession() as session:
 | 
			
		||||
            response = await session.post(
 | 
			
		||||
                url=url, 
 | 
			
		||||
                url=url,
 | 
			
		||||
                data=form
 | 
			
		||||
            )
 | 
			
		||||
            return await response.text()
 | 
			
		||||
        
 | 
			
		||||
    async def download_file(
 | 
			
		||||
            self,
 | 
			
		||||
            path: str,
 | 
			
		||||
            url: str,
 | 
			
		||||
            token: str,
 | 
			
		||||
    ):
 | 
			
		||||
        """
 | 
			
		||||
        Скачивает медиа с указанной ссылки по токену, сохраняя по определенному пути
 | 
			
		||||
 | 
			
		||||
        :param path: Путь сохранения медиа
 | 
			
		||||
        :param url: Ссылка на медиа
 | 
			
		||||
        :param token: Токен медиа
 | 
			
		||||
 | 
			
		||||
        :return: Числовой статус
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        headers = {
 | 
			
		||||
            'Authorization': f'Bearer {token}'
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        async with ClientSession() as session:
 | 
			
		||||
            async with session.get(url, headers=headers) as response:
 | 
			
		||||
                
 | 
			
		||||
                if response.status == 200:
 | 
			
		||||
                    async with aiofiles.open(path, 'wb') as f:
 | 
			
		||||
                        await f.write(await response.read())
 | 
			
		||||
                        
 | 
			
		||||
                return response.status
 | 
			
		||||
            return await response.text()
 | 
			
		||||
@@ -1,4 +1,8 @@
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class State:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Представляет отдельное состояние в FSM-группе.
 | 
			
		||||
 | 
			
		||||
@@ -16,6 +20,7 @@ class State:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class StatesGroup:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Базовый класс для описания группы состояний FSM.
 | 
			
		||||
 | 
			
		||||
@@ -23,7 +28,8 @@ class StatesGroup:
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def states(cls) -> list[str]:
 | 
			
		||||
    def states(cls) -> List[str]:
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Получить список всех состояний в формате 'ИмяКласса:имя_состояния'.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,8 @@ from asyncio.exceptions import TimeoutError as AsyncioTimeoutError
 | 
			
		||||
 | 
			
		||||
from aiohttp import ClientConnectorError
 | 
			
		||||
 | 
			
		||||
from maxapi.exceptions.dispatcher import HandlerException
 | 
			
		||||
 | 
			
		||||
from .filters.filter import BaseFilter
 | 
			
		||||
from .filters.middleware import BaseMiddleware
 | 
			
		||||
from .filters.handler import Handler
 | 
			
		||||
@@ -60,9 +62,9 @@ class Dispatcher:
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Инициализация диспетчера.
 | 
			
		||||
        
 | 
			
		||||
        :param router_id: Идентификатор роутера, используется при логгировании. 
 | 
			
		||||
            По умолчанию индекс зарегистированного роутера в списке 
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            router_id (str | None): Идентификатор роутера для логов.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.router_id = router_id
 | 
			
		||||
@@ -132,6 +134,17 @@ class Dispatcher:
 | 
			
		||||
        handler: Callable[[Any, dict[str, Any]], Awaitable[Any]]
 | 
			
		||||
    ) -> Callable[[Any, dict[str, Any]], Awaitable[Any]]:
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Формирует цепочку вызова middleware вокруг хендлера.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            middlewares (list[BaseMiddleware]): Список middleware.
 | 
			
		||||
            handler (Callable): Финальный обработчик.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            Callable: Обёрнутый обработчик.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        for mw in reversed(middlewares):
 | 
			
		||||
            handler = functools.partial(mw, handler)
 | 
			
		||||
            
 | 
			
		||||
@@ -142,7 +155,8 @@ class Dispatcher:
 | 
			
		||||
        """
 | 
			
		||||
        Добавляет указанные роутеры в диспетчер.
 | 
			
		||||
 | 
			
		||||
        :param routers: Роутеры для добавления.
 | 
			
		||||
        Args:
 | 
			
		||||
            *routers (Router): Роутеры для добавления.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.routers += [r for r in routers]
 | 
			
		||||
@@ -150,9 +164,10 @@ class Dispatcher:
 | 
			
		||||
    def outer_middleware(self, middleware: BaseMiddleware) -> None:
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Добавляет Middleware на первое место в списке
 | 
			
		||||
        
 | 
			
		||||
        :param: middleware: Middleware
 | 
			
		||||
        Добавляет Middleware на первое место в списке.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            middleware (BaseMiddleware): Middleware.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.middlewares.insert(0, middleware)
 | 
			
		||||
@@ -160,9 +175,10 @@ class Dispatcher:
 | 
			
		||||
    def middleware(self, middleware: BaseMiddleware) -> None:
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Добавляет Middleware в список
 | 
			
		||||
        
 | 
			
		||||
        :param middleware: Middleware
 | 
			
		||||
        Добавляет Middleware в конец списка.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            middleware (BaseMiddleware): Middleware.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.middlewares.append(middleware)
 | 
			
		||||
@@ -170,9 +186,10 @@ class Dispatcher:
 | 
			
		||||
    def filter(self, base_filter: BaseFilter) -> None:
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Добавляет фильтр в список
 | 
			
		||||
        
 | 
			
		||||
        :param base_filter: Фильтр
 | 
			
		||||
        Добавляет фильтр в список.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            base_filter (BaseFilter): Фильтр.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.base_filters.append(base_filter)
 | 
			
		||||
@@ -182,7 +199,8 @@ class Dispatcher:
 | 
			
		||||
        """
 | 
			
		||||
        Подготавливает диспетчер: сохраняет бота, регистрирует обработчики, вызывает on_started.
 | 
			
		||||
 | 
			
		||||
        :param bot: Экземпляр бота.
 | 
			
		||||
        Args:
 | 
			
		||||
            bot (Bot): Экземпляр бота.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.bot = bot
 | 
			
		||||
@@ -208,11 +226,14 @@ class Dispatcher:
 | 
			
		||||
    def __get_memory_context(self, chat_id: int, user_id: int):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Возвращает существующий или создает новый контекст по chat_id и user_id.
 | 
			
		||||
        Возвращает существующий или создаёт новый MemoryContext по chat_id и user_id.
 | 
			
		||||
 | 
			
		||||
        :param chat_id: Идентификатор чата.
 | 
			
		||||
        :param user_id: Идентификатор пользователя.
 | 
			
		||||
        :return: Объект MemoryContext.
 | 
			
		||||
        Args:
 | 
			
		||||
            chat_id (int): Идентификатор чата.
 | 
			
		||||
            user_id (int): Идентификатор пользователя.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            MemoryContext: Контекст.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        for ctx in self.contexts:
 | 
			
		||||
@@ -223,10 +244,23 @@ class Dispatcher:
 | 
			
		||||
        self.contexts.append(new_ctx)
 | 
			
		||||
        return new_ctx
 | 
			
		||||
    
 | 
			
		||||
    async def call_handler(self, handler, event_object, data):
 | 
			
		||||
    async def call_handler(
 | 
			
		||||
        self, 
 | 
			
		||||
        handler: Callable[[Any, dict[str, Any]], Awaitable[Any]], 
 | 
			
		||||
        event_object: UpdateType, 
 | 
			
		||||
        data: Dict[str, Any]
 | 
			
		||||
    ):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Правка аргументов конечной функции хендлера и ее вызов 
 | 
			
		||||
        Вызывает хендлер с нужными аргументами.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            handler: Handler.
 | 
			
		||||
            event_object: Объект события.
 | 
			
		||||
            data: Данные для хендлера.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            None
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        func_args = handler.func_event.__annotations__.keys()
 | 
			
		||||
@@ -243,6 +277,17 @@ class Dispatcher:
 | 
			
		||||
            filters: List[BaseFilter]
 | 
			
		||||
        ) -> Optional[Dict[str, Any]] | Literal[False]:
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Асинхронно применяет фильтры к событию.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            event (UpdateUnion): Событие.
 | 
			
		||||
            filters (List[BaseFilter]): Список фильтров.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            Optional[Dict[str, Any]] | Literal[False]: Словарь с результатом или False.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        data = {}
 | 
			
		||||
        
 | 
			
		||||
        for _filter in filters:
 | 
			
		||||
@@ -259,9 +304,10 @@ class Dispatcher:
 | 
			
		||||
    async def handle(self, event_object: UpdateUnion):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Основной обработчик события. Применяет фильтры, middleware и вызывает подходящий handler.
 | 
			
		||||
        Основной обработчик события. Применяет фильтры, middleware и вызывает нужный handler.
 | 
			
		||||
 | 
			
		||||
        :param event_object: Событие, пришедшее в бот.
 | 
			
		||||
        Args:
 | 
			
		||||
            event_object (UpdateUnion): Событие.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        try:
 | 
			
		||||
@@ -335,26 +381,36 @@ class Dispatcher:
 | 
			
		||||
                    )
 | 
			
		||||
                    
 | 
			
		||||
                    kwargs_filtered = {k: v for k, v in kwargs.items() if k in func_args}
 | 
			
		||||
                        
 | 
			
		||||
                    await handler_chain(event_object, kwargs_filtered)
 | 
			
		||||
                    
 | 
			
		||||
                    try:
 | 
			
		||||
                        await handler_chain(event_object, kwargs_filtered)
 | 
			
		||||
                    except:
 | 
			
		||||
                        raise HandlerException(
 | 
			
		||||
                            handler_title=handler.func_event.__name__, 
 | 
			
		||||
                            memory_context={
 | 
			
		||||
                                'data': await memory_context.get_data(),
 | 
			
		||||
                                'state': current_state
 | 
			
		||||
                                }
 | 
			
		||||
                            )
 | 
			
		||||
 | 
			
		||||
                    logger_dp.info(f'Обработано: {router_id} | {process_info}')
 | 
			
		||||
                    logger_dp.info(f'Обработано: router_id: {router_id} | {process_info}')
 | 
			
		||||
 | 
			
		||||
                    is_handled = True
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
            if not is_handled:
 | 
			
		||||
                logger_dp.info(f'Проигнорировано: {router_id} | {process_info}')
 | 
			
		||||
                logger_dp.info(f'Проигнорировано: router_id: {router_id} | {process_info}')
 | 
			
		||||
            
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            logger_dp.error(f"Ошибка при обработке события: {router_id} | {process_info} | {e} ")
 | 
			
		||||
            logger_dp.error(f"Ошибка при обработке события: router_id: {router_id} | {process_info} | {e} ")
 | 
			
		||||
 | 
			
		||||
    async def start_polling(self, bot: Bot):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Запускает цикл получения обновлений с сервера (long polling).
 | 
			
		||||
        Запускает цикл получения обновлений (long polling).
 | 
			
		||||
 | 
			
		||||
        :param bot: Экземпляр бота.
 | 
			
		||||
        Args:
 | 
			
		||||
            bot (Bot): Экземпляр бота.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.polling = True
 | 
			
		||||
@@ -399,9 +455,10 @@ class Dispatcher:
 | 
			
		||||
        """
 | 
			
		||||
        Запускает FastAPI-приложение для приёма обновлений через вебхук.
 | 
			
		||||
 | 
			
		||||
        :param bot: Экземпляр бота.
 | 
			
		||||
        :param host: Хост, на котором запускается сервер.
 | 
			
		||||
        :param port: Порт сервера.
 | 
			
		||||
        Args:
 | 
			
		||||
            bot (Bot): Экземпляр бота.
 | 
			
		||||
            host (str): Хост сервера.
 | 
			
		||||
            port (int): Порт сервера.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        if not FASTAPI_INSTALLED:
 | 
			
		||||
@@ -422,19 +479,6 @@ class Dispatcher:
 | 
			
		||||
                '\n\t pip install maxapi[webhook]'
 | 
			
		||||
            )
 | 
			
		||||
        
 | 
			
		||||
        # try:
 | 
			
		||||
        #     from fastapi import Request
 | 
			
		||||
        #     from fastapi.responses import JSONResponse
 | 
			
		||||
        # except ImportError:
 | 
			
		||||
        #     raise ImportError(
 | 
			
		||||
        #         '\n\t Не установлен fastapi!'
 | 
			
		||||
        #         '\n\t Выполните команду для установки fastapi: '
 | 
			
		||||
        #         '\n\t pip install fastapi>=0.68.0'
 | 
			
		||||
        #         '\n\t Или сразу все зависимости для работы вебхука:'
 | 
			
		||||
        #         '\n\t pip install maxapi[webhook]'
 | 
			
		||||
        #     )
 | 
			
		||||
            
 | 
			
		||||
        
 | 
			
		||||
        @self.webhook_post('/')
 | 
			
		||||
        async def _(request: Request):
 | 
			
		||||
            event_json = await request.json()
 | 
			
		||||
@@ -457,24 +501,14 @@ class Dispatcher:
 | 
			
		||||
    async def init_serve(self, bot: Bot, host: str = 'localhost', port: int = 8080, **kwargs):
 | 
			
		||||
    
 | 
			
		||||
        """
 | 
			
		||||
        Запускает сервер для обработки входящих вебхуков.
 | 
			
		||||
        Запускает сервер для обработки вебхуков.
 | 
			
		||||
 | 
			
		||||
        :param bot: Экземпляр бота.
 | 
			
		||||
        :param host: Хост, на котором запускается сервер.
 | 
			
		||||
        :param port: Порт сервера.
 | 
			
		||||
        Args:
 | 
			
		||||
            bot (Bot): Экземпляр бота.
 | 
			
		||||
            host (str): Хост.
 | 
			
		||||
            port (int): Порт.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        # try:
 | 
			
		||||
        #     from uvicorn import Config, Server
 | 
			
		||||
        # except ImportError:
 | 
			
		||||
        #     raise ImportError(
 | 
			
		||||
        #         '\n\t Не установлен uvicorn!'
 | 
			
		||||
        #         '\n\t Выполните команду для установки uvicorn: '
 | 
			
		||||
        #         '\n\t pip install uvicorn>=0.15.0'
 | 
			
		||||
        #         '\n\t Или сразу все зависимости для работы вебхука:'
 | 
			
		||||
        #         '\n\t pip install maxapi[webhook]'
 | 
			
		||||
        #     )
 | 
			
		||||
        
 | 
			
		||||
        if not UVICORN_INSTALLED:
 | 
			
		||||
            raise ImportError(
 | 
			
		||||
                '\n\t Не установлен uvicorn!'
 | 
			
		||||
@@ -504,10 +538,10 @@ class Router(Dispatcher):
 | 
			
		||||
    def __init__(self, router_id: str | None = None):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Инициализация диспетчера.
 | 
			
		||||
        
 | 
			
		||||
        :param router_id: Идентификатор роутера, используется при логгировании. 
 | 
			
		||||
            По умолчанию индекс зарегистированного роутера в списке 
 | 
			
		||||
        Инициализация роутера.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            router_id (str | None): Идентификатор роутера для логов.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        super().__init__(router_id)
 | 
			
		||||
@@ -524,8 +558,9 @@ class Event:
 | 
			
		||||
        """
 | 
			
		||||
        Инициализирует событие-декоратор.
 | 
			
		||||
 | 
			
		||||
        :param update_type: Тип события (UpdateType).
 | 
			
		||||
        :param router: Роутер или диспетчер, в который регистрируется обработчик.
 | 
			
		||||
        Args:
 | 
			
		||||
            update_type (UpdateType): Тип события.
 | 
			
		||||
            router (Dispatcher | Router): Экземпляр роутера или диспетчера.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.update_type = update_type
 | 
			
		||||
@@ -536,7 +571,8 @@ class Event:
 | 
			
		||||
        """
 | 
			
		||||
        Регистрирует функцию как обработчик события.
 | 
			
		||||
 | 
			
		||||
        :return: Исходная функция.
 | 
			
		||||
        Returns:
 | 
			
		||||
            Callable: Исходная функция.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        def decorator(func_event: Callable):
 | 
			
		||||
 
 | 
			
		||||
@@ -9,14 +9,19 @@ __all__ = [
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def filter_attrs(obj: object, *filters: MagicFilter) -> bool:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Применяет один или несколько фильтров MagicFilter к объекту.
 | 
			
		||||
    
 | 
			
		||||
    :param obj: Любой объект с атрибутами (например, event/message)
 | 
			
		||||
    :param filters: Один или несколько MagicFilter выражений
 | 
			
		||||
    :return: True, если все фильтры возвращают True, иначе False
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        obj (object): Объект, к которому применяются фильтры (например, event или message).
 | 
			
		||||
        *filters (MagicFilter): Один или несколько выражений MagicFilter.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        bool: True, если все фильтры возвращают True, иначе False.
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    try:
 | 
			
		||||
        return all(f.resolve(obj) for f in filters)
 | 
			
		||||
    except Exception:
 | 
			
		||||
        return False
 | 
			
		||||
        return False
 | 
			
		||||
 
 | 
			
		||||
@@ -12,12 +12,12 @@ class Command(BaseFilter):
 | 
			
		||||
    Фильтр сообщений на соответствие команде.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        commands (str | list[str]): Ожидаемая команда или список команд без префикса.
 | 
			
		||||
        commands (str | List[str]): Ожидаемая команда или список команд без префикса.
 | 
			
		||||
        prefix (str, optional): Префикс команды (по умолчанию '/').
 | 
			
		||||
        check_case (bool, optional): Учитывать регистр при сравнении (по умолчанию False).
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        commands (list[str]): Список команд без префикса.
 | 
			
		||||
        commands (List[str]): Список команд без префикса.
 | 
			
		||||
        prefix (str): Префикс команды.
 | 
			
		||||
        check_case (bool): Флаг чувствительности к регистру.
 | 
			
		||||
    """
 | 
			
		||||
 
 | 
			
		||||
@@ -6,5 +6,16 @@ if TYPE_CHECKING:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseFilter:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Базовый класс для фильтров.
 | 
			
		||||
 | 
			
		||||
    Определяет интерфейс фильтрации событий. 
 | 
			
		||||
    Потомки должны переопределять метод __call__.
 | 
			
		||||
 | 
			
		||||
    Methods:
 | 
			
		||||
        __call__(event): Асинхронная проверка события на соответствие фильтру.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    async def __call__(self, event: UpdateUnion) -> bool | dict:
 | 
			
		||||
        return True
 | 
			
		||||
        return True
 | 
			
		||||
 
 | 
			
		||||
@@ -17,27 +17,24 @@ class Handler:
 | 
			
		||||
    """
 | 
			
		||||
    Обработчик события.
 | 
			
		||||
 | 
			
		||||
    Позволяет связать функцию-обработчик с типом обновления, состоянием и набором фильтров.
 | 
			
		||||
    Связывает функцию-обработчик с типом события, состояниями и фильтрами.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(
 | 
			
		||||
            self,
 | 
			
		||||
            *args,
 | 
			
		||||
            func_event: Callable,
 | 
			
		||||
            update_type: UpdateType,
 | 
			
		||||
            **kwargs
 | 
			
		||||
        ):
 | 
			
		||||
        self,
 | 
			
		||||
        *args,
 | 
			
		||||
        func_event: Callable,
 | 
			
		||||
        update_type: UpdateType,
 | 
			
		||||
        **kwargs
 | 
			
		||||
    ):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Инициализация обработчика.
 | 
			
		||||
        Создаёт обработчик события.
 | 
			
		||||
 | 
			
		||||
        :param args: Список фильтров и состояний, в том числе:
 | 
			
		||||
            - MagicFilter — фильтр события,
 | 
			
		||||
            - State — состояние FSM,
 | 
			
		||||
            - Command — команда для фильтрации по началу текста сообщения.
 | 
			
		||||
        :param func_event: Функция-обработчик события
 | 
			
		||||
        :param update_type: Тип обновления (события), на которое подписан обработчик
 | 
			
		||||
        :param kwargs: Дополнительные параметры (не используются)
 | 
			
		||||
        Args:
 | 
			
		||||
            *args: Список фильтров (MagicFilter, State, Command, BaseFilter, BaseMiddleware).
 | 
			
		||||
            func_event (Callable): Функция-обработчик.
 | 
			
		||||
            update_type (UpdateType): Тип обновления.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.func_event: Callable = func_event
 | 
			
		||||
@@ -57,5 +54,6 @@ class Handler:
 | 
			
		||||
            elif isinstance(arg, BaseFilter):
 | 
			
		||||
                self.base_filters.append(arg)
 | 
			
		||||
            else:
 | 
			
		||||
                logger_dp.info(f'Обнаружен неизвестный фильтр `{arg}` при ' 
 | 
			
		||||
                               f'регистрации функции `{func_event.__name__}`')
 | 
			
		||||
                logger_dp.info(
 | 
			
		||||
                    f'Неизвестный фильтр `{arg}` при регистрации `{func_event.__name__}`'
 | 
			
		||||
                )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,30 @@
 | 
			
		||||
from typing import Any, Callable, Awaitable
 | 
			
		||||
 | 
			
		||||
class BaseMiddleware:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Базовый класс для мидлварей.
 | 
			
		||||
 | 
			
		||||
    Используется для обработки события до и после вызова хендлера.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    async def __call__(
 | 
			
		||||
        self,
 | 
			
		||||
        handler: Callable[[Any, dict[str, Any]], Awaitable[Any]],
 | 
			
		||||
        event_object: Any,
 | 
			
		||||
        data: dict[str, Any]
 | 
			
		||||
    ) -> Any:
 | 
			
		||||
        return await handler(event_object, data)
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Вызывает хендлер с переданным событием и данными.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            handler (Callable): Хендлер события.
 | 
			
		||||
            event_object (Any): Событие.
 | 
			
		||||
            data (dict): Дополнительные данные.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            Any: Результат работы хендлера.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        return await handler(event_object, data)
 | 
			
		||||
 
 | 
			
		||||
@@ -113,30 +113,4 @@ class Attachment(BaseModel):
 | 
			
		||||
        bot: Optional[Bot] # type: ignore
 | 
			
		||||
        
 | 
			
		||||
    class Config:
 | 
			
		||||
        use_enum_values = True
 | 
			
		||||
    
 | 
			
		||||
    # async def download(
 | 
			
		||||
    #     self,
 | 
			
		||||
    #     path: str
 | 
			
		||||
    # ):
 | 
			
		||||
        
 | 
			
		||||
    #     """
 | 
			
		||||
    #     Скачивает медиа, сохраняя по определенному пути
 | 
			
		||||
 | 
			
		||||
    #     :param path: Путь сохранения медиа
 | 
			
		||||
 | 
			
		||||
    #     :return: Числовой статус
 | 
			
		||||
    #     """
 | 
			
		||||
        
 | 
			
		||||
    #     if not hasattr(self.payload, 'token') or \
 | 
			
		||||
    #         not hasattr(self.payload, 'url'):
 | 
			
		||||
    #             raise NotAvailableForDownload()
 | 
			
		||||
            
 | 
			
		||||
    #     elif not self.payload.token or not self.payload.url:
 | 
			
		||||
    #         raise NotAvailableForDownload(f'Медиа типа `{self.type}` недоступно для скачивания')
 | 
			
		||||
            
 | 
			
		||||
    #     return await self.bot.download_file(
 | 
			
		||||
    #         path=path,
 | 
			
		||||
    #         url=self.payload.url,
 | 
			
		||||
    #         token=self.payload.token,
 | 
			
		||||
    #     )
 | 
			
		||||
        use_enum_values = True
 | 
			
		||||
@@ -11,7 +11,6 @@ class Audio(Attachment):
 | 
			
		||||
    Вложение с типом аудио.
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        type (Literal['audio']): Тип вложения, всегда 'audio'.
 | 
			
		||||
        transcription (Optional[str]): Транскрипция аудио (если есть).
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,8 @@ from .button import Button
 | 
			
		||||
 | 
			
		||||
class RequestGeoLocationButton(Button):
 | 
			
		||||
    
 | 
			
		||||
    """Кнопка запроса геолокации пользователя.
 | 
			
		||||
    """
 | 
			
		||||
    Кнопка запроса геолокации пользователя.
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        quick: Если True, запрашивает геолокацию без дополнительного 
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,6 @@ class Contact(Attachment):
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Вложение с типом контакта.
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        type (Literal['contact']): Тип вложения, всегда 'contact'.
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    type: Literal[AttachmentType.CONTACT]
 | 
			
		||||
@@ -11,7 +11,6 @@ class File(Attachment):
 | 
			
		||||
    Вложение с типом файла.
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        type (Literal['file']): Тип вложения, всегда 'file'.
 | 
			
		||||
        filename (Optional[str]): Имя файла.
 | 
			
		||||
        size (Optional[int]): Размер файла в байтах.
 | 
			
		||||
    """
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ class Location(Attachment):
 | 
			
		||||
    Вложение с типом геолокации.
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        type (Literal['location']): Тип вложения, всегда 'location'.
 | 
			
		||||
        latitude (Optional[float]): Широта.
 | 
			
		||||
        longitude (Optional[float]): Долгота.
 | 
			
		||||
    """
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ class Share(Attachment):
 | 
			
		||||
    Вложение с типом "share" (поделиться).
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        type (Literal['share']): Тип вложения, всегда 'share'.
 | 
			
		||||
        title (Optional[str]): Заголовок для шаринга.
 | 
			
		||||
        description (Optional[str]): Описание.
 | 
			
		||||
        image_url (Optional[str]): URL изображения для предпросмотра.
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ class Sticker(Attachment):
 | 
			
		||||
    Вложение с типом стикера.
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        type (Literal['sticker']): Тип вложения, всегда 'sticker'.
 | 
			
		||||
        width (Optional[int]): Ширина стикера в пикселях.
 | 
			
		||||
        height (Optional[int]): Высота стикера в пикселях.
 | 
			
		||||
    """
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,6 @@ class Video(Attachment):
 | 
			
		||||
    Вложение с типом видео.
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        type (Optional[Literal['video']]): Тип вложения, всегда 'video'.
 | 
			
		||||
        token (Optional[str]): Токен видео.
 | 
			
		||||
        urls (Optional[VideoUrl]): URLs видео разных разрешений.
 | 
			
		||||
        thumbnail (VideoThumbnail): Миниатюра видео.
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ from ..enums.upload_type import UploadType
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InputMedia:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Класс для представления медиафайла.
 | 
			
		||||
 | 
			
		||||
@@ -15,16 +16,19 @@ class InputMedia:
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    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-типа).
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +38,7 @@ class InputMedia:
 | 
			
		||||
        Returns:
 | 
			
		||||
            UploadType: Тип файла (VIDEO, IMAGE, AUDIO или FILE).
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        with open(path, 'rb') as f:
 | 
			
		||||
            sample = f.read(4096)
 | 
			
		||||
 | 
			
		||||
@@ -60,6 +65,7 @@ class InputMedia:
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
class InputMediaBuffer:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Класс для представления медиафайла из буфера.
 | 
			
		||||
 | 
			
		||||
@@ -69,6 +75,7 @@ class InputMediaBuffer:
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, buffer: bytes, filename: str | None = None):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Инициализирует объект медиафайла из буфера.
 | 
			
		||||
 | 
			
		||||
@@ -76,6 +83,7 @@ class InputMediaBuffer:
 | 
			
		||||
            buffer (IO): Буфер с содержимым файла.
 | 
			
		||||
            filename (str): Название файла (по умолчанию присваивается uuid4).
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        self.filename = filename
 | 
			
		||||
        self.buffer = buffer
 | 
			
		||||
        self.type = self.__detect_file_type(buffer)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,17 @@ from .update import Update
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MessageChatCreated(Update):
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Событие создания чата.
 | 
			
		||||
 | 
			
		||||
    Attributes:
 | 
			
		||||
        chat (Chat): Объект чата.
 | 
			
		||||
        title (Optional[str]): Название чата.
 | 
			
		||||
        message_id (Optional[str]): ID сообщения.
 | 
			
		||||
        start_payload (Optional[str]): Payload для старта.
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    chat: Chat
 | 
			
		||||
    title: Optional[str] = None
 | 
			
		||||
    message_id: Optional[str] = None
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,8 @@ from ..types.attachments.attachment import Attachment, ButtonsPayload
 | 
			
		||||
 | 
			
		||||
class InlineKeyboardBuilder:
 | 
			
		||||
    
 | 
			
		||||
    """Конструктор инлайн-клавиатур.  
 | 
			
		||||
    """
 | 
			
		||||
    Конструктор инлайн-клавиатур.  
 | 
			
		||||
 | 
			
		||||
    Позволяет удобно собирать кнопки в ряды и формировать из них клавиатуру  
 | 
			
		||||
    для отправки в сообщениях.  
 | 
			
		||||
@@ -16,7 +17,8 @@ class InlineKeyboardBuilder:
 | 
			
		||||
 | 
			
		||||
    def row(self, *buttons: InlineButtonUnion):
 | 
			
		||||
        
 | 
			
		||||
        """Добавить новый ряд кнопок в клавиатуру.
 | 
			
		||||
        """
 | 
			
		||||
        Добавить новый ряд кнопок в клавиатуру.
 | 
			
		||||
        
 | 
			
		||||
        Args:
 | 
			
		||||
            *buttons: Произвольное количество кнопок для добавления в ряд.
 | 
			
		||||
@@ -26,7 +28,8 @@ class InlineKeyboardBuilder:
 | 
			
		||||
        
 | 
			
		||||
    def add(self, button: InlineButtonUnion):
 | 
			
		||||
        
 | 
			
		||||
        """Добавить кнопку в последний ряд клавиатуры.
 | 
			
		||||
        """
 | 
			
		||||
        Добавить кнопку в последний ряд клавиатуры.
 | 
			
		||||
        
 | 
			
		||||
        Args:
 | 
			
		||||
            button: Кнопка для добавления.
 | 
			
		||||
@@ -36,7 +39,8 @@ class InlineKeyboardBuilder:
 | 
			
		||||
 | 
			
		||||
    def as_markup(self):
 | 
			
		||||
        
 | 
			
		||||
        """Собрать клавиатуру в объект для отправки.
 | 
			
		||||
        """
 | 
			
		||||
        Собрать клавиатуру в объект для отправки.
 | 
			
		||||
        
 | 
			
		||||
        Returns:
 | 
			
		||||
            Объект вложения с типом INLINE_KEYBOARD.
 | 
			
		||||
 
 | 
			
		||||
@@ -21,9 +21,20 @@ from ..enums.chat_type import ChatType
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    from ..bot import Bot
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
async def enrich_event(event_object: Any, bot: Bot) -> Any:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    Дополняет объект события данными чата, пользователя и ссылкой на бота.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        event_object (Any): Событие, которое нужно дополнить.
 | 
			
		||||
        bot (Bot): Экземпляр бота.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        Any: Обновлённый объект события.
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    if not bot.auto_requests:
 | 
			
		||||
        return event_object
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user