Feat/telegram reply to message and read user display name#9041
Conversation
Introduces a new `telegram_reply_to_message` configuration option, allowing users to control whether the bot automatically quotes the original message when sending a reply. This behavior can be set for `private` chats, `group` chats, `all` chats, or turned `off`. This provides greater flexibility in how the bot interacts in different Telegram chat environments. Additionally, this commit improves the resolution of sender nicknames for Telegram messages, prioritizing a combination of first/last name and username for a more comprehensive display.
This improves the user experience and internationalization of the recently introduced 'telegram_reply_to_message' configuration by providing clear, localized labels for its options in the dashboard.
When the `telegram_reply_to_message` configuration is set to prevent replies, remove any `Reply` components that may have been added to the message chain by other global settings. This ensures the Telegram platform's specific setting to disable quoting is always respected, overriding any default reply behavior.
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The
reply_to_messagesetting is passed around as raw string literals ("off","private","group","all"); consider centralizing these as constants or an enum-like structure and validating the config on load to avoid typos and make future changes safer. - In
TelegramPlatformEvent.send, mutatingmessage.chainin-place to stripReplycomponents couples this behavior tightly to Telegram; you might consider doing this on a clonedMessageChainor in a small helper to make side effects clearer and avoid surprising other platform-specific logic that reuses the same instance.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `reply_to_message` setting is passed around as raw string literals (`"off"`, `"private"`, `"group"`, `"all"`); consider centralizing these as constants or an enum-like structure and validating the config on load to avoid typos and make future changes safer.
- In `TelegramPlatformEvent.send`, mutating `message.chain` in-place to strip `Reply` components couples this behavior tightly to Telegram; you might consider doing this on a cloned `MessageChain` or in a small helper to make side effects clearer and avoid surprising other platform-specific logic that reuses the same instance.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Code Review
This pull request introduces a new configuration option telegram_reply_to_message allowing users to configure whether the Telegram bot quotes the triggering message in replies (with options for off, private, group, or all). It also refactors how sender nicknames are constructed by combining display names and usernames. The review feedback points out a potential issue in unit tests where unconfigured MagicMock attributes for user names could cause TypeError or leak mock strings, and suggests adding defensive type checks.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| display_name = " ".join( | ||
| part for part in (_from_user.first_name, _from_user.last_name) if part | ||
| ).strip() | ||
| if display_name and _from_user.username: | ||
| nickname = f"{display_name} (@{_from_user.username})" | ||
| else: | ||
| nickname = display_name or _from_user.username or "Unknown" |
There was a problem hiding this comment.
在单元测试中,_from_user 经常会被 Mock 为 MagicMock 对象。如果未显式为 Mock 对象设置 first_name、last_name 或 username,直接访问它们会返回新的 MagicMock 实例(其布尔值为 True)。这会导致 " ".join(...) 尝试拼接 MagicMock 对象而抛出 TypeError,或者在 nickname 中泄露 Mock 对象的字符串表示。
建议使用 isinstance(part, str) 进行防御性类型检查,以确保代码在测试和各种边界情况下都能鲁棒运行。
display_name = " ".join(
part for part in (_from_user.first_name, _from_user.last_name) if isinstance(part, str)
).strip()
username = _from_user.username if isinstance(_from_user.username, str) else None
if display_name and username:
nickname = f"{display_name} (@{username})"
else:
nickname = display_name or username or "Unknown"
当前 Telegram 适配器存在两个不足:
username(@handle)作为发送者昵称,忽略first_name/last_name显示名,导致传给 LLM 的昵称信息不完整。本 PR 补充显示名读取和可配置的回复引用功能。
Modifications / 改动点
核心文件:
astrbot/core/config/default.py— 新增telegram_reply_to_message配置项(四档枚举:off/private/group/all,默认off),含 schema 元数据和默认模板。astrbot/core/platform/sources/telegram/tg_adapter.py— 读取配置;构建sender.nickname为显示名称 (@username)格式。astrbot/core/platform/sources/telegram/tg_event.py— 按配置策略决定是否引用原消息;off时清除全局 pipeline 注入的 Reply 组件。国际化文件:
dashboard/src/i18n/locales/zh-CN/features/config-metadata.jsondashboard/src/i18n/locales/en-US/features/config-metadata.jsondashboard/src/i18n/locales/ru-RU/features/config-metadata.json实现的功能:
off档严格屏蔽全局 pipeline 注入的 ReplyScreenshots or Test Results / 运行截图或测试结果
显示名称测试:
引用模式测试:
WebUI 下拉渲染:
机器人>Telegram>编辑的配置页出现「Telegram 回复时引用消息」下拉框,选项显示「关闭 / 仅私聊 / 仅群聊 / 私聊和群聊」。
我已通过ruff执行格式与代码检查
Checklist / 检查清单
😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
/ 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。
👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
/ 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”。
🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in
requirements.txtandpyproject.toml./ 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到
requirements.txt和pyproject.toml文件相应位置。😮 My changes do not introduce malicious code.
/ 我的更改没有引入恶意代码。
Summary by Sourcery
Add configurable reply behavior and richer sender display names to the Telegram adapter.
New Features:
Enhancements: