telekit 2.2.0a0__tar.gz → 2.2.0a1__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 (71) hide show
  1. {telekit-2.2.0a0/telekit.egg-info → telekit-2.2.0a1}/PKG-INFO +6 -2
  2. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_handler.py +2 -2
  3. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_logger.py +29 -28
  4. telekit-2.2.0a1/telekit/_user.py +116 -0
  5. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_version.py +2 -1
  6. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/types.py +5 -1
  7. {telekit-2.2.0a0 → telekit-2.2.0a1/telekit.egg-info}/PKG-INFO +6 -2
  8. telekit-2.2.0a0/telekit/_user.py +0 -138
  9. {telekit-2.2.0a0 → telekit-2.2.0a1}/LICENSE +0 -0
  10. {telekit-2.2.0a0 → telekit-2.2.0a1}/README.md +0 -0
  11. {telekit-2.2.0a0 → telekit-2.2.0a1}/setup.cfg +0 -0
  12. {telekit-2.2.0a0 → telekit-2.2.0a1}/setup.py +0 -0
  13. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/__init__.py +0 -0
  14. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_buildtext/__init__.py +0 -0
  15. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_buildtext/formatter.py +0 -0
  16. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_buildtext/styles.py +0 -0
  17. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_callback_query_handler.py +0 -0
  18. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_chain.py +0 -0
  19. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_chain_base.py +0 -0
  20. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_chain_entry_logic.py +0 -0
  21. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_chain_inline_keyboards_logic.py +0 -0
  22. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_chapters/__init__.py +0 -0
  23. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_chapters/chapters.py +0 -0
  24. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_init.py +0 -0
  25. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_inline_buttons.py +0 -0
  26. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_input_handler.py +0 -0
  27. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_on.py +0 -0
  28. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_snapvault/__init__.py +0 -0
  29. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_snapvault/snapcode.py +0 -0
  30. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_snapvault/snapvault.py +0 -0
  31. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_state.py +0 -0
  32. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/__init__.py +0 -0
  33. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/mixin.py +0 -0
  34. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/parser/__init__.py +0 -0
  35. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/parser/builder.py +0 -0
  36. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/parser/canvas_parser.py +0 -0
  37. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/parser/lexer.py +0 -0
  38. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/parser/nodes.py +0 -0
  39. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/parser/parser.py +0 -0
  40. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/parser/token.py +0 -0
  41. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/telekit_dsl.py +0 -0
  42. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_telekit_dsl/telekit_orm.py +0 -0
  43. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/_timeout.py +0 -0
  44. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/dices.py +0 -0
  45. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/__init__.py +0 -0
  46. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/__init__.py +0 -0
  47. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/complete_hotel.py +0 -0
  48. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/counter.py +0 -0
  49. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/dsl.py +0 -0
  50. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/entry.py +0 -0
  51. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/faq.py +0 -0
  52. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/hotel.py +0 -0
  53. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/on_text.py +0 -0
  54. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/pages.py +0 -0
  55. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/pyapi.py +0 -0
  56. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/qr.py +0 -0
  57. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/quiz.py +0 -0
  58. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/spells.py +0 -0
  59. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/start.py +0 -0
  60. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_handlers/text_document.py +0 -0
  61. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/example/example_server.py +0 -0
  62. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/inline_buttons.py +0 -0
  63. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/parameters.py +0 -0
  64. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/senders.py +0 -0
  65. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/server.py +0 -0
  66. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/styles.py +0 -0
  67. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit/utils.py +0 -0
  68. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit.egg-info/SOURCES.txt +0 -0
  69. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit.egg-info/dependency_links.txt +0 -0
  70. {telekit-2.2.0a0 → telekit-2.2.0a1}/telekit.egg-info/requires.txt +0 -0
  71. {telekit-2.2.0a0 → telekit-2.2.0a1}/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.0a0
3
+ Version: 2.2.0a1
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.0a0
381
+ # Changes in version 2.2.0a1
382
382
 
383
383
  ## New Button Types
384
384
 
@@ -386,3 +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 brief notification at the top of the chat screen. |
389
+
390
+ ## User Refactor
391
+
392
+ `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.
@@ -98,7 +98,7 @@ class Handler:
98
98
 
99
99
  def __init__(self, message: Message):
100
100
  self.message: Message = message
101
- self.user = User(self.message.chat.id, self.message.from_user)
101
+ self.user = User(self.message)
102
102
  self.new_chain()
103
103
 
104
104
  def handle(self) -> Any:
@@ -112,7 +112,7 @@ class Handler:
112
112
  avoids the need for multiple custom entry methods
113
113
  like `start` or `handle_start`.
114
114
  """
115
- library.warning("Handler `handle` was called but not overridden; no logic executed.")
115
+ library.warning(f"`{type(self).__qualname__}().handle()` was called but not overridden; no logic executed.")
116
116
  return
117
117
 
118
118
  # -----------------------------------------------------
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  import sys
3
3
  from pathlib import Path
4
- from typing import Union, Callable, Protocol
4
+ from typing import Union, Callable
5
5
 
6
6
  # ------------------------------
7
7
  # Formatter
@@ -49,31 +49,32 @@ user_logger.addHandler(uch)
49
49
  def enable_user_logging(*user_ids: Union[int, str]) -> None:
50
50
  _enabled_users.update(user_ids)
51
51
 
52
- class UserLoggerProtocol(Protocol):
53
- def info(self, msg: str, *args, **kwargs) -> None: ...
54
- def warning(self, msg: str, *args, **kwargs) -> None: ...
55
- def debug(self, msg: str, *args, **kwargs) -> None: ...
56
- def error(self, msg: str, *args, **kwargs) -> None: ...
57
- def critical(self, msg: str, *args, **kwargs) -> None: ...
58
-
59
- def _users(user_id: Union[int, str]) -> UserLoggerProtocol:
60
- class UserLogger:
61
- def info(self, msg, *args, **kwargs):
62
- if user_id in _enabled_users:
63
- user_logger.info(f"[{user_id}] {msg}", *args, stacklevel=2, **kwargs)
64
- def warning(self, msg, *args, **kwargs):
65
- if user_id in _enabled_users:
66
- user_logger.warning(f"[{user_id}] {msg}", *args, stacklevel=2, **kwargs)
67
- def debug(self, msg, *args, **kwargs):
68
- if user_id in _enabled_users:
69
- user_logger.debug(f"[{user_id}] {msg}", *args, stacklevel=2, **kwargs)
70
- def error(self, msg, *args, **kwargs):
71
- if user_id in _enabled_users:
72
- user_logger.error(f"[{user_id}] {msg}", *args, stacklevel=2, **kwargs)
73
- def critical(self, msg, *args, **kwargs):
74
- if user_id in _enabled_users:
75
- user_logger.critical(f"[{user_id}] {msg}", *args, stacklevel=2, **kwargs)
76
- return UserLogger()
52
+ class _UserLogger:
53
+ """Thin wrapper that prefixes every log line with the user ID."""
54
+
55
+ __slots__ = ("_user_id",)
56
+
57
+ def __init__(self, user_id: int | str | None) -> None:
58
+ self._user_id = user_id
59
+
60
+ def _log(self, level: int, msg: str, *args, **kwargs) -> None:
61
+ if self._user_id in _enabled_users:
62
+ user_logger.log(level, f"[{self._user_id}] {msg}", *args, stacklevel=3, **kwargs)
63
+
64
+ def debug(self, msg: str, *args, **kwargs) -> None:
65
+ self._log(logging.DEBUG, msg, *args, **kwargs)
66
+
67
+ def info(self, msg: str, *args, **kwargs) -> None:
68
+ self._log(logging.INFO, msg, *args, **kwargs)
69
+
70
+ def warning(self, msg: str, *args, **kwargs) -> None:
71
+ self._log(logging.WARNING, msg, *args, **kwargs)
72
+
73
+ def error(self, msg: str, *args, **kwargs) -> None:
74
+ self._log(logging.ERROR, msg, *args, **kwargs)
75
+
76
+ def critical(self, msg: str, *args, **kwargs) -> None:
77
+ self._log(logging.CRITICAL, msg, *args, **kwargs)
77
78
 
78
79
  # ------------------------------
79
80
  # Server Logging
@@ -115,8 +116,8 @@ class LoggerWrapper:
115
116
  enable_user_logging: Callable[..., None] = enable_user_logging
116
117
  enable_file_logging: Callable[..., None] = enable_file_logging
117
118
 
118
- def users(self, user_id: int | str):
119
- return _users(user_id)
119
+ def users(self, user_id: int | str | None):
120
+ return _UserLogger(user_id)
120
121
 
121
122
  logger: LoggerWrapper = LoggerWrapper()
122
123
 
@@ -0,0 +1,116 @@
1
+ #
2
+ # Copyright (C) 2026 Romashka
3
+ #
4
+ # This file is part of Telekit.
5
+ #
6
+ # Telekit is free software: you can redistribute it and/or modify it
7
+ # under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Telekit is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty
13
+ # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14
+ # the GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Telekit. If not, see <https://www.gnu.org/licenses/>.
18
+ #
19
+ from functools import cached_property
20
+ from typing import Literal
21
+
22
+ import telebot
23
+ import telebot.types
24
+
25
+ from ._logger import logger
26
+
27
+ __all__ = ["User"]
28
+
29
+
30
+ class User:
31
+
32
+ bot: telebot.TeleBot
33
+
34
+ @classmethod
35
+ def _init(cls, bot: telebot.TeleBot) -> None:
36
+ cls.bot = bot
37
+
38
+ def __init__(self, message: telebot.types.Message) -> None:
39
+ self._message = message
40
+ self._chat_id = message.chat.id
41
+ self.logger = logger.users(self._chat_id)
42
+
43
+ # ── sender ────────────────────────────────────────────────────
44
+
45
+ @cached_property
46
+ def _sender(self) -> telebot.types.User | telebot.types.Chat:
47
+ return self._message.from_user or self._message.chat
48
+
49
+ # ── logging ───────────────────────────────────────────────────
50
+
51
+ def enable_logging(self, *user_ids: int | str) -> None:
52
+ """Enable logging for this user or for additional user IDs."""
53
+ logger.enable_user_logging(*(user_ids or (self._chat_id,)))
54
+
55
+ # ── identity ──────────────────────────────────────────────────
56
+
57
+ @cached_property
58
+ def id(self) -> int:
59
+ return self._sender.id
60
+
61
+ @cached_property
62
+ def is_bot(self) -> bool:
63
+ if isinstance(self._sender, telebot.types.User):
64
+ return self._sender.is_bot
65
+ return False
66
+
67
+ # ── name ──────────────────────────────────────────────────────
68
+
69
+ @cached_property
70
+ def first_name(self) -> str | None:
71
+ if isinstance(self._sender, telebot.types.User):
72
+ return self._sender.first_name
73
+ return self._sender.first_name or self._sender.title
74
+
75
+ @cached_property
76
+ def last_name(self) -> str | None:
77
+ return self._sender.last_name
78
+
79
+ @cached_property
80
+ def full_name(self) -> str | None:
81
+ if isinstance(self._sender, telebot.types.User):
82
+ return self._sender.full_name
83
+ return " ".join(filter(None, [self.first_name, self.last_name])) or None
84
+
85
+ @cached_property
86
+ def username(self) -> str | None:
87
+ return self._sender.username
88
+
89
+ # ── locale ────────────────────────────────────────────────────
90
+
91
+ @cached_property
92
+ def language_code(self) -> str | None:
93
+ if isinstance(self._sender, telebot.types.User):
94
+ return self._sender.language_code
95
+ return None
96
+
97
+ # ── premium & extras ──────────────────────────────────────────
98
+
99
+ @cached_property
100
+ def is_premium(self) -> bool:
101
+ if isinstance(self._sender, telebot.types.User):
102
+ return bool(self._sender.is_premium)
103
+ return False
104
+
105
+ @cached_property
106
+ def added_to_attachment_menu(self) -> bool:
107
+ if isinstance(self._sender, telebot.types.User):
108
+ return bool(self._sender.added_to_attachment_menu)
109
+ return False
110
+
111
+ # ── chat-only ─────────────────────────────────────────────────
112
+
113
+ @cached_property
114
+ def chat_type(self) -> Literal["private", "group", "supergroup", "channel"]:
115
+ """Type of the chat: private, group, supergroup, or channel."""
116
+ return self._message.chat.type # pyright: ignore[reportReturnType]
@@ -1,5 +1,6 @@
1
1
  # ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
2
2
  # PyPI package version: https://img.shields.io/pypi/v/telekit.svg
3
+ # PyPI history: https://pypi.org/project/telekit/#history
3
4
  # ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
4
5
 
5
- __version__ = "2.2.0a0"
6
+ __version__ = "2.2.0a1"
@@ -26,11 +26,13 @@ from .utils import format_file_size
26
26
 
27
27
  from ._user import User
28
28
  from ._inline_buttons import (
29
+ ButtonStyle,
29
30
  InlineButton,
30
31
  LinkButton, WebAppButton,
31
32
  CopyTextButton, SuggestButton,
32
33
  CallbackButton,
33
- ButtonStyle
34
+ AlertButton,
35
+ NotificationButton
34
36
  )
35
37
 
36
38
  from .styles import Styles, TextEntity, StaticTextEntity, EasyTextEntity
@@ -168,6 +170,8 @@ __all__ = [
168
170
  "CopyTextButton",
169
171
  "SuggestButton",
170
172
  "CallbackButton",
173
+ "AlertButton",
174
+ "NotificationButton",
171
175
 
172
176
  "ButtonStyle",
173
177
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: telekit
3
- Version: 2.2.0a0
3
+ Version: 2.2.0a1
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.0a0
381
+ # Changes in version 2.2.0a1
382
382
 
383
383
  ## New Button Types
384
384
 
@@ -386,3 +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 brief notification at the top of the chat screen. |
389
+
390
+ ## User Refactor
391
+
392
+ `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.
@@ -1,138 +0,0 @@
1
- #
2
- # Copyright (C) 2026 Romashka
3
- #
4
- # This file is part of Telekit.
5
- #
6
- # Telekit is free software: you can redistribute it and/or modify it
7
- # under the terms of the GNU General Public License as published by
8
- # the Free Software Foundation, either version 3 of the License, or
9
- # (at your option) any later version.
10
- #
11
- # Telekit is distributed in the hope that it will be useful,
12
- # but WITHOUT ANY WARRANTY; without even the implied warranty
13
- # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14
- # the GNU General Public License for more details.
15
- #
16
- # You should have received a copy of the GNU General Public License
17
- # along with Telekit. If not, see <https://www.gnu.org/licenses/>.
18
- #
19
-
20
- import telebot.types
21
- import telebot
22
-
23
- from ._logger import logger
24
-
25
- __all__ = ["User"]
26
-
27
-
28
- class User:
29
-
30
- bot: telebot.TeleBot
31
-
32
- @classmethod
33
- def _init(cls, bot: telebot.TeleBot):
34
- """
35
- Initializes the bot instance for the class.
36
-
37
- Args:
38
- bot (TeleBot): The Telegram bot instance to be used for sending messages.
39
- """
40
- cls.bot = bot
41
-
42
- def __init__(self, chat_id: int, from_user: telebot.types.User | None):
43
- self.chat_id = chat_id
44
- self.from_user = from_user
45
-
46
- self.logger = logger.users(self.chat_id)
47
-
48
- def enable_logging(self, *user_ids: int | str):
49
- """
50
- Enable logging for this user or for additional user IDs.
51
-
52
- If no arguments are passed, enables logging for this instance's chat_id.
53
- """
54
- if user_ids:
55
- logger.enable_user_logging(*user_ids)
56
- else:
57
- logger.enable_user_logging(self.chat_id)
58
-
59
- # Chat Full Info
60
-
61
- def get_chat_full_info(self) -> telebot.types.ChatFullInfo | None:
62
- try:
63
- return self.bot.get_chat(self.chat_id)
64
- except:
65
- return None
66
-
67
- @property
68
- def chat_full_info(self) -> telebot.types.ChatFullInfo | None:
69
- # Equivalent to `get_chat_full_info()` but the result is cached so only one API call is needed.
70
- if not hasattr(self, "_chat_full_info"):
71
- self._chat_full_info = self.get_chat_full_info()
72
-
73
- return self._chat_full_info
74
-
75
- # Username
76
-
77
- def get_username(self) -> str | None:
78
- if chat := self.get_chat_full_info():
79
- return chat.username
80
-
81
- @property
82
- def username(self) -> str | None:
83
- if not hasattr(self, "_username"):
84
- self._username = self.get_username()
85
-
86
- return self._username
87
-
88
- # First Name
89
-
90
- def get_first_name(self) -> str | None:
91
- if chat := self.get_chat_full_info():
92
- return chat.first_name
93
-
94
- @property
95
- def first_name(self) -> str | None:
96
- if not hasattr(self, "_first_name"):
97
- self._first_name = self.get_first_name()
98
-
99
- return self._first_name
100
-
101
- # Last Name
102
-
103
- def get_last_name(self) -> str | None:
104
- if chat := self.get_chat_full_info():
105
- return chat.last_name
106
-
107
- @property
108
- def last_name(self) -> str | None:
109
- if not hasattr(self, "_last_name"):
110
- self._last_name = self.get_last_name()
111
-
112
- return self._last_name
113
-
114
- # Full Name
115
-
116
- def get_full_name(self) -> str | None:
117
- if chat := self.from_user: # TODO
118
- return chat.full_name
119
-
120
- @property
121
- def full_name(self) -> str | None:
122
- if not hasattr(self, "_full_name"):
123
- self._full_name = self.get_full_name()
124
-
125
- return self._full_name
126
-
127
- # User ID
128
-
129
- def get_id(self) -> int | None:
130
- if chat := self.from_user: # TODO
131
- return chat.id # TODO
132
-
133
- @property
134
- def id(self) -> int | None:
135
- if not hasattr(self, "_id"):
136
- self._id = self.get_id()
137
-
138
- return self._id
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes