telegrinder 0.1.dev159__py3-none-any.whl → 0.1.dev161__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 +4 -2
- telegrinder/api/__init__.py +0 -0
- telegrinder/api/abc.py +5 -0
- telegrinder/api/api.py +4 -4
- telegrinder/api/error.py +0 -0
- telegrinder/api/response.py +0 -0
- telegrinder/bot/__init__.py +0 -0
- telegrinder/bot/bot.py +0 -0
- telegrinder/bot/cute_types/__init__.py +0 -0
- telegrinder/bot/cute_types/base.py +0 -0
- telegrinder/bot/cute_types/callback_query.py +81 -85
- telegrinder/bot/cute_types/inline_query.py +36 -9
- telegrinder/bot/cute_types/message.py +524 -568
- telegrinder/bot/cute_types/update.py +0 -0
- telegrinder/bot/cute_types/utils.py +201 -453
- telegrinder/bot/dispatch/__init__.py +0 -0
- telegrinder/bot/dispatch/abc.py +0 -0
- telegrinder/bot/dispatch/composition.py +0 -0
- telegrinder/bot/dispatch/context.py +0 -0
- telegrinder/bot/dispatch/dispatch.py +0 -0
- telegrinder/bot/dispatch/handler/__init__.py +0 -0
- telegrinder/bot/dispatch/handler/abc.py +0 -0
- telegrinder/bot/dispatch/handler/func.py +1 -1
- telegrinder/bot/dispatch/handler/message_reply.py +0 -0
- telegrinder/bot/dispatch/middleware/__init__.py +0 -0
- telegrinder/bot/dispatch/middleware/abc.py +0 -0
- telegrinder/bot/dispatch/process.py +0 -0
- telegrinder/bot/dispatch/return_manager/__init__.py +0 -0
- telegrinder/bot/dispatch/return_manager/abc.py +0 -0
- telegrinder/bot/dispatch/return_manager/callback_query.py +0 -0
- telegrinder/bot/dispatch/return_manager/inline_query.py +0 -0
- telegrinder/bot/dispatch/return_manager/message.py +0 -0
- telegrinder/bot/dispatch/view/__init__.py +0 -0
- telegrinder/bot/dispatch/view/abc.py +20 -16
- telegrinder/bot/dispatch/view/box.py +0 -0
- telegrinder/bot/dispatch/view/callback_query.py +0 -0
- telegrinder/bot/dispatch/view/inline_query.py +0 -0
- telegrinder/bot/dispatch/view/message.py +0 -0
- telegrinder/bot/dispatch/waiter_machine/__init__.py +0 -0
- telegrinder/bot/dispatch/waiter_machine/machine.py +0 -0
- telegrinder/bot/dispatch/waiter_machine/middleware.py +0 -0
- telegrinder/bot/dispatch/waiter_machine/short_state.py +0 -0
- telegrinder/bot/polling/__init__.py +0 -0
- telegrinder/bot/polling/abc.py +0 -0
- telegrinder/bot/polling/polling.py +7 -11
- telegrinder/bot/rules/__init__.py +0 -0
- telegrinder/bot/rules/abc.py +1 -1
- telegrinder/bot/rules/adapter/__init__.py +0 -0
- telegrinder/bot/rules/adapter/abc.py +0 -0
- telegrinder/bot/rules/adapter/errors.py +0 -0
- telegrinder/bot/rules/adapter/event.py +0 -0
- telegrinder/bot/rules/adapter/raw_update.py +0 -0
- telegrinder/bot/rules/callback_data.py +3 -11
- telegrinder/bot/rules/command.py +0 -0
- telegrinder/bot/rules/enum_text.py +0 -0
- telegrinder/bot/rules/func.py +0 -0
- telegrinder/bot/rules/fuzzy.py +0 -0
- telegrinder/bot/rules/inline.py +2 -1
- telegrinder/bot/rules/integer.py +0 -0
- telegrinder/bot/rules/is_from.py +0 -0
- telegrinder/bot/rules/markup.py +3 -1
- telegrinder/bot/rules/mention.py +0 -0
- telegrinder/bot/rules/message_entities.py +3 -1
- telegrinder/bot/rules/regex.py +1 -1
- telegrinder/bot/rules/rule_enum.py +0 -0
- telegrinder/bot/rules/start.py +0 -0
- telegrinder/bot/rules/text.py +0 -0
- telegrinder/bot/scenario/__init__.py +2 -2
- telegrinder/bot/scenario/abc.py +0 -0
- telegrinder/bot/scenario/checkbox.py +9 -13
- telegrinder/bot/scenario/choice.py +2 -2
- telegrinder/client/__init__.py +0 -0
- telegrinder/client/abc.py +0 -0
- telegrinder/client/aiohttp.py +0 -0
- telegrinder/model.py +35 -36
- telegrinder/modules.py +21 -11
- telegrinder/msgspec_json.py +0 -0
- telegrinder/msgspec_utils.py +2 -2
- telegrinder/node/__init__.py +0 -0
- telegrinder/node/attachment.py +0 -0
- telegrinder/node/base.py +0 -0
- telegrinder/node/composer.py +0 -0
- telegrinder/node/container.py +0 -0
- telegrinder/node/message.py +0 -0
- telegrinder/node/rule.py +0 -0
- telegrinder/node/source.py +0 -0
- telegrinder/node/text.py +0 -0
- telegrinder/node/tools/__init__.py +0 -0
- telegrinder/node/tools/generator.py +0 -0
- telegrinder/node/update.py +0 -0
- telegrinder/rules.py +0 -0
- telegrinder/tools/__init__.py +2 -3
- telegrinder/tools/buttons.py +0 -0
- telegrinder/tools/error_handler/__init__.py +2 -0
- telegrinder/tools/error_handler/abc.py +5 -1
- telegrinder/tools/error_handler/error.py +10 -0
- telegrinder/tools/error_handler/error_handler.py +100 -81
- telegrinder/tools/formatting/__init__.py +0 -0
- telegrinder/tools/formatting/html.py +0 -0
- telegrinder/tools/formatting/links.py +0 -0
- telegrinder/tools/formatting/spec_html_formats.py +0 -0
- telegrinder/tools/global_context/__init__.py +0 -0
- telegrinder/tools/global_context/abc.py +0 -0
- telegrinder/tools/global_context/global_context.py +65 -67
- telegrinder/tools/global_context/telegrinder_ctx.py +0 -0
- telegrinder/tools/i18n/__init__.py +0 -0
- telegrinder/tools/i18n/base.py +0 -0
- telegrinder/tools/i18n/middleware/__init__.py +0 -0
- telegrinder/tools/i18n/middleware/base.py +0 -0
- telegrinder/tools/i18n/simple.py +0 -0
- telegrinder/tools/kb_set/__init__.py +0 -0
- telegrinder/tools/kb_set/base.py +0 -0
- telegrinder/tools/kb_set/yaml.py +3 -3
- telegrinder/tools/keyboard.py +17 -26
- telegrinder/tools/loop_wrapper/__init__.py +0 -0
- telegrinder/tools/loop_wrapper/abc.py +0 -0
- telegrinder/tools/loop_wrapper/loop_wrapper.py +0 -0
- telegrinder/tools/magic.py +1 -1
- telegrinder/tools/parse_mode.py +0 -0
- telegrinder/types/__init__.py +0 -0
- telegrinder/types/enums.py +2 -0
- telegrinder/types/methods.py +477 -526
- telegrinder/types/objects.py +209 -97
- {telegrinder-0.1.dev159.dist-info → telegrinder-0.1.dev161.dist-info}/LICENSE +0 -0
- {telegrinder-0.1.dev159.dist-info → telegrinder-0.1.dev161.dist-info}/METADATA +9 -8
- {telegrinder-0.1.dev159.dist-info → telegrinder-0.1.dev161.dist-info}/RECORD +38 -37
- {telegrinder-0.1.dev159.dist-info → telegrinder-0.1.dev161.dist-info}/WHEEL +1 -1
|
File without changes
|
telegrinder/bot/dispatch/abc.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -36,7 +36,7 @@ class FuncHandler(ABCHandler[EventT], typing.Generic[EventT, F, ErrorHandlerT]):
|
|
|
36
36
|
|
|
37
37
|
@property
|
|
38
38
|
def on_error(self):
|
|
39
|
-
return self.error_handler.
|
|
39
|
+
return self.error_handler.register_catcher
|
|
40
40
|
|
|
41
41
|
async def check(self, api: ABCAPI, event: Update, ctx: Context | None = None) -> bool:
|
|
42
42
|
ctx = ctx or Context()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -18,6 +18,11 @@ from telegrinder.types.objects import Update
|
|
|
18
18
|
EventType = typing.TypeVar("EventType", bound=BaseCute)
|
|
19
19
|
MiddlewareT = typing.TypeVar("MiddlewareT", bound=ABCMiddleware)
|
|
20
20
|
|
|
21
|
+
FuncType: typing.TypeAlias = typing.Callable[
|
|
22
|
+
typing.Concatenate[EventType, ...],
|
|
23
|
+
typing.Coroutine[typing.Any, typing.Any, typing.Any],
|
|
24
|
+
]
|
|
25
|
+
|
|
21
26
|
|
|
22
27
|
class ABCView(ABC):
|
|
23
28
|
@abstractmethod
|
|
@@ -41,7 +46,7 @@ class ABCStateView(ABCView, typing.Generic[EventType]):
|
|
|
41
46
|
def __repr__(self) -> str:
|
|
42
47
|
return "<{!r}: {}>".format(
|
|
43
48
|
self.__class__.__name__,
|
|
44
|
-
", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
|
|
49
|
+
", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()),
|
|
45
50
|
)
|
|
46
51
|
|
|
47
52
|
|
|
@@ -56,10 +61,12 @@ class BaseView(ABCView, typing.Generic[EventType]):
|
|
|
56
61
|
for base in cls.__dict__.get("__orig_bases__", ()):
|
|
57
62
|
if issubclass(typing.get_origin(base) or base, ABCView):
|
|
58
63
|
for generic_type in typing.get_args(base):
|
|
59
|
-
if issubclass(
|
|
64
|
+
if issubclass(
|
|
65
|
+
typing.get_origin(generic_type) or generic_type, BaseCute
|
|
66
|
+
):
|
|
60
67
|
return Some(generic_type)
|
|
61
68
|
return Nothing()
|
|
62
|
-
|
|
69
|
+
|
|
63
70
|
@classmethod
|
|
64
71
|
def get_raw_event(cls, update: Update) -> Option[Model]:
|
|
65
72
|
match update.update_type:
|
|
@@ -74,13 +81,8 @@ class BaseView(ABCView, typing.Generic[EventType]):
|
|
|
74
81
|
is_blocking: bool = True,
|
|
75
82
|
error_handler: ErrorHandlerT | None = None,
|
|
76
83
|
):
|
|
77
|
-
def wrapper(
|
|
78
|
-
|
|
79
|
-
typing.Concatenate[EventType, ...],
|
|
80
|
-
typing.Coroutine,
|
|
81
|
-
]
|
|
82
|
-
):
|
|
83
|
-
func_handler = FuncHandler(
|
|
84
|
+
def wrapper(func: FuncType[EventType]):
|
|
85
|
+
func_handler = FuncHandler[EventType, FuncType[EventType], ErrorHandlerT](
|
|
84
86
|
func,
|
|
85
87
|
[*self.auto_rules, *rules],
|
|
86
88
|
is_blocking,
|
|
@@ -91,14 +93,14 @@ class BaseView(ABCView, typing.Generic[EventType]):
|
|
|
91
93
|
return func_handler
|
|
92
94
|
|
|
93
95
|
return wrapper
|
|
94
|
-
|
|
96
|
+
|
|
95
97
|
def register_middleware(self, *args: typing.Any, **kwargs: typing.Any):
|
|
96
|
-
def wrapper(cls: type[MiddlewareT]):
|
|
98
|
+
def wrapper(cls: type[MiddlewareT]) -> type[MiddlewareT]:
|
|
97
99
|
self.middlewares.append(cls(*args, **kwargs))
|
|
98
100
|
return cls
|
|
99
|
-
|
|
101
|
+
|
|
100
102
|
return wrapper
|
|
101
|
-
|
|
103
|
+
|
|
102
104
|
async def check(self, event: Update) -> bool:
|
|
103
105
|
match self.get_raw_event(event):
|
|
104
106
|
case Some(e) if issubclass(
|
|
@@ -110,10 +112,12 @@ class BaseView(ABCView, typing.Generic[EventType]):
|
|
|
110
112
|
return True
|
|
111
113
|
case _:
|
|
112
114
|
return False
|
|
113
|
-
|
|
115
|
+
|
|
114
116
|
async def process(self, event: Update, api: ABCAPI) -> bool:
|
|
115
117
|
return await process_inner(
|
|
116
|
-
self.get_event_type()
|
|
118
|
+
self.get_event_type()
|
|
119
|
+
.unwrap()
|
|
120
|
+
.from_update(
|
|
117
121
|
update=self.get_raw_event(event).unwrap(),
|
|
118
122
|
bound_api=api,
|
|
119
123
|
),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
telegrinder/bot/polling/abc.py
CHANGED
|
File without changes
|
|
@@ -71,16 +71,14 @@ class Polling(ABCPolling):
|
|
|
71
71
|
async def listen(self) -> typing.AsyncGenerator[list[Update], None]:
|
|
72
72
|
logger.debug("Listening polling")
|
|
73
73
|
reconn_counter = 0
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
while not self._stop:
|
|
76
76
|
try:
|
|
77
77
|
updates = await self.get_updates()
|
|
78
78
|
reconn_counter = 0
|
|
79
79
|
if not updates:
|
|
80
80
|
continue
|
|
81
|
-
updates_list: list[Update] = decoder.decode(
|
|
82
|
-
updates, type=list[Update]
|
|
83
|
-
)
|
|
81
|
+
updates_list: list[Update] = decoder.decode(updates, type=list[Update])
|
|
84
82
|
if updates_list:
|
|
85
83
|
yield updates_list
|
|
86
84
|
self.offset = updates_list[-1].update_id + 1
|
|
@@ -100,16 +98,14 @@ class Polling(ABCPolling):
|
|
|
100
98
|
self.stop()
|
|
101
99
|
exit(9)
|
|
102
100
|
else:
|
|
103
|
-
logger.warning(
|
|
101
|
+
logger.warning(
|
|
102
|
+
"Server disconnected, waiting 5 seconds to reconnetion...",
|
|
103
|
+
)
|
|
104
104
|
reconn_counter += 1
|
|
105
105
|
await asyncio.sleep(self.reconnection_timeout)
|
|
106
106
|
except aiohttp.ClientConnectorError:
|
|
107
|
-
logger.error(
|
|
108
|
-
|
|
109
|
-
"Please, check your internet connection."
|
|
110
|
-
)
|
|
111
|
-
self.stop()
|
|
112
|
-
exit(3)
|
|
107
|
+
logger.error("Client connection failed, attempted to reconnect...")
|
|
108
|
+
await asyncio.sleep(self.reconnection_timeout)
|
|
113
109
|
except BaseException as e:
|
|
114
110
|
logger.exception(e)
|
|
115
111
|
|
|
File without changes
|
telegrinder/bot/rules/abc.py
CHANGED
|
@@ -19,7 +19,7 @@ Update: typing.TypeAlias = UpdateCute
|
|
|
19
19
|
def with_caching_translations(func):
|
|
20
20
|
"""Should be used as decorator for .translate method. Caches rule translations."""
|
|
21
21
|
|
|
22
|
-
async def wrapper(self: "ABCRule", translator: ABCTranslator):
|
|
22
|
+
async def wrapper(self: "ABCRule[typing.Any]", translator: ABCTranslator):
|
|
23
23
|
if translation := get_cached_translation(self, translator.locale):
|
|
24
24
|
return translation
|
|
25
25
|
translation = await func(self, translator)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -14,18 +14,10 @@ from telegrinder.tools.buttons import DataclassInstance
|
|
|
14
14
|
from .abc import ABCRule
|
|
15
15
|
from .markup import Markup, PatternLike, check_string
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
T = typing.TypeVar("T")
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
else:
|
|
22
|
-
|
|
23
|
-
class Ref:
|
|
24
|
-
def __class_getitem__(cls, code: str) -> typing.ForwardRef:
|
|
25
|
-
return typing.ForwardRef(code)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
CallbackQuery = CallbackQueryCute
|
|
19
|
+
Ref: typing.TypeAlias = typing.Annotated[T, ...]
|
|
20
|
+
CallbackQuery: typing.TypeAlias = CallbackQueryCute
|
|
29
21
|
Validator: typing.TypeAlias = typing.Callable[[typing.Any], bool | typing.Awaitable[bool]]
|
|
30
22
|
MapDict: typing.TypeAlias = dict[
|
|
31
23
|
str, typing.Any | type[typing.Any] | Validator | list[Ref["MapDict"]] | Ref["MapDict"]
|
telegrinder/bot/rules/command.py
CHANGED
|
File without changes
|
|
File without changes
|
telegrinder/bot/rules/func.py
CHANGED
|
File without changes
|
telegrinder/bot/rules/fuzzy.py
CHANGED
|
File without changes
|
telegrinder/bot/rules/inline.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import abc
|
|
2
|
+
import typing
|
|
2
3
|
|
|
3
4
|
from telegrinder.bot.cute_types import InlineQueryCute
|
|
4
5
|
from telegrinder.bot.dispatch.context import Context
|
|
@@ -8,7 +9,7 @@ from telegrinder.types.enums import ChatType
|
|
|
8
9
|
|
|
9
10
|
from .markup import Markup, PatternLike, check_string
|
|
10
11
|
|
|
11
|
-
InlineQuery = InlineQueryCute
|
|
12
|
+
InlineQuery: typing.TypeAlias = InlineQueryCute
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class InlineQueryRule(ABCRule[InlineQuery], abc.ABC):
|
telegrinder/bot/rules/integer.py
CHANGED
|
File without changes
|
telegrinder/bot/rules/is_from.py
CHANGED
|
File without changes
|
telegrinder/bot/rules/markup.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
1
3
|
import vbml
|
|
2
4
|
|
|
3
5
|
from telegrinder.bot.dispatch.context import Context
|
|
@@ -6,7 +8,7 @@ from telegrinder.tools.global_context import TelegrinderCtx
|
|
|
6
8
|
from .abc import Message
|
|
7
9
|
from .text import TextMessageRule
|
|
8
10
|
|
|
9
|
-
PatternLike = str | vbml.Pattern
|
|
11
|
+
PatternLike: typing.TypeAlias = str | vbml.Pattern
|
|
10
12
|
global_ctx = TelegrinderCtx()
|
|
11
13
|
|
|
12
14
|
|
telegrinder/bot/rules/mention.py
CHANGED
|
File without changes
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
1
3
|
from telegrinder.bot.dispatch.context import Context
|
|
2
4
|
from telegrinder.types.enums import MessageEntityType
|
|
3
5
|
from telegrinder.types.objects import MessageEntity
|
|
4
6
|
|
|
5
7
|
from .abc import Message, MessageRule
|
|
6
8
|
|
|
7
|
-
Entity = str | MessageEntityType
|
|
9
|
+
Entity: typing.TypeAlias = str | MessageEntityType
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class HasEntities(MessageRule):
|
telegrinder/bot/rules/regex.py
CHANGED
|
File without changes
|
telegrinder/bot/rules/start.py
CHANGED
|
File without changes
|
telegrinder/bot/rules/text.py
CHANGED
|
File without changes
|
telegrinder/bot/scenario/abc.py
CHANGED
|
File without changes
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import dataclasses
|
|
2
|
-
import
|
|
3
|
-
import string
|
|
2
|
+
import secrets
|
|
4
3
|
import typing
|
|
5
4
|
|
|
6
5
|
from telegrinder.bot.cute_types import CallbackQueryCute
|
|
@@ -25,29 +24,26 @@ class Choice:
|
|
|
25
24
|
code: str
|
|
26
25
|
|
|
27
26
|
|
|
28
|
-
def random_code(length: int) -> str:
|
|
29
|
-
return "".join(random.choices(string.ascii_letters + string.digits, k=length))
|
|
30
|
-
|
|
31
|
-
|
|
32
27
|
class Checkbox(ABCScenario[CallbackQueryCute]):
|
|
33
|
-
INVALID_CODE
|
|
34
|
-
CALLBACK_ANSWER
|
|
35
|
-
PARSE_MODE
|
|
28
|
+
INVALID_CODE = "Invalid code"
|
|
29
|
+
CALLBACK_ANSWER = "Done"
|
|
30
|
+
PARSE_MODE = ParseMode.HTML
|
|
36
31
|
|
|
37
32
|
def __init__(
|
|
38
33
|
self,
|
|
39
34
|
waiter_machine: WaiterMachine,
|
|
40
35
|
chat_id: int,
|
|
41
36
|
msg: str,
|
|
37
|
+
*,
|
|
42
38
|
ready_text: str = "Ready",
|
|
43
39
|
max_in_row: int = 3,
|
|
44
|
-
):
|
|
40
|
+
) -> None:
|
|
45
41
|
self.chat_id = chat_id
|
|
46
42
|
self.msg = msg
|
|
47
43
|
self.choices: list[Choice] = []
|
|
48
44
|
self.ready = ready_text
|
|
49
45
|
self.max_in_row = max_in_row
|
|
50
|
-
self.random_code =
|
|
46
|
+
self.random_code = secrets.token_hex(16)
|
|
51
47
|
self.waiter_machine = waiter_machine
|
|
52
48
|
|
|
53
49
|
def get_markup(self) -> InlineKeyboardMarkup:
|
|
@@ -77,7 +73,7 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
|
|
|
77
73
|
is_picked: bool = False,
|
|
78
74
|
) -> typing.Self:
|
|
79
75
|
self.choices.append(
|
|
80
|
-
Choice(name, is_picked, default_text, picked_text,
|
|
76
|
+
Choice(name, is_picked, default_text, picked_text, secrets.token_hex(16)),
|
|
81
77
|
)
|
|
82
78
|
return self
|
|
83
79
|
|
|
@@ -128,4 +124,4 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
|
|
|
128
124
|
)
|
|
129
125
|
|
|
130
126
|
|
|
131
|
-
__all__ = ("Checkbox", "Choice"
|
|
127
|
+
__all__ = ("Checkbox", "Choice")
|
|
@@ -34,11 +34,11 @@ class SingleChoice(Checkbox):
|
|
|
34
34
|
async def wait(
|
|
35
35
|
self,
|
|
36
36
|
api: "API",
|
|
37
|
-
|
|
37
|
+
view: "BaseStateView[CallbackQueryCute]",
|
|
38
38
|
) -> tuple[str, int]:
|
|
39
39
|
if len([choice for choice in self.choices if choice.is_picked]) != 1:
|
|
40
40
|
raise ValueError("Exactly one choice must be picked")
|
|
41
|
-
choices, m_id = await super().wait(api,
|
|
41
|
+
choices, m_id = await super().wait(api, view)
|
|
42
42
|
return list(choices.keys())[list(choices.values()).index(True)], m_id
|
|
43
43
|
|
|
44
44
|
|
telegrinder/client/__init__.py
CHANGED
|
File without changes
|
telegrinder/client/abc.py
CHANGED
|
File without changes
|
telegrinder/client/aiohttp.py
CHANGED
|
File without changes
|
telegrinder/model.py
CHANGED
|
@@ -47,7 +47,7 @@ def full_result(
|
|
|
47
47
|
|
|
48
48
|
def get_params(params: dict[str, typing.Any]) -> dict[str, typing.Any]:
|
|
49
49
|
return {
|
|
50
|
-
k: v.unwrap() if
|
|
50
|
+
k: v.unwrap() if isinstance(v, Some) else v
|
|
51
51
|
for k, v in (
|
|
52
52
|
*params.pop("other", {}).items(),
|
|
53
53
|
*params.items(),
|
|
@@ -77,63 +77,62 @@ class DataConverter:
|
|
|
77
77
|
files: dict[str, tuple[str, bytes]] = dataclasses.field(default_factory=lambda: {})
|
|
78
78
|
|
|
79
79
|
@property
|
|
80
|
-
def converters(self) -> dict[
|
|
81
|
-
type[typing.Any], typing.Callable[[typing.Self, typing.Any, bool], typing.Any]
|
|
82
|
-
]:
|
|
80
|
+
def converters(self) -> dict[type[typing.Any], typing.Callable[..., typing.Any]]:
|
|
83
81
|
return {
|
|
84
|
-
get_origin(value.__annotations__["
|
|
82
|
+
get_origin(value.__annotations__["data"]): value
|
|
85
83
|
for key, value in vars(self.__class__).items()
|
|
86
|
-
if key.startswith("convert_")
|
|
87
|
-
and callable(value)
|
|
84
|
+
if key.startswith("convert_") and callable(value)
|
|
88
85
|
}
|
|
86
|
+
|
|
87
|
+
@staticmethod
|
|
88
|
+
def convert_enum(data: enum.Enum, _: bool = True) -> typing.Any:
|
|
89
|
+
return data.value
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def convert_datetime(data: datetime, _: bool = True) -> int:
|
|
93
|
+
return int(data.timestamp())
|
|
94
|
+
|
|
95
|
+
def __call__(self, data: typing.Any, *, serialize: bool = True) -> typing.Any:
|
|
96
|
+
converter = self.get_converter(get_origin(type(data)))
|
|
97
|
+
if converter is not None:
|
|
98
|
+
if isinstance(converter, staticmethod):
|
|
99
|
+
return converter(data, serialize)
|
|
100
|
+
return converter(self, data, serialize)
|
|
101
|
+
return data
|
|
89
102
|
|
|
90
|
-
def get_converter(
|
|
91
|
-
self, t: type[typing.Any]
|
|
92
|
-
) -> typing.Callable[[typing.Self, typing.Any, bool], typing.Any] | None:
|
|
103
|
+
def get_converter(self, t: type[typing.Any]):
|
|
93
104
|
for type, converter in self.converters.items():
|
|
94
105
|
if issubclass(t, type):
|
|
95
106
|
return converter
|
|
96
107
|
return None
|
|
97
108
|
|
|
98
|
-
def convert_model(self,
|
|
99
|
-
converted_dct = self
|
|
109
|
+
def convert_model(self, data: Model, serialize: bool = True) -> str | dict[str, typing.Any]:
|
|
110
|
+
converted_dct = self(data.to_dict(), serialize=False)
|
|
100
111
|
return encoder.encode(converted_dct) if serialize is True else converted_dct
|
|
101
112
|
|
|
102
|
-
def convert_dct(self,
|
|
113
|
+
def convert_dct(self, data: dict[str, typing.Any], serialize: bool = True) -> dict[str, typing.Any]:
|
|
103
114
|
return {
|
|
104
|
-
k: self
|
|
105
|
-
for k, v in
|
|
115
|
+
k: self(v, serialize=serialize)
|
|
116
|
+
for k, v in data.items()
|
|
106
117
|
if type(v) not in (NoneType, Nothing)
|
|
107
118
|
}
|
|
108
119
|
|
|
109
|
-
def convert_lst(self,
|
|
110
|
-
converted_lst = [self
|
|
120
|
+
def convert_lst(self, data: list[typing.Any], serialize: bool = True) -> str | list[typing.Any]:
|
|
121
|
+
converted_lst = [self(x, serialize=False) for x in data]
|
|
111
122
|
return encoder.encode(converted_lst) if serialize is True else converted_lst
|
|
112
123
|
|
|
113
|
-
def convert_tpl(self,
|
|
124
|
+
def convert_tpl(self, data: tuple[typing.Any, ...], _: bool = True) -> str | tuple[typing.Any, ...]:
|
|
114
125
|
if (
|
|
115
|
-
isinstance(
|
|
116
|
-
and len(
|
|
117
|
-
and isinstance(
|
|
118
|
-
and isinstance(
|
|
126
|
+
isinstance(data, tuple)
|
|
127
|
+
and len(data) == 2
|
|
128
|
+
and isinstance(data[0], str)
|
|
129
|
+
and isinstance(data[1], bytes)
|
|
119
130
|
):
|
|
120
131
|
attach_name = secrets.token_urlsafe(16)
|
|
121
|
-
self.files[attach_name] =
|
|
132
|
+
self.files[attach_name] = data
|
|
122
133
|
return "attach://{}".format(attach_name)
|
|
123
|
-
return d
|
|
124
|
-
|
|
125
|
-
def convert_enum(self, d: enum.Enum, serialize: bool = True) -> str:
|
|
126
|
-
return d.value
|
|
127
|
-
|
|
128
|
-
def convert_datetime(self, d: datetime, serialize: bool = True) -> int:
|
|
129
|
-
return int(d.timestamp())
|
|
130
|
-
|
|
131
|
-
def convert(self, data: typing.Any, *, serialize: bool = True) -> typing.Any:
|
|
132
|
-
converter = self.get_converter(get_origin(type(data)))
|
|
133
|
-
if converter is not None:
|
|
134
|
-
return converter(self, data, serialize)
|
|
135
134
|
return data
|
|
136
|
-
|
|
135
|
+
|
|
137
136
|
|
|
138
137
|
__all__ = (
|
|
139
138
|
"DataConverter",
|
telegrinder/modules.py
CHANGED
|
@@ -5,7 +5,7 @@ from choicelib import choice_in_order
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class JSONModule(typing.Protocol):
|
|
8
|
-
def loads(self, s: str) -> dict[str, typing.Any] | list[typing.Any]:
|
|
8
|
+
def loads(self, s: str | bytes) -> dict[str, typing.Any] | list[typing.Any]:
|
|
9
9
|
...
|
|
10
10
|
|
|
11
11
|
def dumps(self, o: dict[str, typing.Any] | list[typing.Any]) -> str:
|
|
@@ -13,22 +13,22 @@ class JSONModule(typing.Protocol):
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class LoggerModule(typing.Protocol):
|
|
16
|
-
def debug(self, __msg: object, *args: object, **kwargs: object):
|
|
16
|
+
def debug(self, __msg: object, *args: object, **kwargs: object) -> None:
|
|
17
17
|
...
|
|
18
18
|
|
|
19
|
-
def info(self, __msg: object, *args: object, **kwargs: object):
|
|
19
|
+
def info(self, __msg: object, *args: object, **kwargs: object) -> None:
|
|
20
20
|
...
|
|
21
21
|
|
|
22
|
-
def warning(self, __msg: object, *args: object, **kwargs: object):
|
|
22
|
+
def warning(self, __msg: object, *args: object, **kwargs: object) -> None:
|
|
23
23
|
...
|
|
24
24
|
|
|
25
|
-
def error(self, __msg: object, *args: object, **kwargs: object):
|
|
25
|
+
def error(self, __msg: object, *args: object, **kwargs: object) -> None:
|
|
26
26
|
...
|
|
27
27
|
|
|
28
|
-
def critical(self, __msg: object, *args: object, **kwargs: object):
|
|
28
|
+
def critical(self, __msg: object, *args: object, **kwargs: object) -> None:
|
|
29
29
|
...
|
|
30
30
|
|
|
31
|
-
def exception(self, __msg: object, *args: object, **kwargs: object):
|
|
31
|
+
def exception(self, __msg: object, *args: object, **kwargs: object) -> None:
|
|
32
32
|
...
|
|
33
33
|
|
|
34
34
|
def set_level(
|
|
@@ -187,7 +187,7 @@ elif logging_module == "logging":
|
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
class LogMessage:
|
|
190
|
-
def __init__(self, fmt, args, kwargs):
|
|
190
|
+
def __init__(self, fmt: typing.Any, args: typing.Any, kwargs: typing.Any) -> None:
|
|
191
191
|
self.fmt = fmt
|
|
192
192
|
self.args = args
|
|
193
193
|
self.kwargs = kwargs
|
|
@@ -195,17 +195,27 @@ elif logging_module == "logging":
|
|
|
195
195
|
def __str__(self) -> str:
|
|
196
196
|
return self.fmt.format(*self.args, **self.kwargs)
|
|
197
197
|
|
|
198
|
+
|
|
198
199
|
class TelegrinderLoggingStyleAdapter(logging.LoggerAdapter):
|
|
199
|
-
def __init__(
|
|
200
|
+
def __init__(
|
|
201
|
+
self,
|
|
202
|
+
logger: LoggerModule,
|
|
203
|
+
extra: dict[str, typing.Any] | None = None,
|
|
204
|
+
) -> None:
|
|
200
205
|
super().__init__(logger, extra or {})
|
|
201
206
|
|
|
202
|
-
def log(self, level, msg, *args, **kwargs):
|
|
207
|
+
def log(self, level: int, msg: object, *args: object, **kwargs: object) -> None:
|
|
203
208
|
if self.isEnabledFor(level):
|
|
204
209
|
kwargs.setdefault("stacklevel", 2)
|
|
205
210
|
msg, args, kwargs = self.proc(msg, args, kwargs)
|
|
206
211
|
self.logger._log(level, msg, args, **kwargs)
|
|
207
212
|
|
|
208
|
-
def proc(
|
|
213
|
+
def proc(
|
|
214
|
+
self,
|
|
215
|
+
msg: object,
|
|
216
|
+
args: tuple[object, ...],
|
|
217
|
+
kwargs: dict[str, object],
|
|
218
|
+
) -> tuple[LogMessage | object, tuple[object, ...], dict[str, object]]:
|
|
209
219
|
log_kwargs = {
|
|
210
220
|
key: kwargs[key]
|
|
211
221
|
for key in inspect.getfullargspec(self.logger._log).args[1:]
|
telegrinder/msgspec_json.py
CHANGED
|
File without changes
|
telegrinder/msgspec_utils.py
CHANGED
|
@@ -191,11 +191,11 @@ class Encoder:
|
|
|
191
191
|
return self.enc_hooks[origin_type](obj)
|
|
192
192
|
|
|
193
193
|
@typing.overload
|
|
194
|
-
def encode(self, obj: typing.Any) -> str:
|
|
194
|
+
def encode(self, obj: typing.Any, *, as_str: typing.Literal[True] = True) -> str:
|
|
195
195
|
...
|
|
196
196
|
|
|
197
197
|
@typing.overload
|
|
198
|
-
def encode(self, obj: typing.Any, *, as_str:
|
|
198
|
+
def encode(self, obj: typing.Any, *, as_str: typing.Literal[False] = False) -> bytes:
|
|
199
199
|
...
|
|
200
200
|
|
|
201
201
|
def encode(self, obj: typing.Any, *, as_str: bool = True) -> str | bytes:
|
telegrinder/node/__init__.py
CHANGED
|
File without changes
|
telegrinder/node/attachment.py
CHANGED
|
File without changes
|
telegrinder/node/base.py
CHANGED
|
File without changes
|
telegrinder/node/composer.py
CHANGED
|
File without changes
|
telegrinder/node/container.py
CHANGED
|
File without changes
|
telegrinder/node/message.py
CHANGED
|
File without changes
|
telegrinder/node/rule.py
CHANGED
|
File without changes
|
telegrinder/node/source.py
CHANGED
|
File without changes
|