Немного оптимизировано и поправлен список зависимостей

This commit is contained in:
Денис Семёнов 2025-06-29 15:27:19 +03:00
parent c481e3e931
commit b5947e5f47
6 changed files with 96 additions and 88 deletions

View File

@ -1,68 +1,69 @@
from __future__ import annotations
from datetime import datetime from datetime import datetime
from typing import Any, Dict, List, TYPE_CHECKING, Optional from typing import Any, Dict, List, Optional, TYPE_CHECKING
from .methods.download_media import DownloadMedia
from .methods.get_upload_url import GetUploadURL
from .methods.get_updates import GetUpdates
from .methods.remove_member_chat import RemoveMemberChat
from .methods.add_admin_chat import AddAdminChat
from .methods.add_members_chat import AddMembersChat
from .methods.get_members_chat import GetMembersChat
from .methods.remove_admin import RemoveAdmin
from .methods.get_list_admin_chat import GetListAdminChat
from .methods.delete_bot_from_chat import DeleteMeFromMessage
from .methods.get_me_from_chat import GetMeFromChat
from .methods.delete_pin_message import DeletePinMessage
from .methods.get_pinned_message import GetPinnedMessage
from .methods.pin_message import PinMessage
from .methods.delete_chat import DeleteChat
from .methods.send_action import SendAction
from .methods.edit_chat import EditChat
from .methods.get_chat_by_id import GetChatById
from .methods.get_chat_by_link import GetChatByLink
from .methods.send_callback import SendCallback
from .methods.get_video import GetVideo
from .methods.delete_message import DeleteMessage
from .methods.edit_message import EditMessage
from .methods.change_info import ChangeInfo
from .methods.get_me import GetMe
from .methods.get_messages import GetMessages
from .methods.get_chats import GetChats
from .methods.send_message import SendMessage
from .connection.base import BaseConnection
from .enums.parse_mode import ParseMode from .enums.parse_mode import ParseMode
from .enums.sender_action import SenderAction from .enums.sender_action import SenderAction
from .enums.upload_type import UploadType from .enums.upload_type import UploadType
from .types.message import Message from .methods.add_admin_chat import AddAdminChat
from .types.attachments.attachment import Attachment from .methods.add_members_chat import AddMembersChat
from .types.attachments.image import PhotoAttachmentRequestPayload from .methods.change_info import ChangeInfo
from .types.message import Messages, NewMessageLink from .methods.delete_bot_from_chat import DeleteMeFromMessage
from .types.users import ChatAdmin, User from .methods.delete_chat import DeleteChat
from .types.command import BotCommand from .methods.delete_message import DeleteMessage
from .methods.delete_pin_message import DeletePinMessage
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
from .methods.get_chat_by_link import GetChatByLink
from .methods.get_chats import GetChats
from .methods.get_list_admin_chat import GetListAdminChat
from .methods.get_me import GetMe
from .methods.get_me_from_chat import GetMeFromChat
from .methods.get_members_chat import GetMembersChat
from .methods.get_messages import GetMessages
from .methods.get_pinned_message import GetPinnedMessage
from .methods.get_updates import GetUpdates
from .methods.get_upload_url import GetUploadURL
from .methods.get_video import GetVideo
from .methods.pin_message import PinMessage
from .methods.remove_admin import RemoveAdmin
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 .connection.base import BaseConnection if TYPE_CHECKING:
from .types.attachments.attachment import Attachment
from .types.attachments.image import PhotoAttachmentRequestPayload
from .types.attachments.video import Video
from .types.chats import Chat, ChatMember, Chats
from .types.command import BotCommand
from .types.message import Message, Messages, NewMessageLink
from .types.updates import UpdateUnion
from .types.users import ChatAdmin, User
from .methods.types.added_admin_chat import AddedListAdminChat from .methods.types.added_admin_chat import AddedListAdminChat
from .methods.types.added_members_chat import AddedMembersChat from .methods.types.added_members_chat import AddedMembersChat
from .methods.types.deleted_bot_from_chat import DeletedBotFromChat from .methods.types.deleted_bot_from_chat import DeletedBotFromChat
from .methods.types.deleted_chat import DeletedChat from .methods.types.deleted_chat import DeletedChat
from .methods.types.deleted_message import DeletedMessage from .methods.types.deleted_message import DeletedMessage
from .methods.types.deleted_pin_message import DeletedPinMessage from .methods.types.deleted_pin_message import DeletedPinMessage
from .methods.types.edited_message import EditedMessage from .methods.types.edited_message import EditedMessage
from .methods.types.getted_list_admin_chat import GettedListAdminChat from .methods.types.getted_list_admin_chat import GettedListAdminChat
from .methods.types.getted_members_chat import GettedMembersChat from .methods.types.getted_members_chat import GettedMembersChat
from .methods.types.getted_pineed_message import GettedPin from .methods.types.getted_pineed_message import GettedPin
from .methods.types.getted_upload_url import GettedUploadUrl from .methods.types.getted_upload_url import GettedUploadUrl
from .methods.types.pinned_message import PinnedMessage from .methods.types.pinned_message import PinnedMessage
from .methods.types.removed_admin import RemovedAdmin from .methods.types.removed_admin import RemovedAdmin
from .methods.types.removed_member_chat import RemovedMemberChat from .methods.types.removed_member_chat import RemovedMemberChat
from .methods.types.sended_action import SendedAction from .methods.types.sended_action import SendedAction
from .methods.types.sended_callback import SendedCallback from .methods.types.sended_callback import SendedCallback
from .methods.types.sended_message import SendedMessage from .methods.types.sended_message import SendedMessage
from .types.attachments.video import Video
from .types.chats import Chat, ChatMember, Chats
from .types.updates import UpdateUnion
class Bot(BaseConnection): class Bot(BaseConnection):
@ -102,6 +103,12 @@ class Bot(BaseConnection):
self.notify = notify self.notify = notify
self.auto_requests = auto_requests self.auto_requests = auto_requests
def _resolve_notify(self, notify: Optional[bool]) -> Optional[bool]:
return notify if notify is not None else self.notify
def _resolve_parse_mode(self, mode: Optional[ParseMode]) -> Optional[ParseMode]:
return mode if mode is not None else self.parse_mode
async def send_message( async def send_message(
self, self,
chat_id: int = None, chat_id: int = None,
@ -133,10 +140,8 @@ class Bot(BaseConnection):
text=text, text=text,
attachments=attachments, attachments=attachments,
link=link, link=link,
notify=notify if notify \ notify=self._resolve_notify(notify),
else self.notify, parse_mode=self._resolve_parse_mode(notify)
parse_mode=parse_mode if parse_mode \
else self.parse_mode
).request() ).request()
async def send_action( async def send_action(
@ -187,10 +192,8 @@ class Bot(BaseConnection):
text=text, text=text,
attachments=attachments, attachments=attachments,
link=link, link=link,
notify=notify if notify \ notify=self._resolve_notify(notify),
else self.notify, parse_mode=self._resolve_parse_mode(notify)
parse_mode=parse_mode if parse_mode \
else self.parse_mode
).request() ).request()
async def delete_message( async def delete_message(
@ -398,8 +401,7 @@ class Bot(BaseConnection):
icon=icon, icon=icon,
title=title, title=title,
pin=pin, pin=pin,
notify=notify if notify \ notify=self._resolve_notify(notify),
else self.notify,
).request() ).request()
async def get_video( async def get_video(
@ -422,7 +424,7 @@ class Bot(BaseConnection):
async def send_callback( async def send_callback(
self, self,
callback_id: str, callback_id: str,
message: 'Message' = None, message: Message = None,
notification: str = None notification: str = None
) -> SendedCallback: ) -> SendedCallback:
@ -462,8 +464,7 @@ class Bot(BaseConnection):
bot=self, bot=self,
chat_id=chat_id, chat_id=chat_id,
message_id=message_id, message_id=message_id,
notify=notify if notify \ notify=self._resolve_notify(notify),
else self.notify,
).request() ).request()
async def delete_pin_message( async def delete_pin_message(

View File

@ -113,8 +113,8 @@ class BaseConnection:
:return: Сырой .text() ответ от сервера после загрузки файла :return: Сырой .text() ответ от сервера после загрузки файла
""" """
with open(path, 'rb') as f: async with aiofiles.open(path, 'rb') as f:
file_data = f.read() file_data = await f.read()
basename = os.path.basename(path) basename = os.path.basename(path)
_, ext = os.path.splitext(basename) _, ext = os.path.splitext(basename)

View File

@ -1,3 +1,5 @@
import asyncio
from typing import Any, Callable, Dict, List from typing import Any, Callable, Dict, List
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
@ -22,7 +24,8 @@ from .enums.update import UpdateType
from .loggers import logger_dp from .loggers import logger_dp
app = FastAPI() webhook_app = FastAPI()
CONNECTION_RETRY_DELAY = 30
class Dispatcher: class Dispatcher:
@ -39,8 +42,8 @@ class Dispatcher:
self.filters: List[MagicFilter] = [] self.filters: List[MagicFilter] = []
self.middlewares: List[BaseMiddleware] = [] self.middlewares: List[BaseMiddleware] = []
self.bot = None self.bot: Bot = None
self.on_started_func = None self.on_started_func: Callable = None
self.message_created = Event(update_type=UpdateType.MESSAGE_CREATED, router=self) self.message_created = Event(update_type=UpdateType.MESSAGE_CREATED, router=self)
self.bot_added = Event(update_type=UpdateType.BOT_ADDED, router=self) self.bot_added = Event(update_type=UpdateType.BOT_ADDED, router=self)
@ -230,7 +233,8 @@ class Dispatcher:
for event in processed_events: for event in processed_events:
await self.handle(event) await self.handle(event)
except ClientConnectorError: except ClientConnectorError:
logger_dp.error(f'Ошибка подключения: {e}') logger_dp.error(f'Ошибка подключения, жду {CONNECTION_RETRY_DELAY} секунд')
await asyncio.sleep(CONNECTION_RETRY_DELAY)
except Exception as e: except Exception as e:
logger_dp.error(f'Общая ошибка при обработке событий: {e}') logger_dp.error(f'Общая ошибка при обработке событий: {e}')
@ -246,7 +250,7 @@ class Dispatcher:
await self.__ready(bot) await self.__ready(bot)
@app.post('/') @webhook_app.post('/')
async def _(request: Request): async def _(request: Request):
try: try:
event_json = await request.json() event_json = await request.json()
@ -262,7 +266,7 @@ class Dispatcher:
except Exception as e: except Exception as e:
logger_dp.error(f"Ошибка при обработке события: {event_json['update_type']}: {e}") logger_dp.error(f"Ошибка при обработке события: {event_json['update_type']}: {e}")
config = Config(app=app, host=host, port=port, log_level="critical") config = Config(app=webhook_app, host=host, port=port, log_level="critical")
server = Server(config) server = Server(config)
await server.serve() await server.serve()

View File

@ -1,5 +1,4 @@
from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from ..methods.types.sended_callback import SendedCallback from ..methods.types.sended_callback import SendedCallback
@ -37,7 +36,7 @@ class SendCallback(BaseConnection):
self, self,
bot: 'Bot', bot: 'Bot',
callback_id: str, callback_id: str,
message: 'Message' = None, message: Message = None,
notification: str = None notification: str = None
): ):
self.bot = bot self.bot = bot

View File

@ -25,8 +25,8 @@ if TYPE_CHECKING:
from ..bot import Bot from ..bot import Bot
class UploadResponse: RETRY_DELAY = 2
token: str = None ATTEMPTS_COUNT = 5
class SendMessage(BaseConnection): class SendMessage(BaseConnection):
@ -70,6 +70,9 @@ class SendMessage(BaseConnection):
att: InputMedia att: InputMedia
): ):
# очень нестабильный метод независящий от модуля
# ждем обновлений MAX API
""" """
Загружает файл вложения и формирует объект AttachmentUpload. Загружает файл вложения и формирует объект AttachmentUpload.
@ -140,11 +143,11 @@ class SendMessage(BaseConnection):
json['attachments'].append(att.model_dump()) json['attachments'].append(att.model_dump())
if not self.link is None: json['link'] = self.link.model_dump() if not self.link is None: json['link'] = self.link.model_dump()
if not self.notify is None: json['notify'] = self.notify json['notify'] = self.notify
if not self.parse_mode is None: json['format'] = self.parse_mode.value if not self.parse_mode is None: json['format'] = self.parse_mode.value
response = None response = None
for attempt in range(5): for attempt in range(ATTEMPTS_COUNT):
response = await super().request( response = await super().request(
method=HTTPMethod.POST, method=HTTPMethod.POST,
path=ApiPath.MESSAGES, path=ApiPath.MESSAGES,
@ -155,8 +158,8 @@ class SendMessage(BaseConnection):
if isinstance(response, Error): if isinstance(response, Error):
if response.raw.get('code') == 'attachment.not.ready': if response.raw.get('code') == 'attachment.not.ready':
logger_bot.info(f'Ошибка при отправке загруженного медиа, попытка {attempt+1}, жду 2 секунды') logger_bot.info(f'Ошибка при отправке загруженного медиа, попытка {attempt+1}, жду {RETRY_DELAY} секунды')
await asyncio.sleep(2) await asyncio.sleep(RETRY_DELAY)
continue continue
return response return response

View File

@ -18,6 +18,7 @@ dependencies = [
"magic_filter>=1.0.0", "magic_filter>=1.0.0",
"pydantic>=1.8.0", "pydantic>=1.8.0",
"uvicorn>=0.15.0", "uvicorn>=0.15.0",
"aiofiles==24.1.0",
] ]
[project.urls] [project.urls]