telegrinder 0.4.2__py3-none-any.whl → 0.5.0__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 +37 -55
- telegrinder/__meta__.py +1 -0
- telegrinder/api/__init__.py +6 -4
- telegrinder/api/api.py +100 -26
- telegrinder/api/error.py +42 -8
- telegrinder/api/response.py +4 -1
- telegrinder/api/token.py +2 -2
- telegrinder/bot/__init__.py +9 -25
- telegrinder/bot/bot.py +31 -25
- telegrinder/bot/cute_types/__init__.py +0 -0
- telegrinder/bot/cute_types/base.py +103 -61
- telegrinder/bot/cute_types/callback_query.py +447 -400
- telegrinder/bot/cute_types/chat_join_request.py +59 -62
- telegrinder/bot/cute_types/chat_member_updated.py +154 -157
- telegrinder/bot/cute_types/inline_query.py +41 -44
- telegrinder/bot/cute_types/message.py +2621 -2590
- telegrinder/bot/cute_types/pre_checkout_query.py +38 -42
- telegrinder/bot/cute_types/update.py +1 -8
- telegrinder/bot/cute_types/utils.py +1 -1
- telegrinder/bot/dispatch/__init__.py +10 -15
- telegrinder/bot/dispatch/abc.py +12 -11
- telegrinder/bot/dispatch/action.py +104 -0
- telegrinder/bot/dispatch/context.py +32 -26
- telegrinder/bot/dispatch/dispatch.py +61 -134
- telegrinder/bot/dispatch/handler/__init__.py +2 -0
- telegrinder/bot/dispatch/handler/abc.py +10 -8
- telegrinder/bot/dispatch/handler/audio_reply.py +2 -3
- telegrinder/bot/dispatch/handler/base.py +10 -33
- telegrinder/bot/dispatch/handler/document_reply.py +2 -3
- telegrinder/bot/dispatch/handler/func.py +55 -87
- telegrinder/bot/dispatch/handler/media_group_reply.py +2 -3
- telegrinder/bot/dispatch/handler/message_reply.py +2 -3
- telegrinder/bot/dispatch/handler/photo_reply.py +2 -3
- telegrinder/bot/dispatch/handler/sticker_reply.py +2 -3
- telegrinder/bot/dispatch/handler/video_reply.py +2 -3
- telegrinder/bot/dispatch/middleware/__init__.py +0 -0
- telegrinder/bot/dispatch/middleware/abc.py +79 -55
- telegrinder/bot/dispatch/middleware/global_middleware.py +18 -33
- telegrinder/bot/dispatch/process.py +84 -105
- telegrinder/bot/dispatch/return_manager/__init__.py +0 -0
- telegrinder/bot/dispatch/return_manager/abc.py +102 -65
- telegrinder/bot/dispatch/return_manager/callback_query.py +4 -5
- telegrinder/bot/dispatch/return_manager/inline_query.py +3 -4
- telegrinder/bot/dispatch/return_manager/message.py +8 -10
- telegrinder/bot/dispatch/return_manager/pre_checkout_query.py +4 -5
- telegrinder/bot/dispatch/view/__init__.py +4 -4
- telegrinder/bot/dispatch/view/abc.py +6 -16
- telegrinder/bot/dispatch/view/base.py +54 -178
- telegrinder/bot/dispatch/view/box.py +19 -18
- telegrinder/bot/dispatch/view/callback_query.py +4 -8
- telegrinder/bot/dispatch/view/chat_join_request.py +5 -6
- telegrinder/bot/dispatch/view/chat_member.py +5 -25
- telegrinder/bot/dispatch/view/error.py +9 -0
- telegrinder/bot/dispatch/view/inline_query.py +4 -8
- telegrinder/bot/dispatch/view/message.py +5 -25
- telegrinder/bot/dispatch/view/pre_checkout_query.py +4 -8
- telegrinder/bot/dispatch/view/raw.py +3 -109
- telegrinder/bot/dispatch/waiter_machine/__init__.py +2 -5
- telegrinder/bot/dispatch/waiter_machine/actions.py +6 -4
- telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +1 -3
- telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +1 -1
- telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +11 -7
- telegrinder/bot/dispatch/waiter_machine/hasher/message.py +0 -0
- telegrinder/bot/dispatch/waiter_machine/machine.py +43 -60
- telegrinder/bot/dispatch/waiter_machine/middleware.py +19 -23
- telegrinder/bot/dispatch/waiter_machine/short_state.py +6 -5
- telegrinder/bot/polling/__init__.py +0 -0
- telegrinder/bot/polling/abc.py +0 -0
- telegrinder/bot/polling/polling.py +209 -88
- telegrinder/bot/rules/__init__.py +3 -16
- telegrinder/bot/rules/abc.py +42 -122
- telegrinder/bot/rules/callback_data.py +29 -49
- telegrinder/bot/rules/chat_join.py +5 -23
- telegrinder/bot/rules/command.py +8 -4
- telegrinder/bot/rules/enum_text.py +3 -4
- telegrinder/bot/rules/func.py +7 -14
- telegrinder/bot/rules/fuzzy.py +3 -4
- telegrinder/bot/rules/inline.py +8 -20
- telegrinder/bot/rules/integer.py +2 -3
- telegrinder/bot/rules/is_from.py +12 -11
- telegrinder/bot/rules/logic.py +11 -5
- telegrinder/bot/rules/markup.py +22 -14
- telegrinder/bot/rules/mention.py +8 -7
- telegrinder/bot/rules/message_entities.py +8 -4
- telegrinder/bot/rules/node.py +23 -12
- telegrinder/bot/rules/payload.py +5 -4
- telegrinder/bot/rules/payment_invoice.py +6 -21
- telegrinder/bot/rules/regex.py +2 -4
- telegrinder/bot/rules/rule_enum.py +8 -7
- telegrinder/bot/rules/start.py +5 -6
- telegrinder/bot/rules/state.py +1 -1
- telegrinder/bot/rules/text.py +4 -15
- telegrinder/bot/rules/update.py +3 -4
- telegrinder/bot/scenario/__init__.py +0 -0
- telegrinder/bot/scenario/abc.py +6 -5
- telegrinder/bot/scenario/checkbox.py +1 -1
- telegrinder/bot/scenario/choice.py +30 -39
- telegrinder/client/__init__.py +3 -5
- telegrinder/client/abc.py +11 -6
- telegrinder/client/aiohttp.py +141 -27
- telegrinder/client/form_data.py +1 -1
- telegrinder/model.py +61 -89
- telegrinder/modules.py +325 -102
- telegrinder/msgspec_utils/__init__.py +40 -0
- telegrinder/msgspec_utils/abc.py +18 -0
- telegrinder/msgspec_utils/custom_types/__init__.py +6 -0
- telegrinder/msgspec_utils/custom_types/datetime.py +24 -0
- telegrinder/msgspec_utils/custom_types/enum_meta.py +43 -0
- telegrinder/msgspec_utils/custom_types/literal.py +25 -0
- telegrinder/msgspec_utils/custom_types/option.py +17 -0
- telegrinder/msgspec_utils/decoder.py +389 -0
- telegrinder/msgspec_utils/encoder.py +206 -0
- telegrinder/{msgspec_json.py → msgspec_utils/json.py} +6 -5
- telegrinder/msgspec_utils/tools.py +75 -0
- telegrinder/node/__init__.py +24 -7
- telegrinder/node/attachment.py +1 -0
- telegrinder/node/base.py +154 -72
- telegrinder/node/callback_query.py +5 -5
- telegrinder/node/collection.py +39 -0
- telegrinder/node/command.py +1 -2
- telegrinder/node/composer.py +121 -72
- telegrinder/node/container.py +11 -8
- telegrinder/node/context.py +48 -0
- telegrinder/node/either.py +27 -40
- telegrinder/node/error.py +41 -0
- telegrinder/node/event.py +37 -11
- telegrinder/node/exceptions.py +7 -0
- telegrinder/node/file.py +0 -0
- telegrinder/node/i18n.py +108 -0
- telegrinder/node/me.py +3 -2
- telegrinder/node/payload.py +1 -1
- telegrinder/node/polymorphic.py +63 -28
- telegrinder/node/reply_message.py +12 -0
- telegrinder/node/rule.py +6 -13
- telegrinder/node/scope.py +14 -5
- telegrinder/node/session.py +53 -0
- telegrinder/node/source.py +41 -9
- telegrinder/node/text.py +1 -2
- telegrinder/node/tools/__init__.py +0 -0
- telegrinder/node/tools/generator.py +3 -5
- telegrinder/node/utility.py +16 -0
- telegrinder/py.typed +0 -0
- telegrinder/rules.py +0 -0
- telegrinder/tools/__init__.py +48 -88
- telegrinder/tools/aio.py +103 -0
- telegrinder/tools/callback_data_serialization/__init__.py +5 -0
- telegrinder/tools/{callback_data_serilization → callback_data_serialization}/abc.py +0 -0
- telegrinder/tools/{callback_data_serilization → callback_data_serialization}/json_ser.py +2 -3
- telegrinder/tools/{callback_data_serilization → callback_data_serialization}/msgpack_ser.py +45 -27
- telegrinder/tools/final.py +21 -0
- telegrinder/tools/formatting/__init__.py +2 -18
- telegrinder/tools/formatting/deep_links/__init__.py +39 -0
- telegrinder/tools/formatting/{deep_links.py → deep_links/links.py} +12 -85
- telegrinder/tools/formatting/deep_links/parsing.py +90 -0
- telegrinder/tools/formatting/deep_links/validators.py +8 -0
- telegrinder/tools/formatting/html_formatter.py +18 -45
- telegrinder/tools/fullname.py +83 -0
- telegrinder/tools/global_context/__init__.py +4 -3
- telegrinder/tools/global_context/abc.py +17 -14
- telegrinder/tools/global_context/builtin_context.py +39 -0
- telegrinder/tools/global_context/global_context.py +138 -39
- telegrinder/tools/input_file_directory.py +0 -0
- telegrinder/tools/keyboard/__init__.py +39 -0
- telegrinder/tools/keyboard/abc.py +159 -0
- telegrinder/tools/keyboard/base.py +77 -0
- telegrinder/tools/keyboard/buttons/__init__.py +14 -0
- telegrinder/tools/keyboard/buttons/base.py +18 -0
- telegrinder/tools/{buttons.py → keyboard/buttons/buttons.py} +71 -23
- telegrinder/tools/keyboard/buttons/static_buttons.py +56 -0
- telegrinder/tools/keyboard/buttons/tools.py +18 -0
- telegrinder/tools/keyboard/data.py +20 -0
- telegrinder/tools/keyboard/keyboard.py +131 -0
- telegrinder/tools/keyboard/static_keyboard.py +83 -0
- telegrinder/tools/lifespan.py +87 -51
- telegrinder/tools/limited_dict.py +4 -1
- telegrinder/tools/loop_wrapper.py +332 -0
- telegrinder/tools/magic/__init__.py +32 -0
- telegrinder/tools/magic/annotations.py +165 -0
- telegrinder/tools/magic/dictionary.py +20 -0
- telegrinder/tools/magic/function.py +246 -0
- telegrinder/tools/magic/shortcut.py +111 -0
- telegrinder/tools/parse_mode.py +9 -3
- telegrinder/tools/singleton/__init__.py +4 -0
- telegrinder/tools/singleton/abc.py +14 -0
- telegrinder/tools/singleton/singleton.py +18 -0
- telegrinder/tools/state_storage/__init__.py +0 -0
- telegrinder/tools/state_storage/abc.py +6 -1
- telegrinder/tools/state_storage/memory.py +1 -1
- telegrinder/tools/strings.py +0 -0
- telegrinder/types/__init__.py +307 -268
- telegrinder/types/enums.py +64 -37
- telegrinder/types/input_file.py +3 -3
- telegrinder/types/methods.py +5699 -5055
- telegrinder/types/methods_utils.py +62 -0
- telegrinder/types/objects.py +7846 -7058
- telegrinder/verification_utils.py +3 -1
- telegrinder-0.5.0.dist-info/METADATA +162 -0
- telegrinder-0.5.0.dist-info/RECORD +200 -0
- {telegrinder-0.4.2.dist-info → telegrinder-0.5.0.dist-info}/licenses/LICENSE +2 -2
- telegrinder/bot/dispatch/waiter_machine/hasher/state.py +0 -20
- telegrinder/bot/rules/id.py +0 -24
- telegrinder/bot/rules/message.py +0 -15
- telegrinder/client/sonic.py +0 -212
- telegrinder/msgspec_utils.py +0 -478
- telegrinder/tools/adapter/__init__.py +0 -19
- telegrinder/tools/adapter/abc.py +0 -49
- telegrinder/tools/adapter/dataclass.py +0 -56
- telegrinder/tools/adapter/errors.py +0 -5
- telegrinder/tools/adapter/event.py +0 -61
- telegrinder/tools/adapter/node.py +0 -46
- telegrinder/tools/adapter/raw_event.py +0 -27
- telegrinder/tools/adapter/raw_update.py +0 -30
- telegrinder/tools/callback_data_serilization/__init__.py +0 -5
- telegrinder/tools/error_handler/__init__.py +0 -10
- telegrinder/tools/error_handler/abc.py +0 -30
- telegrinder/tools/error_handler/error.py +0 -9
- telegrinder/tools/error_handler/error_handler.py +0 -179
- telegrinder/tools/formatting/spec_html_formats.py +0 -75
- telegrinder/tools/functional.py +0 -8
- telegrinder/tools/global_context/telegrinder_ctx.py +0 -27
- telegrinder/tools/i18n/__init__.py +0 -12
- telegrinder/tools/i18n/abc.py +0 -32
- telegrinder/tools/i18n/middleware/__init__.py +0 -3
- telegrinder/tools/i18n/middleware/abc.py +0 -22
- telegrinder/tools/i18n/simple.py +0 -43
- telegrinder/tools/keyboard.py +0 -132
- telegrinder/tools/loop_wrapper/__init__.py +0 -4
- telegrinder/tools/loop_wrapper/abc.py +0 -20
- telegrinder/tools/loop_wrapper/loop_wrapper.py +0 -169
- telegrinder/tools/magic.py +0 -344
- telegrinder-0.4.2.dist-info/METADATA +0 -151
- telegrinder-0.4.2.dist-info/RECORD +0 -182
- {telegrinder-0.4.2.dist-info → telegrinder-0.5.0.dist-info}/WHEEL +0 -0
telegrinder/tools/adapter/abc.py
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import dataclasses
|
|
3
|
-
import inspect
|
|
4
|
-
import typing
|
|
5
|
-
|
|
6
|
-
from fntypes import Error, Nothing, Ok, Option, Some
|
|
7
|
-
from fntypes.result import Result
|
|
8
|
-
|
|
9
|
-
from telegrinder.modules import logger
|
|
10
|
-
from telegrinder.tools.adapter.errors import AdapterError
|
|
11
|
-
|
|
12
|
-
type AdaptResult[To] = Result[To, AdapterError] | typing.Awaitable[Result[To, AdapterError]]
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if typing.TYPE_CHECKING:
|
|
16
|
-
from telegrinder.api.api import API
|
|
17
|
-
from telegrinder.bot.dispatch.context import Context
|
|
18
|
-
from telegrinder.model import Model
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class ABCAdapter[From: "Model", To](abc.ABC):
|
|
22
|
-
ADAPTED_VALUE_KEY: str | None = None
|
|
23
|
-
|
|
24
|
-
@abc.abstractmethod
|
|
25
|
-
def adapt(self, api: "API", update: From, context: "Context") -> AdaptResult[To]:
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@dataclasses.dataclass(slots=True)
|
|
30
|
-
class Event[To]:
|
|
31
|
-
obj: To
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
async def run_adapter[T, U: "Model"](
|
|
35
|
-
adapter: "ABCAdapter[U, T]",
|
|
36
|
-
api: "API",
|
|
37
|
-
update: U,
|
|
38
|
-
context: "Context",
|
|
39
|
-
) -> Option[T]:
|
|
40
|
-
adapt_result = adapter.adapt(api, update, context)
|
|
41
|
-
match await adapt_result if inspect.isawaitable(adapt_result) else adapt_result:
|
|
42
|
-
case Ok(value):
|
|
43
|
-
return Some(value)
|
|
44
|
-
case Error(err):
|
|
45
|
-
logger.debug("Adapter {!r} failed with error message: {!r}", adapter, str(err))
|
|
46
|
-
return Nothing()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
__all__ = ("ABCAdapter", "AdaptResult", "Event", "run_adapter")
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
from fntypes.option import Nothing, Some
|
|
2
|
-
from fntypes.result import Error, Ok, Result
|
|
3
|
-
|
|
4
|
-
from telegrinder.api.api import API
|
|
5
|
-
from telegrinder.bot.cute_types.base import BaseCute
|
|
6
|
-
from telegrinder.bot.cute_types.update import UpdateCute
|
|
7
|
-
from telegrinder.bot.dispatch.context import Context
|
|
8
|
-
from telegrinder.tools.adapter.abc import ABCAdapter
|
|
9
|
-
from telegrinder.tools.adapter.errors import AdapterError
|
|
10
|
-
from telegrinder.types.enums import UpdateType
|
|
11
|
-
from telegrinder.types.objects import Update
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class DataclassAdapter[Dataclass](ABCAdapter[Update, Dataclass]):
|
|
15
|
-
ADAPTED_VALUE_KEY: str
|
|
16
|
-
|
|
17
|
-
def __init__(
|
|
18
|
-
self,
|
|
19
|
-
dataclass: type[Dataclass],
|
|
20
|
-
update_type: UpdateType | None = None,
|
|
21
|
-
) -> None:
|
|
22
|
-
self.ADAPTED_VALUE_KEY = f"_adapted_dataclass_{dataclass.__name__}"
|
|
23
|
-
self.dataclass = dataclass
|
|
24
|
-
self.update_type = update_type
|
|
25
|
-
|
|
26
|
-
def __repr__(self) -> str:
|
|
27
|
-
return f"<Update -> {self.dataclass.__name__}>"
|
|
28
|
-
|
|
29
|
-
def adapt(self, api: API, update: Update, context: Context) -> Result[Dataclass, AdapterError]:
|
|
30
|
-
if self.ADAPTED_VALUE_KEY in context:
|
|
31
|
-
return Ok(context[self.ADAPTED_VALUE_KEY])
|
|
32
|
-
|
|
33
|
-
update_type = (self.update_type or update.update_type).value
|
|
34
|
-
try:
|
|
35
|
-
if self.dataclass is Update:
|
|
36
|
-
return Ok(update) # type: ignore
|
|
37
|
-
elif issubclass(self.dataclass, UpdateCute):
|
|
38
|
-
dataclass = self.dataclass.from_update(update, bound_api=api)
|
|
39
|
-
else:
|
|
40
|
-
match getattr(update, update_type):
|
|
41
|
-
case Some(val):
|
|
42
|
-
dataclass = (
|
|
43
|
-
self.dataclass.from_update(val, bound_api=api)
|
|
44
|
-
if issubclass(self.dataclass, BaseCute)
|
|
45
|
-
else self.dataclass(**val.to_dict())
|
|
46
|
-
)
|
|
47
|
-
case Nothing():
|
|
48
|
-
return Error(AdapterError(f"Update has no event {update_type!r}."))
|
|
49
|
-
except Exception as e:
|
|
50
|
-
return Error(AdapterError(f"Cannot adapt Update to {self.dataclass!r}, error: {e!r}"))
|
|
51
|
-
|
|
52
|
-
context[self.ADAPTED_VALUE_KEY] = dataclass
|
|
53
|
-
return Ok(dataclass) # type: ignore
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
__all__ = ("DataclassAdapter",)
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
|
|
3
|
-
from fntypes.result import Error, Ok, Result
|
|
4
|
-
|
|
5
|
-
from telegrinder.api.api import API
|
|
6
|
-
from telegrinder.bot.cute_types.base import BaseCute
|
|
7
|
-
from telegrinder.bot.cute_types.update import UpdateCute
|
|
8
|
-
from telegrinder.bot.dispatch.context import Context
|
|
9
|
-
from telegrinder.tools.adapter.abc import ABCAdapter
|
|
10
|
-
from telegrinder.tools.adapter.errors import AdapterError
|
|
11
|
-
from telegrinder.tools.adapter.raw_update import RawUpdateAdapter
|
|
12
|
-
from telegrinder.types.enums import UpdateType
|
|
13
|
-
from telegrinder.types.objects import Model, Update
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class EventAdapter[ToEvent: BaseCute](ABCAdapter[Update, ToEvent]):
|
|
17
|
-
ADAPTED_VALUE_KEY: str = "_adapted_cute_event"
|
|
18
|
-
|
|
19
|
-
def __init__(self, event: UpdateType | type[Model], cute_model: type[ToEvent]) -> None:
|
|
20
|
-
self.event = event
|
|
21
|
-
self.cute_model = cute_model
|
|
22
|
-
|
|
23
|
-
def __repr__(self) -> str:
|
|
24
|
-
raw_update_type = (
|
|
25
|
-
f"Update -> {self.event.__name__}" if isinstance(self.event, type) else f"Update.{self.event.value}" # type: ignore
|
|
26
|
-
)
|
|
27
|
-
return "<{}: adapt {} -> {}>".format(
|
|
28
|
-
self.__class__.__name__,
|
|
29
|
-
raw_update_type,
|
|
30
|
-
self.cute_model.__name__,
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
def get_event(self, update: UpdateCute) -> Model | None:
|
|
34
|
-
if isinstance(self.event, UpdateType) and self.event == update.update_type:
|
|
35
|
-
return update.incoming_update
|
|
36
|
-
|
|
37
|
-
if not isinstance(self.event, UpdateType) and (event := update.get_event(self.event)):
|
|
38
|
-
return event.unwrap()
|
|
39
|
-
|
|
40
|
-
return None
|
|
41
|
-
|
|
42
|
-
def adapt(self, api: API, update: Update, context: Context) -> Result[ToEvent, AdapterError]:
|
|
43
|
-
match RawUpdateAdapter().adapt(api, update, context):
|
|
44
|
-
case Ok(update_cute) if event := self.get_event(update_cute):
|
|
45
|
-
if self.ADAPTED_VALUE_KEY in context:
|
|
46
|
-
return Ok(context[self.ADAPTED_VALUE_KEY])
|
|
47
|
-
|
|
48
|
-
adapted = (
|
|
49
|
-
typing.cast(ToEvent, event)
|
|
50
|
-
if isinstance(event, BaseCute)
|
|
51
|
-
else self.cute_model.from_update(event, bound_api=api)
|
|
52
|
-
)
|
|
53
|
-
context[self.ADAPTED_VALUE_KEY] = adapted
|
|
54
|
-
return Ok(adapted)
|
|
55
|
-
case Error(_) as err:
|
|
56
|
-
return err
|
|
57
|
-
case _:
|
|
58
|
-
return Error(AdapterError(f"Update is not an {self.event!r}."))
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
__all__ = ("EventAdapter",)
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import typing_extensions as typing
|
|
2
|
-
from fntypes.result import Error, Ok, Result
|
|
3
|
-
|
|
4
|
-
from telegrinder.api.api import API
|
|
5
|
-
from telegrinder.bot.dispatch.context import Context
|
|
6
|
-
from telegrinder.msgspec_utils import repr_type
|
|
7
|
-
from telegrinder.node.composer import NodeSession, compose_nodes
|
|
8
|
-
from telegrinder.tools.adapter.abc import ABCAdapter, Event
|
|
9
|
-
from telegrinder.tools.adapter.errors import AdapterError
|
|
10
|
-
from telegrinder.types.objects import Update
|
|
11
|
-
|
|
12
|
-
if typing.TYPE_CHECKING:
|
|
13
|
-
from telegrinder.node.base import IsNode
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class NodeAdapter(ABCAdapter[Update, Event[tuple["IsNode", ...]]]):
|
|
17
|
-
def __init__(self, *nodes: "IsNode") -> None:
|
|
18
|
-
self.nodes = nodes
|
|
19
|
-
|
|
20
|
-
def __repr__(self) -> str:
|
|
21
|
-
return "<{}: adapt Update -> ({})>".format(
|
|
22
|
-
self.__class__.__name__,
|
|
23
|
-
", ".join(repr_type(node) for node in self.nodes),
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
async def adapt(
|
|
27
|
-
self,
|
|
28
|
-
api: API,
|
|
29
|
-
update: Update,
|
|
30
|
-
context: Context,
|
|
31
|
-
) -> Result[Event[tuple[NodeSession, ...]], AdapterError]:
|
|
32
|
-
result = await compose_nodes(
|
|
33
|
-
nodes={f"node_{i}": typing.cast("IsNode", node) for i, node in enumerate(self.nodes)},
|
|
34
|
-
ctx=context,
|
|
35
|
-
data={Update: update, API: api},
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
match result:
|
|
39
|
-
case Ok(collection):
|
|
40
|
-
sessions: list[NodeSession] = list(collection.sessions.values())
|
|
41
|
-
return Ok(Event(tuple(sessions)))
|
|
42
|
-
case Error(err):
|
|
43
|
-
return Error(AdapterError(f"Couldn't compose nodes, error: {err}."))
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
__all__ = ("NodeAdapter",)
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
from fntypes.result import Error, Ok, Result
|
|
2
|
-
|
|
3
|
-
from telegrinder.api.api import API
|
|
4
|
-
from telegrinder.bot.dispatch.context import Context
|
|
5
|
-
from telegrinder.model import Model
|
|
6
|
-
from telegrinder.tools.adapter.abc import ABCAdapter
|
|
7
|
-
from telegrinder.tools.adapter.errors import AdapterError
|
|
8
|
-
from telegrinder.types.objects import Update
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class RawEventAdapter(ABCAdapter[Update, Model]):
|
|
12
|
-
def __init__(self, event_model: type[Model], /) -> None:
|
|
13
|
-
self.event_model = event_model
|
|
14
|
-
|
|
15
|
-
def __repr__(self) -> str:
|
|
16
|
-
return "<{}: adapt Update -> {}>".format(
|
|
17
|
-
self.__class__.__name__,
|
|
18
|
-
self.event_model.__name__,
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
def adapt(self, api: API, update: Update, context: Context) -> Result[Model, AdapterError]:
|
|
22
|
-
if isinstance(update.incoming_update, self.event_model):
|
|
23
|
-
return Ok(update.incoming_update)
|
|
24
|
-
return Error(AdapterError(f"Update is not an {self.event_model.__name__!r}."))
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
__all__ = ("RawEventAdapter",)
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from fntypes.result import Ok, Result
|
|
2
|
-
|
|
3
|
-
from telegrinder.api.api import API
|
|
4
|
-
from telegrinder.bot.cute_types.update import UpdateCute
|
|
5
|
-
from telegrinder.bot.dispatch.context import Context
|
|
6
|
-
from telegrinder.tools.adapter.abc import ABCAdapter
|
|
7
|
-
from telegrinder.tools.adapter.errors import AdapterError
|
|
8
|
-
from telegrinder.types.objects import Update
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class RawUpdateAdapter(ABCAdapter[Update, UpdateCute]):
|
|
12
|
-
ADAPTED_VALUE_KEY: str = "_adapted_update_cute"
|
|
13
|
-
|
|
14
|
-
def __repr__(self) -> str:
|
|
15
|
-
return f"<{self.__class__.__name__}: adapt Update -> UpdateCute>"
|
|
16
|
-
|
|
17
|
-
def adapt(
|
|
18
|
-
self,
|
|
19
|
-
api: API,
|
|
20
|
-
update: Update,
|
|
21
|
-
context: Context,
|
|
22
|
-
) -> Result[UpdateCute, AdapterError]:
|
|
23
|
-
if self.ADAPTED_VALUE_KEY not in context:
|
|
24
|
-
context[self.ADAPTED_VALUE_KEY] = (
|
|
25
|
-
UpdateCute.from_update(update, api) if not isinstance(update, UpdateCute) else update
|
|
26
|
-
)
|
|
27
|
-
return Ok(context[self.ADAPTED_VALUE_KEY])
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
__all__ = ("RawUpdateAdapter",)
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
from abc import ABC, abstractmethod
|
|
3
|
-
|
|
4
|
-
from telegrinder.api import API
|
|
5
|
-
from telegrinder.bot.dispatch.context import Context
|
|
6
|
-
|
|
7
|
-
type Handler = typing.Callable[..., typing.Awaitable[typing.Any]]
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class ABCErrorHandler[Event](ABC):
|
|
11
|
-
@abstractmethod
|
|
12
|
-
def __call__(
|
|
13
|
-
self,
|
|
14
|
-
*args: typing.Any,
|
|
15
|
-
**kwargs: typing.Any,
|
|
16
|
-
) -> typing.Callable[[typing.Callable[..., typing.Any]], typing.Callable[..., typing.Any]]:
|
|
17
|
-
"""Decorator for registering callback as a catcher for the error handler."""
|
|
18
|
-
|
|
19
|
-
@abstractmethod
|
|
20
|
-
async def run(
|
|
21
|
-
self,
|
|
22
|
-
exception: BaseException,
|
|
23
|
-
event: Event,
|
|
24
|
-
api: API,
|
|
25
|
-
ctx: Context,
|
|
26
|
-
) -> typing.Any:
|
|
27
|
-
"""Run the error handler."""
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
__all__ = ("ABCErrorHandler",)
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import dataclasses
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from fntypes.result import Error, Ok, Result
|
|
5
|
-
|
|
6
|
-
from telegrinder.api.api import API
|
|
7
|
-
from telegrinder.bot.dispatch.context import Context
|
|
8
|
-
from telegrinder.modules import logger
|
|
9
|
-
from telegrinder.tools.error_handler.abc import ABCErrorHandler
|
|
10
|
-
from telegrinder.tools.error_handler.error import CatcherError
|
|
11
|
-
from telegrinder.tools.magic import magic_bundle
|
|
12
|
-
|
|
13
|
-
type FuncCatcher[Exc: BaseException] = typing.Callable[
|
|
14
|
-
typing.Concatenate[Exc, ...],
|
|
15
|
-
typing.Awaitable[typing.Any],
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@dataclasses.dataclass(frozen=True, repr=False, slots=True)
|
|
20
|
-
class Catcher[Event]:
|
|
21
|
-
func: FuncCatcher[BaseException]
|
|
22
|
-
exceptions: list[type[BaseException] | BaseException] = dataclasses.field(
|
|
23
|
-
default_factory=lambda: [],
|
|
24
|
-
kw_only=True,
|
|
25
|
-
)
|
|
26
|
-
logging: bool = dataclasses.field(default=False, kw_only=True)
|
|
27
|
-
raise_exception: bool = dataclasses.field(default=False, kw_only=True)
|
|
28
|
-
ignore_errors: bool = dataclasses.field(default=False, kw_only=True)
|
|
29
|
-
|
|
30
|
-
def __repr__(self) -> str:
|
|
31
|
-
return "<Catcher: function={!r}, logging={}, raise_exception={}, ignore_errors={}>".format(
|
|
32
|
-
self.func.__name__,
|
|
33
|
-
self.logging,
|
|
34
|
-
self.raise_exception,
|
|
35
|
-
self.ignore_errors,
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
async def __call__(
|
|
39
|
-
self,
|
|
40
|
-
exception: BaseException,
|
|
41
|
-
event: Event,
|
|
42
|
-
api: API,
|
|
43
|
-
ctx: Context,
|
|
44
|
-
) -> Result[typing.Any, BaseException]:
|
|
45
|
-
return await self.run(api, event, ctx, exception)
|
|
46
|
-
|
|
47
|
-
def match_exception(self, exception: BaseException) -> bool:
|
|
48
|
-
for exc in self.exceptions:
|
|
49
|
-
if isinstance(exc, type) and type(exception) is exc:
|
|
50
|
-
return True
|
|
51
|
-
if isinstance(exc, object) and type(exception) is type(exc):
|
|
52
|
-
return True if not exc.args else exc.args == exception.args
|
|
53
|
-
|
|
54
|
-
return False
|
|
55
|
-
|
|
56
|
-
async def run(
|
|
57
|
-
self,
|
|
58
|
-
api: API,
|
|
59
|
-
event: Event,
|
|
60
|
-
ctx: Context,
|
|
61
|
-
exception: BaseException,
|
|
62
|
-
) -> Result[typing.Any, BaseException]:
|
|
63
|
-
if self.match_exception(exception):
|
|
64
|
-
logger.debug(
|
|
65
|
-
"Error handler caught an exception {!r}, running catcher {!r}...".format(
|
|
66
|
-
exception,
|
|
67
|
-
self.func.__name__,
|
|
68
|
-
)
|
|
69
|
-
)
|
|
70
|
-
return Ok(await self.func(exception, **magic_bundle(self.func, {"event": event, "api": api} | ctx)))
|
|
71
|
-
|
|
72
|
-
logger.debug("Failed to match exception {!r}.", exception.__class__.__name__)
|
|
73
|
-
return Error(exception)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
class ErrorHandler[Event](ABCErrorHandler[Event]):
|
|
77
|
-
def __init__(self, catcher: Catcher[Event] | None = None, /) -> None:
|
|
78
|
-
self.catcher = catcher
|
|
79
|
-
|
|
80
|
-
def __repr__(self) -> str:
|
|
81
|
-
return (
|
|
82
|
-
"<{}: exceptions=[{}], catcher={!r}>".format(
|
|
83
|
-
self.__class__.__name__,
|
|
84
|
-
", ".join(e.__name__ if isinstance(e, type) else repr(e) for e in self.catcher.exceptions),
|
|
85
|
-
self.catcher,
|
|
86
|
-
)
|
|
87
|
-
if self.catcher is not None
|
|
88
|
-
else "<{}()>".format(self.__class__.__name__)
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
def __call__(
|
|
92
|
-
self,
|
|
93
|
-
*exceptions: type[BaseException] | BaseException,
|
|
94
|
-
logging: bool = False,
|
|
95
|
-
raise_exception: bool = False,
|
|
96
|
-
ignore_errors: bool = False,
|
|
97
|
-
):
|
|
98
|
-
"""Register the catcher.
|
|
99
|
-
|
|
100
|
-
:param logging: Logging the result of the catcher at the level `DEBUG`.
|
|
101
|
-
:param raise_exception: Raise an exception if the catcher has not started.
|
|
102
|
-
:param ignore_errors: Ignore errors that may occur.
|
|
103
|
-
"""
|
|
104
|
-
|
|
105
|
-
def decorator[Func: FuncCatcher](catcher: Func, /) -> Func:
|
|
106
|
-
if not self.catcher:
|
|
107
|
-
self.catcher = Catcher(
|
|
108
|
-
catcher,
|
|
109
|
-
exceptions=list(exceptions),
|
|
110
|
-
logging=logging,
|
|
111
|
-
raise_exception=raise_exception,
|
|
112
|
-
ignore_errors=ignore_errors,
|
|
113
|
-
)
|
|
114
|
-
return catcher
|
|
115
|
-
|
|
116
|
-
return decorator
|
|
117
|
-
|
|
118
|
-
def _process_catcher_error(self, error: CatcherError) -> Result[None, BaseException]:
|
|
119
|
-
assert self.catcher is not None
|
|
120
|
-
|
|
121
|
-
if self.catcher.raise_exception:
|
|
122
|
-
raise error.exc from None
|
|
123
|
-
if self.catcher.logging:
|
|
124
|
-
logger.error(error.message)
|
|
125
|
-
if not self.catcher.ignore_errors:
|
|
126
|
-
return Error(error.exc)
|
|
127
|
-
|
|
128
|
-
return Ok(None)
|
|
129
|
-
|
|
130
|
-
async def suppress(
|
|
131
|
-
self,
|
|
132
|
-
exception: BaseException,
|
|
133
|
-
event: Event,
|
|
134
|
-
api: API,
|
|
135
|
-
ctx: Context,
|
|
136
|
-
) -> Result[typing.Any, BaseException]:
|
|
137
|
-
assert self.catcher is not None
|
|
138
|
-
|
|
139
|
-
try:
|
|
140
|
-
return await self.catcher(exception, event, api, ctx)
|
|
141
|
-
except BaseException as exc:
|
|
142
|
-
return Error(
|
|
143
|
-
CatcherError(
|
|
144
|
-
exc,
|
|
145
|
-
"{!r} was occurred during the running catcher {!r}.".format(
|
|
146
|
-
exc,
|
|
147
|
-
self.catcher.func.__name__,
|
|
148
|
-
),
|
|
149
|
-
)
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
async def run(
|
|
153
|
-
self,
|
|
154
|
-
exception: BaseException,
|
|
155
|
-
event: Event,
|
|
156
|
-
api: API,
|
|
157
|
-
ctx: Context,
|
|
158
|
-
) -> typing.Any:
|
|
159
|
-
if not self.catcher:
|
|
160
|
-
raise exception from None
|
|
161
|
-
|
|
162
|
-
match await self.suppress(exception, event, api, ctx):
|
|
163
|
-
case Ok(value):
|
|
164
|
-
if self.catcher.logging:
|
|
165
|
-
logger.debug(
|
|
166
|
-
"Catcher {!r} returned: {!r}",
|
|
167
|
-
self.catcher.func.__name__,
|
|
168
|
-
value,
|
|
169
|
-
)
|
|
170
|
-
return value
|
|
171
|
-
case Error(exc):
|
|
172
|
-
if isinstance(exc, CatcherError):
|
|
173
|
-
return self._process_catcher_error(exc).unwrap()
|
|
174
|
-
if self.catcher.ignore_errors:
|
|
175
|
-
return None
|
|
176
|
-
raise exc from None
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
__all__ = ("Catcher", "ErrorHandler")
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import dataclasses
|
|
2
|
-
import typing
|
|
3
|
-
|
|
4
|
-
from telegrinder.types.enums import ProgrammingLanguage
|
|
5
|
-
|
|
6
|
-
SpecialFormat: typing.TypeAlias = typing.Union[
|
|
7
|
-
"BlockQuote",
|
|
8
|
-
"Link",
|
|
9
|
-
"Mention",
|
|
10
|
-
"PreCode",
|
|
11
|
-
"TgEmoji",
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def is_spec_format(obj: typing.Any) -> typing.TypeGuard[SpecialFormat]:
|
|
16
|
-
return dataclasses.is_dataclass(obj) and hasattr(obj, "__formatter_name__") and isinstance(obj, Base)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@dataclasses.dataclass(repr=False)
|
|
20
|
-
class Base:
|
|
21
|
-
__formatter_name__: typing.ClassVar[str] = dataclasses.field(init=False, repr=False)
|
|
22
|
-
|
|
23
|
-
def __repr__(self) -> str:
|
|
24
|
-
return f"<Special formatter {self.__class__.__name__!r} -> {self.__formatter_name__!r}>"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@dataclasses.dataclass(repr=False, slots=True)
|
|
28
|
-
class Mention(Base):
|
|
29
|
-
__formatter_name__ = "mention"
|
|
30
|
-
|
|
31
|
-
string: str
|
|
32
|
-
user_id: int
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@dataclasses.dataclass(repr=False, slots=True)
|
|
36
|
-
class Link(Base):
|
|
37
|
-
__formatter_name__ = "link"
|
|
38
|
-
|
|
39
|
-
href: str
|
|
40
|
-
string: str | None = None
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@dataclasses.dataclass(repr=False, slots=True)
|
|
44
|
-
class PreCode(Base):
|
|
45
|
-
__formatter_name__ = "pre_code"
|
|
46
|
-
|
|
47
|
-
string: str
|
|
48
|
-
lang: str | ProgrammingLanguage | None = None
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
@dataclasses.dataclass(repr=False, slots=True)
|
|
52
|
-
class TgEmoji(Base):
|
|
53
|
-
__formatter_name__ = "tg_emoji"
|
|
54
|
-
|
|
55
|
-
string: str
|
|
56
|
-
emoji_id: int
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
@dataclasses.dataclass(repr=False, slots=True)
|
|
60
|
-
class BlockQuote(Base):
|
|
61
|
-
__formatter_name__ = "block_quote"
|
|
62
|
-
|
|
63
|
-
string: str
|
|
64
|
-
expandable: bool = False
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
__all__ = (
|
|
68
|
-
"Base",
|
|
69
|
-
"BlockQuote",
|
|
70
|
-
"Link",
|
|
71
|
-
"Mention",
|
|
72
|
-
"PreCode",
|
|
73
|
-
"SpecialFormat",
|
|
74
|
-
"TgEmoji",
|
|
75
|
-
)
|
telegrinder/tools/functional.py
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
|
|
3
|
-
import vbml
|
|
4
|
-
|
|
5
|
-
from telegrinder.tools.global_context import GlobalContext, ctx_var
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class TelegrinderContext(GlobalContext):
|
|
9
|
-
"""Basic type-hinted telegrinder context with context name `"telegrinder"`.
|
|
10
|
-
|
|
11
|
-
You can use this class or GlobalContext:
|
|
12
|
-
```
|
|
13
|
-
from telegrinder.tools.global_context import GlobalContext, TelegrinderContext
|
|
14
|
-
|
|
15
|
-
ctx1 = TelegrinderContext()
|
|
16
|
-
ctx2 = GlobalContext("telegrinder") # same, but without the type-hints
|
|
17
|
-
assert ctx1 == ctx2 # ok
|
|
18
|
-
```
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
__ctx_name__ = "telegrinder"
|
|
22
|
-
|
|
23
|
-
vbml_pattern_flags: re.RegexFlag | None = None
|
|
24
|
-
vbml_patcher: vbml.Patcher = ctx_var(default=vbml.Patcher(), frozen=True)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
__all__ = ("TelegrinderContext",)
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
from .abc import ABCI18n, ABCTranslator, I18nEnum
|
|
2
|
-
from .middleware import ABCTranslatorMiddleware
|
|
3
|
-
from .simple import SimpleI18n, SimpleTranslator
|
|
4
|
-
|
|
5
|
-
__all__ = (
|
|
6
|
-
"ABCI18n",
|
|
7
|
-
"ABCTranslator",
|
|
8
|
-
"ABCTranslatorMiddleware",
|
|
9
|
-
"I18nEnum",
|
|
10
|
-
"SimpleI18n",
|
|
11
|
-
"SimpleTranslator",
|
|
12
|
-
)
|
telegrinder/tools/i18n/abc.py
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import enum
|
|
2
|
-
import typing
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class ABCI18n(ABC):
|
|
7
|
-
@abstractmethod
|
|
8
|
-
def get_translator_by_locale(self, locale: str) -> "ABCTranslator":
|
|
9
|
-
pass
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ABCTranslator(ABC):
|
|
13
|
-
def __init__(self, locale: str, **kwargs: typing.Any) -> None:
|
|
14
|
-
self.locale = locale
|
|
15
|
-
|
|
16
|
-
@abstractmethod
|
|
17
|
-
def get(self, __key: str, *args: typing.Any, **kwargs: typing.Any) -> str:
|
|
18
|
-
"""This translates a key to actual human-readable string"""
|
|
19
|
-
|
|
20
|
-
def __call__(self, __key: str, *args: typing.Any, **kwargs: typing.Any) -> str:
|
|
21
|
-
return self.get(__key, *args, **kwargs)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class I18nEnum(enum.Enum):
|
|
25
|
-
I18N = "_"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
__all__ = (
|
|
29
|
-
"ABCI18n",
|
|
30
|
-
"ABCTranslator",
|
|
31
|
-
"I18nEnum",
|
|
32
|
-
)
|