telegrinder 0.1.dev158__py3-none-any.whl → 0.1.dev160__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 +6 -4
- telegrinder/api/api.py +25 -11
- 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 +100 -9
- telegrinder/bot/cute_types/callback_query.py +426 -37
- telegrinder/bot/cute_types/inline_query.py +44 -17
- telegrinder/bot/cute_types/message.py +2885 -117
- telegrinder/bot/cute_types/update.py +14 -7
- telegrinder/bot/cute_types/utils.py +542 -0
- 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 +40 -29
- 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 +12 -6
- 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 +0 -0
- telegrinder/bot/scenario/abc.py +0 -0
- telegrinder/bot/scenario/checkbox.py +0 -0
- telegrinder/bot/scenario/choice.py +0 -0
- telegrinder/client/__init__.py +2 -2
- telegrinder/client/abc.py +35 -12
- telegrinder/client/aiohttp.py +35 -22
- telegrinder/model.py +70 -23
- telegrinder/modules.py +22 -12
- telegrinder/msgspec_json.py +0 -0
- telegrinder/msgspec_utils.py +30 -10
- 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 -30
- telegrinder/tools/buttons.py +19 -5
- 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 +13 -9
- telegrinder/types/methods.py +783 -673
- telegrinder/types/objects.py +317 -163
- {telegrinder-0.1.dev158.dist-info → telegrinder-0.1.dev160.dist-info}/LICENSE +0 -0
- {telegrinder-0.1.dev158.dist-info → telegrinder-0.1.dev160.dist-info}/METADATA +9 -7
- {telegrinder-0.1.dev158.dist-info → telegrinder-0.1.dev160.dist-info}/RECORD +42 -41
- {telegrinder-0.1.dev158.dist-info → telegrinder-0.1.dev160.dist-info}/WHEEL +1 -1
- telegrinder/tools/inline_query.py +0 -684
|
@@ -16,6 +16,12 @@ from telegrinder.msgspec_utils import Option
|
|
|
16
16
|
from telegrinder.types.objects import Update
|
|
17
17
|
|
|
18
18
|
EventType = typing.TypeVar("EventType", bound=BaseCute)
|
|
19
|
+
MiddlewareT = typing.TypeVar("MiddlewareT", bound=ABCMiddleware)
|
|
20
|
+
|
|
21
|
+
FuncType: typing.TypeAlias = typing.Callable[
|
|
22
|
+
typing.Concatenate[EventType, ...],
|
|
23
|
+
typing.Coroutine[typing.Any, typing.Any, typing.Any],
|
|
24
|
+
]
|
|
19
25
|
|
|
20
26
|
|
|
21
27
|
class ABCView(ABC):
|
|
@@ -40,7 +46,7 @@ class ABCStateView(ABCView, typing.Generic[EventType]):
|
|
|
40
46
|
def __repr__(self) -> str:
|
|
41
47
|
return "<{!r}: {}>".format(
|
|
42
48
|
self.__class__.__name__,
|
|
43
|
-
", ".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()),
|
|
44
50
|
)
|
|
45
51
|
|
|
46
52
|
|
|
@@ -55,21 +61,19 @@ class BaseView(ABCView, typing.Generic[EventType]):
|
|
|
55
61
|
for base in cls.__dict__.get("__orig_bases__", ()):
|
|
56
62
|
if issubclass(typing.get_origin(base) or base, ABCView):
|
|
57
63
|
for generic_type in typing.get_args(base):
|
|
58
|
-
if issubclass(
|
|
64
|
+
if issubclass(
|
|
65
|
+
typing.get_origin(generic_type) or generic_type, BaseCute
|
|
66
|
+
):
|
|
59
67
|
return Some(generic_type)
|
|
60
68
|
return Nothing()
|
|
61
|
-
|
|
69
|
+
|
|
62
70
|
@classmethod
|
|
63
|
-
def
|
|
64
|
-
match
|
|
65
|
-
case Some(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
event_raw = event_raw.unwrap_or_none()
|
|
70
|
-
if event_raw is not None and issubclass(event_type, event_raw.__class__):
|
|
71
|
-
return Some(event_raw)
|
|
72
|
-
return Nothing()
|
|
71
|
+
def get_raw_event(cls, update: Update) -> Option[Model]:
|
|
72
|
+
match update.update_type:
|
|
73
|
+
case Some(update_type):
|
|
74
|
+
return getattr(update, update_type.value)
|
|
75
|
+
case _:
|
|
76
|
+
return Nothing()
|
|
73
77
|
|
|
74
78
|
def __call__(
|
|
75
79
|
self,
|
|
@@ -77,13 +81,8 @@ class BaseView(ABCView, typing.Generic[EventType]):
|
|
|
77
81
|
is_blocking: bool = True,
|
|
78
82
|
error_handler: ErrorHandlerT | None = None,
|
|
79
83
|
):
|
|
80
|
-
def wrapper(
|
|
81
|
-
|
|
82
|
-
typing.Concatenate[EventType, ...],
|
|
83
|
-
typing.Coroutine,
|
|
84
|
-
]
|
|
85
|
-
):
|
|
86
|
-
func_handler = FuncHandler(
|
|
84
|
+
def wrapper(func: FuncType[EventType]):
|
|
85
|
+
func_handler = FuncHandler[EventType, FuncType[EventType], ErrorHandlerT](
|
|
87
86
|
func,
|
|
88
87
|
[*self.auto_rules, *rules],
|
|
89
88
|
is_blocking,
|
|
@@ -94,22 +93,34 @@ class BaseView(ABCView, typing.Generic[EventType]):
|
|
|
94
93
|
return func_handler
|
|
95
94
|
|
|
96
95
|
return wrapper
|
|
97
|
-
|
|
96
|
+
|
|
98
97
|
def register_middleware(self, *args: typing.Any, **kwargs: typing.Any):
|
|
99
|
-
def wrapper(cls: type[
|
|
98
|
+
def wrapper(cls: type[MiddlewareT]) -> type[MiddlewareT]:
|
|
100
99
|
self.middlewares.append(cls(*args, **kwargs))
|
|
101
100
|
return cls
|
|
102
|
-
|
|
101
|
+
|
|
103
102
|
return wrapper
|
|
104
|
-
|
|
103
|
+
|
|
105
104
|
async def check(self, event: Update) -> bool:
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
match self.get_raw_event(event):
|
|
106
|
+
case Some(e) if issubclass(
|
|
107
|
+
self.get_event_type().expect(
|
|
108
|
+
"{!r} has no event type in generic.".format(self.__class__.__name__),
|
|
109
|
+
),
|
|
110
|
+
e.__class__,
|
|
111
|
+
):
|
|
112
|
+
return True
|
|
113
|
+
case _:
|
|
114
|
+
return False
|
|
115
|
+
|
|
108
116
|
async def process(self, event: Update, api: ABCAPI) -> bool:
|
|
109
|
-
event_raw = self.get_event_raw(event).unwrap()
|
|
110
|
-
event_type = self.get_event_type().unwrap()
|
|
111
117
|
return await process_inner(
|
|
112
|
-
|
|
118
|
+
self.get_event_type()
|
|
119
|
+
.unwrap()
|
|
120
|
+
.from_update(
|
|
121
|
+
update=self.get_raw_event(event).unwrap(),
|
|
122
|
+
bound_api=api,
|
|
123
|
+
),
|
|
113
124
|
event,
|
|
114
125
|
self.middlewares,
|
|
115
126
|
self.handlers,
|
|
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
|
|
@@ -14,14 +14,20 @@ CuteT = typing.TypeVar("CuteT", bound=BaseCute)
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class EventAdapter(ABCAdapter[Update, CuteT]):
|
|
17
|
-
def __init__(self, event_name: str, model: type[CuteT]):
|
|
17
|
+
def __init__(self, event_name: str, model: type[CuteT]) -> None:
|
|
18
18
|
self.event_name = event_name
|
|
19
19
|
self.model = model
|
|
20
20
|
|
|
21
21
|
def __repr__(self) -> str:
|
|
22
|
-
|
|
22
|
+
raw_update_type = Update.__annotations__.get(self.event_name, "Unknown")
|
|
23
|
+
raw_update_type = (
|
|
24
|
+
typing.get_args(raw_update_type)[0].__forward_arg__
|
|
25
|
+
if typing.get_args(raw_update_type)
|
|
26
|
+
else raw_update_type
|
|
27
|
+
)
|
|
28
|
+
return "<{}: adapt {} -> {}>".format(
|
|
23
29
|
self.__class__.__name__,
|
|
24
|
-
|
|
30
|
+
raw_update_type,
|
|
25
31
|
self.model.__name__,
|
|
26
32
|
)
|
|
27
33
|
|
|
@@ -29,14 +35,14 @@ class EventAdapter(ABCAdapter[Update, CuteT]):
|
|
|
29
35
|
update_dct = update.to_dict()
|
|
30
36
|
if self.event_name not in update_dct:
|
|
31
37
|
return Error(
|
|
32
|
-
AdapterError(f"Update is not of event type {self.event_name!r}.")
|
|
38
|
+
AdapterError(f"Update is not of event type {self.event_name!r}."),
|
|
33
39
|
)
|
|
34
40
|
if update_dct[self.event_name] is Nothing:
|
|
35
41
|
return Error(
|
|
36
|
-
AdapterError(f"Update is not an {self.event_name!r}.")
|
|
42
|
+
AdapterError(f"Update is not an {self.event_name!r}."),
|
|
37
43
|
)
|
|
38
44
|
return Ok(
|
|
39
|
-
self.model.from_update(update_dct[self.event_name].unwrap(), bound_api=api)
|
|
45
|
+
self.model.from_update(update_dct[self.event_name].unwrap(), bound_api=api),
|
|
40
46
|
)
|
|
41
47
|
|
|
42
48
|
|
|
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
|
|
File without changes
|
telegrinder/bot/scenario/abc.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
telegrinder/client/__init__.py
CHANGED
telegrinder/client/abc.py
CHANGED
|
@@ -1,35 +1,49 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
3
|
|
|
4
|
-
ClientData = typing.Any
|
|
5
|
-
|
|
6
4
|
|
|
7
5
|
class ABCClient(ABC):
|
|
8
6
|
@abstractmethod
|
|
9
|
-
def __init__(self, *args, **kwargs):
|
|
7
|
+
def __init__(self, *args: typing.Any, **kwargs: typing.Any):
|
|
10
8
|
pass
|
|
11
9
|
|
|
12
10
|
@abstractmethod
|
|
13
11
|
async def request_text(
|
|
14
|
-
self,
|
|
12
|
+
self,
|
|
13
|
+
url: str,
|
|
14
|
+
method: str = "GET",
|
|
15
|
+
data: dict[str, typing.Any] | None = None,
|
|
16
|
+
**kwargs: typing.Any,
|
|
15
17
|
) -> str:
|
|
16
18
|
pass
|
|
17
19
|
|
|
18
20
|
@abstractmethod
|
|
19
21
|
async def request_json(
|
|
20
|
-
self,
|
|
21
|
-
|
|
22
|
+
self,
|
|
23
|
+
url: str,
|
|
24
|
+
method: str = "GET",
|
|
25
|
+
data: dict[str, typing.Any] | None = None,
|
|
26
|
+
**kwargs: typing.Any,
|
|
27
|
+
) -> dict[str, typing.Any]:
|
|
22
28
|
pass
|
|
23
29
|
|
|
24
30
|
@abstractmethod
|
|
25
31
|
async def request_content(
|
|
26
|
-
self,
|
|
32
|
+
self,
|
|
33
|
+
url: str,
|
|
34
|
+
method: str = "GET",
|
|
35
|
+
data: dict[str, typing.Any] | None = None,
|
|
36
|
+
**kwargs: typing.Any,
|
|
27
37
|
) -> bytes:
|
|
28
38
|
pass
|
|
29
39
|
|
|
30
40
|
@abstractmethod
|
|
31
41
|
async def request_bytes(
|
|
32
|
-
self,
|
|
42
|
+
self,
|
|
43
|
+
url: str,
|
|
44
|
+
method: str = "GET",
|
|
45
|
+
data: dict[str, typing.Any] | None = None,
|
|
46
|
+
**kwargs: typing.Any,
|
|
33
47
|
) -> bytes:
|
|
34
48
|
pass
|
|
35
49
|
|
|
@@ -39,14 +53,23 @@ class ABCClient(ABC):
|
|
|
39
53
|
|
|
40
54
|
@classmethod
|
|
41
55
|
@abstractmethod
|
|
42
|
-
def get_form(
|
|
56
|
+
def get_form(
|
|
57
|
+
cls,
|
|
58
|
+
data: dict[str, typing.Any],
|
|
59
|
+
files: dict[str, tuple[str, bytes]] | None = None,
|
|
60
|
+
) -> typing.Any:
|
|
43
61
|
pass
|
|
44
62
|
|
|
45
|
-
async def __aenter__(self) ->
|
|
63
|
+
async def __aenter__(self) -> typing.Self:
|
|
46
64
|
return self
|
|
47
65
|
|
|
48
|
-
async def __aexit__(
|
|
66
|
+
async def __aexit__(
|
|
67
|
+
self,
|
|
68
|
+
exc_type: type[BaseException],
|
|
69
|
+
exc_val: typing.Any,
|
|
70
|
+
exc_tb: typing.Any,
|
|
71
|
+
) -> None:
|
|
49
72
|
await self.close()
|
|
50
73
|
|
|
51
74
|
|
|
52
|
-
__all__ = ("ABCClient",
|
|
75
|
+
__all__ = ("ABCClient",)
|
telegrinder/client/aiohttp.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import secrets
|
|
1
2
|
import ssl
|
|
2
3
|
import typing
|
|
3
4
|
|
|
@@ -18,19 +19,27 @@ class AiohttpClient(ABCClient):
|
|
|
18
19
|
session: ClientSession | None = None,
|
|
19
20
|
json_processing_module: JSONModule | None = None,
|
|
20
21
|
timeout: aiohttp.ClientTimeout | None = None,
|
|
21
|
-
**session_params,
|
|
22
|
-
):
|
|
22
|
+
**session_params: typing.Any,
|
|
23
|
+
) -> None:
|
|
23
24
|
self.session = session
|
|
24
25
|
self.json_processing_module = json_processing_module or json
|
|
25
26
|
self.session_params = session_params
|
|
26
27
|
self.timeout = timeout or aiohttp.ClientTimeout(total=0)
|
|
27
|
-
|
|
28
|
+
|
|
29
|
+
def __repr__(self) -> str:
|
|
30
|
+
return "<{}: session={!r}, timeout={}, closed={}>".format(
|
|
31
|
+
self.__class__.__name__,
|
|
32
|
+
self.session,
|
|
33
|
+
self.timeout,
|
|
34
|
+
False if self.session is None else self.session.closed,
|
|
35
|
+
)
|
|
36
|
+
|
|
28
37
|
async def request_raw(
|
|
29
38
|
self,
|
|
30
39
|
url: str,
|
|
31
40
|
method: str = "GET",
|
|
32
|
-
data: dict | None = None,
|
|
33
|
-
**kwargs,
|
|
41
|
+
data: dict[str, typing.Any] | None = None,
|
|
42
|
+
**kwargs: typing.Any,
|
|
34
43
|
) -> "ClientResponse":
|
|
35
44
|
if not self.session:
|
|
36
45
|
self.session = ClientSession(
|
|
@@ -54,9 +63,9 @@ class AiohttpClient(ABCClient):
|
|
|
54
63
|
self,
|
|
55
64
|
url: str,
|
|
56
65
|
method: str = "GET",
|
|
57
|
-
data: dict | None = None,
|
|
58
|
-
**kwargs,
|
|
59
|
-
) -> dict:
|
|
66
|
+
data: dict[str, typing.Any] | None = None,
|
|
67
|
+
**kwargs: typing.Any,
|
|
68
|
+
) -> dict[str, typing.Any]:
|
|
60
69
|
response = await self.request_raw(url, method, data, **kwargs)
|
|
61
70
|
return await response.json(
|
|
62
71
|
encoding="utf-8",
|
|
@@ -68,8 +77,8 @@ class AiohttpClient(ABCClient):
|
|
|
68
77
|
self,
|
|
69
78
|
url: str,
|
|
70
79
|
method: str = "GET",
|
|
71
|
-
data: dict | aiohttp.FormData | None = None,
|
|
72
|
-
**kwargs,
|
|
80
|
+
data: dict[str, typing.Any] | aiohttp.FormData | None = None,
|
|
81
|
+
**kwargs: typing.Any,
|
|
73
82
|
) -> str:
|
|
74
83
|
response = await self.request_raw(url, method, data, **kwargs) # type: ignore
|
|
75
84
|
return await response.text(encoding="utf-8")
|
|
@@ -78,8 +87,8 @@ class AiohttpClient(ABCClient):
|
|
|
78
87
|
self,
|
|
79
88
|
url: str,
|
|
80
89
|
method: str = "GET",
|
|
81
|
-
data: dict | aiohttp.FormData | None = None,
|
|
82
|
-
**kwargs,
|
|
90
|
+
data: dict[str, typing.Any] | aiohttp.FormData | None = None,
|
|
91
|
+
**kwargs: typing.Any,
|
|
83
92
|
) -> bytes:
|
|
84
93
|
response = await self.request_raw(url, method, data, **kwargs) # type: ignore
|
|
85
94
|
if response._body is None:
|
|
@@ -90,8 +99,8 @@ class AiohttpClient(ABCClient):
|
|
|
90
99
|
self,
|
|
91
100
|
url: str,
|
|
92
101
|
method: str = "GET",
|
|
93
|
-
data: dict | None = None,
|
|
94
|
-
**kwargs,
|
|
102
|
+
data: dict[str, typing.Any] | None = None,
|
|
103
|
+
**kwargs: typing.Any,
|
|
95
104
|
) -> bytes:
|
|
96
105
|
response = await self.request_raw(url, method, data, **kwargs)
|
|
97
106
|
return response._body
|
|
@@ -101,18 +110,22 @@ class AiohttpClient(ABCClient):
|
|
|
101
110
|
await self.session.close()
|
|
102
111
|
|
|
103
112
|
@classmethod
|
|
104
|
-
def get_form(
|
|
113
|
+
def get_form(
|
|
114
|
+
cls,
|
|
115
|
+
data: dict[str, typing.Any],
|
|
116
|
+
files: dict[str, tuple[str, bytes]] | None = None,
|
|
117
|
+
) -> aiohttp.formdata.FormData:
|
|
118
|
+
files = files or {}
|
|
105
119
|
form = aiohttp.formdata.FormData(quote_fields=False)
|
|
106
120
|
for k, v in data.items():
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
form.add_field(k, v, **params)
|
|
121
|
+
form.add_field(k, str(v))
|
|
122
|
+
|
|
123
|
+
for n, f in files.items():
|
|
124
|
+
form.add_field(n, f[1], filename=f[0])
|
|
125
|
+
|
|
113
126
|
return form
|
|
114
127
|
|
|
115
|
-
def __del__(self):
|
|
128
|
+
def __del__(self) -> None:
|
|
116
129
|
if self.session and not self.session.closed:
|
|
117
130
|
if self.session._connector is not None and self.session._connector_owner:
|
|
118
131
|
self.session._connector.close()
|