telegrinder 0.1.dev20__py3-none-any.whl → 0.1.dev159__py3-none-any.whl
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.
Potentially problematic release.
This version of telegrinder might be problematic. Click here for more details.
- telegrinder/__init__.py +129 -22
- telegrinder/api/__init__.py +11 -2
- telegrinder/api/abc.py +25 -9
- telegrinder/api/api.py +47 -28
- telegrinder/api/error.py +14 -4
- telegrinder/api/response.py +11 -7
- telegrinder/bot/__init__.py +68 -7
- telegrinder/bot/bot.py +30 -24
- telegrinder/bot/cute_types/__init__.py +11 -1
- telegrinder/bot/cute_types/base.py +138 -0
- telegrinder/bot/cute_types/callback_query.py +458 -15
- telegrinder/bot/cute_types/inline_query.py +30 -24
- telegrinder/bot/cute_types/message.py +2982 -78
- telegrinder/bot/cute_types/update.py +30 -0
- telegrinder/bot/cute_types/utils.py +794 -0
- telegrinder/bot/dispatch/__init__.py +56 -3
- telegrinder/bot/dispatch/abc.py +9 -7
- telegrinder/bot/dispatch/composition.py +74 -0
- telegrinder/bot/dispatch/context.py +71 -0
- telegrinder/bot/dispatch/dispatch.py +86 -49
- telegrinder/bot/dispatch/handler/__init__.py +3 -0
- telegrinder/bot/dispatch/handler/abc.py +11 -5
- telegrinder/bot/dispatch/handler/func.py +41 -32
- telegrinder/bot/dispatch/handler/message_reply.py +46 -0
- telegrinder/bot/dispatch/middleware/__init__.py +2 -0
- telegrinder/bot/dispatch/middleware/abc.py +10 -4
- telegrinder/bot/dispatch/process.py +53 -49
- telegrinder/bot/dispatch/return_manager/__init__.py +19 -0
- telegrinder/bot/dispatch/return_manager/abc.py +95 -0
- telegrinder/bot/dispatch/return_manager/callback_query.py +19 -0
- telegrinder/bot/dispatch/return_manager/inline_query.py +14 -0
- telegrinder/bot/dispatch/return_manager/message.py +25 -0
- telegrinder/bot/dispatch/view/__init__.py +14 -2
- telegrinder/bot/dispatch/view/abc.py +128 -2
- telegrinder/bot/dispatch/view/box.py +38 -0
- telegrinder/bot/dispatch/view/callback_query.py +13 -39
- telegrinder/bot/dispatch/view/inline_query.py +11 -39
- telegrinder/bot/dispatch/view/message.py +11 -47
- telegrinder/bot/dispatch/waiter_machine/__init__.py +9 -0
- telegrinder/bot/dispatch/waiter_machine/machine.py +116 -0
- telegrinder/bot/dispatch/waiter_machine/middleware.py +76 -0
- telegrinder/bot/dispatch/waiter_machine/short_state.py +37 -0
- telegrinder/bot/polling/__init__.py +2 -0
- telegrinder/bot/polling/abc.py +11 -4
- telegrinder/bot/polling/polling.py +89 -40
- telegrinder/bot/rules/__init__.py +91 -5
- telegrinder/bot/rules/abc.py +81 -63
- telegrinder/bot/rules/adapter/__init__.py +11 -0
- telegrinder/bot/rules/adapter/abc.py +21 -0
- telegrinder/bot/rules/adapter/errors.py +5 -0
- telegrinder/bot/rules/adapter/event.py +49 -0
- telegrinder/bot/rules/adapter/raw_update.py +24 -0
- telegrinder/bot/rules/callback_data.py +159 -38
- telegrinder/bot/rules/command.py +116 -0
- telegrinder/bot/rules/enum_text.py +28 -0
- telegrinder/bot/rules/func.py +17 -17
- telegrinder/bot/rules/fuzzy.py +13 -10
- telegrinder/bot/rules/inline.py +61 -0
- telegrinder/bot/rules/integer.py +12 -7
- telegrinder/bot/rules/is_from.py +148 -7
- telegrinder/bot/rules/markup.py +21 -18
- telegrinder/bot/rules/mention.py +17 -0
- telegrinder/bot/rules/message_entities.py +33 -0
- telegrinder/bot/rules/regex.py +27 -19
- telegrinder/bot/rules/rule_enum.py +74 -0
- telegrinder/bot/rules/start.py +25 -13
- telegrinder/bot/rules/text.py +23 -14
- telegrinder/bot/scenario/__init__.py +2 -0
- telegrinder/bot/scenario/abc.py +12 -5
- telegrinder/bot/scenario/checkbox.py +48 -30
- telegrinder/bot/scenario/choice.py +16 -10
- telegrinder/client/__init__.py +3 -1
- telegrinder/client/abc.py +26 -16
- telegrinder/client/aiohttp.py +54 -32
- telegrinder/model.py +119 -40
- telegrinder/modules.py +189 -21
- telegrinder/msgspec_json.py +14 -0
- telegrinder/msgspec_utils.py +227 -0
- telegrinder/node/__init__.py +31 -0
- telegrinder/node/attachment.py +71 -0
- telegrinder/node/base.py +93 -0
- telegrinder/node/composer.py +71 -0
- telegrinder/node/container.py +22 -0
- telegrinder/node/message.py +18 -0
- telegrinder/node/rule.py +56 -0
- telegrinder/node/source.py +31 -0
- telegrinder/node/text.py +13 -0
- telegrinder/node/tools/__init__.py +3 -0
- telegrinder/node/tools/generator.py +40 -0
- telegrinder/node/update.py +12 -0
- telegrinder/rules.py +1 -1
- telegrinder/tools/__init__.py +138 -4
- telegrinder/tools/buttons.py +89 -51
- telegrinder/tools/error_handler/__init__.py +8 -0
- telegrinder/tools/error_handler/abc.py +30 -0
- telegrinder/tools/error_handler/error_handler.py +156 -0
- telegrinder/tools/formatting/__init__.py +81 -3
- telegrinder/tools/formatting/html.py +283 -37
- telegrinder/tools/formatting/links.py +32 -0
- telegrinder/tools/formatting/spec_html_formats.py +121 -0
- telegrinder/tools/global_context/__init__.py +12 -0
- telegrinder/tools/global_context/abc.py +66 -0
- telegrinder/tools/global_context/global_context.py +451 -0
- telegrinder/tools/global_context/telegrinder_ctx.py +25 -0
- telegrinder/tools/i18n/__init__.py +12 -0
- telegrinder/tools/i18n/base.py +31 -0
- telegrinder/tools/i18n/middleware/__init__.py +3 -0
- telegrinder/tools/i18n/middleware/base.py +26 -0
- telegrinder/tools/i18n/simple.py +48 -0
- telegrinder/tools/kb_set/__init__.py +2 -0
- telegrinder/tools/kb_set/base.py +3 -0
- telegrinder/tools/kb_set/yaml.py +28 -17
- telegrinder/tools/keyboard.py +84 -62
- telegrinder/tools/loop_wrapper/__init__.py +4 -0
- telegrinder/tools/loop_wrapper/abc.py +18 -0
- telegrinder/tools/loop_wrapper/loop_wrapper.py +132 -0
- telegrinder/tools/magic.py +48 -23
- telegrinder/tools/parse_mode.py +1 -2
- telegrinder/types/__init__.py +1 -0
- telegrinder/types/enums.py +653 -0
- telegrinder/types/methods.py +4107 -1279
- telegrinder/types/objects.py +4771 -1745
- {telegrinder-0.1.dev20.dist-info → telegrinder-0.1.dev159.dist-info}/LICENSE +2 -1
- telegrinder-0.1.dev159.dist-info/METADATA +109 -0
- telegrinder-0.1.dev159.dist-info/RECORD +126 -0
- {telegrinder-0.1.dev20.dist-info → telegrinder-0.1.dev159.dist-info}/WHEEL +1 -1
- telegrinder/bot/dispatch/waiter.py +0 -38
- telegrinder/result.py +0 -38
- telegrinder/tools/formatting/abc.py +0 -52
- telegrinder/tools/formatting/markdown.py +0 -57
- telegrinder-0.1.dev20.dist-info/METADATA +0 -22
- telegrinder-0.1.dev20.dist-info/RECORD +0 -71
telegrinder/__init__.py
CHANGED
|
@@ -1,39 +1,146 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
from .api import ABCAPI, API, APIError, APIResponse, Token
|
|
3
4
|
from .bot import (
|
|
4
|
-
ABCPolling,
|
|
5
|
-
Polling,
|
|
6
5
|
ABCDispatch,
|
|
6
|
+
ABCHandler,
|
|
7
|
+
ABCMiddleware,
|
|
8
|
+
ABCPolling,
|
|
9
|
+
ABCReturnManager,
|
|
7
10
|
ABCRule,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Telegrinder,
|
|
11
|
+
ABCScenario,
|
|
12
|
+
ABCStateView,
|
|
11
13
|
ABCView,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
BaseCute,
|
|
15
|
+
BaseReturnManager,
|
|
16
|
+
BaseStateView,
|
|
17
|
+
BaseView,
|
|
18
|
+
CallbackQueryCute,
|
|
19
|
+
CallbackQueryReturnManager,
|
|
14
20
|
CallbackQueryView,
|
|
21
|
+
Checkbox,
|
|
22
|
+
Dispatch,
|
|
15
23
|
FuncHandler,
|
|
16
|
-
MessageCute,
|
|
17
|
-
CallbackQueryCute,
|
|
18
24
|
InlineQueryCute,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
InlineQueryReturnManager,
|
|
26
|
+
MessageCute,
|
|
27
|
+
MessageReplyHandler,
|
|
28
|
+
MessageReturnManager,
|
|
29
|
+
MessageRule,
|
|
30
|
+
MessageView,
|
|
31
|
+
Polling,
|
|
22
32
|
SingleChoice,
|
|
33
|
+
Telegrinder,
|
|
34
|
+
ViewBox,
|
|
35
|
+
WaiterMachine,
|
|
36
|
+
register_manager,
|
|
23
37
|
)
|
|
38
|
+
from .client import ABCClient, AiohttpClient
|
|
39
|
+
from .model import Model
|
|
40
|
+
from .modules import logger
|
|
24
41
|
from .tools import (
|
|
25
|
-
|
|
42
|
+
ABCGlobalContext,
|
|
43
|
+
ABCLoopWrapper,
|
|
44
|
+
ABCTranslator,
|
|
45
|
+
ABCTranslatorMiddleware,
|
|
46
|
+
AnyMarkup,
|
|
26
47
|
Button,
|
|
48
|
+
CtxVar,
|
|
49
|
+
DelayedTask,
|
|
50
|
+
FormatString,
|
|
51
|
+
GlobalContext,
|
|
52
|
+
HTMLFormatter,
|
|
53
|
+
I18nEnum,
|
|
27
54
|
InlineButton,
|
|
28
55
|
InlineKeyboard,
|
|
29
|
-
|
|
30
|
-
magic_bundle,
|
|
56
|
+
Keyboard,
|
|
31
57
|
KeyboardSetBase,
|
|
32
58
|
KeyboardSetYAML,
|
|
33
|
-
|
|
59
|
+
LoopWrapper,
|
|
60
|
+
ParseMode,
|
|
61
|
+
RowButtons,
|
|
62
|
+
SimpleI18n,
|
|
63
|
+
SimpleTranslator,
|
|
64
|
+
ctx_var,
|
|
65
|
+
keyboard_remove,
|
|
66
|
+
magic_bundle,
|
|
34
67
|
)
|
|
35
|
-
from .result import Result
|
|
36
68
|
|
|
37
|
-
Message = MessageCute
|
|
38
|
-
CallbackQuery = CallbackQueryCute
|
|
39
|
-
InlineQuery = InlineQueryCute
|
|
69
|
+
Message: typing.TypeAlias = MessageCute
|
|
70
|
+
CallbackQuery: typing.TypeAlias = CallbackQueryCute
|
|
71
|
+
InlineQuery: typing.TypeAlias = InlineQueryCute
|
|
72
|
+
Bot: typing.TypeAlias = Telegrinder
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
__all__ = (
|
|
76
|
+
"ABCAPI",
|
|
77
|
+
"ABCClient",
|
|
78
|
+
"ABCDispatch",
|
|
79
|
+
"ABCGlobalContext",
|
|
80
|
+
"ABCHandler",
|
|
81
|
+
"ABCLoopWrapper",
|
|
82
|
+
"ABCMiddleware",
|
|
83
|
+
"ABCPolling",
|
|
84
|
+
"ABCReturnManager",
|
|
85
|
+
"ABCRule",
|
|
86
|
+
"ABCScenario",
|
|
87
|
+
"ABCStateView",
|
|
88
|
+
"ABCTranslator",
|
|
89
|
+
"ABCTranslatorMiddleware",
|
|
90
|
+
"ABCView",
|
|
91
|
+
"API",
|
|
92
|
+
"APIError",
|
|
93
|
+
"APIResponse",
|
|
94
|
+
"AiohttpClient",
|
|
95
|
+
"AnyMarkup",
|
|
96
|
+
"BaseCute",
|
|
97
|
+
"BaseReturnManager",
|
|
98
|
+
"BaseStateView",
|
|
99
|
+
"BaseView",
|
|
100
|
+
"Bot",
|
|
101
|
+
"Button",
|
|
102
|
+
"CallbackQuery",
|
|
103
|
+
"CallbackQueryCute",
|
|
104
|
+
"CallbackQueryReturnManager",
|
|
105
|
+
"CallbackQueryView",
|
|
106
|
+
"Checkbox",
|
|
107
|
+
"CtxVar",
|
|
108
|
+
"DelayedTask",
|
|
109
|
+
"Dispatch",
|
|
110
|
+
"FormatString",
|
|
111
|
+
"FuncHandler",
|
|
112
|
+
"GlobalContext",
|
|
113
|
+
"HTMLFormatter",
|
|
114
|
+
"I18nEnum",
|
|
115
|
+
"InlineButton",
|
|
116
|
+
"InlineKeyboard",
|
|
117
|
+
"InlineQuery",
|
|
118
|
+
"InlineQueryCute",
|
|
119
|
+
"InlineQueryReturnManager",
|
|
120
|
+
"Keyboard",
|
|
121
|
+
"KeyboardSetBase",
|
|
122
|
+
"KeyboardSetYAML",
|
|
123
|
+
"LoopWrapper",
|
|
124
|
+
"Message",
|
|
125
|
+
"MessageCute",
|
|
126
|
+
"MessageReplyHandler",
|
|
127
|
+
"MessageReturnManager",
|
|
128
|
+
"MessageRule",
|
|
129
|
+
"MessageView",
|
|
130
|
+
"Model",
|
|
131
|
+
"ParseMode",
|
|
132
|
+
"Polling",
|
|
133
|
+
"RowButtons",
|
|
134
|
+
"SimpleI18n",
|
|
135
|
+
"SimpleTranslator",
|
|
136
|
+
"SingleChoice",
|
|
137
|
+
"Telegrinder",
|
|
138
|
+
"Token",
|
|
139
|
+
"ViewBox",
|
|
140
|
+
"WaiterMachine",
|
|
141
|
+
"ctx_var",
|
|
142
|
+
"keyboard_remove",
|
|
143
|
+
"logger",
|
|
144
|
+
"magic_bundle",
|
|
145
|
+
"register_manager",
|
|
146
|
+
)
|
telegrinder/api/__init__.py
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
from .abc import ABCAPI,
|
|
1
|
+
from .abc import ABCAPI, Token
|
|
2
2
|
from .api import API
|
|
3
|
+
from .error import APIError, InvalidTokenError
|
|
3
4
|
from .response import APIResponse
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
__all__ = (
|
|
7
|
+
"ABCAPI",
|
|
8
|
+
"API",
|
|
9
|
+
"APIError",
|
|
10
|
+
"APIResponse",
|
|
11
|
+
"InvalidTokenError",
|
|
12
|
+
"Token",
|
|
13
|
+
)
|
telegrinder/api/abc.py
CHANGED
|
@@ -1,20 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
import pathlib
|
|
2
2
|
import typing
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
3
4
|
|
|
4
5
|
import msgspec
|
|
6
|
+
from envparse import env
|
|
7
|
+
from fntypes.result import Result
|
|
5
8
|
|
|
6
|
-
from telegrinder.client import ABCClient
|
|
7
|
-
from telegrinder.result import Result
|
|
8
9
|
from telegrinder.api.error import APIError
|
|
10
|
+
from telegrinder.client import ABCClient
|
|
9
11
|
|
|
10
|
-
from
|
|
12
|
+
from .error import InvalidTokenError
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class Token(str):
|
|
16
|
+
def __new__(cls, token: str) -> typing.Self:
|
|
17
|
+
if token.count(":") != 1 or not token.split(":")[0].isdigit():
|
|
18
|
+
raise InvalidTokenError("Invalid token, it should look like this '123:ABC'.")
|
|
19
|
+
return super().__new__(cls, token)
|
|
20
|
+
|
|
14
21
|
@classmethod
|
|
15
|
-
def from_env(
|
|
22
|
+
def from_env(
|
|
23
|
+
cls,
|
|
24
|
+
var_name: str = "BOT_TOKEN",
|
|
25
|
+
*,
|
|
26
|
+
is_read: bool = False,
|
|
27
|
+
path_to_envfile: str | pathlib.Path | None = None,
|
|
28
|
+
) -> typing.Self:
|
|
16
29
|
if not is_read:
|
|
17
|
-
env.read_envfile()
|
|
30
|
+
env.read_envfile(path_to_envfile)
|
|
18
31
|
return cls(env.str(var_name))
|
|
19
32
|
|
|
20
33
|
@property
|
|
@@ -29,15 +42,15 @@ class ABCAPI(ABC):
|
|
|
29
42
|
async def request(
|
|
30
43
|
self,
|
|
31
44
|
method: str,
|
|
32
|
-
data: typing.
|
|
33
|
-
) -> Result[typing.
|
|
45
|
+
data: dict[str, typing.Any] | None = None,
|
|
46
|
+
) -> Result[list[typing.Any] | dict[str, typing.Any] | bool, APIError]:
|
|
34
47
|
pass
|
|
35
48
|
|
|
36
49
|
@abstractmethod
|
|
37
50
|
async def request_raw(
|
|
38
51
|
self,
|
|
39
52
|
method: str,
|
|
40
|
-
data: typing.
|
|
53
|
+
data: dict[str, typing.Any] | None = None,
|
|
41
54
|
) -> Result[msgspec.Raw, APIError]:
|
|
42
55
|
pass
|
|
43
56
|
|
|
@@ -50,3 +63,6 @@ class ABCAPI(ABC):
|
|
|
50
63
|
@abstractmethod
|
|
51
64
|
def id(self) -> int:
|
|
52
65
|
pass
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
__all__ = ("ABCAPI", "Token")
|
telegrinder/api/api.py
CHANGED
|
@@ -1,32 +1,46 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
1
3
|
import msgspec
|
|
4
|
+
from fntypes.result import Error, Ok, Result
|
|
2
5
|
|
|
3
|
-
from .
|
|
4
|
-
import typing
|
|
5
|
-
from telegrinder.result import Result
|
|
6
|
+
from telegrinder.api.response import APIResponse
|
|
6
7
|
from telegrinder.client import ABCClient, AiohttpClient
|
|
8
|
+
from telegrinder.model import DataConverter, decoder
|
|
7
9
|
from telegrinder.types.methods import APIMethods
|
|
8
|
-
|
|
9
|
-
from
|
|
10
|
+
|
|
11
|
+
from .abc import ABCAPI, APIError, Token
|
|
10
12
|
|
|
11
13
|
|
|
12
|
-
def compose_data(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
def compose_data(
|
|
15
|
+
client: ABCClient,
|
|
16
|
+
data: dict[str, typing.Any],
|
|
17
|
+
files: dict[str, tuple[str, bytes]],
|
|
18
|
+
) -> typing.Any:
|
|
19
|
+
converter = DataConverter(files=files)
|
|
20
|
+
return client.get_form(
|
|
21
|
+
data={k: converter.convert(v) for k, v in data.items()},
|
|
22
|
+
files=converter.files,
|
|
23
|
+
)
|
|
17
24
|
|
|
18
25
|
|
|
19
26
|
class API(ABCAPI, APIMethods):
|
|
20
|
-
API_URL = "https://api.telegram.org/"
|
|
27
|
+
API_URL: typing.ClassVar[str] = "https://api.telegram.org/"
|
|
21
28
|
|
|
22
|
-
def __init__(self, token: Token, http:
|
|
29
|
+
def __init__(self, token: Token, *, http: ABCClient | None = None) -> None:
|
|
23
30
|
self.token = token
|
|
24
31
|
self.http = http or AiohttpClient()
|
|
25
32
|
super().__init__(self)
|
|
33
|
+
|
|
34
|
+
def __repr__(self) -> str:
|
|
35
|
+
return "<{}: id={}, http={!r}>".format(
|
|
36
|
+
self.__class__.__name__,
|
|
37
|
+
self.id,
|
|
38
|
+
self.http,
|
|
39
|
+
)
|
|
26
40
|
|
|
27
41
|
@property
|
|
28
42
|
def id(self) -> int:
|
|
29
|
-
return
|
|
43
|
+
return self.token.bot_id
|
|
30
44
|
|
|
31
45
|
@property
|
|
32
46
|
def request_url(self) -> str:
|
|
@@ -35,27 +49,32 @@ class API(ABCAPI, APIMethods):
|
|
|
35
49
|
async def request(
|
|
36
50
|
self,
|
|
37
51
|
method: str,
|
|
38
|
-
data: typing.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
response = await self.http.request_json(
|
|
52
|
+
data: dict[str, typing.Any] | None = None,
|
|
53
|
+
files: dict[str, tuple[str, bytes]] | None = None,
|
|
54
|
+
) -> Result[dict[str, typing.Any] | list[typing.Any] | bool, APIError]:
|
|
55
|
+
response = await self.http.request_json(
|
|
56
|
+
url=self.request_url + method,
|
|
57
|
+
data=compose_data(self.http, data or {}, files or {})
|
|
58
|
+
)
|
|
42
59
|
if response.get("ok"):
|
|
43
60
|
assert "result" in response
|
|
44
|
-
return
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
return Ok(response["result"])
|
|
62
|
+
return Error(APIError(
|
|
63
|
+
code=response.get("error_code", 0),
|
|
64
|
+
error=response.get("description"),
|
|
65
|
+
))
|
|
48
66
|
|
|
49
67
|
async def request_raw(
|
|
50
68
|
self,
|
|
51
69
|
method: str,
|
|
52
|
-
data: typing.
|
|
70
|
+
data: dict[str, typing.Any] | None = None,
|
|
71
|
+
files: dict[str, tuple[str, bytes]] | None = None,
|
|
53
72
|
) -> Result[msgspec.Raw, APIError]:
|
|
54
|
-
data = compose_data(self.http, data)
|
|
55
73
|
response_bytes = await self.http.request_bytes(
|
|
56
|
-
self.request_url + method,
|
|
74
|
+
url=self.request_url + method,
|
|
75
|
+
data=compose_data(self.http, data or {}, files or {}),
|
|
57
76
|
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
77
|
+
return decoder.decode(response_bytes, type=APIResponse).to_result()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
__all__ = ("API",)
|
telegrinder/api/error.py
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
class APIError(BaseException):
|
|
5
|
-
def __init__(self, code: int, error:
|
|
2
|
+
def __init__(self, code: int, error: str | None = None):
|
|
6
3
|
self.code, self.error = code, error
|
|
4
|
+
|
|
5
|
+
def __str__(self) -> str:
|
|
6
|
+
return f"[{self.code}] {self.error}"
|
|
7
|
+
|
|
8
|
+
def __repr__(self) -> str:
|
|
9
|
+
return f"<APIError {self.__str__()}>"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class InvalidTokenError(BaseException):
|
|
13
|
+
...
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = ("APIError", "InvalidTokenError")
|
telegrinder/api/response.py
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
from telegrinder.model import Model
|
|
2
|
-
from telegrinder.result import Result
|
|
3
|
-
from telegrinder.api.error import APIError
|
|
4
1
|
import msgspec
|
|
2
|
+
from fntypes.result import Error, Ok, Result
|
|
3
|
+
|
|
4
|
+
from telegrinder.api.error import APIError
|
|
5
|
+
from telegrinder.model import Model
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class APIResponse(Model):
|
|
8
|
-
ok: bool
|
|
9
|
-
result: msgspec.Raw = b""
|
|
9
|
+
ok: bool = False
|
|
10
|
+
result: msgspec.Raw = msgspec.Raw(b"")
|
|
10
11
|
error_code: int = 0
|
|
11
12
|
description: str = ""
|
|
12
13
|
|
|
13
14
|
def to_result(self) -> Result[msgspec.Raw, APIError]:
|
|
14
15
|
if self.ok:
|
|
15
|
-
return
|
|
16
|
-
return
|
|
16
|
+
return Ok(self.result)
|
|
17
|
+
return Error(APIError(self.error_code, self.description))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
__all__ = ("APIResponse",)
|
telegrinder/bot/__init__.py
CHANGED
|
@@ -1,15 +1,76 @@
|
|
|
1
|
-
from .
|
|
1
|
+
from .bot import Telegrinder
|
|
2
|
+
from .cute_types import (
|
|
3
|
+
BaseCute,
|
|
4
|
+
CallbackQueryCute,
|
|
5
|
+
InlineQueryCute,
|
|
6
|
+
MessageCute,
|
|
7
|
+
UpdateCute,
|
|
8
|
+
)
|
|
2
9
|
from .dispatch import (
|
|
3
10
|
ABCDispatch,
|
|
4
|
-
Dispatch,
|
|
5
11
|
ABCHandler,
|
|
12
|
+
ABCMiddleware,
|
|
13
|
+
ABCReturnManager,
|
|
14
|
+
ABCStateView,
|
|
6
15
|
ABCView,
|
|
16
|
+
BaseReturnManager,
|
|
17
|
+
BaseStateView,
|
|
18
|
+
BaseView,
|
|
19
|
+
CallbackQueryReturnManager,
|
|
20
|
+
CallbackQueryView,
|
|
21
|
+
CompositionDispatch,
|
|
22
|
+
Context,
|
|
23
|
+
Dispatch,
|
|
7
24
|
FuncHandler,
|
|
25
|
+
InlineQueryReturnManager,
|
|
26
|
+
Manager,
|
|
27
|
+
MessageReplyHandler,
|
|
28
|
+
MessageReturnManager,
|
|
8
29
|
MessageView,
|
|
9
|
-
|
|
10
|
-
|
|
30
|
+
ViewBox,
|
|
31
|
+
WaiterMachine,
|
|
32
|
+
register_manager,
|
|
11
33
|
)
|
|
12
|
-
from .
|
|
13
|
-
from .
|
|
14
|
-
from .rules import ABCRule, ABCMessageRule
|
|
34
|
+
from .polling import ABCPolling, Polling
|
|
35
|
+
from .rules import ABCRule, CallbackQueryRule, MessageRule
|
|
15
36
|
from .scenario import ABCScenario, Checkbox, SingleChoice
|
|
37
|
+
|
|
38
|
+
__all__ = (
|
|
39
|
+
"ABCDispatch",
|
|
40
|
+
"ABCHandler",
|
|
41
|
+
"ABCMiddleware",
|
|
42
|
+
"ABCPolling",
|
|
43
|
+
"ABCReturnManager",
|
|
44
|
+
"ABCRule",
|
|
45
|
+
"ABCScenario",
|
|
46
|
+
"ABCStateView",
|
|
47
|
+
"ABCView",
|
|
48
|
+
"BaseCute",
|
|
49
|
+
"BaseReturnManager",
|
|
50
|
+
"BaseStateView",
|
|
51
|
+
"BaseView",
|
|
52
|
+
"CallbackQueryCute",
|
|
53
|
+
"CallbackQueryReturnManager",
|
|
54
|
+
"CallbackQueryRule",
|
|
55
|
+
"CallbackQueryView",
|
|
56
|
+
"Checkbox",
|
|
57
|
+
"CompositionDispatch",
|
|
58
|
+
"Context",
|
|
59
|
+
"Dispatch",
|
|
60
|
+
"FuncHandler",
|
|
61
|
+
"InlineQueryCute",
|
|
62
|
+
"InlineQueryReturnManager",
|
|
63
|
+
"Manager",
|
|
64
|
+
"MessageCute",
|
|
65
|
+
"MessageReplyHandler",
|
|
66
|
+
"MessageReturnManager",
|
|
67
|
+
"MessageRule",
|
|
68
|
+
"MessageView",
|
|
69
|
+
"Polling",
|
|
70
|
+
"SingleChoice",
|
|
71
|
+
"Telegrinder",
|
|
72
|
+
"UpdateCute",
|
|
73
|
+
"ViewBox",
|
|
74
|
+
"WaiterMachine",
|
|
75
|
+
"register_manager",
|
|
76
|
+
)
|
telegrinder/bot/bot.py
CHANGED
|
@@ -1,53 +1,59 @@
|
|
|
1
|
-
import
|
|
1
|
+
import typing_extensions as typing
|
|
2
2
|
|
|
3
3
|
from telegrinder.api import API
|
|
4
|
-
from telegrinder.bot.polling import ABCPolling, Polling
|
|
5
4
|
from telegrinder.bot.dispatch import ABCDispatch, Dispatch
|
|
5
|
+
from telegrinder.bot.polling import ABCPolling, Polling
|
|
6
6
|
from telegrinder.modules import logger
|
|
7
|
-
import
|
|
7
|
+
from telegrinder.tools.loop_wrapper import ABCLoopWrapper, LoopWrapper
|
|
8
|
+
|
|
9
|
+
DispatchT = typing.TypeVar("DispatchT", bound=ABCDispatch, default=Dispatch)
|
|
10
|
+
PollingT = typing.TypeVar("PollingT", bound=ABCPolling, default=Polling)
|
|
11
|
+
LoopWrapperT = typing.TypeVar("LoopWrapperT", bound=ABCLoopWrapper, default=LoopWrapper)
|
|
12
|
+
|
|
8
13
|
|
|
14
|
+
class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
|
|
15
|
+
dispatch: DispatchT
|
|
16
|
+
polling: PollingT
|
|
17
|
+
loop_wrapper: LoopWrapperT
|
|
9
18
|
|
|
10
|
-
class Telegrinder:
|
|
11
19
|
def __init__(
|
|
12
20
|
self,
|
|
13
21
|
api: API,
|
|
14
|
-
|
|
15
|
-
|
|
22
|
+
*,
|
|
23
|
+
polling: PollingT | None = None,
|
|
24
|
+
dispatch: DispatchT | None = None,
|
|
25
|
+
loop_wrapper: LoopWrapperT | None = None,
|
|
16
26
|
):
|
|
17
27
|
self.api = api
|
|
18
|
-
self.
|
|
19
|
-
self.
|
|
28
|
+
self.dispatch = dispatch or Dispatch() # type: ignore
|
|
29
|
+
self.polling = polling or Polling(api) # type: ignore
|
|
30
|
+
self.loop_wrapper = loop_wrapper or LoopWrapper() # type: ignore
|
|
20
31
|
|
|
21
32
|
@property
|
|
22
|
-
def on(self) ->
|
|
23
|
-
return self.dispatch
|
|
33
|
+
def on(self) -> DispatchT:
|
|
34
|
+
return self.dispatch
|
|
24
35
|
|
|
25
36
|
async def reset_webhook(self) -> None:
|
|
26
37
|
if not (await self.api.get_webhook_info()).unwrap().url:
|
|
27
38
|
return
|
|
28
|
-
|
|
29
39
|
await self.api.delete_webhook()
|
|
30
40
|
|
|
31
41
|
async def run_polling(self, offset: int = 0, skip_updates: bool = False) -> None:
|
|
32
42
|
if skip_updates:
|
|
33
|
-
logger.debug("
|
|
43
|
+
logger.debug("Dropping pending updates")
|
|
34
44
|
await self.reset_webhook()
|
|
35
45
|
await self.api.delete_webhook(drop_pending_updates=True)
|
|
36
46
|
self.polling.offset = offset
|
|
37
47
|
|
|
38
|
-
loop = asyncio.get_running_loop()
|
|
39
|
-
assert loop, "No running loop"
|
|
40
|
-
|
|
41
48
|
async for updates in self.polling.listen():
|
|
42
49
|
for update in updates:
|
|
43
|
-
logger.debug("
|
|
44
|
-
|
|
50
|
+
logger.debug("Received update (update_id={})", update.update_id)
|
|
51
|
+
self.loop_wrapper.add_task(self.dispatch.feed(update, self.api))
|
|
45
52
|
|
|
46
53
|
def run_forever(self, offset: int = 0, skip_updates: bool = False) -> None:
|
|
47
|
-
logger.debug("
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
logger.info("KeyboardInterrupt")
|
|
54
|
+
logger.debug("Running blocking polling (id={})", self.api.id)
|
|
55
|
+
self.loop_wrapper.add_task(self.run_polling(offset, skip_updates=skip_updates))
|
|
56
|
+
self.loop_wrapper.run_event_loop()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
__all__ = ("Telegrinder",)
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
-
from .
|
|
1
|
+
from .base import BaseCute
|
|
2
2
|
from .callback_query import CallbackQueryCute
|
|
3
3
|
from .inline_query import InlineQueryCute
|
|
4
|
+
from .message import MessageCute
|
|
5
|
+
from .update import UpdateCute
|
|
6
|
+
|
|
7
|
+
__all__ = (
|
|
8
|
+
"BaseCute",
|
|
9
|
+
"CallbackQueryCute",
|
|
10
|
+
"InlineQueryCute",
|
|
11
|
+
"MessageCute",
|
|
12
|
+
"UpdateCute",
|
|
13
|
+
)
|