Compare commits
13 Commits
e0e7bb53b6
...
103535d3ba
| Author | SHA1 | Date | |
|---|---|---|---|
| 103535d3ba | |||
| 82dc8d255a | |||
| 35b60a1b44 | |||
| e07aeef726 | |||
| 03a60014d4 | |||
| b69713f996 | |||
| 9010c697f4 | |||
| b994717f64 | |||
| 44dcf39f42 | |||
| 0bd59ddb4a | |||
| f497760f5b | |||
| 5c64c3d040 | |||
| c8dd896691 |
129
maxapi/bot.py
129
maxapi/bot.py
@@ -9,9 +9,12 @@ from .types.errors import Error
|
||||
from .types.input_media import InputMedia, InputMediaBuffer
|
||||
|
||||
from .connection.base import BaseConnection
|
||||
from .loggers import logger_bot
|
||||
|
||||
from .enums.parse_mode import ParseMode
|
||||
from .enums.sender_action import SenderAction
|
||||
from .enums.upload_type import UploadType
|
||||
from .enums.update import UpdateType
|
||||
|
||||
from .methods.add_admin_chat import AddAdminChat
|
||||
from .methods.add_members_chat import AddMembersChat
|
||||
@@ -20,7 +23,7 @@ from .methods.delete_bot_from_chat import DeleteMeFromMessage
|
||||
from .methods.delete_chat import DeleteChat
|
||||
from .methods.delete_message import DeleteMessage
|
||||
from .methods.delete_pin_message import DeletePinMessage
|
||||
from .methods.download_media import DownloadMedia
|
||||
# from .methods.download_media import DownloadMedia
|
||||
from .methods.edit_chat import EditChat
|
||||
from .methods.edit_message import EditMessage
|
||||
from .methods.get_chat_by_id import GetChatById
|
||||
@@ -41,6 +44,12 @@ from .methods.remove_member_chat import RemoveMemberChat
|
||||
from .methods.send_action import SendAction
|
||||
from .methods.send_callback import SendCallback
|
||||
from .methods.send_message import SendMessage
|
||||
from .methods.get_subscriptions import GetSubscriptions
|
||||
from .methods.types.getted_subscriptions import GettedSubscriptions
|
||||
from .methods.subscribe_webhook import SubscribeWebhook
|
||||
from .methods.types.subscribed import Subscribed
|
||||
from .methods.types.unsubscribed import Unsubscribed
|
||||
from .methods.unsubscribe_webhook import UnsubscribeWebhook
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .types.attachments.attachment import Attachment
|
||||
@@ -85,7 +94,8 @@ class Bot(BaseConnection):
|
||||
notify: Optional[bool] = None,
|
||||
auto_requests: bool = True,
|
||||
default_connection: Optional[DefaultConnectionProperties] = None,
|
||||
after_input_media_delay: Optional[float] = None
|
||||
after_input_media_delay: Optional[float] = None,
|
||||
auto_check_subscriptions: bool = True
|
||||
):
|
||||
|
||||
"""
|
||||
@@ -94,17 +104,18 @@ class Bot(BaseConnection):
|
||||
:param token: Токен доступа к API бота
|
||||
:param parse_mode: Форматирование по умолчанию
|
||||
:param notify: Отключение уведомлений при отправке сообщений (по умолчанию игнорируется) (не работает на стороне MAX)
|
||||
:param auto_requests: Автоматическое заполнение полей chat и from_user в Update
|
||||
:param auto_requests: Автоматическое заполнение полей chat и from_user в Update с помощью API запросов если они не заложены как полноценные объекты в Update (по умолчанию True, при False chat и from_user в некоторых событиях будут выдавать None)
|
||||
:param default_connection: Настройки aiohttp
|
||||
:param after_input_media_delay: Задержка в секундах после загрузки файла на сервера MAX (без этого чаще всего MAX не успевает обработать вложение и выдает ошибку `errors.process.attachment.file.not.processed`)
|
||||
с помощью API запросов если они не заложены как полноценные объекты в Update (по умолчанию True, при False chat и from_user в некоторых событиях будут выдавать None)
|
||||
:param auto_check_subscriptions: Проверка на установленные подписки для метода start_polling (бот не работает в поллинге при установленных подписках)
|
||||
"""
|
||||
|
||||
super().__init__()
|
||||
|
||||
self.bot = self
|
||||
self.default_connection = default_connection or DefaultConnectionProperties()
|
||||
self.after_input_media_delay = after_input_media_delay or 2.0
|
||||
self.after_input_media_delay = after_input_media_delay or 2.0
|
||||
self.auto_check_subscriptions = auto_check_subscriptions
|
||||
|
||||
self.__token = token
|
||||
self.params: Dict[str, Any] = {'access_token': self.__token}
|
||||
@@ -765,26 +776,100 @@ class Bot(BaseConnection):
|
||||
commands=list(commands)
|
||||
).fetch()
|
||||
|
||||
async def download_file(
|
||||
self,
|
||||
path: str,
|
||||
url: str,
|
||||
token: str
|
||||
):
|
||||
async def get_subscriptions(self) -> GettedSubscriptions:
|
||||
|
||||
"""
|
||||
Скачивает медиа с указанной ссылки по токену, сохраняя по определенному пути
|
||||
Получает список всех подписок.
|
||||
|
||||
:param path: Путь сохранения медиа
|
||||
:param url: Ссылка на медиа
|
||||
:param token: Токен медиа
|
||||
|
||||
:return: Числовой статус
|
||||
:return: Объект со списком подписок
|
||||
"""
|
||||
|
||||
return await DownloadMedia(
|
||||
return await GetSubscriptions(bot=self).fetch()
|
||||
|
||||
async def subscribe_webhook(
|
||||
self,
|
||||
url: str,
|
||||
update_types: Optional[List[UpdateType]] = None,
|
||||
secret: Optional[str] = None
|
||||
) -> Subscribed:
|
||||
|
||||
"""
|
||||
Подписывает бота на получение обновлений через WebHook.
|
||||
После вызова этого метода бот будет получать уведомления о новых событиях в чатах на указанный URL.
|
||||
Ваш сервер должен прослушивать один из следующих портов: `80`, `8080`, `443`, `8443`, `16384`-`32383`.
|
||||
|
||||
:param url: URL HTTP(S)-эндпойнта вашего бота. Должен начинаться с http(s)://
|
||||
:param update_types: Список типов обновлений, которые ваш бот хочет получать.
|
||||
Для полного списка типов см. объект
|
||||
:param secret: От 5 до 256 символов. Cекрет, который должен быть отправлен в заголовке X-Max-Bot-Api-Secret
|
||||
в каждом запросе Webhook. Разрешены только символы A-Z, a-z, 0-9, и дефис.
|
||||
Заголовок рекомендован, чтобы запрос поступал из установленного веб-узла
|
||||
|
||||
:return: Обновленная информация о боте
|
||||
"""
|
||||
|
||||
return await SubscribeWebhook(
|
||||
bot=self,
|
||||
path=path,
|
||||
media_url=url,
|
||||
media_token=token
|
||||
).fetch()
|
||||
url=url,
|
||||
update_types=update_types,
|
||||
secret=secret
|
||||
).fetch()
|
||||
|
||||
async def unsubscribe_webhook(
|
||||
self,
|
||||
url: str,
|
||||
) -> Unsubscribed:
|
||||
|
||||
"""
|
||||
Отписывает бота от получения обновлений через WebHook.
|
||||
После вызова этого метода бот перестает получать уведомления о новых событиях,
|
||||
и доступна доставка уведомлений через API с длительным опросом.
|
||||
|
||||
:param url: URL HTTP(S)-эндпойнта вашего бота. Должен начинаться с http(s)://
|
||||
|
||||
:return: Обновленная информация о боте
|
||||
"""
|
||||
|
||||
return await UnsubscribeWebhook(
|
||||
bot=self,
|
||||
url=url,
|
||||
).fetch()
|
||||
|
||||
async def delete_webhook(self):
|
||||
|
||||
"""
|
||||
Удаление всех подписок на Webhook
|
||||
"""
|
||||
|
||||
subs = await self.get_subscriptions()
|
||||
if subs.subscriptions:
|
||||
|
||||
for sub in subs.subscriptions:
|
||||
|
||||
await self.unsubscribe_webhook(sub.url)
|
||||
logger_bot.info('Удалена подписка на Webhook: %s', sub.url)
|
||||
|
||||
|
||||
# async def download_file(
|
||||
# self,
|
||||
# path: str,
|
||||
# url: str,
|
||||
# token: str
|
||||
# ):
|
||||
|
||||
# """
|
||||
# Скачивает медиа с указанной ссылки по токену, сохраняя по определенному пути
|
||||
|
||||
# :param path: Путь сохранения медиа
|
||||
# :param url: Ссылка на медиа
|
||||
# :param token: Токен медиа
|
||||
|
||||
# :return: Числовой статус
|
||||
# """
|
||||
|
||||
# return await DownloadMedia(
|
||||
# bot=self,
|
||||
# path=path,
|
||||
# media_url=url,
|
||||
# media_token=token
|
||||
# ).fetch()
|
||||
@@ -2,7 +2,8 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
|
||||
from typing import Any, Callable, Dict, List, TYPE_CHECKING, Optional
|
||||
import functools
|
||||
from typing import Any, Awaitable, Callable, Dict, List, TYPE_CHECKING, Optional
|
||||
from asyncio.exceptions import TimeoutError as AsyncioTimeoutError
|
||||
|
||||
from aiohttp import ClientConnectorError
|
||||
@@ -74,6 +75,7 @@ class Dispatcher:
|
||||
self.bot: Optional[Bot] = None
|
||||
self.webhook_app: Optional[FastAPI] = None
|
||||
self.on_started_func: Optional[Callable] = None
|
||||
self.polling = False
|
||||
|
||||
self.message_created = Event(update_type=UpdateType.MESSAGE_CREATED, router=self)
|
||||
self.bot_added = Event(update_type=UpdateType.BOT_ADDED, router=self)
|
||||
@@ -120,6 +122,17 @@ class Dispatcher:
|
||||
self.bot._me = me
|
||||
|
||||
logger_dp.info(f'Бот: @{me.username} first_name={me.first_name} id={me.user_id}')
|
||||
|
||||
def build_middleware_chain(
|
||||
self,
|
||||
middlewares: list[BaseMiddleware],
|
||||
handler: Callable[[Any, dict[str, Any]], Awaitable[Any]]
|
||||
) -> Callable[[Any, dict[str, Any]], Awaitable[Any]]:
|
||||
|
||||
for mw in reversed(middlewares):
|
||||
handler = functools.partial(mw, handler)
|
||||
|
||||
return handler
|
||||
|
||||
def include_routers(self, *routers: 'Router'):
|
||||
|
||||
@@ -141,6 +154,13 @@ class Dispatcher:
|
||||
|
||||
self.bot = bot
|
||||
|
||||
if self.polling and self.bot.auto_check_subscriptions:
|
||||
response = await self.bot.get_subscriptions()
|
||||
|
||||
if response.subscriptions:
|
||||
logger_subscriptions_text = ', '.join([s.url for s in response.subscriptions])
|
||||
logger_dp.warning('БОТ ИГНОРИРУЕТ POLLING! Обнаружены установленные подписки: %s', logger_subscriptions_text)
|
||||
|
||||
await self.check_me()
|
||||
|
||||
self.routers += [self]
|
||||
@@ -169,38 +189,18 @@ class Dispatcher:
|
||||
new_ctx = MemoryContext(chat_id, user_id)
|
||||
self.contexts.append(new_ctx)
|
||||
return new_ctx
|
||||
|
||||
async def process_middlewares(
|
||||
self,
|
||||
middlewares: List[BaseMiddleware],
|
||||
event_object: UpdateUnion,
|
||||
result_data_kwargs: Dict[str, Any]
|
||||
):
|
||||
|
||||
async def call_handler(self, handler, event_object, data):
|
||||
|
||||
"""
|
||||
Последовательно обрабатывает middleware цепочку.
|
||||
|
||||
:param middlewares: Список middleware.
|
||||
:param event_object: Объект события.
|
||||
:param result_data_kwargs: Аргументы, передаваемые обработчику.
|
||||
:return: Изменённые аргументы или None.
|
||||
Правка аргументов конечной функции хендлера и ее вызов
|
||||
"""
|
||||
|
||||
for middleware in middlewares:
|
||||
result = await middleware.process_middleware(
|
||||
event_object=event_object,
|
||||
result_data_kwargs=result_data_kwargs
|
||||
)
|
||||
|
||||
if result is None or result is False:
|
||||
return
|
||||
|
||||
elif result is True:
|
||||
continue
|
||||
|
||||
result_data_kwargs.update(result)
|
||||
func_args = handler.func_event.__annotations__.keys()
|
||||
kwargs_filtered = {k: v for k, v in data.items() if k in func_args}
|
||||
|
||||
await handler.func_event(event_object, **kwargs_filtered)
|
||||
|
||||
return result_data_kwargs
|
||||
|
||||
async def handle(self, event_object: UpdateUnion):
|
||||
|
||||
@@ -232,12 +232,6 @@ class Dispatcher:
|
||||
if not filter_attrs(event_object, *router.filters):
|
||||
continue
|
||||
|
||||
kwargs = await self.process_middlewares(
|
||||
middlewares=router.middlewares,
|
||||
event_object=event_object,
|
||||
result_data_kwargs=kwargs
|
||||
)
|
||||
|
||||
for handler in router.event_handlers:
|
||||
|
||||
if not handler.update_type == event_object.update_type:
|
||||
@@ -252,20 +246,19 @@ class Dispatcher:
|
||||
|
||||
func_args = handler.func_event.__annotations__.keys()
|
||||
|
||||
kwargs = await self.process_middlewares(
|
||||
middlewares=handler.middlewares,
|
||||
event_object=event_object,
|
||||
result_data_kwargs=kwargs
|
||||
)
|
||||
if isinstance(router, Router):
|
||||
full_middlewares = self.middlewares + router.middlewares + handler.middlewares
|
||||
elif isinstance(router, Dispatcher):
|
||||
full_middlewares = self.middlewares + handler.middlewares
|
||||
|
||||
if not kwargs:
|
||||
continue
|
||||
handler_chain = self.build_middleware_chain(
|
||||
full_middlewares,
|
||||
functools.partial(self.call_handler, handler)
|
||||
)
|
||||
|
||||
kwargs_filtered = {k: v for k, v in kwargs.items() if k in func_args}
|
||||
|
||||
for key in kwargs.copy().keys():
|
||||
if key not in func_args:
|
||||
del kwargs[key]
|
||||
|
||||
await handler.func_event(event_object, **kwargs)
|
||||
await handler_chain(event_object, kwargs_filtered)
|
||||
|
||||
logger_dp.info(f'Обработано: {router_id} | {process_info}')
|
||||
|
||||
@@ -286,12 +279,14 @@ class Dispatcher:
|
||||
:param bot: Экземпляр бота.
|
||||
"""
|
||||
|
||||
self.polling = True
|
||||
|
||||
await self.__ready(bot)
|
||||
|
||||
if self.bot is None:
|
||||
raise RuntimeError('Bot не инициализирован')
|
||||
|
||||
while True:
|
||||
|
||||
if self.bot is None:
|
||||
raise RuntimeError('Bot не инициализирован')
|
||||
while self.polling:
|
||||
|
||||
try:
|
||||
events: Dict = await self.bot.get_updates()
|
||||
|
||||
@@ -19,4 +19,5 @@ class ApiPath(str, Enum):
|
||||
PIN = '/pin'
|
||||
MEMBERS = '/members'
|
||||
ADMINS = '/admins'
|
||||
UPLOADS = '/uploads'
|
||||
UPLOADS = '/uploads'
|
||||
SUBSCRIPTIONS = '/subscriptions'
|
||||
@@ -1,27 +1,10 @@
|
||||
from typing import Any, Dict
|
||||
from ..types.updates import UpdateUnion
|
||||
|
||||
from typing import Any, Callable, Awaitable
|
||||
|
||||
class BaseMiddleware:
|
||||
def __init__(self):
|
||||
...
|
||||
|
||||
async def process_middleware(
|
||||
self,
|
||||
result_data_kwargs: Dict[str, Any],
|
||||
event_object: UpdateUnion
|
||||
):
|
||||
|
||||
# пока что заглушка
|
||||
if result_data_kwargs is None:
|
||||
return {}
|
||||
|
||||
kwargs_temp = {'data': result_data_kwargs.copy()}
|
||||
|
||||
for key in kwargs_temp.copy().keys():
|
||||
if key not in self.__call__.__annotations__.keys(): # type: ignore
|
||||
del kwargs_temp[key]
|
||||
|
||||
result: Dict[str, Any] = await self(event_object, **kwargs_temp) # type: ignore
|
||||
|
||||
return result
|
||||
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)
|
||||
44
maxapi/methods/get_subscriptions.py
Normal file
44
maxapi/methods/get_subscriptions.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..methods.types.getted_subscriptions import GettedSubscriptions
|
||||
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class GetSubscriptions(BaseConnection):
|
||||
|
||||
"""
|
||||
Если ваш бот получает данные через WebHook, этот класс возвращает список всех подписок.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
):
|
||||
self.bot = bot
|
||||
|
||||
async def fetch(self) -> GettedSubscriptions:
|
||||
|
||||
"""
|
||||
Отправляет запрос на получение списка всех подписок.
|
||||
|
||||
Returns:
|
||||
GettedSubscriptions: Объект со списком подписок
|
||||
"""
|
||||
|
||||
if self.bot is None:
|
||||
raise RuntimeError('Bot не инициализирован')
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.GET,
|
||||
path=ApiPath.SUBSCRIPTIONS,
|
||||
model=GettedSubscriptions,
|
||||
params=self.bot.params
|
||||
)
|
||||
70
maxapi/methods/subscribe_webhook.py
Normal file
70
maxapi/methods/subscribe_webhook.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
||||
|
||||
from ..methods.types.subscribed import Subscribed
|
||||
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
from ..enums.update import UpdateType
|
||||
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class SubscribeWebhook(BaseConnection):
|
||||
|
||||
"""
|
||||
Подписывает бота на получение обновлений через WebHook.
|
||||
После вызова этого метода бот будет получать уведомления о новых событиях в чатах на указанный URL.
|
||||
Ваш сервер должен прослушивать один из следующих портов: `80`, `8080`, `443`, `8443`, `16384`-`32383`.
|
||||
|
||||
Args:
|
||||
bot (Bot): Экземпляр бота для выполнения запроса.
|
||||
url (str): URL HTTP(S)-эндпойнта вашего бота. Должен начинаться с http(s)://
|
||||
update_types (Optional[List[str]]): Список типов обновлений, которые ваш бот хочет получать. Для полного списка типов см. объект
|
||||
secret (str): От 5 до 256 символов. Cекрет, который должен быть отправлен в заголовке X-Max-Bot-Api-Secret в каждом запросе Webhook. Разрешены только символы A-Z, a-z, 0-9, и дефис. Заголовок рекомендован, чтобы запрос поступал из установленного веб-узла
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
url: str,
|
||||
update_types: Optional[List[UpdateType]] = None,
|
||||
secret: Optional[str] = None
|
||||
):
|
||||
self.bot = bot
|
||||
self.url = url
|
||||
self.update_types = update_types
|
||||
self.secret = secret
|
||||
|
||||
async def fetch(self) -> Subscribed:
|
||||
|
||||
"""
|
||||
Отправляет запрос на подписку бота на получение обновлений через WebHook
|
||||
|
||||
Returns:
|
||||
Subscribed: Объект с информацией об операции
|
||||
"""
|
||||
|
||||
if self.bot is None:
|
||||
raise RuntimeError('Bot не инициализирован')
|
||||
|
||||
json: Dict[str, Any] = {}
|
||||
|
||||
json['url'] = self.url
|
||||
|
||||
if self.update_types:
|
||||
json['update_types'] = self.update_types
|
||||
|
||||
if self.secret:
|
||||
json['secret'] = self.secret
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.POST,
|
||||
path=ApiPath.SUBSCRIPTIONS,
|
||||
model=Subscribed,
|
||||
params=self.bot.params,
|
||||
json=json
|
||||
)
|
||||
16
maxapi/methods/types/getted_subscriptions.py
Normal file
16
maxapi/methods/types/getted_subscriptions.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from typing import List
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ...types.subscription import Subscription
|
||||
|
||||
|
||||
class GettedSubscriptions(BaseModel):
|
||||
|
||||
"""
|
||||
Ответ API с отправленным сообщением.
|
||||
|
||||
Attributes:
|
||||
message (Message): Объект отправленного сообщения.
|
||||
"""
|
||||
|
||||
subscriptions: List[Subscription]
|
||||
16
maxapi/methods/types/subscribed.py
Normal file
16
maxapi/methods/types/subscribed.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Subscribed(BaseModel):
|
||||
|
||||
"""
|
||||
Результат подписки на обновления на Webhook
|
||||
|
||||
Attributes:
|
||||
success (bool): Статус успешности операции.
|
||||
message (Optional[str]): Дополнительное сообщение или ошибка.
|
||||
"""
|
||||
|
||||
success: bool
|
||||
message: Optional[str] = None
|
||||
16
maxapi/methods/types/unsubscribed.py
Normal file
16
maxapi/methods/types/unsubscribed.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Unsubscribed(BaseModel):
|
||||
|
||||
"""
|
||||
Результат отписки от обновлений на Webhook
|
||||
|
||||
Attributes:
|
||||
success (bool): Статус успешности операции.
|
||||
message (Optional[str]): Дополнительное сообщение или ошибка.
|
||||
"""
|
||||
|
||||
success: bool
|
||||
message: Optional[str] = None
|
||||
54
maxapi/methods/unsubscribe_webhook.py
Normal file
54
maxapi/methods/unsubscribe_webhook.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..methods.types.unsubscribed import Unsubscribed
|
||||
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class UnsubscribeWebhook(BaseConnection):
|
||||
|
||||
"""
|
||||
Отписывает бота от получения обновлений через WebHook. После вызова этого метода бот перестает получать уведомления о новых событиях, и доступна доставка уведомлений через API с длительным опросом.
|
||||
|
||||
Args:
|
||||
bot (Bot): Экземпляр бота для выполнения запроса.
|
||||
url (str): URL, который нужно удалить из подписок на WebHook
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
url: str,
|
||||
):
|
||||
self.bot = bot
|
||||
self.url = url
|
||||
|
||||
async def fetch(self) -> Unsubscribed:
|
||||
|
||||
"""
|
||||
Отправляет запрос на подписку бота на получение обновлений через WebHook
|
||||
|
||||
Returns:
|
||||
Unsubscribed: Объект с информацией об операции
|
||||
"""
|
||||
|
||||
if self.bot is None:
|
||||
raise RuntimeError('Bot не инициализирован')
|
||||
|
||||
params = self.bot.params.copy()
|
||||
|
||||
params['url'] = self.url
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.DELETE,
|
||||
path=ApiPath.SUBSCRIPTIONS,
|
||||
model=Unsubscribed,
|
||||
params=params,
|
||||
)
|
||||
18
maxapi/types/subscription.py
Normal file
18
maxapi/types/subscription.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from typing import List, Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Subscription(BaseModel):
|
||||
|
||||
"""
|
||||
Подписка для вебхука
|
||||
|
||||
Attributes:
|
||||
url (str): URL вебхука
|
||||
time (int): Unix-время, когда была создана подписка
|
||||
update_types (List[str]): Типы обновлений, на которые подписан бот
|
||||
"""
|
||||
|
||||
url: str
|
||||
time: int
|
||||
update_types: Optional[List[str]] = None
|
||||
@@ -8,10 +8,10 @@ from ...types.users import User
|
||||
class UserRemoved(Update):
|
||||
|
||||
"""
|
||||
Класс для обработки события удаления пользователя из чата.
|
||||
Класс для обработки события выходе/удаления пользователя из чата.
|
||||
|
||||
Attributes:
|
||||
admin_id (Optional[int]): Идентификатор администратора, удалившего пользователя. Может быть None.
|
||||
admin_id (Optional[int]): Идентификатор администратора, удалившего пользователя. None при выходе из чата самим пользователем.
|
||||
chat_id (int): Идентификатор чата. Может быть None.
|
||||
user (User): Объект пользователя, удаленного из чата.
|
||||
is_channel (bool): Указывает, был ли пользователь удален из канала или нет
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
| `message_edited` | Сообщение было отредактировано |
|
||||
| `message_removed` | Сообщение было удалено |
|
||||
| `user_added` | Пользователь добавлен в чат |
|
||||
| `user_removed` | Пользователь удалён из чата |
|
||||
| `user_removed` | Пользователь удалён/вышел из чата |
|
||||
| `on_started` | Бот запущен (**внутреннее** событие библиотеки) |
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user