telegrinder 0.1.dev161__py3-none-any.whl → 0.1.dev163__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.

Files changed (35) hide show
  1. telegrinder/api/api.py +4 -2
  2. telegrinder/api/error.py +3 -3
  3. telegrinder/bot/bot.py +8 -12
  4. telegrinder/bot/cute_types/base.py +1 -4
  5. telegrinder/bot/cute_types/message.py +140 -0
  6. telegrinder/bot/dispatch/composition.py +1 -1
  7. telegrinder/bot/dispatch/dispatch.py +3 -4
  8. telegrinder/bot/dispatch/view/box.py +6 -6
  9. telegrinder/bot/dispatch/waiter_machine/short_state.py +1 -1
  10. telegrinder/bot/rules/__init__.py +4 -0
  11. telegrinder/bot/rules/is_from.py +18 -3
  12. telegrinder/bot/scenario/checkbox.py +3 -4
  13. telegrinder/client/aiohttp.py +1 -2
  14. telegrinder/modules.py +5 -3
  15. telegrinder/msgspec_json.py +3 -3
  16. telegrinder/msgspec_utils.py +80 -38
  17. telegrinder/node/source.py +2 -3
  18. telegrinder/tools/__init__.py +6 -0
  19. telegrinder/tools/buttons.py +8 -13
  20. telegrinder/tools/error_handler/error_handler.py +2 -2
  21. telegrinder/tools/formatting/__init__.py +6 -0
  22. telegrinder/tools/formatting/html.py +10 -0
  23. telegrinder/tools/formatting/links.py +7 -0
  24. telegrinder/tools/formatting/spec_html_formats.py +27 -15
  25. telegrinder/tools/global_context/global_context.py +7 -5
  26. telegrinder/tools/keyboard.py +3 -3
  27. telegrinder/tools/loop_wrapper/abc.py +4 -4
  28. telegrinder/tools/magic.py +1 -1
  29. telegrinder/types/enums.py +4 -0
  30. telegrinder/types/methods.py +175 -41
  31. telegrinder/types/objects.py +442 -201
  32. {telegrinder-0.1.dev161.dist-info → telegrinder-0.1.dev163.dist-info}/METADATA +1 -1
  33. {telegrinder-0.1.dev161.dist-info → telegrinder-0.1.dev163.dist-info}/RECORD +35 -35
  34. {telegrinder-0.1.dev161.dist-info → telegrinder-0.1.dev163.dist-info}/WHEEL +1 -1
  35. {telegrinder-0.1.dev161.dist-info → telegrinder-0.1.dev163.dist-info}/LICENSE +0 -0
telegrinder/api/api.py CHANGED
@@ -16,7 +16,7 @@ def compose_data(
16
16
  data: dict[str, typing.Any],
17
17
  files: dict[str, tuple[str, bytes]],
18
18
  ) -> typing.Any:
19
- converter = DataConverter(files=files)
19
+ converter = DataConverter(files=files.copy())
20
20
  return client.get_form(
21
21
  data={k: converter(v) for k, v in data.items()},
22
22
  files=converter.files,
@@ -24,6 +24,8 @@ def compose_data(
24
24
 
25
25
 
26
26
  class API(ABCAPI, APIMethods):
27
+ """Bot API with available API methods."""
28
+
27
29
  API_URL = "https://api.telegram.org/"
28
30
 
29
31
  def __init__(self, token: Token, *, http: ABCClient | None = None) -> None:
@@ -60,7 +62,7 @@ class API(ABCAPI, APIMethods):
60
62
  assert "result" in response
61
63
  return Ok(response["result"])
62
64
  return Error(APIError(
63
- code=response.get("error_code", 0),
65
+ code=response.get("error_code", 400),
64
66
  error=response.get("description"),
65
67
  ))
66
68
 
telegrinder/api/error.py CHANGED
@@ -1,12 +1,12 @@
1
1
  class APIError(BaseException):
2
- def __init__(self, code: int, error: str | None = None):
2
+ def __init__(self, code: int, error: str | None = None) -> None:
3
3
  self.code, self.error = code, error
4
4
 
5
5
  def __str__(self) -> str:
6
- return f"[{self.code}] {self.error}"
6
+ return f"[{self.code}] {self.error or 'Something went wrong'}"
7
7
 
8
8
  def __repr__(self) -> str:
9
- return f"<APIError {self.__str__()}>"
9
+ return f"<APIError: {self.__str__()}>"
10
10
 
11
11
 
12
12
  class InvalidTokenError(BaseException):
telegrinder/bot/bot.py CHANGED
@@ -11,11 +11,7 @@ PollingT = typing.TypeVar("PollingT", bound=ABCPolling, default=Polling)
11
11
  LoopWrapperT = typing.TypeVar("LoopWrapperT", bound=ABCLoopWrapper, default=LoopWrapper)
12
12
 
13
13
 
14
- class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
15
- dispatch: DispatchT
16
- polling: PollingT
17
- loop_wrapper: LoopWrapperT
18
-
14
+ class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
19
15
  def __init__(
20
16
  self,
21
17
  api: API,
@@ -23,11 +19,11 @@ class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
23
19
  polling: PollingT | None = None,
24
20
  dispatch: DispatchT | None = None,
25
21
  loop_wrapper: LoopWrapperT | None = None,
26
- ):
22
+ ) -> None:
27
23
  self.api = api
28
- self.dispatch = dispatch or Dispatch() # type: ignore
29
- self.polling = polling or Polling(api) # type: ignore
30
- self.loop_wrapper = loop_wrapper or LoopWrapper() # type: ignore
24
+ self.dispatch = typing.cast(DispatchT, dispatch or Dispatch())
25
+ self.polling = typing.cast(PollingT, polling or Polling(api))
26
+ self.loop_wrapper = typing.cast(LoopWrapperT, loop_wrapper or LoopWrapper())
31
27
 
32
28
  @property
33
29
  def on(self) -> DispatchT:
@@ -38,7 +34,7 @@ class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
38
34
  return
39
35
  await self.api.delete_webhook()
40
36
 
41
- async def run_polling(self, offset: int = 0, skip_updates: bool = False) -> None:
37
+ async def run_polling(self, *, offset: int = 0, skip_updates: bool = False) -> None:
42
38
  if skip_updates:
43
39
  logger.debug("Dropping pending updates")
44
40
  await self.reset_webhook()
@@ -50,9 +46,9 @@ class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
50
46
  logger.debug("Received update (update_id={})", update.update_id)
51
47
  self.loop_wrapper.add_task(self.dispatch.feed(update, self.api))
52
48
 
53
- def run_forever(self, offset: int = 0, skip_updates: bool = False) -> None:
49
+ def run_forever(self, *, offset: int = 0, skip_updates: bool = False) -> None:
54
50
  logger.debug("Running blocking polling (id={})", self.api.id)
55
- self.loop_wrapper.add_task(self.run_polling(offset, skip_updates=skip_updates))
51
+ self.loop_wrapper.add_task(self.run_polling(offset=offset, skip_updates=skip_updates))
56
52
  self.loop_wrapper.run_event_loop()
57
53
 
58
54
 
@@ -33,8 +33,6 @@ if typing.TYPE_CHECKING:
33
33
  else:
34
34
 
35
35
  class BaseCute(typing.Generic[UpdateT]):
36
- api: ABCAPI
37
-
38
36
  @classmethod
39
37
  def from_update(cls, update, bound_api):
40
38
  return cls(**update.to_dict(), api=bound_api)
@@ -115,8 +113,7 @@ def shortcut(
115
113
  params[k] = kwargs.pop(k, p.default) if p.default is not p.empty else kwargs.pop(k)
116
114
 
117
115
  return await executor(self, method_name, get_params(params))
118
-
119
- func.__repr__ = lambda _: f"<Shortcut {method_name!r}@{func!r}>"
116
+
120
117
  inner.__shortcut__ = Shortcut( # type: ignore
121
118
  method_name=method_name,
122
119
  executor=executor,