maxapi 0.6__tar.gz → 0.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {maxapi-0.6/maxapi.egg-info → maxapi-0.8}/PKG-INFO +13 -1
- {maxapi-0.6 → maxapi-0.8}/README.md +12 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/bot.py +71 -24
- {maxapi-0.6 → maxapi-0.8}/maxapi/connection/base.py +39 -1
- {maxapi-0.6 → maxapi-0.8}/maxapi/context/__init__.py +1 -1
- {maxapi-0.6 → maxapi-0.8}/maxapi/dispatcher.py +58 -39
- maxapi-0.8/maxapi/exceptions/download_file.py +4 -0
- maxapi-0.8/maxapi/exceptions/invalid_token.py +4 -0
- maxapi-0.8/maxapi/filters/__init__.py +20 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/filters/handler.py +11 -3
- maxapi-0.8/maxapi/filters/middleware.py +6 -0
- maxapi-0.8/maxapi/methods/download_media.py +52 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_members_chat.py +3 -1
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/getted_updates.py +43 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/attachment.py +40 -5
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/bot_added.py +0 -4
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/bot_removed.py +0 -4
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/bot_started.py +1 -4
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/chat_title_changed.py +0 -4
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/message_callback.py +5 -8
- maxapi-0.8/maxapi/types/updates/message_chat_created.py +15 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/message_created.py +1 -11
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/message_edited.py +0 -12
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/message_removed.py +1 -11
- maxapi-0.8/maxapi/types/updates/update.py +36 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/user_added.py +1 -12
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/user_removed.py +1 -11
- {maxapi-0.6 → maxapi-0.8/maxapi.egg-info}/PKG-INFO +13 -1
- {maxapi-0.6 → maxapi-0.8}/maxapi.egg-info/SOURCES.txt +4 -1
- {maxapi-0.6 → maxapi-0.8}/pyproject.toml +2 -2
- maxapi-0.6/LICENSE.md +0 -21
- maxapi-0.6/maxapi/filters/__init__.py +0 -53
- maxapi-0.6/maxapi/types/updates/message_chat_created.py +0 -24
- maxapi-0.6/maxapi/types/updates/update.py +0 -20
- {maxapi-0.6 → maxapi-0.8}/MANIFEST.in +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/connection/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/context/state_machine.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/api_path.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/attachment.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/button_type.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/chat_permission.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/chat_status.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/chat_type.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/http_method.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/intent.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/message_link_type.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/parse_mode.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/sender_action.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/text_style.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/update.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/enums/upload_type.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/loggers.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/add_admin_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/add_members_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/change_info.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/delete_bot_from_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/delete_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/delete_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/delete_pin_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/edit_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/edit_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_chat_by_id.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_chat_by_link.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_chats.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_list_admin_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_me.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_me_from_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_messages.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_pinned_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_updates.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_upload_url.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/get_video.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/pin_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/remove_admin.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/remove_member_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/send_action.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/send_callback.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/send_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/added_admin_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/added_members_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/deleted_bot_from_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/deleted_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/deleted_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/deleted_pin_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/edited_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/getted_list_admin_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/getted_members_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/getted_pineed_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/getted_upload_url.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/pinned_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/removed_admin.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/removed_member_chat.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/sended_action.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/sended_callback.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/methods/types/sended_message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/audio.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/buttons/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/buttons/attachment_button.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/buttons/button.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/buttons/callback_button.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/buttons/chat_button.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/buttons/link_button.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/buttons/request_contact.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/buttons/request_geo_location_button.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/contact.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/file.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/image.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/location.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/share.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/sticker.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/upload.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/attachments/video.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/callback.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/chats.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/command.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/errors.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/input_media.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/message.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/updates/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/types/users.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/utils/__init__.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi/utils/inline_keyboard.py +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi.egg-info/dependency_links.txt +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi.egg-info/requires.txt +0 -0
- {maxapi-0.6 → maxapi-0.8}/maxapi.egg-info/top_level.txt +0 -0
- {maxapi-0.6 → maxapi-0.8}/setup.cfg +0 -0
- {maxapi-0.6 → maxapi-0.8}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maxapi
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8
|
|
4
4
|
Summary: Библиотека для разработки чат-ботов с помощью API мессенджера MAX
|
|
5
5
|
Author-email: Denis <your-email@example.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/love-apples/maxapi
|
|
@@ -33,6 +33,8 @@ pip install maxapi
|
|
|
33
33
|
|
|
34
34
|
## 🚀 Быстрый старт
|
|
35
35
|
|
|
36
|
+
Если вы тестируете бота в чате - не забудьте дать ему права администратора!
|
|
37
|
+
|
|
36
38
|
```python
|
|
37
39
|
import asyncio
|
|
38
40
|
import logging
|
|
@@ -75,6 +77,16 @@ if __name__ == '__main__':
|
|
|
75
77
|
|
|
76
78
|
---
|
|
77
79
|
|
|
80
|
+
## ⭐️ Примеры
|
|
81
|
+
|
|
82
|
+
- [Эхо бот](https://love-apples/maxapi/blob/main/examples/echo/main.py)
|
|
83
|
+
- [Обработчик доступных событий](https://love-apples/maxapi/blob/main/examples/events/main.py)
|
|
84
|
+
- [Обработчики с MagicFilter](https://love-apples/maxapi/blob/main/examples/magic_filters/main.py)
|
|
85
|
+
- [Демонстрация роутинга, InputMedia и механика контекста](https://love-apples/maxapi/blob/main/examples/router_with_input_media/main.py) (audio.mp3 для команды /media)
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
|
|
78
90
|
## 🧩 Возможности
|
|
79
91
|
|
|
80
92
|
- ✅ Роутеры
|
|
@@ -16,6 +16,8 @@ pip install maxapi
|
|
|
16
16
|
|
|
17
17
|
## 🚀 Быстрый старт
|
|
18
18
|
|
|
19
|
+
Если вы тестируете бота в чате - не забудьте дать ему права администратора!
|
|
20
|
+
|
|
19
21
|
```python
|
|
20
22
|
import asyncio
|
|
21
23
|
import logging
|
|
@@ -58,6 +60,16 @@ if __name__ == '__main__':
|
|
|
58
60
|
|
|
59
61
|
---
|
|
60
62
|
|
|
63
|
+
## ⭐️ Примеры
|
|
64
|
+
|
|
65
|
+
- [Эхо бот](https://love-apples/maxapi/blob/main/examples/echo/main.py)
|
|
66
|
+
- [Обработчик доступных событий](https://love-apples/maxapi/blob/main/examples/events/main.py)
|
|
67
|
+
- [Обработчики с MagicFilter](https://love-apples/maxapi/blob/main/examples/magic_filters/main.py)
|
|
68
|
+
- [Демонстрация роутинга, InputMedia и механика контекста](https://love-apples/maxapi/blob/main/examples/router_with_input_media/main.py) (audio.mp3 для команды /media)
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
|
|
61
73
|
## 🧩 Возможности
|
|
62
74
|
|
|
63
75
|
- ✅ Роутеры
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
from typing import Any, Dict, List, TYPE_CHECKING
|
|
3
3
|
|
|
4
|
+
from maxapi.methods.download_media import DownloadMedia
|
|
5
|
+
|
|
4
6
|
from .methods.get_upload_url import GetUploadURL
|
|
5
7
|
from .methods.get_updates import GetUpdates
|
|
6
8
|
from .methods.remove_member_chat import RemoveMemberChat
|
|
@@ -33,6 +35,7 @@ from .enums.parse_mode import ParseMode
|
|
|
33
35
|
from .enums.sender_action import SenderAction
|
|
34
36
|
from .enums.upload_type import UploadType
|
|
35
37
|
|
|
38
|
+
from .types.message import Message
|
|
36
39
|
from .types.attachments.attachment import Attachment
|
|
37
40
|
from .types.attachments.image import PhotoAttachmentRequestPayload
|
|
38
41
|
from .types.message import Messages, NewMessageLink
|
|
@@ -41,29 +44,27 @@ from .types.command import BotCommand
|
|
|
41
44
|
|
|
42
45
|
from .connection.base import BaseConnection
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
from maxapi.types.updates import UpdateUnion
|
|
66
|
-
|
|
47
|
+
from .methods.types.added_admin_chat import AddedListAdminChat
|
|
48
|
+
from .methods.types.added_members_chat import AddedMembersChat
|
|
49
|
+
from .methods.types.deleted_bot_from_chat import DeletedBotFromChat
|
|
50
|
+
from .methods.types.deleted_chat import DeletedChat
|
|
51
|
+
from .methods.types.deleted_message import DeletedMessage
|
|
52
|
+
from .methods.types.deleted_pin_message import DeletedPinMessage
|
|
53
|
+
from .methods.types.edited_message import EditedMessage
|
|
54
|
+
from .methods.types.getted_list_admin_chat import GettedListAdminChat
|
|
55
|
+
from .methods.types.getted_members_chat import GettedMembersChat
|
|
56
|
+
from .methods.types.getted_pineed_message import GettedPin
|
|
57
|
+
from .methods.types.getted_upload_url import GettedUploadUrl
|
|
58
|
+
from .methods.types.pinned_message import PinnedMessage
|
|
59
|
+
from .methods.types.removed_admin import RemovedAdmin
|
|
60
|
+
from .methods.types.removed_member_chat import RemovedMemberChat
|
|
61
|
+
from .methods.types.sended_action import SendedAction
|
|
62
|
+
from .methods.types.sended_callback import SendedCallback
|
|
63
|
+
from .methods.types.sended_message import SendedMessage
|
|
64
|
+
from .types.attachments.video import Video
|
|
65
|
+
from .types.chats import Chat, ChatMember, Chats
|
|
66
|
+
from .types.updates import UpdateUnion
|
|
67
|
+
|
|
67
68
|
|
|
68
69
|
class Bot(BaseConnection):
|
|
69
70
|
|
|
@@ -571,7 +572,7 @@ class Bot(BaseConnection):
|
|
|
571
572
|
"""Получает участников чата.
|
|
572
573
|
|
|
573
574
|
:param chat_id: ID чата
|
|
574
|
-
:param user_ids:
|
|
575
|
+
:param user_ids: Список ID участников
|
|
575
576
|
:param marker: Маркер для пагинации
|
|
576
577
|
:param count: Количество участников
|
|
577
578
|
|
|
@@ -585,6 +586,28 @@ class Bot(BaseConnection):
|
|
|
585
586
|
marker=marker,
|
|
586
587
|
count=count,
|
|
587
588
|
).request()
|
|
589
|
+
|
|
590
|
+
async def get_chat_member(
|
|
591
|
+
self,
|
|
592
|
+
chat_id: int,
|
|
593
|
+
user_id: int,
|
|
594
|
+
) -> GettedMembersChat:
|
|
595
|
+
|
|
596
|
+
"""Получает участника чата.
|
|
597
|
+
|
|
598
|
+
:param chat_id: ID чата
|
|
599
|
+
:param user_id: ID участника
|
|
600
|
+
|
|
601
|
+
:return: Участник
|
|
602
|
+
"""
|
|
603
|
+
|
|
604
|
+
members = await self.get_chat_members(
|
|
605
|
+
chat_id=chat_id,
|
|
606
|
+
user_ids=[user_id]
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
if members.members:
|
|
610
|
+
return members.members[0]
|
|
588
611
|
|
|
589
612
|
async def add_chat_members(
|
|
590
613
|
self,
|
|
@@ -674,4 +697,28 @@ class Bot(BaseConnection):
|
|
|
674
697
|
return await ChangeInfo(
|
|
675
698
|
bot=self,
|
|
676
699
|
commands=list(commands)
|
|
700
|
+
).request()
|
|
701
|
+
|
|
702
|
+
async def download_file(
|
|
703
|
+
self,
|
|
704
|
+
path: str,
|
|
705
|
+
url: str,
|
|
706
|
+
token: str
|
|
707
|
+
):
|
|
708
|
+
|
|
709
|
+
"""
|
|
710
|
+
Скачивает медиа с указанной ссылки по токену, сохраняя по определенному пути
|
|
711
|
+
|
|
712
|
+
:param path: Путь сохранения медиа
|
|
713
|
+
:param url: Ссылка на медиа
|
|
714
|
+
:param token: Токен медиа
|
|
715
|
+
|
|
716
|
+
:return: Числовой статус
|
|
717
|
+
"""
|
|
718
|
+
|
|
719
|
+
return await DownloadMedia(
|
|
720
|
+
bot=self,
|
|
721
|
+
path=path,
|
|
722
|
+
media_url=url,
|
|
723
|
+
media_token=token
|
|
677
724
|
).request()
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import os
|
|
2
|
+
|
|
2
3
|
from typing import TYPE_CHECKING
|
|
3
4
|
|
|
5
|
+
import aiofiles
|
|
4
6
|
import aiohttp
|
|
7
|
+
|
|
5
8
|
from pydantic import BaseModel
|
|
6
9
|
|
|
10
|
+
from ..exceptions.invalid_token import InvalidToken
|
|
11
|
+
|
|
7
12
|
from ..types.errors import Error
|
|
8
13
|
from ..enums.http_method import HTTPMethod
|
|
9
14
|
from ..enums.api_path import ApiPath
|
|
10
15
|
from ..enums.upload_type import UploadType
|
|
16
|
+
|
|
11
17
|
from ..loggers import logger_bot, logger_connection
|
|
12
18
|
|
|
13
19
|
if TYPE_CHECKING:
|
|
@@ -65,6 +71,9 @@ class BaseConnection:
|
|
|
65
71
|
)
|
|
66
72
|
except aiohttp.ClientConnectorDNSError as e:
|
|
67
73
|
return logger_connection.error(f'Ошибка при отправке запроса: {e}')
|
|
74
|
+
|
|
75
|
+
if r.status == 401:
|
|
76
|
+
raise InvalidToken('Неверный токен!')
|
|
68
77
|
|
|
69
78
|
if not r.ok:
|
|
70
79
|
raw = await r.json()
|
|
@@ -124,4 +133,33 @@ class BaseConnection:
|
|
|
124
133
|
data=form
|
|
125
134
|
)
|
|
126
135
|
|
|
127
|
-
return await response.text()
|
|
136
|
+
return await response.text()
|
|
137
|
+
|
|
138
|
+
async def download_file(
|
|
139
|
+
self,
|
|
140
|
+
path: str,
|
|
141
|
+
url: str,
|
|
142
|
+
token: str,
|
|
143
|
+
):
|
|
144
|
+
"""
|
|
145
|
+
Скачивает медиа с указанной ссылки по токену, сохраняя по определенному пути
|
|
146
|
+
|
|
147
|
+
:param path: Путь сохранения медиа
|
|
148
|
+
:param url: Ссылка на медиа
|
|
149
|
+
:param token: Токен медиа
|
|
150
|
+
|
|
151
|
+
:return: Числовой статус
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
headers = {
|
|
155
|
+
'Authorization': f'Bearer {token}'
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async with aiohttp.ClientSession() as session:
|
|
159
|
+
async with session.get(url, headers=headers) as response:
|
|
160
|
+
|
|
161
|
+
if response.status == 200:
|
|
162
|
+
async with aiofiles.open(path, 'wb') as f:
|
|
163
|
+
await f.write(await response.read())
|
|
164
|
+
|
|
165
|
+
return response.status
|
|
@@ -2,6 +2,7 @@ from typing import Callable, List
|
|
|
2
2
|
|
|
3
3
|
from fastapi import FastAPI, Request
|
|
4
4
|
from fastapi.responses import JSONResponse
|
|
5
|
+
from magic_filter import MagicFilter
|
|
5
6
|
from uvicorn import Config, Server
|
|
6
7
|
from aiohttp import ClientConnectorError
|
|
7
8
|
|
|
@@ -33,6 +34,8 @@ class Dispatcher:
|
|
|
33
34
|
def __init__(self):
|
|
34
35
|
self.event_handlers: List[Handler] = []
|
|
35
36
|
self.contexts: List[MemoryContext] = []
|
|
37
|
+
self.routers: List[Router] = []
|
|
38
|
+
self.filters: List[MagicFilter] = []
|
|
36
39
|
self.bot = None
|
|
37
40
|
self.on_started_func = None
|
|
38
41
|
|
|
@@ -65,9 +68,24 @@ class Dispatcher:
|
|
|
65
68
|
"""
|
|
66
69
|
|
|
67
70
|
for router in routers:
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
self.routers.append(router)
|
|
72
|
+
|
|
73
|
+
async def __ready(self, bot: Bot):
|
|
74
|
+
self.bot = bot
|
|
75
|
+
await self.check_me()
|
|
76
|
+
|
|
77
|
+
self.routers += [self]
|
|
78
|
+
|
|
79
|
+
handlers_count = 0
|
|
80
|
+
for router in self.routers:
|
|
81
|
+
for handler in router.event_handlers:
|
|
82
|
+
handlers_count += 1
|
|
70
83
|
|
|
84
|
+
logger_dp.info(f'{handlers_count} событий на обработку')
|
|
85
|
+
|
|
86
|
+
if self.on_started_func:
|
|
87
|
+
await self.on_started_func()
|
|
88
|
+
|
|
71
89
|
def __get_memory_context(self, chat_id: int, user_id: int):
|
|
72
90
|
|
|
73
91
|
"""Возвращает или создает контекст для чата и пользователя.
|
|
@@ -95,40 +113,51 @@ class Dispatcher:
|
|
|
95
113
|
Args:
|
|
96
114
|
event_object: Объект события для обработки
|
|
97
115
|
"""
|
|
116
|
+
ids = event_object.get_ids()
|
|
98
117
|
|
|
99
118
|
is_handled = False
|
|
119
|
+
|
|
120
|
+
for router in self.routers:
|
|
121
|
+
|
|
122
|
+
if is_handled:
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
if router.filters:
|
|
126
|
+
if not filter_attrs(event_object, *router.filters):
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
for handler in router.event_handlers:
|
|
100
130
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if not handler.update_type == event_object.update_type:
|
|
104
|
-
continue
|
|
105
|
-
|
|
106
|
-
if handler.filters:
|
|
107
|
-
if not filter_attrs(event_object, *handler.filters):
|
|
131
|
+
if not handler.update_type == event_object.update_type:
|
|
108
132
|
continue
|
|
109
133
|
|
|
110
|
-
|
|
134
|
+
if handler.filters:
|
|
135
|
+
if not filter_attrs(event_object, *handler.filters):
|
|
136
|
+
continue
|
|
111
137
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
138
|
+
memory_context = self.__get_memory_context(*ids)
|
|
139
|
+
|
|
140
|
+
if not handler.state == await memory_context.get_state() \
|
|
141
|
+
and handler.state:
|
|
142
|
+
continue
|
|
143
|
+
|
|
144
|
+
func_args = handler.func_event.__annotations__.keys()
|
|
119
145
|
|
|
120
|
-
|
|
146
|
+
kwargs = {'context': memory_context}
|
|
121
147
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
148
|
+
for key in kwargs.copy().keys():
|
|
149
|
+
if not key in func_args:
|
|
150
|
+
del kwargs[key]
|
|
151
|
+
|
|
152
|
+
if handler.middleware:
|
|
153
|
+
await handler.middleware()
|
|
125
154
|
|
|
126
|
-
|
|
155
|
+
await handler.func_event(event_object, **kwargs)
|
|
127
156
|
|
|
128
|
-
|
|
157
|
+
logger_dp.info(f'Обработано: {event_object.update_type} | chat_id: {ids[0]}, user_id: {ids[1]}')
|
|
129
158
|
|
|
130
|
-
|
|
131
|
-
|
|
159
|
+
is_handled = True
|
|
160
|
+
break
|
|
132
161
|
|
|
133
162
|
if not is_handled:
|
|
134
163
|
logger_dp.info(f'Проигнорировано: {event_object.update_type} | chat_id: {ids[0]}, user_id: {ids[1]}')
|
|
@@ -140,14 +169,7 @@ class Dispatcher:
|
|
|
140
169
|
Args:
|
|
141
170
|
bot: Экземпляр бота
|
|
142
171
|
"""
|
|
143
|
-
|
|
144
|
-
self.bot = bot
|
|
145
|
-
await self.check_me()
|
|
146
|
-
|
|
147
|
-
logger_dp.info(f'{len(self.event_handlers)} событий на обработку')
|
|
148
|
-
|
|
149
|
-
if self.on_started_func:
|
|
150
|
-
await self.on_started_func()
|
|
172
|
+
await self.__ready(bot)
|
|
151
173
|
|
|
152
174
|
while True:
|
|
153
175
|
try:
|
|
@@ -184,11 +206,7 @@ class Dispatcher:
|
|
|
184
206
|
port: Порт для сервера
|
|
185
207
|
"""
|
|
186
208
|
|
|
187
|
-
self.bot
|
|
188
|
-
await self.check_me()
|
|
189
|
-
|
|
190
|
-
if self.on_started_func:
|
|
191
|
-
await self.on_started_func()
|
|
209
|
+
await self.__ready(bot)
|
|
192
210
|
|
|
193
211
|
@app.post('/')
|
|
194
212
|
async def _(request: Request):
|
|
@@ -206,7 +224,6 @@ class Dispatcher:
|
|
|
206
224
|
except Exception as e:
|
|
207
225
|
logger_dp.error(f"Ошибка при обработке события: {event_json['update_type']}: {e}")
|
|
208
226
|
|
|
209
|
-
logger_dp.info(f'{len(self.event_handlers)} событий на обработку')
|
|
210
227
|
config = Config(app=app, host=host, port=port, log_level="critical")
|
|
211
228
|
server = Server(config)
|
|
212
229
|
|
|
@@ -231,8 +248,10 @@ class Event:
|
|
|
231
248
|
|
|
232
249
|
def __call__(self, *args, **kwargs):
|
|
233
250
|
def decorator(func_event: Callable):
|
|
251
|
+
|
|
234
252
|
if self.update_type == UpdateType.ON_STARTED:
|
|
235
253
|
self.router.on_started_func = func_event
|
|
254
|
+
|
|
236
255
|
else:
|
|
237
256
|
self.router.event_handlers.append(
|
|
238
257
|
Handler(
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from magic_filter import MagicFilter
|
|
2
|
+
from magic_filter.operations.call import CallOperation as mf_call
|
|
3
|
+
from magic_filter.operations.function import FunctionOperation as mf_func
|
|
4
|
+
from magic_filter.operations.comparator import ComparatorOperation as mf_comparator
|
|
5
|
+
|
|
6
|
+
F = MagicFilter()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def filter_attrs(obj: object, *filters: MagicFilter) -> bool:
|
|
10
|
+
"""
|
|
11
|
+
Применяет один или несколько фильтров MagicFilter к объекту.
|
|
12
|
+
|
|
13
|
+
:param obj: Любой объект с атрибутами (например, event/message)
|
|
14
|
+
:param filters: Один или несколько MagicFilter выражений
|
|
15
|
+
:return: True, если все фильтры возвращают True, иначе False
|
|
16
|
+
"""
|
|
17
|
+
try:
|
|
18
|
+
return all(f.resolve(obj) for f in filters)
|
|
19
|
+
except Exception:
|
|
20
|
+
return False
|
|
@@ -2,9 +2,14 @@ from typing import Callable
|
|
|
2
2
|
|
|
3
3
|
from magic_filter import F, MagicFilter
|
|
4
4
|
|
|
5
|
+
from ..filters.middleware import BaseMiddleware
|
|
6
|
+
|
|
5
7
|
from ..types.command import Command
|
|
8
|
+
|
|
6
9
|
from ..context.state_machine import State
|
|
10
|
+
|
|
7
11
|
from ..enums.update import UpdateType
|
|
12
|
+
|
|
8
13
|
from ..loggers import logger_dp
|
|
9
14
|
|
|
10
15
|
|
|
@@ -36,10 +41,11 @@ class Handler:
|
|
|
36
41
|
:param kwargs: Дополнительные параметры (не используются)
|
|
37
42
|
"""
|
|
38
43
|
|
|
39
|
-
self.func_event = func_event
|
|
40
|
-
self.update_type = update_type
|
|
44
|
+
self.func_event: Callable = func_event
|
|
45
|
+
self.update_type: UpdateType = update_type
|
|
41
46
|
self.filters = []
|
|
42
|
-
self.state = None
|
|
47
|
+
self.state: State = None
|
|
48
|
+
self.middleware: BaseMiddleware = None
|
|
43
49
|
|
|
44
50
|
for arg in args:
|
|
45
51
|
if isinstance(arg, MagicFilter):
|
|
@@ -48,6 +54,8 @@ class Handler:
|
|
|
48
54
|
self.state = arg
|
|
49
55
|
elif isinstance(arg, Command):
|
|
50
56
|
self.filters.insert(0, F.message.body.text.startswith(arg.command))
|
|
57
|
+
elif isinstance(arg, BaseMiddleware):
|
|
58
|
+
self.middleware = arg
|
|
51
59
|
else:
|
|
52
60
|
logger_dp.info(f'Обнаружен неизвестный фильтр `{arg}` при '
|
|
53
61
|
f'регистрации функции `{func_event.__name__}`')
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from ..methods.types.deleted_pin_message import DeletedPinMessage
|
|
4
|
+
|
|
5
|
+
from ..enums.http_method import HTTPMethod
|
|
6
|
+
from ..enums.api_path import ApiPath
|
|
7
|
+
from ..enums.upload_type import UploadType
|
|
8
|
+
|
|
9
|
+
from ..connection.base import BaseConnection
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..bot import Bot
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DownloadMedia(BaseConnection):
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
Класс для скачивания медиафайлов.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
bot (Bot): Экземпляр бота для выполнения запроса.
|
|
23
|
+
media_url (str): Ссылка на медиа.
|
|
24
|
+
media_token (str): Токен медиа.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
bot: 'Bot',
|
|
30
|
+
path: str,
|
|
31
|
+
media_url: str,
|
|
32
|
+
media_token: str
|
|
33
|
+
):
|
|
34
|
+
self.bot = bot
|
|
35
|
+
self.path = path
|
|
36
|
+
self.media_url = media_url
|
|
37
|
+
self.media_token = media_token
|
|
38
|
+
|
|
39
|
+
async def request(self) -> int:
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
Выполняет GET-запрос для скачивания медиафайла
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
int: Код операции.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
return await super().download_file(
|
|
49
|
+
path=self.path,
|
|
50
|
+
url=self.media_url,
|
|
51
|
+
token=self.media_token
|
|
52
|
+
)
|
|
@@ -60,7 +60,9 @@ class GetMembersChat(BaseConnection):
|
|
|
60
60
|
|
|
61
61
|
params = self.bot.params.copy()
|
|
62
62
|
|
|
63
|
-
if self.user_ids:
|
|
63
|
+
if self.user_ids:
|
|
64
|
+
self.user_ids = [str(user_id) for user_id in self.user_ids]
|
|
65
|
+
params['user_ids'] = ','.join(self.user_ids)
|
|
64
66
|
if self.marker: params['marker'] = self.marker
|
|
65
67
|
if self.count: params['marker'] = self.count
|
|
66
68
|
|
|
@@ -19,34 +19,77 @@ if TYPE_CHECKING:
|
|
|
19
19
|
|
|
20
20
|
async def get_update_model(event: dict, bot: 'Bot'):
|
|
21
21
|
event_object = None
|
|
22
|
+
|
|
22
23
|
match event['update_type']:
|
|
24
|
+
|
|
23
25
|
case UpdateType.BOT_ADDED:
|
|
24
26
|
event_object = BotAdded(**event)
|
|
27
|
+
|
|
25
28
|
case UpdateType.BOT_REMOVED:
|
|
26
29
|
event_object = BotRemoved(**event)
|
|
30
|
+
|
|
27
31
|
case UpdateType.BOT_STARTED:
|
|
28
32
|
event_object = BotStarted(**event)
|
|
33
|
+
|
|
29
34
|
case UpdateType.CHAT_TITLE_CHANGED:
|
|
30
35
|
event_object = ChatTitleChanged(**event)
|
|
36
|
+
|
|
31
37
|
case UpdateType.MESSAGE_CALLBACK:
|
|
32
38
|
event_object = MessageCallback(**event)
|
|
39
|
+
event_object.chat = await bot.get_chat_by_id(event_object.message.recipient.chat_id)
|
|
40
|
+
event_object.from_user = event_object.callback.user
|
|
41
|
+
|
|
33
42
|
case UpdateType.MESSAGE_CHAT_CREATED:
|
|
34
43
|
event_object = MessageChatCreated(**event)
|
|
44
|
+
event_object.chat = event_object.chat
|
|
45
|
+
|
|
35
46
|
case UpdateType.MESSAGE_CREATED:
|
|
36
47
|
event_object = MessageCreated(**event)
|
|
48
|
+
event_object.chat = await bot.get_chat_by_id(event_object.message.recipient.chat_id)
|
|
49
|
+
event_object.from_user = event_object.message.sender
|
|
50
|
+
|
|
37
51
|
case UpdateType.MESSAGE_EDITED:
|
|
38
52
|
event_object = MessageEdited(**event)
|
|
53
|
+
event_object.chat = await bot.get_chat_by_id(event_object.message.recipient.chat_id)
|
|
54
|
+
event_object.from_user = event_object.message.sender
|
|
55
|
+
|
|
39
56
|
case UpdateType.MESSAGE_REMOVED:
|
|
40
57
|
event_object = MessageRemoved(**event)
|
|
58
|
+
event_object.chat = await bot.get_chat_by_id(event_object.chat_id)
|
|
59
|
+
event_object.from_user = await bot.get_chat_member(
|
|
60
|
+
chat_id=event_object.chat_id,
|
|
61
|
+
user_id=event_object.user_id
|
|
62
|
+
)
|
|
63
|
+
|
|
41
64
|
case UpdateType.USER_ADDED:
|
|
42
65
|
event_object = UserAdded(**event)
|
|
66
|
+
event_object.chat = await bot.get_chat_by_id(event_object.chat_id)
|
|
67
|
+
event_object.from_user = event_object.user
|
|
68
|
+
|
|
43
69
|
case UpdateType.USER_REMOVED:
|
|
44
70
|
event_object = UserRemoved(**event)
|
|
71
|
+
event_object.chat = await bot.get_chat_by_id(event_object.chat_id)
|
|
72
|
+
event_object.from_user = await bot.get_chat_member(
|
|
73
|
+
chat_id=event_object.chat_id,
|
|
74
|
+
user_id=event_object.admin_id
|
|
75
|
+
) if event_object.admin_id else None
|
|
76
|
+
|
|
77
|
+
if event['update_type'] in (UpdateType.BOT_ADDED,
|
|
78
|
+
UpdateType.BOT_REMOVED,
|
|
79
|
+
UpdateType.BOT_STARTED,
|
|
80
|
+
UpdateType.CHAT_TITLE_CHANGED):
|
|
81
|
+
event_object.chat = await bot.get_chat_by_id(event_object.chat_id)
|
|
82
|
+
event_object.from_user = event_object.user
|
|
45
83
|
|
|
46
84
|
if hasattr(event_object, 'bot'):
|
|
47
85
|
event_object.bot = bot
|
|
86
|
+
|
|
48
87
|
if hasattr(event_object, 'message'):
|
|
49
88
|
event_object.message.bot = bot
|
|
89
|
+
|
|
90
|
+
for attachment in event_object.message.body.attachments:
|
|
91
|
+
if hasattr(attachment, 'bot'):
|
|
92
|
+
attachment.bot = bot
|
|
50
93
|
|
|
51
94
|
return event_object
|
|
52
95
|
|