telegrinder 0.1.dev20__py3-none-any.whl → 0.1.dev158__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 +29 -24
- 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 +47 -0
- telegrinder/bot/cute_types/callback_query.py +64 -14
- telegrinder/bot/cute_types/inline_query.py +22 -16
- telegrinder/bot/cute_types/message.py +145 -53
- telegrinder/bot/cute_types/update.py +23 -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 +121 -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 +43 -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 +2 -0
- telegrinder/client/abc.py +8 -21
- telegrinder/client/aiohttp.py +30 -21
- telegrinder/model.py +68 -37
- telegrinder/modules.py +189 -21
- telegrinder/msgspec_json.py +14 -0
- telegrinder/msgspec_utils.py +207 -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 +165 -4
- telegrinder/tools/buttons.py +75 -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/inline_query.py +684 -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 +651 -0
- telegrinder/types/methods.py +3920 -1251
- telegrinder/types/objects.py +4702 -1718
- {telegrinder-0.1.dev20.dist-info → telegrinder-0.1.dev158.dist-info}/LICENSE +2 -1
- telegrinder-0.1.dev158.dist-info/METADATA +108 -0
- telegrinder-0.1.dev158.dist-info/RECORD +126 -0
- {telegrinder-0.1.dev20.dist-info → telegrinder-0.1.dev158.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:token'.")
|
|
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:
|
|
33
|
-
) -> Result[
|
|
45
|
+
data: dict | None = None,
|
|
46
|
+
) -> Result[list | dict | 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:
|
|
53
|
+
data: dict | 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,15 +1,17 @@
|
|
|
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 convert, decoder
|
|
7
9
|
from telegrinder.types.methods import APIMethods
|
|
8
|
-
from telegrinder.model import convert
|
|
9
|
-
from telegrinder.api.response import APIResponse
|
|
10
10
|
|
|
11
|
+
from .abc import ABCAPI, APIError, Token
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
|
|
14
|
+
def compose_data(client: ABCClient, data: dict[str, typing.Any]) -> typing.Any:
|
|
13
15
|
data = {k: convert(v) for k, v in data.items()}
|
|
14
16
|
if any(isinstance(v, tuple) for v in data.values()):
|
|
15
17
|
data = client.get_form(data)
|
|
@@ -17,16 +19,16 @@ def compose_data(client: ABCClient, data: dict) -> typing.Any:
|
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
class API(ABCAPI, APIMethods):
|
|
20
|
-
API_URL = "https://api.telegram.org/"
|
|
22
|
+
API_URL: typing.ClassVar[str] = "https://api.telegram.org/"
|
|
21
23
|
|
|
22
|
-
def __init__(self, token: Token, http:
|
|
24
|
+
def __init__(self, token: Token, *, http: ABCClient | None = None):
|
|
23
25
|
self.token = token
|
|
24
26
|
self.http = http or AiohttpClient()
|
|
25
27
|
super().__init__(self)
|
|
26
28
|
|
|
27
29
|
@property
|
|
28
30
|
def id(self) -> int:
|
|
29
|
-
return
|
|
31
|
+
return self.token.bot_id
|
|
30
32
|
|
|
31
33
|
@property
|
|
32
34
|
def request_url(self) -> str:
|
|
@@ -35,27 +37,30 @@ class API(ABCAPI, APIMethods):
|
|
|
35
37
|
async def request(
|
|
36
38
|
self,
|
|
37
39
|
method: str,
|
|
38
|
-
data:
|
|
39
|
-
) -> Result[
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
data: dict | None = None,
|
|
41
|
+
) -> Result[dict | list | bool, APIError]:
|
|
42
|
+
response = await self.http.request_json(
|
|
43
|
+
url=self.request_url + method,
|
|
44
|
+
data=compose_data(self.http, data or {})
|
|
45
|
+
)
|
|
42
46
|
if response.get("ok"):
|
|
43
47
|
assert "result" in response
|
|
44
|
-
return
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
return Ok(response["result"])
|
|
49
|
+
return Error(APIError(
|
|
50
|
+
code=response.get("error_code", 0),
|
|
51
|
+
error=response.get("description"),
|
|
52
|
+
))
|
|
48
53
|
|
|
49
54
|
async def request_raw(
|
|
50
55
|
self,
|
|
51
56
|
method: str,
|
|
52
|
-
data: typing.
|
|
57
|
+
data: dict[str, typing.Any] | None = None,
|
|
53
58
|
) -> Result[msgspec.Raw, APIError]:
|
|
54
|
-
data = compose_data(self.http, data)
|
|
55
59
|
response_bytes = await self.http.request_bytes(
|
|
56
|
-
self.request_url + method,
|
|
60
|
+
url=self.request_url + method,
|
|
61
|
+
data=compose_data(self.http, data or {}),
|
|
57
62
|
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
return decoder.decode(response_bytes, type=APIResponse).to_result()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
__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
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
from telegrinder.api import ABCAPI, API
|
|
4
|
+
from telegrinder.model import Model
|
|
5
|
+
|
|
6
|
+
UpdateT = typing.TypeVar("UpdateT", bound=Model)
|
|
7
|
+
|
|
8
|
+
if typing.TYPE_CHECKING:
|
|
9
|
+
|
|
10
|
+
class BaseCute(Model, typing.Generic[UpdateT]):
|
|
11
|
+
api: ABCAPI
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def from_update(cls, update: UpdateT, bound_api: ABCAPI) -> typing.Self:
|
|
15
|
+
...
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def ctx_api(self) -> API:
|
|
19
|
+
...
|
|
20
|
+
|
|
21
|
+
def to_dict(
|
|
22
|
+
self,
|
|
23
|
+
*,
|
|
24
|
+
exclude_fields: set[str] | None = None,
|
|
25
|
+
) -> dict[str, typing.Any]:
|
|
26
|
+
...
|
|
27
|
+
|
|
28
|
+
else:
|
|
29
|
+
|
|
30
|
+
class BaseCute(typing.Generic[UpdateT]):
|
|
31
|
+
api: ABCAPI
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def from_update(cls, update, bound_api):
|
|
35
|
+
return cls(**update.to_dict(), api=bound_api)
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def ctx_api(self):
|
|
39
|
+
assert isinstance(self.api, API)
|
|
40
|
+
return self.api
|
|
41
|
+
|
|
42
|
+
def to_dict(self, *, exclude_fields=None):
|
|
43
|
+
exclude_fields = exclude_fields or set()
|
|
44
|
+
return super().to_dict(exclude_fields={"api"} | exclude_fields)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
__all__ = ("BaseCute",)
|