telekit 2.5.0b2__tar.gz → 2.5.0b3__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 (88) hide show
  1. {telekit-2.5.0b2 → telekit-2.5.0b3}/PKG-INFO +14 -2
  2. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/__init__.py +4 -0
  3. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_buildtext/formatter.py +47 -13
  4. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_buildtext/styles.py +72 -54
  5. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_inline_buttons.py +2 -0
  6. telekit-2.5.0b3/telekit/_text_builder.py +529 -0
  7. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_version.py +1 -1
  8. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/__init__.py +2 -0
  9. telekit-2.5.0b3/telekit/example/example_handlers/article.py +66 -0
  10. telekit-2.5.0b3/telekit/example/example_handlers/counter.py +84 -0
  11. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/start.py +4 -1
  12. telekit-2.5.0b3/telekit/example/example_handlers/style.py +73 -0
  13. telekit-2.5.0b3/telekit/html_text.py +812 -0
  14. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/traits/__init__.py +1 -0
  15. telekit-2.5.0b3/telekit/traits/paginated_text.py +378 -0
  16. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/types.py +26 -21
  17. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/utils.py +22 -0
  18. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit.egg-info/PKG-INFO +14 -2
  19. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit.egg-info/SOURCES.txt +5 -0
  20. telekit-2.5.0b2/telekit/example/example_handlers/counter.py +0 -50
  21. {telekit-2.5.0b2 → telekit-2.5.0b3}/LICENSE +0 -0
  22. {telekit-2.5.0b2 → telekit-2.5.0b3}/README.md +0 -0
  23. {telekit-2.5.0b2 → telekit-2.5.0b3}/setup.cfg +0 -0
  24. {telekit-2.5.0b2 → telekit-2.5.0b3}/setup.py +0 -0
  25. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_buildtext/__init__.py +0 -0
  26. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_callback_query_handler.py +0 -0
  27. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_chain.py +0 -0
  28. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_chain_base.py +0 -0
  29. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_chain_entry_logic.py +0 -0
  30. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_chain_inline_keyboards_logic.py +0 -0
  31. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_chapters/__init__.py +0 -0
  32. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_chapters/chapters.py +0 -0
  33. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_handler.py +0 -0
  34. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_init.py +0 -0
  35. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_inline_keyboard.py +0 -0
  36. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_input_handler.py +0 -0
  37. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_logger.py +0 -0
  38. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_on.py +0 -0
  39. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_reply_keyboard.py +0 -0
  40. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_snapvault/__init__.py +0 -0
  41. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_snapvault/snapcode.py +0 -0
  42. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_snapvault/snapvault.py +0 -0
  43. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_state.py +0 -0
  44. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/__init__.py +0 -0
  45. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/mixin.py +0 -0
  46. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/parser/__init__.py +0 -0
  47. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/parser/builder.py +0 -0
  48. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/parser/canvas_parser.py +0 -0
  49. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/parser/lexer.py +0 -0
  50. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/parser/nodes.py +0 -0
  51. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/parser/parser.py +0 -0
  52. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/parser/token.py +0 -0
  53. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/telekit_dsl.py +0 -0
  54. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_telekit_dsl/telekit_orm.py +0 -0
  55. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_timeout.py +0 -0
  56. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_trait.py +0 -0
  57. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/_user.py +0 -0
  58. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/chat.py +0 -0
  59. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/debug.py +0 -0
  60. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/dices.py +0 -0
  61. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/__init__.py +0 -0
  62. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/calendar.py +0 -0
  63. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/complete_hotel.py +0 -0
  64. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/dsl.py +0 -0
  65. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/entry.py +0 -0
  66. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/faq.py +0 -0
  67. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/hotel.py +0 -0
  68. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/on_text.py +0 -0
  69. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/pages.py +0 -0
  70. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/pyapi.py +0 -0
  71. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/qr.py +0 -0
  72. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/quiz.py +0 -0
  73. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/spells.py +0 -0
  74. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_handlers/text_document.py +0 -0
  75. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/example/example_server.py +0 -0
  76. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/inline_buttons.py +0 -0
  77. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/parameters.py +0 -0
  78. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/reply_buttons.py +0 -0
  79. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/scheduler.py +0 -0
  80. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/senders.py +0 -0
  81. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/server.py +0 -0
  82. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/styles.py +0 -0
  83. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/traits/calendar_pick.py +0 -0
  84. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/traits/paginated_choice.py +0 -0
  85. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit/traits/track_handoff_origin.py +0 -0
  86. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit.egg-info/dependency_links.txt +0 -0
  87. {telekit-2.5.0b2 → telekit-2.5.0b3}/telekit.egg-info/requires.txt +0 -0
  88. {telekit-2.5.0b2 → telekit-2.5.0b3}/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.5.0b2
3
+ Version: 2.5.0b3
4
4
  Summary: Declarative, developer-friendly library for building Telegram bots
5
5
  Home-page: https://github.com/Romashkaa/telekit
6
6
  Author: romashka
@@ -477,7 +477,7 @@ It tries to make Telegram bot development easier.
477
477
 
478
478
  ---
479
479
 
480
- # Changes in version 2.5.0b2
480
+ # Changes in version 2.5.0b3
481
481
 
482
482
  ### v2.5.0`b0`
483
483
  - Added support for t-strings (PEP 750, Python 3.14+) in `TextEntity`.
@@ -501,3 +501,15 @@ It tries to make Telegram bot development easier.
501
501
  - `Handler.handlers_dict` now excludes private handlers (classes whose names start with `_`).
502
502
  - Added `Debug.duplicate_handler_warnings` to warn about duplicate handler names during initialization.
503
503
  - Added `Handler.chat` object (BETA)
504
+
505
+ ### v2.5.0`b3`
506
+ - Added `utils.Markers` class
507
+ - Added `HTMLText` class for handling Telegram HTML strings with tag-aware indexing and slicing.
508
+ - Added `PaginatedText` trait for displaying long HTML text in a paginated format, supporting navigation and smart splitting.
509
+ - Added `__radd__` to `TextEntity`: `"Regular" + Bold(" and Bold")`
510
+ - Added `__mul__` to `TextEntity`: `Bold("Text") * 3`
511
+ - Added `enabled=` parameter to `TextEntity`: `Bold("bold text", enabled=is_text_bold)`
512
+ - Added `TextBuilder` class – a fluent message composition API mirroring `InlineKeyboard`'s builder pattern
513
+ - Added styles to `telekit.types`
514
+ - Added `utils.CyclicList`
515
+ - Fixed `_answer_callback_query` to always call `bot.answer_callback_query()`, even without a popup text
@@ -24,6 +24,7 @@ from ._callback_query_handler import CallbackQueryHandler
24
24
  from .server import Server, example
25
25
  from ._inline_keyboard import InlineKeyboard
26
26
  from ._reply_keyboard import ReplyKeyboard
27
+ from ._text_builder import TextBuilder
27
28
  from ._snapvault import Vault
28
29
  from ._chapters import chapters
29
30
  from ._user import User
@@ -43,6 +44,7 @@ from . import traits
43
44
  from . import debug
44
45
  from . import scheduler
45
46
  from . import chat
47
+ from . import html_text
46
48
 
47
49
  Styles = styles.Styles
48
50
 
@@ -59,6 +61,7 @@ __all__ = [
59
61
  "dices",
60
62
  "scheduler",
61
63
  "chat",
64
+ "html_text",
62
65
 
63
66
  "Styles",
64
67
  "User",
@@ -72,6 +75,7 @@ __all__ = [
72
75
 
73
76
  "InlineKeyboard",
74
77
  "ReplyKeyboard",
78
+ "TextBuilder",
75
79
 
76
80
  "TelekitDSL",
77
81
  "DSLHandler",
@@ -33,17 +33,36 @@ else:
33
33
  _Template = None
34
34
 
35
35
  class TextEntity:
36
-
37
- def __init__(self, *content, escape: bool = True, sep: Union["TextEntity", str, "Template"] = ""):
36
+ def __init__(self, *content, escape: bool = True, sep: Union["TextEntity", str, "Template"] = "", enabled: bool | Any = True):
38
37
  self._content = content
39
38
  self._escape_strings = escape
40
39
  self._separator = sep
40
+ self._enabled = enabled
41
41
 
42
42
  def __add__(self, other):
43
43
  if isinstance(other, (str, TextEntity)) \
44
44
  or (_HAS_TEMPLATE_LIB and isinstance(other, _Template)): # pyright: ignore[reportArgumentType]
45
45
  return Group(self, other)
46
- raise TypeError(f"Cannot add {type(other)} to Style")
46
+ raise TypeError(f"Cannot add {type(other)} to TextEntity")
47
+
48
+ def __radd__(self, other):
49
+ if isinstance(other, str):
50
+ return Group(other, self)
51
+ if isinstance(other, TextEntity) \
52
+ or (_HAS_TEMPLATE_LIB and isinstance(other, _Template)): # pyright: ignore[reportArgumentType]
53
+ return Group(other, self)
54
+ return NotImplemented
55
+
56
+ def __hash__(self) -> int:
57
+ return hash(self.render_html())
58
+
59
+ def __mul__(self, n: int):
60
+ if not isinstance(n, int):
61
+ return NotImplemented
62
+ return Group(*([self] * n))
63
+
64
+ def __rmul__(self, n: int):
65
+ return self.__mul__(n)
47
66
 
48
67
  @property
49
68
  def markdown(self) -> str:
@@ -81,7 +100,7 @@ class TextEntity:
81
100
  return sep.join(
82
101
  self._render_item(item, parse_mode) for item in self._content
83
102
  )
84
-
103
+
85
104
  def _render_item(self, item: Union[str, "TextEntity", "Template"], parse_mode: Literal["html", "markdown"] | None) -> str:
86
105
  if _HAS_TEMPLATE_LIB and isinstance(item, _Template): # pyright: ignore[reportArgumentType]
87
106
  return self._render_template(item, parse_mode) # pyright: ignore[reportAttributeAccessIssue]
@@ -164,13 +183,22 @@ class TextEntity:
164
183
 
165
184
  class EasyTextEntity(TextEntity):
166
185
  def render_markdown(self) -> str:
167
- return self._render_markdown(self._render_content("markdown"))
186
+ content = self._render_content("markdown")
187
+ if not self._enabled:
188
+ return content
189
+ return self._render_markdown(content)
168
190
 
169
191
  def render_html(self) -> str:
170
- return self._render_html(self._render_content("html"))
192
+ content = self._render_content("html")
193
+ if not self._enabled:
194
+ return content
195
+ return self._render_html(content)
171
196
 
172
197
  def render_none(self) -> str:
173
- return self._render_none(self._render_content(None))
198
+ content = self._render_content(None)
199
+ if not self._enabled:
200
+ return content
201
+ return self._render_none(content)
174
202
 
175
203
  # redefine
176
204
 
@@ -185,32 +213,38 @@ class EasyTextEntity(TextEntity):
185
213
 
186
214
  class EasyTextEntityWithPostRender(EasyTextEntity):
187
215
  def render_markdown(self) -> str:
188
- return self._post_render(self._render_markdown(self._render_content("markdown")))
216
+ return self._post_render(super().render_markdown())
189
217
 
190
218
  def render_html(self) -> str:
191
- return self._post_render(self._render_html(self._render_content("html")))
219
+ return self._post_render(super().render_html())
192
220
 
193
221
  def render_none(self) -> str:
194
- return self._post_render(self._render_none(self._render_content(None)))
222
+ return self._post_render(super().render_none())
195
223
 
196
224
  # redefine
197
225
 
198
226
  def _post_render(self, rendered: str) -> str:
199
227
  return rendered
200
228
 
201
- # + _render_markdown, _render_html, _render_none
229
+ # + redefine: _render_markdown, _render_html, _render_none
202
230
 
203
231
  class StaticTextEntity(TextEntity):
204
232
  def render_markdown(self) -> str:
205
233
  content: str = self._render_content("markdown")
234
+ if not self._enabled:
235
+ return content
206
236
  return self._render_any(content)
207
237
 
208
238
  def render_html(self) -> str:
209
239
  content: str = self._render_content("html")
240
+ if not self._enabled:
241
+ return content
210
242
  return self._render_any(content)
211
243
 
212
244
  def render_none(self) -> str:
213
245
  content: str = self._render_content(None)
246
+ if not self._enabled:
247
+ return content
214
248
  return self._render_any(content)
215
249
 
216
250
  # redefine
@@ -221,8 +255,8 @@ class StaticTextEntity(TextEntity):
221
255
  # Grouping
222
256
 
223
257
  class Group(TextEntity):
224
- def __init__(self, *content, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = ""):
225
- super().__init__(*content, escape=escape, sep=sep)
258
+ def __init__(self, *content, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = "", enabled: bool | Any = True):
259
+ super().__init__(*content, escape=escape, sep=sep, enabled=enabled)
226
260
 
227
261
  # Debugger
228
262
 
@@ -16,7 +16,7 @@
16
16
  # You should have received a copy of the GNU General Public License
17
17
  # along with Telekit. If not, see <https://www.gnu.org/licenses/>.
18
18
  #
19
- from typing import Union, Literal, TYPE_CHECKING, Union
19
+ from typing import Union, Literal, TYPE_CHECKING, Union, Any
20
20
  from urllib.parse import quote
21
21
 
22
22
  if TYPE_CHECKING: # Union[str, "TextEntity", "Template"]
@@ -30,7 +30,6 @@ from .formatter import TextEntity, EasyTextEntity, StaticTextEntity, EasyTextEnt
30
30
 
31
31
 
32
32
  class Bold(EasyTextEntity):
33
-
34
33
  """
35
34
  Applies **bold formatting** to the provided content.
36
35
 
@@ -45,6 +44,8 @@ class Bold(EasyTextEntity):
45
44
 
46
45
  :param sep: Separator inserted between multiple content elements.
47
46
  Defaults to ``""``.
47
+ :param enabled: If falsy, renders content without bold formatting.
48
+ Defaults to ``True``.
48
49
 
49
50
  Examples::
50
51
 
@@ -53,6 +54,8 @@ class Bold(EasyTextEntity):
53
54
 
54
55
  Bold("Hello", "World", sep=" ").html # "<b>Hello World</b>"
55
56
 
57
+ Bold("title", enabled=is_important).html # "title" if not is_important
58
+
56
59
  sender.set_text(Bold("Hello!"))
57
60
 
58
61
  `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
@@ -66,7 +69,6 @@ class Bold(EasyTextEntity):
66
69
 
67
70
 
68
71
  class Italic(EasyTextEntity):
69
-
70
72
  """
71
73
  Applies *italic formatting* to the provided content.
72
74
 
@@ -81,6 +83,8 @@ class Italic(EasyTextEntity):
81
83
 
82
84
  :param sep: Separator inserted between multiple content elements.
83
85
  Defaults to ``""``.
86
+ :param enabled: If falsy, renders content without italic formatting.
87
+ Defaults to ``True``.
84
88
 
85
89
  Examples::
86
90
 
@@ -114,6 +118,8 @@ class Underline(EasyTextEntity):
114
118
 
115
119
  :param sep: Separator inserted between multiple content elements.
116
120
  Defaults to ``""``.
121
+ :param enabled: If falsy, renders content without underline formatting.
122
+ Defaults to ``True``.
117
123
 
118
124
  Examples::
119
125
 
@@ -147,6 +153,8 @@ class Strikethrough(EasyTextEntity):
147
153
 
148
154
  :param sep: Separator inserted between multiple content elements.
149
155
  Defaults to ``""``.
156
+ :param enabled: If falsy, renders content without strikethrough formatting.
157
+ Defaults to ``True``.
150
158
 
151
159
  Examples::
152
160
 
@@ -182,6 +190,8 @@ class Code(EasyTextEntity):
182
190
 
183
191
  :param sep: Separator inserted between multiple content elements.
184
192
  Defaults to ``""``.
193
+ :param enabled: If falsy, renders content without code formatting.
194
+ Defaults to ``True``.
185
195
 
186
196
  Examples::
187
197
 
@@ -198,7 +208,7 @@ class Code(EasyTextEntity):
198
208
 
199
209
  def _render_html(self, content: str) -> str:
200
210
  return f"<code>{content}</code>"
201
-
211
+
202
212
 
203
213
  class Language(EasyTextEntity):
204
214
  """
@@ -217,6 +227,8 @@ class Language(EasyTextEntity):
217
227
 
218
228
  :param sep: Separator inserted between multiple content elements.
219
229
  Defaults to ``""``.
230
+ :param enabled: If falsy, renders content without code block formatting.
231
+ Defaults to ``True``.
220
232
 
221
233
  Examples::
222
234
 
@@ -231,9 +243,9 @@ class Language(EasyTextEntity):
231
243
  `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
232
244
  """
233
245
 
234
- def __init__(self, *content, lang: str, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = ""):
246
+ def __init__(self, *content, lang: str, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = "", enabled: bool | Any = True):
235
247
  self._language: str = lang
236
- super().__init__(*content, escape=escape, sep=sep)
248
+ super().__init__(*content, escape=escape, sep=sep, enabled=enabled)
237
249
 
238
250
  def _render_markdown(self, content: str) -> str:
239
251
  return telebot.formatting.mcode(content, language=self._language, escape=False)
@@ -259,6 +271,8 @@ class Python(Language):
259
271
 
260
272
  :param sep: Separator inserted between multiple content elements.
261
273
  Defaults to ``""``.
274
+ :param enabled: If falsy, renders content without code block formatting.
275
+ Defaults to ``True``.
262
276
 
263
277
  Examples::
264
278
 
@@ -270,8 +284,8 @@ class Python(Language):
270
284
  `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
271
285
  """
272
286
 
273
- def __init__(self, *content, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = ""):
274
- super().__init__(*content, lang="python", escape=escape, sep=sep)
287
+ def __init__(self, *content, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = "", enabled: bool | Any = True):
288
+ super().__init__(*content, lang="python", escape=escape, sep=sep, enabled=enabled)
275
289
 
276
290
 
277
291
  class Spoiler(EasyTextEntity):
@@ -289,6 +303,8 @@ class Spoiler(EasyTextEntity):
289
303
 
290
304
  :param sep: Separator inserted between multiple content elements.
291
305
  Defaults to ``""``.
306
+ :param enabled: If falsy, renders content without spoiler formatting.
307
+ Defaults to ``True``.
292
308
 
293
309
  Examples::
294
310
 
@@ -304,7 +320,6 @@ class Spoiler(EasyTextEntity):
304
320
  return telebot.formatting.mspoiler(content, escape=False)
305
321
 
306
322
  def _render_html(self, content: str) -> str:
307
- # or '<span class="tg-spoiler">', '</span>'
308
323
  return f'<tg-spoiler>{content}</tg-spoiler>'
309
324
 
310
325
 
@@ -326,6 +341,8 @@ class Quote(EasyTextEntityWithPostRender):
326
341
 
327
342
  :param sep: Separator inserted between multiple content elements.
328
343
  Defaults to ``""``.
344
+ :param enabled: If falsy, renders content without quote formatting.
345
+ Defaults to ``True``.
329
346
 
330
347
  Examples::
331
348
 
@@ -340,17 +357,17 @@ class Quote(EasyTextEntityWithPostRender):
340
357
  `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
341
358
  """
342
359
 
343
- def __init__(self, *content, expandable: bool = False, end: str = "\n", escape: bool = True, sep: Union[str, "TextEntity", "Template"] = ""):
360
+ def __init__(self, *content, expandable: bool = False, end: str = "\n", escape: bool = True, sep: Union[str, "TextEntity", "Template"] = "", enabled: bool | Any = True):
344
361
  self._expandable: bool = expandable
345
362
  self._end: str = end
346
- super().__init__(*content, escape=escape, sep=sep)
363
+ super().__init__(*content, escape=escape, sep=sep, enabled=enabled)
347
364
 
348
365
  def _render_markdown(self, content: str) -> str:
349
366
  return telebot.formatting.mcite(content, escape=False, expandable=self._expandable)
350
367
 
351
368
  def _render_html(self, content: str) -> str:
352
369
  return telebot.formatting.hcite(content, escape=False, expandable=self._expandable)
353
-
370
+
354
371
  def _post_render(self, rendered: str) -> str:
355
372
  return rendered + self._end if self._end else rendered
356
373
 
@@ -401,10 +418,10 @@ class Raw(TextEntity):
401
418
 
402
419
  `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
403
420
  """
404
-
421
+
405
422
  def __init__(self, *content, sep: Union[str, "TextEntity", "Template"] = ""):
406
423
  super().__init__(*content, escape=False, sep=sep)
407
-
424
+
408
425
 
409
426
  class Link(EasyTextEntity):
410
427
  """
@@ -425,6 +442,8 @@ class Link(EasyTextEntity):
425
442
 
426
443
  :param sep: Separator inserted between multiple content elements.
427
444
  Defaults to ``""``.
445
+ :param enabled: If falsy, renders content without link formatting.
446
+ Defaults to ``True``.
428
447
 
429
448
  Examples::
430
449
 
@@ -434,7 +453,7 @@ class Link(EasyTextEntity):
434
453
  >>> Link("Open site", url="https://example.com").markdown
435
454
  "[Open site](https://example.com)"
436
455
 
437
- >>> Link("Open site", url="https://example.com").none
456
+ >>> Link("Open site", url="https://example.com").none
438
457
  "Open site (https://example.com)"
439
458
 
440
459
  sender.set_text(Link(Bold("Telekit on GitHub"), url="https://github.com/Romashkaa/telekit"))
@@ -442,19 +461,19 @@ class Link(EasyTextEntity):
442
461
  `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
443
462
  """
444
463
 
445
- def __init__(self, *content, url: str, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = ""):
464
+ def __init__(self, *content, url: str, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = "", enabled: bool | Any = True):
446
465
  self._url: str = url
447
- super().__init__(*content, escape=escape, sep=sep)
466
+ super().__init__(*content, escape=escape, sep=sep, enabled=enabled)
448
467
 
449
468
  def _render_markdown(self, content: str) -> str:
450
469
  return f"[{content}]({self._url})"
451
470
 
452
471
  def _render_html(self, content: str) -> str:
453
472
  return f'<a href="{self._url}">{content}</a>'
454
-
473
+
455
474
  def _render_none(self, content: str) -> str:
456
475
  return f"{content} ({self._url})"
457
-
476
+
458
477
 
459
478
  class Mention(Link):
460
479
  """
@@ -470,6 +489,8 @@ class Mention(Link):
470
489
  Defaults to ``True``.
471
490
  :param sep: Separator inserted between multiple content elements.
472
491
  Defaults to ``""``.
492
+ :param enabled: If falsy, renders content without mention link formatting.
493
+ Defaults to ``True``.
473
494
 
474
495
  Examples::
475
496
 
@@ -484,10 +505,10 @@ class Mention(Link):
484
505
  `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
485
506
  """
486
507
 
487
- def __init__(self, *content, user_id: int | str, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = ""):
508
+ def __init__(self, *content, user_id: int | str, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = "", enabled: bool | Any = True):
488
509
  url: str = telekit.utils.make_mention(user_id)
489
- super().__init__(*content, url=url, escape=escape, sep=sep)
490
-
510
+ super().__init__(*content, url=url, escape=escape, sep=sep, enabled=enabled)
511
+
491
512
 
492
513
  class UserLink(Link):
493
514
  """
@@ -505,6 +526,8 @@ class UserLink(Link):
505
526
  Defaults to ``True``.
506
527
  :param sep: Separator inserted between multiple content elements.
507
528
  Defaults to ``""``.
529
+ :param enabled: If falsy, renders content without user link formatting.
530
+ Defaults to ``True``.
508
531
 
509
532
  Examples::
510
533
 
@@ -516,10 +539,10 @@ class UserLink(Link):
516
539
 
517
540
  `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
518
541
  """
519
- def __init__(self, *content, username: str, text: str | None = None, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = ""):
520
- url: str = telekit.utils.make_user_link(username, text)
521
542
 
522
- super().__init__(*content, url=url, escape=escape, sep=sep)
543
+ def __init__(self, *content, username: str, text: str | None = None, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = "", enabled: bool | Any = True):
544
+ url: str = telekit.utils.make_user_link(username, text)
545
+ super().__init__(*content, url=url, escape=escape, sep=sep, enabled=enabled)
523
546
 
524
547
 
525
548
  class BotLink(Link):
@@ -537,6 +560,8 @@ class BotLink(Link):
537
560
  Defaults to ``True``.
538
561
  :param sep: Separator inserted between multiple content elements.
539
562
  Defaults to ``""``.
563
+ :param enabled: If falsy, renders content without bot link formatting.
564
+ Defaults to ``True``.
540
565
 
541
566
  Examples::
542
567
 
@@ -548,11 +573,11 @@ class BotLink(Link):
548
573
 
549
574
  `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
550
575
  """
551
-
552
- def __init__(self, *content, username: str, start: str | None = None, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = ""):
576
+
577
+ def __init__(self, *content, username: str, start: str | None = None, escape: bool = True, sep: Union[str, "TextEntity", "Template"] = "", enabled: bool | Any = True):
553
578
  url: str = telekit.utils.make_bot_link(username, start)
579
+ super().__init__(*content, url=url, escape=escape, sep=sep, enabled=enabled)
554
580
 
555
- super().__init__(*content, url=url, escape=escape, sep=sep)
556
581
 
557
582
  class EncodeURL(StaticTextEntity):
558
583
  """
@@ -573,7 +598,8 @@ class EncodeURL(StaticTextEntity):
573
598
 
574
599
  def _render_any(self, content: str) -> str:
575
600
  return quote(content, safe="")
576
-
601
+
602
+
577
603
  class Stack(TextEntity):
578
604
  """
579
605
  Renders a list of items as a formatted stack with a customizable prefix per line.
@@ -589,20 +615,16 @@ class Stack(TextEntity):
589
615
  Example::
590
616
 
591
617
  >>> Stack("A", "B", start="- {{index}}. ").html
592
- ```
593
618
  \"""
594
619
  - 1. A
595
620
  - 2. B
596
621
  \"""
597
- ```
598
622
 
599
623
  >>> Stack("A", "B", start=Stack.Markers.DOT).html
600
- ```
601
624
  \"""
602
625
  • A
603
626
  • B
604
627
  \"""
605
- ```
606
628
 
607
629
  :param sep: Separator appended at the end of each item except the last.
608
630
  Defaults to ``"\\n"``.
@@ -610,13 +632,11 @@ class Stack(TextEntity):
610
632
  Example::
611
633
 
612
634
  >>> Stack("A", "B", "C", sep=";\\n").html
613
- ```
614
635
  \"""
615
636
  1. A;
616
637
  2. B;
617
638
  3. C
618
639
  \"""
619
- ```
620
640
 
621
641
  :param end: Appended after the last item, e.g. a closing punctuation mark.
622
642
  Defaults to ``""``.
@@ -624,42 +644,36 @@ class Stack(TextEntity):
624
644
  Example::
625
645
 
626
646
  >>> Stack("A", "B", end=".").none
627
- ```
628
647
  \"""
629
648
  1. A
630
649
  2. B.
631
650
  \"""
632
- ```
633
651
 
634
652
  :param escape: Whether to escape HTML/Markdown special characters in plain string content.
635
653
  Defaults to ``True``.
654
+ :param enabled: If falsy, renders content without stack formatting.
655
+ Defaults to ``True``.
636
656
 
637
657
  Examples::
638
658
 
639
659
  Stack("Buy milk", "Walk the dog", "Read a book").html
640
- ```
641
660
  \"""
642
661
  1. Buy milk
643
662
  2. Walk the dog
644
663
  3. Read a book
645
664
  \"""
646
- ```
647
665
 
648
666
  Stack("Buy milk", "Walk the dog", start=Stack.Markers.CHECK).html
649
- ```
650
667
  \"""
651
668
  ✓ Buy milk
652
669
  ✓ Walk the dog
653
670
  \"""
654
- ```
655
671
 
656
672
  Stack("Step one", "Step two", sep=";\\n", end=".").html
657
- ```
658
673
  \"""
659
674
  1. Step one;
660
675
  2. Step two.
661
676
  \"""
662
- ```
663
677
 
664
678
  sender.set_text(Stack("Item 1", "Item 2", "Item 3"))
665
679
 
@@ -683,13 +697,18 @@ class Stack(TextEntity):
683
697
  CHECK = "✓ "
684
698
  CROSS = "✕ "
685
699
 
686
- def __init__(self, *content, start: str = "{{index}}. ", sep: Union[str, "TextEntity", "Template"] = "\n", end: Union[str, "TextEntity", "Template"] = "", escape: bool = True):
700
+ def __init__(self, *content, start: str = "{{index}}. ", sep: Union[str, "TextEntity", "Template"] = "\n", end: Union[str, "TextEntity", "Template"] = "", escape: bool = True, enabled: bool | Any = True):
687
701
  self._start = start
688
702
  self._end = end
689
-
690
- super().__init__(*content, escape=escape, sep=sep)
703
+ super().__init__(*content, escape=escape, sep=sep, enabled=enabled)
691
704
 
692
705
  def _render_content(self, parse_mode: None | Literal['html'] | Literal['markdown']) -> str:
706
+ if not self._enabled:
707
+ # render content without stack formatting
708
+ end: str = self._render_item(self._end, parse_mode)
709
+ content = super()._render_content(parse_mode)
710
+ return f"\n{content}{end}\n"
711
+
693
712
  stack: list[str] = []
694
713
 
695
714
  for index, item in enumerate(self._content, start=1):
@@ -703,11 +722,13 @@ class Stack(TextEntity):
703
722
 
704
723
  sep: str = self._render_item(self._separator, parse_mode)
705
724
  end: str = self._render_item(self._end, parse_mode)
725
+
726
+ content: str = sep.join(stack)
706
727
 
707
- return "\n" + sep.join(stack) + end + "\n"
728
+ return f"\n{content}{end}\n"
708
729
 
709
- class Styles:
710
730
 
731
+ class Styles:
711
732
  """
712
733
  Namespace for message formatting styles:
713
734
 
@@ -718,8 +739,8 @@ class Styles:
718
739
 
719
740
  Pass it as a style object to the `sender`:
720
741
  >>> sender.set_text(Styles.Bold("Hello"))
721
-
722
- [Documentation](https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md) · on GitHub
742
+
743
+ `Documentation <https://github.com/Romashkaa/telekit/blob/main/docs/tutorial2/6_styles.md>`_ · on GitHub
723
744
  """
724
745
 
725
746
  Bold: type[TextEntity] = Bold
@@ -736,7 +757,4 @@ class Styles:
736
757
  Mention: type[TextEntity] = Mention
737
758
  UserLink: type[TextEntity] = UserLink
738
759
  BotLink: type[TextEntity] = BotLink
739
- Group: type[TextEntity] = Group
740
-
741
-
742
-
760
+ Group: type[TextEntity] = Group
@@ -449,6 +449,8 @@ class CallbackButton(InlineButton):
449
449
  self._answer_text,
450
450
  self._answer_as_alert
451
451
  )
452
+ else:
453
+ InlineButton._bot.answer_callback_query(call.id)
452
454
 
453
455
  def __call__(self, call: CallbackQuery):
454
456
  self._invoke_chain_callback()