telekit 2.2.0a2__tar.gz → 2.2.0a3__tar.gz

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.
Files changed (70) hide show
  1. {telekit-2.2.0a2/telekit.egg-info → telekit-2.2.0a3}/PKG-INFO +22 -2
  2. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_chain.py +1 -4
  3. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_chain_base.py +6 -0
  4. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_chain_entry_logic.py +12 -0
  5. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_chain_inline_keyboards_logic.py +41 -20
  6. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_inline_buttons.py +132 -4
  7. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/mixin.py +2 -2
  8. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_version.py +1 -1
  9. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/pages.py +12 -5
  10. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/inline_buttons.py +2 -0
  11. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/senders.py +277 -66
  12. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/types.py +43 -30
  13. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/utils.py +25 -0
  14. {telekit-2.2.0a2 → telekit-2.2.0a3/telekit.egg-info}/PKG-INFO +22 -2
  15. {telekit-2.2.0a2 → telekit-2.2.0a3}/LICENSE +0 -0
  16. {telekit-2.2.0a2 → telekit-2.2.0a3}/README.md +0 -0
  17. {telekit-2.2.0a2 → telekit-2.2.0a3}/setup.cfg +0 -0
  18. {telekit-2.2.0a2 → telekit-2.2.0a3}/setup.py +0 -0
  19. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/__init__.py +0 -0
  20. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_buildtext/__init__.py +0 -0
  21. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_buildtext/formatter.py +0 -0
  22. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_buildtext/styles.py +0 -0
  23. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_callback_query_handler.py +0 -0
  24. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_chapters/__init__.py +0 -0
  25. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_chapters/chapters.py +0 -0
  26. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_handler.py +0 -0
  27. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_init.py +0 -0
  28. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_input_handler.py +0 -0
  29. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_logger.py +0 -0
  30. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_on.py +0 -0
  31. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_snapvault/__init__.py +0 -0
  32. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_snapvault/snapcode.py +0 -0
  33. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_snapvault/snapvault.py +0 -0
  34. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_state.py +0 -0
  35. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/__init__.py +0 -0
  36. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/parser/__init__.py +0 -0
  37. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/parser/builder.py +0 -0
  38. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/parser/canvas_parser.py +0 -0
  39. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/parser/lexer.py +0 -0
  40. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/parser/nodes.py +0 -0
  41. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/parser/parser.py +0 -0
  42. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/parser/token.py +0 -0
  43. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/telekit_dsl.py +0 -0
  44. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_telekit_dsl/telekit_orm.py +0 -0
  45. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_timeout.py +0 -0
  46. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/_user.py +0 -0
  47. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/dices.py +0 -0
  48. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/__init__.py +0 -0
  49. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/__init__.py +0 -0
  50. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/complete_hotel.py +0 -0
  51. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/counter.py +0 -0
  52. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/dsl.py +0 -0
  53. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/entry.py +0 -0
  54. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/faq.py +0 -0
  55. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/hotel.py +0 -0
  56. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/on_text.py +0 -0
  57. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/pyapi.py +0 -0
  58. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/qr.py +0 -0
  59. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/quiz.py +0 -0
  60. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/spells.py +0 -0
  61. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/start.py +0 -0
  62. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_handlers/text_document.py +0 -0
  63. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/example/example_server.py +0 -0
  64. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/parameters.py +0 -0
  65. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/server.py +0 -0
  66. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit/styles.py +0 -0
  67. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit.egg-info/SOURCES.txt +0 -0
  68. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit.egg-info/dependency_links.txt +0 -0
  69. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit.egg-info/requires.txt +0 -0
  70. {telekit-2.2.0a2 → telekit-2.2.0a3}/telekit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: telekit
3
- Version: 2.2.0a2
3
+ Version: 2.2.0a3
4
4
  Summary: Declarative, developer-friendly library for building Telegram bots
5
5
  Home-page: https://github.com/Romashkaa/telekit
6
6
  Author: romashka
@@ -378,7 +378,7 @@ It tries to make Telegram bot development easier.
378
378
 
379
379
  ---
380
380
 
381
- # Changes in version 2.2.0a2
381
+ # Changes in version 2.2.0a3
382
382
 
383
383
  ## New Button Types
384
384
 
@@ -386,6 +386,7 @@ It tries to make Telegram bot development easier.
386
386
  |----------------------|----------------------------------------------------------|
387
387
  | `AlertButton` | A callback button that shows a popup alert when pressed. |
388
388
  | `NotificationButton` | A callback button that shows a notification. |
389
+ | `InvokeButton` | A callback button that calls the object method. |
389
390
 
390
391
  ## User Improvements
391
392
 
@@ -404,3 +405,22 @@ It tries to make Telegram bot development easier.
404
405
 
405
406
  - Refactor: `User` now accepts a `Message` object instead of `chat_id` + `from_user`. All properties are derived from `_sender` (`from_user` or `chat`) and migrated to `cached_property`. Fixed broken `get_id` and `get_full_name` references.
406
407
  - Added `__repr__`.
408
+
409
+ ## Sender Improvements
410
+
411
+ | **Name** | **Description** |
412
+ | -------------------------- | ------------------------------------------------------ |
413
+ | `sent_message` | The last message sent by this sender instance. |
414
+ | `disable_notification` | Disables notification sound when the message is sent. |
415
+ | `protect_content` | Protects the message contents from forwarding and saving. |
416
+ | `reply_parameters` | Reply parameters for the message to be sent. |
417
+ | `link_preview_options` | Link preview options for the message to be sent. |
418
+ | `show_caption_above_media` | Shows the caption above the media instead of below. |
419
+
420
+ - Refactored sending system.
421
+
422
+ ## Chain Improvements
423
+
424
+ | **Name** | **Description** |
425
+ | ----------- | ------------------------------------------------------------ |
426
+ | `received` | The message received from the user during entry processing. |
@@ -28,11 +28,8 @@ from telebot.types import Message
28
28
  from . import senders
29
29
  from .styles import TextEntity
30
30
 
31
- # Logging
32
- from ._logger import logger
33
- library = logger.library
34
-
35
31
  # Chain modules
32
+ from ._chain_base import library
36
33
  from ._chain_inline_keyboards_logic import ChainInlineKeyboardLogic
37
34
  from ._chain_entry_logic import ChainEntryLogic, TextDocument
38
35
 
@@ -30,6 +30,10 @@ from . import senders
30
30
  from . import _input_handler
31
31
  from . import _timeout
32
32
 
33
+ # Logging
34
+ from ._logger import logger
35
+ library = logger.library
36
+
33
37
  class ChainBase:
34
38
 
35
39
  bot: telebot.TeleBot
@@ -49,6 +53,8 @@ class ChainBase:
49
53
  def __init__(self, chat_id: int, *, previous_message: Message | None = None):
50
54
  self.chat_id = chat_id
51
55
  self.sender = senders.Sender(chat_id)
56
+ self.received = None
57
+
52
58
  self._handler = _input_handler.InputHandler(chat_id)
53
59
  self._previous_message = previous_message
54
60
  self._timeout_handler = _timeout.TimeoutHandler()
@@ -68,6 +68,8 @@ class ChainEntryLogic(ChainBase):
68
68
  """
69
69
 
70
70
  def callback(message: Message) -> bool:
71
+ self.received = message
72
+
71
73
  if delete_user_response:
72
74
  self.sender.delete_message(message, True)
73
75
 
@@ -154,6 +156,8 @@ class ChainEntryLogic(ChainBase):
154
156
  """
155
157
 
156
158
  def callback(message: Message) -> bool:
159
+ self.received = message
160
+
157
161
  if delete_user_response:
158
162
  self.sender.delete_message(message, True)
159
163
 
@@ -246,6 +250,8 @@ class ChainEntryLogic(ChainBase):
246
250
  """
247
251
 
248
252
  def callback(message: Message) -> bool:
253
+ self.received = message
254
+
249
255
  if delete_user_response:
250
256
  self.sender.delete_message(message, True)
251
257
 
@@ -340,6 +346,8 @@ class ChainEntryLogic(ChainBase):
340
346
  """
341
347
 
342
348
  def callback(message: Message) -> bool:
349
+ self.received = message
350
+
343
351
  if delete_user_response:
344
352
  self.sender.delete_message(message, True)
345
353
 
@@ -453,6 +461,8 @@ class ChainEntryLogic(ChainBase):
453
461
  """
454
462
 
455
463
  def callback(message: Message) -> bool:
464
+ self.received = message
465
+
456
466
  if delete_user_response:
457
467
  self.sender.delete_message(message, True)
458
468
 
@@ -592,6 +602,8 @@ class ChainEntryLogic(ChainBase):
592
602
  """
593
603
 
594
604
  def callback(message: Message) -> bool:
605
+ self.received = message
606
+
595
607
  if delete_user_response:
596
608
  self.sender.delete_message(message, True)
597
609
 
@@ -32,7 +32,7 @@ from telebot.types import (
32
32
 
33
33
  from ._callback_query_handler import CallbackQueryHandler
34
34
  from ._inline_buttons import InlineButton, CallbackButton
35
- from ._chain_base import ChainBase
35
+ from ._chain_base import ChainBase, library
36
36
 
37
37
  if typing.TYPE_CHECKING:
38
38
  from ._chain import Chain # only for type hints
@@ -151,15 +151,24 @@ class ChainInlineKeyboardLogic(ChainBase):
151
151
  buttons: list[InlineKeyboardButton] = []
152
152
 
153
153
  for index, (caption, value) in enumerate(keyboard.items()):
154
- if enable_special_buttons and isinstance(value, InlineButton):
154
+ if enable_special_buttons and isinstance(value, InlineButton) and not isinstance(value, CallbackButton):
155
155
  buttons.append(value._compile(caption))
156
156
  else:
157
+ if isinstance(value, CallbackButton):
158
+ invoker = value.build_invoker(self._cancel_timeout_and_handlers)
159
+ else:
160
+ invoker = self._get_invoker_with_argument(func, value)
161
+
157
162
  callback_data = CallbackQueryHandler.inline_button(f"{index}:{random.randint(1000, 9999)}")
158
- callback_functions[callback_data] = self._get_callback_with_argument(func, value)
163
+ callback_functions[callback_data] = invoker
164
+
165
+ kwargs: dict[str, Any] = getattr(invoker, "_kwargs", None) or {}
166
+
159
167
  buttons.append(
160
168
  InlineKeyboardButton(
161
169
  text=caption,
162
- callback_data=callback_data
170
+ callback_data=callback_data,
171
+ **kwargs
163
172
  )
164
173
  )
165
174
 
@@ -242,18 +251,34 @@ class ChainInlineKeyboardLogic(ChainBase):
242
251
  buttons: list[InlineKeyboardButton] = []
243
252
 
244
253
  if not isinstance(choices, dict):
254
+ for c in choices:
255
+ if type(c).__str__ is object.__str__:
256
+ library.warning(
257
+ f"{type(c).__name__} does not implement __str__. "
258
+ f"Consider passing a dict with explicit labels.",
259
+ stacklevel=3
260
+ )
245
261
  choices = {str(c): c for c in choices}
246
262
 
247
263
  for index, (caption, value) in enumerate(choices.items()):
248
- if enable_special_buttons and isinstance(value, InlineButton):
264
+ if enable_special_buttons and isinstance(value, InlineButton) and not isinstance(value, CallbackButton):
249
265
  buttons.append(value._compile(caption))
250
266
  else:
267
+ if isinstance(value, CallbackButton):
268
+ invoker = value.build_invoker(self._cancel_timeout_and_handlers)
269
+ else:
270
+ invoker = self._get_invoker_with_argument(func, value)
271
+
251
272
  callback_data = CallbackQueryHandler.inline_button(f"{index}:{random.randint(1000, 9999)}")
252
- callback_functions[callback_data] = self._get_callback_with_argument(func, value)
273
+ callback_functions[callback_data] = invoker
274
+
275
+ kwargs: dict[str, Any] = getattr(invoker, "_kwargs", None) or {}
276
+
253
277
  buttons.append(
254
278
  InlineKeyboardButton(
255
279
  text=caption,
256
- callback_data=callback_data
280
+ callback_data=callback_data,
281
+ **kwargs
257
282
  )
258
283
  )
259
284
 
@@ -314,21 +339,21 @@ class ChainInlineKeyboardLogic(ChainBase):
314
339
 
315
340
  self.sender.set_reply_markup(markup)
316
341
 
317
- def _get_callback_with_argument(self, func: Callable, argument: Any, query_answer: tuple[str, bool] | None = None) -> Callable[[CallbackQuery], None]:
318
- def callback(call: CallbackQuery) -> None:
342
+ def _get_invoker_with_argument(self, callback: Callable, argument: Any, query_answer: tuple[str, bool] | None = None) -> Callable[[CallbackQuery], None]:
343
+ def invoker(call: CallbackQuery) -> None:
319
344
  self._cancel_timeout_and_handlers()
320
- func(argument)
345
+ callback(argument)
321
346
  self._answer_callback_query(call, query_answer)
322
347
 
323
- return callback
348
+ return invoker
324
349
 
325
- def _get_callback(self, func: Callable[..., None], query_answer: tuple[str, bool] | None = None) -> Callable[[CallbackQuery], None]:
326
- def callback(call: CallbackQuery):
350
+ def _get_invoker(self, callback: Callable[..., None], query_answer: tuple[str, bool] | None = None) -> Callable[[CallbackQuery], None]:
351
+ def invoker(call: CallbackQuery):
327
352
  self._cancel_timeout_and_handlers()
328
- func()
353
+ callback()
329
354
  self._answer_callback_query(call, query_answer)
330
355
 
331
- return callback
356
+ return invoker
332
357
 
333
358
  def _answer_callback_query(self, call: CallbackQuery, query_answer: tuple[str, bool] | None = None):
334
359
  if query_answer is None:
@@ -369,8 +394,4 @@ class ChainInlineKeyboardLogic(ChainBase):
369
394
  rows.append(buttons[index:index + last_width])
370
395
  index += last_width
371
396
 
372
- return rows
373
-
374
- def _is_valid_telegram_callback(self, data: str) -> bool:
375
- byte_size = len(data.encode('utf-8'))
376
- return 1 <= byte_size <= 64
397
+ return rows
@@ -36,6 +36,7 @@ __all__ = [
36
36
  "CallbackButton",
37
37
  "AlertButton",
38
38
  "NotificationButton",
39
+ "InvokeButton",
39
40
 
40
41
  "ButtonStyle"
41
42
  ]
@@ -56,8 +57,9 @@ class InlineButton:
56
57
  - `SuggestButton`
57
58
  - `CopyTextButton`
58
59
  - `CallbackButton`
59
- - `AlertButton
60
- - `NotificationButton
60
+ - `AlertButton`
61
+ - `NotificationButton`
62
+ - `InvokeButton`
61
63
  """
62
64
 
63
65
  _bot: TeleBot
@@ -76,6 +78,7 @@ class InlineButton:
76
78
  Callback: type["CallbackButton"]
77
79
  Alert: type["AlertButton"]
78
80
  Notification: type["NotificationButton"]
81
+ Invoke: type["InvokeButton"]
79
82
 
80
83
  Styles: type[ButtonStyle] = ButtonStyle
81
84
 
@@ -340,7 +343,7 @@ class CallbackButton(InlineButton):
340
343
  self._answer_callback_query(call)
341
344
 
342
345
  def __init__(
343
- self,
346
+ self,
344
347
  callback: Callable[..., Any] | None,
345
348
 
346
349
  pass_args: tuple | list | None = None,
@@ -482,6 +485,130 @@ class NotificationButton(CallbackButton):
482
485
  style=style,
483
486
  **kwargs
484
487
  )
488
+
489
+ class InvokeButton(CallbackButton):
490
+ """
491
+ An inline keyboard button that calls a named method on a given object when pressed.
492
+
493
+ Unlike `CallbackButton`, which takes a callable directly, `InvokeButton` resolves
494
+ the method at invocation time via `getattr(obj, invoke)`.
495
+
496
+ :param obj: The object on which the method will be called.
497
+ :type obj: `Any`
498
+
499
+ :param invoke: Name of the method to call on `obj`.
500
+ :type invoke: `str`
501
+
502
+ :param pass_args: Positional arguments to pass into the method.
503
+ :type pass_args: `tuple | list | None`
504
+
505
+ :param pass_kwargs: Keyword arguments to pass into the method.
506
+ :type pass_kwargs: `dict[str, Any] | None`
507
+
508
+ :param answer_text: Optional text to send as an answer to the callback query.
509
+ :type answer_text: `str | None`
510
+
511
+ :param answer_as_alert: If `True`, the answer is shown as a popup alert.
512
+ If `False`, it appears as a notification at the top of the chat.
513
+ :type answer_as_alert: `bool`
514
+
515
+ :param style: Style of the button. Must be one of `ButtonStyle.DANGER` (red),
516
+ `*.SUCCESS` (green) or `*.PRIMARY` (blue).
517
+ You can also pass these as string values: "danger", "success", "primary".
518
+ If omitted, an app-specific default style is used.
519
+ :type style: `str | ButtonStyle | None`
520
+
521
+ :param kwargs: Additional keyword arguments passed directly to `InlineKeyboardButton`.
522
+ :type kwargs: `Any`
523
+
524
+ Example::
525
+
526
+ self.chain.set_inline_keyboard({
527
+ "📖 My Deck": InvokeButton(self.handoff(DeckHandler), "handle"),
528
+ })
529
+ """
530
+ class _CallbackInvoker(CallbackButton._CallbackInvoker):
531
+ def __init__(
532
+ self,
533
+ chain_callback: Callable[[], None],
534
+
535
+ obj: Any,
536
+ invoke: str,
537
+
538
+ pass_args: tuple | list | None = None,
539
+ pass_kwargs: dict[str, Any] | None = None,
540
+
541
+ answer_text: str | None = None,
542
+ answer_as_alert: bool = True,
543
+
544
+ style: str | None | ButtonStyle = None,
545
+
546
+ kwargs: dict[str, Any] = {}
547
+ ):
548
+ self._obj = obj
549
+ self._invoke = invoke
550
+
551
+ self._pass_args = pass_args
552
+ self._pass_kwargs = pass_kwargs
553
+
554
+ self._answer_text = answer_text
555
+ self._answer_as_alert = answer_as_alert
556
+
557
+ self._style = style
558
+
559
+ self._kwargs = {"style": style} | kwargs
560
+
561
+ self._chain_callback: Callable[[], None] = chain_callback
562
+
563
+ def _invoke_callback(self):
564
+ obj: Any = self.__dict__["_obj"]
565
+ callback: Any = getattr(obj, self._invoke)
566
+
567
+ args = self._pass_args or ()
568
+ kwargs = self._pass_kwargs or {}
569
+
570
+ callback(*args, **kwargs)
571
+
572
+ def __init__(
573
+ self,
574
+ obj: Any,
575
+ invoke: str,
576
+
577
+ pass_args: tuple | list | None = None,
578
+ pass_kwargs: dict[str, Any] | None = None,
579
+ *,
580
+ answer_text: str | None = None,
581
+ answer_as_alert: bool = True,
582
+
583
+ style: str | None | ButtonStyle = None,
584
+
585
+ **kwargs
586
+ ):
587
+ self._obj = obj
588
+ self._invoke = invoke
589
+
590
+ self._pass_args = pass_args
591
+ self._pass_kwargs = pass_kwargs
592
+
593
+ self._answer_text = answer_text
594
+ self._answer_as_alert = answer_as_alert
595
+
596
+ self._style = self._normalize_style(style)
597
+
598
+ self._kwargs = kwargs
599
+
600
+ def build_invoker(self, chain_callback: Callable[[], None]) -> _CallbackInvoker:
601
+ return self._CallbackInvoker(
602
+ chain_callback=chain_callback,
603
+ obj=self._obj,
604
+ invoke=self._invoke,
605
+ pass_args=self._pass_args,
606
+ pass_kwargs=self._pass_kwargs,
607
+ answer_text=self._answer_text,
608
+ answer_as_alert=self._answer_as_alert,
609
+ style=self._style,
610
+ kwargs=self._kwargs
611
+ )
485
612
 
486
613
  InlineButton.Link = LinkButton
487
614
  InlineButton.WebApp = WebAppButton
@@ -489,4 +616,5 @@ InlineButton.Suggest = SuggestButton
489
616
  InlineButton.CopyText = CopyTextButton
490
617
  InlineButton.Callback = CallbackButton
491
618
  InlineButton.Alert = AlertButton
492
- InlineButton.Notification = NotificationButton
619
+ InlineButton.Notification = NotificationButton
620
+ InlineButton.Invoke = InvokeButton
@@ -368,7 +368,7 @@ class DSLHandler(telekit.Handler):
368
368
  if not hasattr(self, "_script_data_factory"):
369
369
  message: str = f"{type(self).__name__}().start_script(): Script is not analyzed yet. Call cls.analyze_file() or cls.analyze_string() before starting it."
370
370
  library.error(message)
371
- self.chain.sender.pyerror(RuntimeError(message))
371
+ self.chain.sender.send_error("DSLError", message)
372
372
  return
373
373
 
374
374
  self.script_data = self._script_data_factory()
@@ -799,7 +799,7 @@ class DSLHandler(telekit.Handler):
799
799
  # ----------------------------------------------------------------------------
800
800
 
801
801
  def _fail(self, message: str, exception: type[Exception]=Exception):
802
- self.chain.sender.error("🤷 Something went wrong...", message)
802
+ self.chain.sender.send_error("🤷 Something went wrong...", message)
803
803
  library.error(message)
804
804
  return exception(message)
805
805
 
@@ -3,4 +3,4 @@
3
3
  # PyPI history: https://pypi.org/project/telekit/#history
4
4
  # ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
5
5
 
6
- __version__ = "2.2.0a2"
6
+ __version__ = "2.2.0a3"
@@ -1,6 +1,7 @@
1
- import telebot.types
2
1
  import telekit
3
2
 
3
+ from telekit.inline_buttons import CallbackButton
4
+
4
5
  source = """
5
6
  # Page Title
6
7
 
@@ -46,9 +47,12 @@ class PagesHandler(telekit.Handler):
46
47
  self.chain.sender.set_title("Simple Pages Example")
47
48
  self.chain.sender.set_message("Here are some common questions and answers to help you get started:")
48
49
 
49
- @self.chain.inline_keyboard(pages)
50
- def _(page: tuple[str, str]) -> None:
51
- self.display_page(page)
50
+ self.chain.set_inline_choice(
51
+ self.display_page,
52
+ pages | {
53
+ "« Back": CallbackButton(self.handoff_start)
54
+ }
55
+ )
52
56
 
53
57
  self.chain.disable_timeout_warnings()
54
58
  self.chain.edit()
@@ -60,4 +64,7 @@ class PagesHandler(telekit.Handler):
60
64
  self.chain.sender.set_message(page[1])
61
65
 
62
66
  self.chain.set_inline_keyboard({"« Back": self.display_home_page})
63
- self.chain.edit()
67
+ self.chain.edit()
68
+
69
+ def handoff_start(self):
70
+ self.handoff("StartHandler").handle()
@@ -28,6 +28,7 @@ from ._inline_buttons import (
28
28
  CallbackButton,
29
29
  AlertButton,
30
30
  NotificationButton,
31
+ InvokeButton,
31
32
  )
32
33
 
33
34
  __all__ = [
@@ -41,4 +42,5 @@ __all__ = [
41
42
  "CallbackButton",
42
43
  "AlertButton",
43
44
  "NotificationButton",
45
+ "InvokeButton",
44
46
  ]