feat: add static help image command (/鹿帮助) v2.1.2 - #25
Conversation
Add /鹿帮助 with static assets/help.png, plain-text help triggers, and event-level dedup/stop for help/deer/calendar double-fire. Also allow no-space 🦌@用户 plain triggers and ignore local data/.
Reviewer's Guide实现一个静态帮助图片命令(/鹿帮助),同时支持斜杠命令和纯文本触发;为帮助 / 鹿 / 日历在斜杠与纯文本处理器之间增加事件级去重;扩展纯文本“鹿”匹配模式以支持无空格提及;更新文档描述新行为,并将插件版本提升到 v2.1.2。 帮助命令处理与斜杠/纯文本去重的序列图sequenceDiagram
actor User
participant AstrBot
participant Main as MainHandler
participant Help as HelpCommandHandler
participant Event as AstrMessageEvent
User->>AstrBot: /鹿帮助
AstrBot->>Main: help_cmd(event)
Main->>Help: handle_help(event)
Help->>Event: get_extra(EVENT_DEDUP_HELP)
alt [event not yet handled]
Help->>Event: set_extra(EVENT_DEDUP_HELP, True)
Help->>Help: help_image.is_file()
alt [image exists]
Help->>Event: image_result(help.png)
Help->>Event: stop_event()
else [image missing]
Help->>Event: plain_result("帮助图资源缺失,请重新安装或更新插件。")
Help->>Event: stop_event()
end
else [event already handled]
Help-->>Main: return
end
User->>AstrBot: 鹿帮助
AstrBot->>Main: plain_help_cmd(event)
Main->>Main: _is_explicit_slash_command(event)
alt [_is_explicit_slash_command returns False]
Main->>Help: handle_help(event)
else [_is_explicit_slash_command returns True]
Main-->>AstrBot: return (do not run plain handler)
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your Experience访问你的 dashboard 以:
Getting HelpOriginal review guide in EnglishReviewer's GuideImplements a static help image command (/鹿帮助) with both slash and plain-text triggers, adds event-level deduplication between slash/plain handlers for help/deer/calendar, extends plain deer patterns to support no-space mentions, documents the new behavior, and bumps the plugin to v2.1.2. Sequence diagram for help command handling and slash/plain deduplicationsequenceDiagram
actor User
participant AstrBot
participant Main as MainHandler
participant Help as HelpCommandHandler
participant Event as AstrMessageEvent
User->>AstrBot: /鹿帮助
AstrBot->>Main: help_cmd(event)
Main->>Help: handle_help(event)
Help->>Event: get_extra(EVENT_DEDUP_HELP)
alt [event not yet handled]
Help->>Event: set_extra(EVENT_DEDUP_HELP, True)
Help->>Help: help_image.is_file()
alt [image exists]
Help->>Event: image_result(help.png)
Help->>Event: stop_event()
else [image missing]
Help->>Event: plain_result("帮助图资源缺失,请重新安装或更新插件。")
Help->>Event: stop_event()
end
else [event already handled]
Help-->>Main: return
end
User->>AstrBot: 鹿帮助
AstrBot->>Main: plain_help_cmd(event)
Main->>Main: _is_explicit_slash_command(event)
alt [_is_explicit_slash_command returns False]
Main->>Help: handle_help(event)
else [_is_explicit_slash_command returns True]
Main-->>AstrBot: return (do not run plain handler)
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (17)
📝 WalkthroughWalkthrough新增固定帮助图命令(/鹿帮助 及纯文本触发),实现 HelpCommandHandler 直接发送 assets/help.png(无 t2i 依赖),并在 main.py 中接入相应命令与正则处理器。新增事件去重常量并在打卡/日历命令流程中添加去重检查与 stop_event 调用。新增帮助图生成脚本、测试及文档/版本更新。 Changes帮助图命令与去重停止事件
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers: Poem
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
误提到上游,已经关闭惹 |
There was a problem hiding this comment.
Hey - 我发现了两个问题,并给出了一些整体层面的反馈:
- 事件去重模式(
EVENT_DEDUP_*+get_extra/set_extra+stop_event)现在在help_cmd、deer_cmd和calendar_cmd中都有重复;建议提取一个小的辅助函数(例如mark_handled(event, key))来集中这部分逻辑,以避免未来新 handler 中出现一些不易察觉的不一致。 tests/test_help_handler.py::_load_help_command_handler中的自定义导入路径脚手架逻辑比较复杂、也比较脆弱;可以考虑通过直接从真实的src包中(或者通过一个最小的测试专用 shim 模块)导入HelpCommandHandler和EVENT_DEDUP_HELP,而不是去模拟一套单独的包层级结构,从而简化实现。
给 AI Agent 的提示
请根据本次代码评审中的意见进行修改:
## 整体性评论
- 事件去重模式(`EVENT_DEDUP_*` + `get_extra/set_extra` + `stop_event`)现在在 `help_cmd`、`deer_cmd` 和 `calendar_cmd` 中都有重复;建议提取一个小的辅助函数(例如 `mark_handled(event, key)`)来集中这部分逻辑,以避免未来新 handler 中出现一些不易察觉的不一致。
- `tests/test_help_handler.py::_load_help_command_handler` 中的自定义导入路径脚手架逻辑比较复杂、也比较脆弱;可以考虑通过直接从真实的 `src` 包中(或者通过一个最小的测试专用 shim 模块)导入 `HelpCommandHandler` 和 `EVENT_DEDUP_HELP`,而不是去模拟一套单独的包层级结构,从而简化实现。
## 单条评论
### 评论 1
<location path="scripts/gen_help_image.py" line_range="197" />
<code_context>
+ await browser.close()
+ finally:
+ html_path.unlink(missing_ok=True)
+ print(f"saved {OUT_PNG} ({OUT_PNG.stat().st_size} bytes)")
+
+
</code_context>
<issue_to_address>
**issue:** 为最后一次 OUT_PNG.stat() 调用增加保护,以避免在截图生成失败时导致崩溃。
如果 Playwright 在渲染或写入截图时失败,OUT_PNG 可能不会被创建,而此时调用 OUT_PNG.stat() 会抛出 FileNotFoundError。这样会把工具层面的问题(例如缺少 Chromium、字体下载出错等)变成脚本里一个不友好的崩溃。请在调用 stat() 之前先检查 OUT_PNG.exists(),并在文件缺失时输出更清晰的提示信息,使脚本在失败时表现得更“温和”一些。
</issue_to_address>
### 评论 2
<location path="src/shared/constants.py" line_range="14-21" />
<code_context>
# =============================================================================
PLAIN_DEER_TRIGGER_PATTERN: Final[str] = (
- r"^(?!/)(?:[🦌鹿撸]|撸🦌|帮\s*(?:[🦌鹿撸]|撸🦌))(?:\s+.*)?$"
+ r"^(?!/)"
+ r"(?:"
+ r"帮\s*(?:[🦌鹿撸]|撸🦌)(?:\s+.*|@.*)?|"
</code_context>
<issue_to_address>
**suggestion:** 重新审视 PLAIN_DEER_TRIGGER_PATTERN,以更好处理像不带目标对象的裸 "帮🦌" 这类边界情况。
由于增加了可选的 (?:\s+.*|@.*)? 分组,现在该模式会匹配裸 "帮🦌" / "帮鹿"。在 run_deer_checkin 中,当 at_ids 为空时,帮 分支会退回到自助打卡,因此这些输入会被当作普通打卡,而不是“帮别人打卡”命令。如果这不是你想要的行为,可以考虑收紧 帮… 的正则,让它必须包含 @ 提及或额外文本(例如 @.* 或 \s+@...)。
```suggestion
PLAIN_DEER_TRIGGER_PATTERN: Final[str] = (
r"^(?!/)"
r"(?:"
r"帮\s*(?:[🦌鹿撸]|撸🦌)(?:\s+.+|@.+)|"
r"(?:撸🦌|[🦌鹿撸])(?!\s*(?:帮助|菜单))(?:\s+.*|@.*)?"
r")$"
)
"""纯文本打卡触发:短命令或“帮鹿/帮🦌 ...”;要求帮命令后有 @ 或额外文本;允许 🦌@用户 无空格;排除“鹿帮助/鹿菜单”."""
```
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的评审。
Original comment in English
Hey - I've found 2 issues, and left some high level feedback:
- The event deduplication pattern (
EVENT_DEDUP_*+get_extra/set_extra+stop_event) is now duplicated acrosshelp_cmd,deer_cmd, andcalendar_cmd; consider extracting a small helper (e.g.,mark_handled(event, key)) to centralize this behavior and avoid subtle inconsistencies in future handlers. - The custom import path scaffolding in
tests/test_help_handler.py::_load_help_command_handleris quite involved and brittle; you might simplify this by importingHelpCommandHandlerandEVENT_DEDUP_HELPfrom the realsrcpackage (or via a minimal test-only shim module) instead of emulating a separate package hierarchy.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The event deduplication pattern (`EVENT_DEDUP_*` + `get_extra/set_extra` + `stop_event`) is now duplicated across `help_cmd`, `deer_cmd`, and `calendar_cmd`; consider extracting a small helper (e.g., `mark_handled(event, key)`) to centralize this behavior and avoid subtle inconsistencies in future handlers.
- The custom import path scaffolding in `tests/test_help_handler.py::_load_help_command_handler` is quite involved and brittle; you might simplify this by importing `HelpCommandHandler` and `EVENT_DEDUP_HELP` from the real `src` package (or via a minimal test-only shim module) instead of emulating a separate package hierarchy.
## Individual Comments
### Comment 1
<location path="scripts/gen_help_image.py" line_range="197" />
<code_context>
+ await browser.close()
+ finally:
+ html_path.unlink(missing_ok=True)
+ print(f"saved {OUT_PNG} ({OUT_PNG.stat().st_size} bytes)")
+
+
</code_context>
<issue_to_address>
**issue:** Guard the final OUT_PNG.stat() call to avoid crashing when screenshot generation fails.
If Playwright fails to render or write the screenshot, OUT_PNG may not be created and OUT_PNG.stat() will raise FileNotFoundError. This turns tooling issues (e.g. missing Chromium, font download problems) into an unhelpful crash in this script. Please check OUT_PNG.exists() before calling stat(), and emit a clearer message when the file is missing so the script fails more gracefully.
</issue_to_address>
### Comment 2
<location path="src/shared/constants.py" line_range="14-21" />
<code_context>
# =============================================================================
PLAIN_DEER_TRIGGER_PATTERN: Final[str] = (
- r"^(?!/)(?:[🦌鹿撸]|撸🦌|帮\s*(?:[🦌鹿撸]|撸🦌))(?:\s+.*)?$"
+ r"^(?!/)"
+ r"(?:"
+ r"帮\s*(?:[🦌鹿撸]|撸🦌)(?:\s+.*|@.*)?|"
</code_context>
<issue_to_address>
**suggestion:** Revisit the PLAIN_DEER_TRIGGER_PATTERN for edge cases like bare "帮🦌" without a target.
With the optional (?:\s+.*|@.*)? group, the pattern now matches bare "帮🦌" / "帮鹿". In run_deer_checkin, the 帮 branch falls back to self-checkin when at_ids is empty, so these inputs are treated as normal check-ins rather than "help others" commands. If that’s not desired, consider tightening the 帮… regex to require an @ mention or additional text (e.g., @.* or \s+@...).
```suggestion
PLAIN_DEER_TRIGGER_PATTERN: Final[str] = (
r"^(?!/)"
r"(?:"
r"帮\s*(?:[🦌鹿撸]|撸🦌)(?:\s+.+|@.+)|"
r"(?:撸🦌|[🦌鹿撸])(?!\s*(?:帮助|菜单))(?:\s+.*|@.*)?"
r")$"
)
"""纯文本打卡触发:短命令或“帮鹿/帮🦌 ...”;要求帮命令后有 @ 或额外文本;允许 🦌@用户 无空格;排除“鹿帮助/鹿菜单”."""
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| await browser.close() | ||
| finally: | ||
| html_path.unlink(missing_ok=True) | ||
| print(f"saved {OUT_PNG} ({OUT_PNG.stat().st_size} bytes)") |
There was a problem hiding this comment.
issue: 为最后一次 OUT_PNG.stat() 调用增加保护,以避免在截图生成失败时导致崩溃。
如果 Playwright 在渲染或写入截图时失败,OUT_PNG 可能不会被创建,而此时调用 OUT_PNG.stat() 会抛出 FileNotFoundError。这样会把工具层面的问题(例如缺少 Chromium、字体下载出错等)变成脚本里一个不友好的崩溃。请在调用 stat() 之前先检查 OUT_PNG.exists(),并在文件缺失时输出更清晰的提示信息,使脚本在失败时表现得更“温和”一些。
Original comment in English
issue: Guard the final OUT_PNG.stat() call to avoid crashing when screenshot generation fails.
If Playwright fails to render or write the screenshot, OUT_PNG may not be created and OUT_PNG.stat() will raise FileNotFoundError. This turns tooling issues (e.g. missing Chromium, font download problems) into an unhelpful crash in this script. Please check OUT_PNG.exists() before calling stat(), and emit a clearer message when the file is missing so the script fails more gracefully.
| PLAIN_DEER_TRIGGER_PATTERN: Final[str] = ( | ||
| r"^(?!/)(?:[🦌鹿撸]|撸🦌|帮\s*(?:[🦌鹿撸]|撸🦌))(?:\s+.*)?$" | ||
| r"^(?!/)" | ||
| r"(?:" | ||
| r"帮\s*(?:[🦌鹿撸]|撸🦌)(?:\s+.*|@.*)?|" | ||
| r"(?:撸🦌|[🦌鹿撸])(?!\s*(?:帮助|菜单))(?:\s+.*|@.*)?" | ||
| r")$" | ||
| ) | ||
| """纯文本打卡触发:仅完整短命令或“帮鹿/帮🦌 ...”格式,避免普通文本误触发.""" | ||
| """纯文本打卡触发:短命令或“帮鹿/帮🦌 ...”;允许 🦌@用户 无空格;排除“鹿帮助/鹿菜单”.""" |
There was a problem hiding this comment.
suggestion: 重新审视 PLAIN_DEER_TRIGGER_PATTERN,以更好处理像不带目标对象的裸 "帮🦌" 这类边界情况。
由于增加了可选的 (?:\s+.|@.)? 分组,现在该模式会匹配裸 "帮🦌" / "帮鹿"。在 run_deer_checkin 中,当 at_ids 为空时,帮 分支会退回到自助打卡,因此这些输入会被当作普通打卡,而不是“帮别人打卡”命令。如果这不是你想要的行为,可以考虑收紧 帮… 的正则,让它必须包含 @ 提及或额外文本(例如 @.* 或 \s+@...)。
| PLAIN_DEER_TRIGGER_PATTERN: Final[str] = ( | |
| r"^(?!/)(?:[🦌鹿撸]|撸🦌|帮\s*(?:[🦌鹿撸]|撸🦌))(?:\s+.*)?$" | |
| r"^(?!/)" | |
| r"(?:" | |
| r"帮\s*(?:[🦌鹿撸]|撸🦌)(?:\s+.*|@.*)?|" | |
| r"(?:撸🦌|[🦌鹿撸])(?!\s*(?:帮助|菜单))(?:\s+.*|@.*)?" | |
| r")$" | |
| ) | |
| """纯文本打卡触发:仅完整短命令或“帮鹿/帮🦌 ...”格式,避免普通文本误触发.""" | |
| """纯文本打卡触发:短命令或“帮鹿/帮🦌 ...”;允许 🦌@用户 无空格;排除“鹿帮助/鹿菜单”.""" | |
| PLAIN_DEER_TRIGGER_PATTERN: Final[str] = ( | |
| r"^(?!/)" | |
| r"(?:" | |
| r"帮\s*(?:[🦌鹿撸]|撸🦌)(?:\s+.+|@.+)|" | |
| r"(?:撸🦌|[🦌鹿撸])(?!\s*(?:帮助|菜单))(?:\s+.*|@.*)?" | |
| r")$" | |
| ) | |
| """纯文本打卡触发:短命令或“帮鹿/帮🦌 ...”;要求帮命令后有 @ 或额外文本;允许 🦌@用户 无空格;排除“鹿帮助/鹿菜单”.""" |
Original comment in English
suggestion: Revisit the PLAIN_DEER_TRIGGER_PATTERN for edge cases like bare "帮🦌" without a target.
With the optional (?:\s+.|@.)? group, the pattern now matches bare "帮🦌" / "帮鹿". In run_deer_checkin, the 帮 branch falls back to self-checkin when at_ids is empty, so these inputs are treated as normal check-ins rather than "help others" commands. If that’s not desired, consider tightening the 帮… regex to require an @ mention or additional text (e.g., @.* or \s+@...).
| PLAIN_DEER_TRIGGER_PATTERN: Final[str] = ( | |
| r"^(?!/)(?:[🦌鹿撸]|撸🦌|帮\s*(?:[🦌鹿撸]|撸🦌))(?:\s+.*)?$" | |
| r"^(?!/)" | |
| r"(?:" | |
| r"帮\s*(?:[🦌鹿撸]|撸🦌)(?:\s+.*|@.*)?|" | |
| r"(?:撸🦌|[🦌鹿撸])(?!\s*(?:帮助|菜单))(?:\s+.*|@.*)?" | |
| r")$" | |
| ) | |
| """纯文本打卡触发:仅完整短命令或“帮鹿/帮🦌 ...”格式,避免普通文本误触发.""" | |
| """纯文本打卡触发:短命令或“帮鹿/帮🦌 ...”;允许 🦌@用户 无空格;排除“鹿帮助/鹿菜单”.""" | |
| PLAIN_DEER_TRIGGER_PATTERN: Final[str] = ( | |
| r"^(?!/)" | |
| r"(?:" | |
| r"帮\s*(?:[🦌鹿撸]|撸🦌)(?:\s+.+|@.+)|" | |
| r"(?:撸🦌|[🦌鹿撸])(?!\s*(?:帮助|菜单))(?:\s+.*|@.*)?" | |
| r")$" | |
| ) | |
| """纯文本打卡触发:短命令或“帮鹿/帮🦌 ...”;要求帮命令后有 @ 或额外文本;允许 🦌@用户 无空格;排除“鹿帮助/鹿菜单”.""" |
Add
/鹿帮助with staticassets/help.png, plain-text help triggers, and event-level dedup/stop for help/deer/calendar double-fire. Also allow no-space🦌@用户plain triggers and ignore localdata/.Motivation / 动机
@拼进message_str时,无空格🦌@用户无法触发 plain 打卡。data/(含配置/缓存)不应被误提交。Modifications / 改动点
新增固定帮助图命令:
/鹿帮助(别名🦌帮助/鹿菜单/deer_help/deerhelp)新增纯文本帮助触发:
鹿帮助、🦌帮助、鹿菜单、deer help等(大小写不敏感,允许中文空格)运行时直接发送打包资源
assets/help.png;缺失时回退文本提示新增开发机截图脚本
scripts/gen_help_image.py(非运行时依赖)帮助 / 打卡 / 鹿历共用
event.extra幂等键,并在处理后stop_event,避免 slash + plain 双发plain 打卡正则支持无空格
🦌@用户/帮🦌@用户.gitignore增加data/版本号
v2.1.2;同步CHANGELOG.md/README.md/CLAUDE.md测试:
tests/test_help_handler.py、扩展tests/test_plain_message_patterns.pyThis is NOT a breaking change. / 这不是一个破坏性变更。
Screenshots or Test Results / 运行截图或测试结果
帮助图已本地生成:
assets/help.png(约 472KB)。建议真机再验证:私聊发鹿帮助是否只回一张图。Verification Steps / 验证步骤
(可选)语法检查:
(可选)重生成帮助图(需本机 Playwright Chromium):
python scripts/gen_help_image.py真机抽查:
鹿帮助//鹿帮助→ 应只收到 一张 帮助图🦌@用户(客户端 @)→ 应走帮打卡鹿/鹿历→ 不应双发Checklist / 检查清单
😊 If there are new features added in the PR, I have discussed them 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./ 无新运行时依赖;Playwright 仅用于开发机生成
help.png。😮 My changes do not introduce malicious code.
/ 我的更改没有引入恶意代码。
📘 I have read and followed repository contribution guidelines.
/ 我已阅读并遵守仓库贡献规范。
Summary by Sourcery
添加一个静态帮助图片命令,并统一纯文本触发词、文档及事件处理逻辑,以避免重复响应并支持更自然的帮助/打卡使用方式。
New Features:
Bug Fixes:
Enhancements:
HelpCommandHandler中集中处理帮助逻辑,以事件为粒度实现幂等行为并发送静态图片。Documentation:
README.md和CLAUDE.md中记录新的静态帮助图片命令、无空格 @ 提及支持以及帮助维护流程,并更新 v2.1.2 的更新日志。Tests:
Chores:
data/目录。Original summary in English
Summary by Sourcery
Add a static help image command and align plain-text triggers, documentation, and event handling to avoid duplicate responses and support more natural help/check-in usage.
New Features:
Bug Fixes:
Enhancements:
Documentation:
Tests:
Chores:
Summary by CodeRabbit
新功能
/鹿帮助、鹿帮助及相关别名,发送固定帮助图片。问题修复
文档