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/tools/__init__.py
CHANGED
|
@@ -1,5 +1,166 @@
|
|
|
1
|
-
from .
|
|
2
|
-
from .
|
|
1
|
+
from .buttons import BaseButton
|
|
2
|
+
from .error_handler import ABCErrorHandler, Catcher, ErrorHandler
|
|
3
|
+
from .formatting import (
|
|
4
|
+
BaseSpecFormat,
|
|
5
|
+
ChannelBoostLink,
|
|
6
|
+
FormatString,
|
|
7
|
+
HTMLFormatter,
|
|
8
|
+
InviteChatLink,
|
|
9
|
+
Link,
|
|
10
|
+
Mention,
|
|
11
|
+
PreCode,
|
|
12
|
+
ResolveDomain,
|
|
13
|
+
SpecialFormat,
|
|
14
|
+
StartBotLink,
|
|
15
|
+
StartGroupLink,
|
|
16
|
+
TgEmoji,
|
|
17
|
+
block_quote,
|
|
18
|
+
bold,
|
|
19
|
+
channel_boost_link,
|
|
20
|
+
code_inline,
|
|
21
|
+
escape,
|
|
22
|
+
get_channel_boost_link,
|
|
23
|
+
get_invite_chat_link,
|
|
24
|
+
get_mention_link,
|
|
25
|
+
get_resolve_domain_link,
|
|
26
|
+
get_start_bot_link,
|
|
27
|
+
get_start_group_link,
|
|
28
|
+
invite_chat_link,
|
|
29
|
+
italic,
|
|
30
|
+
link,
|
|
31
|
+
mention,
|
|
32
|
+
pre_code,
|
|
33
|
+
resolve_domain,
|
|
34
|
+
spoiler,
|
|
35
|
+
start_bot_link,
|
|
36
|
+
start_group_link,
|
|
37
|
+
strike,
|
|
38
|
+
tg_emoji,
|
|
39
|
+
underline,
|
|
40
|
+
)
|
|
41
|
+
from .global_context import (
|
|
42
|
+
ABCGlobalContext,
|
|
43
|
+
CtxVar,
|
|
44
|
+
GlobalContext,
|
|
45
|
+
GlobalCtxVar,
|
|
46
|
+
TelegrinderCtx,
|
|
47
|
+
ctx_var,
|
|
48
|
+
)
|
|
49
|
+
from .i18n import (
|
|
50
|
+
ABCI18n,
|
|
51
|
+
ABCTranslator,
|
|
52
|
+
ABCTranslatorMiddleware,
|
|
53
|
+
I18nEnum,
|
|
54
|
+
SimpleI18n,
|
|
55
|
+
SimpleTranslator,
|
|
56
|
+
)
|
|
57
|
+
from .inline_query import (
|
|
58
|
+
inline_query_article,
|
|
59
|
+
inline_query_audio,
|
|
60
|
+
inline_query_cached_audio,
|
|
61
|
+
inline_query_cached_document,
|
|
62
|
+
inline_query_cached_gif,
|
|
63
|
+
inline_query_cached_mpeg4_gif,
|
|
64
|
+
inline_query_cached_photo,
|
|
65
|
+
inline_query_cached_sticker,
|
|
66
|
+
inline_query_cached_video,
|
|
67
|
+
inline_query_cached_voice,
|
|
68
|
+
inline_query_contact,
|
|
69
|
+
inline_query_document,
|
|
70
|
+
inline_query_game,
|
|
71
|
+
inline_query_gif,
|
|
72
|
+
inline_query_location,
|
|
73
|
+
inline_query_mpeg4_gif,
|
|
74
|
+
inline_query_photo,
|
|
75
|
+
inline_query_venue,
|
|
76
|
+
inline_query_video,
|
|
77
|
+
inline_query_voice,
|
|
78
|
+
input_contact_message_content,
|
|
79
|
+
input_invoice_message_content,
|
|
80
|
+
input_location_message_content,
|
|
81
|
+
input_text_message_content,
|
|
82
|
+
input_venue_message_content,
|
|
83
|
+
)
|
|
3
84
|
from .kb_set import KeyboardSetBase, KeyboardSetYAML
|
|
4
|
-
from .
|
|
5
|
-
|
|
85
|
+
from .keyboard import (
|
|
86
|
+
AnyMarkup,
|
|
87
|
+
Button,
|
|
88
|
+
InlineButton,
|
|
89
|
+
InlineKeyboard,
|
|
90
|
+
Keyboard,
|
|
91
|
+
RowButtons,
|
|
92
|
+
keyboard_remove,
|
|
93
|
+
)
|
|
94
|
+
from .loop_wrapper import ABCLoopWrapper, DelayedTask, LoopWrapper
|
|
95
|
+
from .magic import magic_bundle, resolve_arg_names
|
|
96
|
+
from .parse_mode import ParseMode
|
|
97
|
+
|
|
98
|
+
__all__ = (
|
|
99
|
+
"ABCErrorHandler",
|
|
100
|
+
"ABCGlobalContext",
|
|
101
|
+
"ABCI18n",
|
|
102
|
+
"ABCLoopWrapper",
|
|
103
|
+
"ABCTranslator",
|
|
104
|
+
"ABCTranslatorMiddleware",
|
|
105
|
+
"AnyMarkup",
|
|
106
|
+
"BaseButton",
|
|
107
|
+
"BaseSpecFormat",
|
|
108
|
+
"Button",
|
|
109
|
+
"Catcher",
|
|
110
|
+
"ChannelBoostLink",
|
|
111
|
+
"CtxVar",
|
|
112
|
+
"DelayedTask",
|
|
113
|
+
"ErrorHandler",
|
|
114
|
+
"FormatString",
|
|
115
|
+
"GlobalContext",
|
|
116
|
+
"GlobalCtxVar",
|
|
117
|
+
"HTMLFormatter",
|
|
118
|
+
"I18nEnum",
|
|
119
|
+
"InlineButton",
|
|
120
|
+
"InlineKeyboard",
|
|
121
|
+
"InviteChatLink",
|
|
122
|
+
"Keyboard",
|
|
123
|
+
"KeyboardSetBase",
|
|
124
|
+
"KeyboardSetYAML",
|
|
125
|
+
"Link",
|
|
126
|
+
"LoopWrapper",
|
|
127
|
+
"Mention",
|
|
128
|
+
"ParseMode",
|
|
129
|
+
"PreCode",
|
|
130
|
+
"ResolveDomain",
|
|
131
|
+
"RowButtons",
|
|
132
|
+
"SimpleI18n",
|
|
133
|
+
"SimpleTranslator",
|
|
134
|
+
"SpecialFormat",
|
|
135
|
+
"StartBotLink",
|
|
136
|
+
"StartGroupLink",
|
|
137
|
+
"TelegrinderCtx",
|
|
138
|
+
"TgEmoji",
|
|
139
|
+
"block_quote",
|
|
140
|
+
"bold",
|
|
141
|
+
"channel_boost_link",
|
|
142
|
+
"code_inline",
|
|
143
|
+
"ctx_var",
|
|
144
|
+
"escape",
|
|
145
|
+
"get_channel_boost_link",
|
|
146
|
+
"get_invite_chat_link",
|
|
147
|
+
"get_mention_link",
|
|
148
|
+
"get_resolve_domain_link",
|
|
149
|
+
"get_start_bot_link",
|
|
150
|
+
"get_start_group_link",
|
|
151
|
+
"invite_chat_link",
|
|
152
|
+
"italic",
|
|
153
|
+
"keyboard_remove",
|
|
154
|
+
"link",
|
|
155
|
+
"magic_bundle",
|
|
156
|
+
"mention",
|
|
157
|
+
"pre_code",
|
|
158
|
+
"resolve_arg_names",
|
|
159
|
+
"resolve_domain",
|
|
160
|
+
"spoiler",
|
|
161
|
+
"start_bot_link",
|
|
162
|
+
"start_group_link",
|
|
163
|
+
"strike",
|
|
164
|
+
"tg_emoji",
|
|
165
|
+
"underline",
|
|
166
|
+
)
|
telegrinder/tools/buttons.py
CHANGED
|
@@ -1,51 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
1
|
+
import dataclasses
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
import msgspec
|
|
5
|
+
|
|
6
|
+
from telegrinder.model import encoder
|
|
7
|
+
|
|
8
|
+
ButtonT = typing.TypeVar("ButtonT", bound="BaseButton")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@typing.runtime_checkable
|
|
12
|
+
class DataclassInstance(typing.Protocol):
|
|
13
|
+
__dataclass_fields__: typing.ClassVar[dict[str, dataclasses.Field[typing.Any]]]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclasses.dataclass
|
|
17
|
+
class BaseButton:
|
|
18
|
+
def get_data(self) -> dict[str, typing.Any]:
|
|
19
|
+
return {
|
|
20
|
+
k: v
|
|
21
|
+
if k != "callback_data" or isinstance(v, str)
|
|
22
|
+
else encoder.encode(v)
|
|
23
|
+
for k, v in dataclasses.asdict(self).items()
|
|
24
|
+
if v is not None
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class RowButtons(typing.Generic[ButtonT]):
|
|
29
|
+
buttons: list[ButtonT]
|
|
30
|
+
auto_row: bool
|
|
31
|
+
|
|
32
|
+
def __init__(self, *buttons: ButtonT, auto_row: bool = True) -> None:
|
|
33
|
+
self.buttons = list(buttons)
|
|
34
|
+
self.auto_row = auto_row
|
|
35
|
+
|
|
36
|
+
def get_data(self) -> list[dict[str, typing.Any]]:
|
|
37
|
+
return [b.get_data() for b in self.buttons]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclasses.dataclass
|
|
41
|
+
class Button(BaseButton):
|
|
42
|
+
text: str
|
|
43
|
+
_: dataclasses.KW_ONLY
|
|
44
|
+
request_contact: bool = False
|
|
45
|
+
request_location: bool = False
|
|
46
|
+
request_poll: dict | None = None
|
|
47
|
+
web_app: dict | None = None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclasses.dataclass
|
|
51
|
+
class InlineButton(BaseButton):
|
|
52
|
+
text: str
|
|
53
|
+
_: dataclasses.KW_ONLY
|
|
54
|
+
url: str | None = None
|
|
55
|
+
login_url: dict | None = None
|
|
56
|
+
pay: bool | None = None
|
|
57
|
+
callback_data: typing.Union[
|
|
58
|
+
str,
|
|
59
|
+
dict[str, typing.Any],
|
|
60
|
+
DataclassInstance,
|
|
61
|
+
msgspec.Struct,
|
|
62
|
+
] | None = None
|
|
63
|
+
callback_game: dict | None = None
|
|
64
|
+
switch_inline_query: str | None = None
|
|
65
|
+
switch_inline_query_current_chat: str | None = None
|
|
66
|
+
web_app: dict | None = None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
__all__ = (
|
|
70
|
+
"BaseButton",
|
|
71
|
+
"Button",
|
|
72
|
+
"DataclassInstance",
|
|
73
|
+
"InlineButton",
|
|
74
|
+
"RowButtons",
|
|
75
|
+
)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
|
|
4
|
+
from fntypes.result import Result
|
|
5
|
+
|
|
6
|
+
from telegrinder.api import ABCAPI
|
|
7
|
+
from telegrinder.bot.cute_types import BaseCute
|
|
8
|
+
from telegrinder.bot.dispatch.context import Context
|
|
9
|
+
|
|
10
|
+
EventT = typing.TypeVar("EventT", bound=BaseCute)
|
|
11
|
+
Handler = typing.Callable[typing.Concatenate[EventT, ...], typing.Awaitable[typing.Any]]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ABCErrorHandler(ABC, typing.Generic[EventT]):
|
|
15
|
+
@abstractmethod
|
|
16
|
+
def catch(self) -> typing.Callable[[typing.Callable], typing.Callable]:
|
|
17
|
+
...
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
async def run(
|
|
21
|
+
self,
|
|
22
|
+
handler: Handler[EventT],
|
|
23
|
+
event: EventT,
|
|
24
|
+
api: ABCAPI,
|
|
25
|
+
ctx: Context,
|
|
26
|
+
) -> Result[typing.Any, typing.Any]:
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
__all__ = ("ABCErrorHandler",)
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from fntypes.result import Error, Ok, Result
|
|
5
|
+
|
|
6
|
+
from telegrinder.api import ABCAPI
|
|
7
|
+
from telegrinder.bot.dispatch.context import Context
|
|
8
|
+
from telegrinder.modules import logger
|
|
9
|
+
from telegrinder.tools.magic import magic_bundle
|
|
10
|
+
|
|
11
|
+
from .abc import ABCErrorHandler, EventT, Handler
|
|
12
|
+
|
|
13
|
+
F = typing.TypeVar("F", bound="FuncCatcher")
|
|
14
|
+
ExceptionT = typing.TypeVar("ExceptionT", bound=BaseException, contravariant=True)
|
|
15
|
+
FuncCatcher = typing.Callable[typing.Concatenate[ExceptionT, ...], typing.Awaitable[typing.Any]]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclasses.dataclass(frozen=True)
|
|
19
|
+
class Catcher(typing.Generic[EventT]):
|
|
20
|
+
func: FuncCatcher
|
|
21
|
+
_: dataclasses.KW_ONLY
|
|
22
|
+
exceptions: list[type[BaseException] | BaseException] = dataclasses.field(
|
|
23
|
+
default_factory=lambda: []
|
|
24
|
+
)
|
|
25
|
+
logging: bool = dataclasses.field(default=False)
|
|
26
|
+
raise_exception: bool = dataclasses.field(default=False)
|
|
27
|
+
ignore_errors: bool = dataclasses.field(default=False)
|
|
28
|
+
|
|
29
|
+
def match_exception(self, exception: BaseException) -> bool:
|
|
30
|
+
for exc in self.exceptions:
|
|
31
|
+
if isinstance(exc, type) and type(exception) == exc:
|
|
32
|
+
return True
|
|
33
|
+
if isinstance(exc, object) and type(exception) == type(exc):
|
|
34
|
+
return True if not exc.args else exc.args == exception.args
|
|
35
|
+
return False
|
|
36
|
+
|
|
37
|
+
async def __call__(
|
|
38
|
+
self,
|
|
39
|
+
handler: Handler[EventT],
|
|
40
|
+
event: EventT,
|
|
41
|
+
api: ABCAPI,
|
|
42
|
+
ctx: Context,
|
|
43
|
+
) -> Result[typing.Any, typing.Any]:
|
|
44
|
+
try:
|
|
45
|
+
result = Ok(await handler(event, **magic_bundle(handler, ctx))) # type: ignore
|
|
46
|
+
except BaseException as exc:
|
|
47
|
+
logger.debug(
|
|
48
|
+
"Exception {!r} occurred while running handler {!r}. Matching "
|
|
49
|
+
"exceptions it with exception that can be caught by the catcher {!r}...",
|
|
50
|
+
exc.__class__.__name__,
|
|
51
|
+
handler.__name__,
|
|
52
|
+
self.func.__name__,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
if self.match_exception(exc):
|
|
56
|
+
logger.debug(
|
|
57
|
+
"Catcher {!r} caught an exception in handler {!r}, "
|
|
58
|
+
"running catcher...".format(
|
|
59
|
+
self.func.__name__,
|
|
60
|
+
handler.__name__,
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
result = Ok(
|
|
64
|
+
await self.func(
|
|
65
|
+
exc,
|
|
66
|
+
**magic_bundle(
|
|
67
|
+
self.func,
|
|
68
|
+
{"event": event, "api": api} | ctx # type: ignore
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
logger.debug("Failed to match exception {!r}!", exc.__class__.__name__)
|
|
74
|
+
result = Error(exc)
|
|
75
|
+
|
|
76
|
+
logger.debug(
|
|
77
|
+
"Catcher {!r} {} with result: {!r}",
|
|
78
|
+
self.func.__name__,
|
|
79
|
+
"completed" if result else "failed",
|
|
80
|
+
result,
|
|
81
|
+
)
|
|
82
|
+
return result
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class ErrorHandler(ABCErrorHandler[EventT]):
|
|
86
|
+
def __init__(self, __catcher: Catcher[EventT] | None = None):
|
|
87
|
+
self.catcher = __catcher
|
|
88
|
+
|
|
89
|
+
def __repr__(self) -> str:
|
|
90
|
+
return f"<ErrorHandler: {self.catcher!r}>"
|
|
91
|
+
|
|
92
|
+
def catch(
|
|
93
|
+
self,
|
|
94
|
+
*exceptions: type[BaseException] | BaseException,
|
|
95
|
+
logging: bool = False,
|
|
96
|
+
raise_exception: bool = False,
|
|
97
|
+
ignore_errors: bool = False,
|
|
98
|
+
):
|
|
99
|
+
"""Catch an exception while the handler is running.
|
|
100
|
+
:param logging: Error logging in stderr.
|
|
101
|
+
:param raise_exception: Raise an exception if the catcher hasn't started.
|
|
102
|
+
:param ignore_errors: Ignore errors that may occur in the catcher.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
def decorator(func: F) -> F:
|
|
106
|
+
if not self.catcher:
|
|
107
|
+
self.catcher = Catcher(
|
|
108
|
+
func,
|
|
109
|
+
exceptions=list(exceptions),
|
|
110
|
+
logging=logging,
|
|
111
|
+
raise_exception=raise_exception,
|
|
112
|
+
ignore_errors=ignore_errors,
|
|
113
|
+
)
|
|
114
|
+
return func
|
|
115
|
+
return decorator
|
|
116
|
+
|
|
117
|
+
async def run(
|
|
118
|
+
self,
|
|
119
|
+
handler: Handler[EventT],
|
|
120
|
+
event: EventT,
|
|
121
|
+
api: ABCAPI,
|
|
122
|
+
ctx: Context,
|
|
123
|
+
) -> Result[typing.Any, typing.Any]:
|
|
124
|
+
if not self.catcher:
|
|
125
|
+
return Ok(await handler(event, **magic_bundle(handler, ctx))) # type: ignore
|
|
126
|
+
|
|
127
|
+
ok_none = Ok(None)
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
result = await self.catcher(handler, event, api, ctx)
|
|
131
|
+
except BaseException as e:
|
|
132
|
+
error_msg = "Exception {} was occurred during the running catcher {!r}.".format(
|
|
133
|
+
repr(e.__class__.__name__)
|
|
134
|
+
if not e.args
|
|
135
|
+
else f"{e.__class__.__name__!r}: {str(e)!r}",
|
|
136
|
+
self.catcher.func.__name__,
|
|
137
|
+
)
|
|
138
|
+
result = ok_none
|
|
139
|
+
|
|
140
|
+
if not self.catcher.ignore_errors:
|
|
141
|
+
return Error(error_msg)
|
|
142
|
+
if self.catcher.logging:
|
|
143
|
+
logger.error(error_msg)
|
|
144
|
+
|
|
145
|
+
if self.catcher.raise_exception and not result:
|
|
146
|
+
return result
|
|
147
|
+
|
|
148
|
+
if self.catcher.logging and not result:
|
|
149
|
+
logger.error(
|
|
150
|
+
"Catcher {!r} failed with error: {!r}",
|
|
151
|
+
self.catcher.func.__name__,
|
|
152
|
+
result.error,
|
|
153
|
+
)
|
|
154
|
+
return ok_none
|
|
155
|
+
|
|
156
|
+
return result or ok_none
|
|
@@ -1,3 +1,81 @@
|
|
|
1
|
-
from .
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
from .html import (
|
|
2
|
+
FormatString,
|
|
3
|
+
HTMLFormatter,
|
|
4
|
+
block_quote,
|
|
5
|
+
bold,
|
|
6
|
+
channel_boost_link,
|
|
7
|
+
code_inline,
|
|
8
|
+
escape,
|
|
9
|
+
invite_chat_link,
|
|
10
|
+
italic,
|
|
11
|
+
link,
|
|
12
|
+
mention,
|
|
13
|
+
pre_code,
|
|
14
|
+
resolve_domain,
|
|
15
|
+
spoiler,
|
|
16
|
+
start_bot_link,
|
|
17
|
+
start_group_link,
|
|
18
|
+
strike,
|
|
19
|
+
tg_emoji,
|
|
20
|
+
underline,
|
|
21
|
+
)
|
|
22
|
+
from .links import (
|
|
23
|
+
get_channel_boost_link,
|
|
24
|
+
get_invite_chat_link,
|
|
25
|
+
get_mention_link,
|
|
26
|
+
get_resolve_domain_link,
|
|
27
|
+
get_start_bot_link,
|
|
28
|
+
get_start_group_link,
|
|
29
|
+
)
|
|
30
|
+
from .spec_html_formats import (
|
|
31
|
+
BaseSpecFormat,
|
|
32
|
+
ChannelBoostLink,
|
|
33
|
+
InviteChatLink,
|
|
34
|
+
Link,
|
|
35
|
+
Mention,
|
|
36
|
+
PreCode,
|
|
37
|
+
ResolveDomain,
|
|
38
|
+
SpecialFormat,
|
|
39
|
+
StartBotLink,
|
|
40
|
+
StartGroupLink,
|
|
41
|
+
TgEmoji,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
__all__ = (
|
|
45
|
+
"BaseSpecFormat",
|
|
46
|
+
"ChannelBoostLink",
|
|
47
|
+
"FormatString",
|
|
48
|
+
"HTMLFormatter",
|
|
49
|
+
"InviteChatLink",
|
|
50
|
+
"Link",
|
|
51
|
+
"Mention",
|
|
52
|
+
"PreCode",
|
|
53
|
+
"ResolveDomain",
|
|
54
|
+
"SpecialFormat",
|
|
55
|
+
"StartBotLink",
|
|
56
|
+
"StartGroupLink",
|
|
57
|
+
"TgEmoji",
|
|
58
|
+
"block_quote",
|
|
59
|
+
"bold",
|
|
60
|
+
"channel_boost_link",
|
|
61
|
+
"code_inline",
|
|
62
|
+
"escape",
|
|
63
|
+
"get_channel_boost_link",
|
|
64
|
+
"get_invite_chat_link",
|
|
65
|
+
"get_mention_link",
|
|
66
|
+
"get_resolve_domain_link",
|
|
67
|
+
"get_start_bot_link",
|
|
68
|
+
"get_start_group_link",
|
|
69
|
+
"invite_chat_link",
|
|
70
|
+
"italic",
|
|
71
|
+
"link",
|
|
72
|
+
"mention",
|
|
73
|
+
"pre_code",
|
|
74
|
+
"resolve_domain",
|
|
75
|
+
"spoiler",
|
|
76
|
+
"start_bot_link",
|
|
77
|
+
"start_group_link",
|
|
78
|
+
"strike",
|
|
79
|
+
"tg_emoji",
|
|
80
|
+
"underline",
|
|
81
|
+
)
|