入群欢迎词支持@和图片的cq码 - #98
Conversation
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
Reviewer's Guide此 PR 更改了进群欢迎消息的发送逻辑,改为构造并发送由 CQ 码解析得到的 MessageChain,同时引入了一个 CQ 码解析器,用于将包含 @ 和图片 CQ 码(包括本地文件路径)的文本转换为 AstrBot 消息组件。 解析 CQ 并发送进群欢迎消息的时序图sequenceDiagram
actor GroupMember
participant BotEventHandler as Bot_event_monitoring
participant Database as DB
participant CQParser as parse_cq_to_chain
participant MessageChain as MessageChain
participant MessageAPI as AiocqhttpMessageEvent
GroupMember->>BotEventHandler: member_joins_group(event)
BotEventHandler->>DB: get(gid, join_welcome)
DB-->>BotEventHandler: join_welcome_template
BotEventHandler->>DB: get_nickname(event, uid)
DB-->>BotEventHandler: nickname
BotEventHandler->>BotEventHandler: welcome = join_welcome_template.format(nickname)
BotEventHandler->>CQParser: parse_cq_to_chain(welcome)
CQParser-->>BotEventHandler: components_list
BotEventHandler->>MessageChain: MessageChain(chain=components_list)
MessageChain-->>BotEventHandler: chain_instance
BotEventHandler->>MessageAPI: send(chain_instance)
MessageAPI-->>GroupMember: welcome_message_with_at_and_images
CQ 解析与消息组件的类图classDiagram
class ParseCQToChainModule {
+parse_cq_to_chain(text str) list
}
class Plain {
+text str
}
class At {
+qq str
+name str
}
class Image {
+file str
+url str
+fromURL(url str) Image
+fromFileSystem(path str) Image
}
class MessageChain {
+chain list
}
class AiocqhttpMessageEvent {
+send(message MessageChain) None
+plain_result(text str) str
}
ParseCQToChainModule ..> Plain : creates
ParseCQToChainModule ..> At : creates
ParseCQToChainModule ..> Image : creates
MessageChain o-- Plain : contains
MessageChain o-- At : contains
MessageChain o-- Image : contains
AiocqhttpMessageEvent ..> MessageChain : sends
class JoinHandleEventMonitoring {
+event_monitoring(event AiocqhttpMessageEvent) None
}
JoinHandleEventMonitoring ..> ParseCQToChainModule : uses
JoinHandleEventMonitoring ..> MessageChain : constructs
JoinHandleEventMonitoring ..> AiocqhttpMessageEvent : sends_message_via_event
文件级改动
可能关联的 Issues
Tips and commandsInteracting with Sourcery
Customizing Your Experience访问你的 dashboard 来:
Getting HelpOriginal review guide in EnglishReviewer's GuideThis PR changes the join-welcome sending logic to construct and send a MessageChain parsed from CQ codes, and introduces a CQ-code parser that converts text with @ and image CQ codes (including local file paths) into AstrBot message components. Sequence diagram for sending join welcome with CQ parsingsequenceDiagram
actor GroupMember
participant BotEventHandler as Bot_event_monitoring
participant Database as DB
participant CQParser as parse_cq_to_chain
participant MessageChain as MessageChain
participant MessageAPI as AiocqhttpMessageEvent
GroupMember->>BotEventHandler: member_joins_group(event)
BotEventHandler->>DB: get(gid, join_welcome)
DB-->>BotEventHandler: join_welcome_template
BotEventHandler->>DB: get_nickname(event, uid)
DB-->>BotEventHandler: nickname
BotEventHandler->>BotEventHandler: welcome = join_welcome_template.format(nickname)
BotEventHandler->>CQParser: parse_cq_to_chain(welcome)
CQParser-->>BotEventHandler: components_list
BotEventHandler->>MessageChain: MessageChain(chain=components_list)
MessageChain-->>BotEventHandler: chain_instance
BotEventHandler->>MessageAPI: send(chain_instance)
MessageAPI-->>GroupMember: welcome_message_with_at_and_images
Class diagram for CQ parsing and message componentsclassDiagram
class ParseCQToChainModule {
+parse_cq_to_chain(text str) list
}
class Plain {
+text str
}
class At {
+qq str
+name str
}
class Image {
+file str
+url str
+fromURL(url str) Image
+fromFileSystem(path str) Image
}
class MessageChain {
+chain list
}
class AiocqhttpMessageEvent {
+send(message MessageChain) None
+plain_result(text str) str
}
ParseCQToChainModule ..> Plain : creates
ParseCQToChainModule ..> At : creates
ParseCQToChainModule ..> Image : creates
MessageChain o-- Plain : contains
MessageChain o-- At : contains
MessageChain o-- Image : contains
AiocqhttpMessageEvent ..> MessageChain : sends
class JoinHandleEventMonitoring {
+event_monitoring(event AiocqhttpMessageEvent) None
}
JoinHandleEventMonitoring ..> ParseCQToChainModule : uses
JoinHandleEventMonitoring ..> MessageChain : constructs
JoinHandleEventMonitoring ..> AiocqhttpMessageEvent : sends_message_via_event
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - 我发现了两个问题,并给出了一些整体性的反馈:
- 目前 CQ 解析只处理
at和image类型,并且会静默丢弃其他任何[CQ:...]段;建议把未知的 CQ 代码以纯文本的形式保留下来,这样在出现新的 CQ 类型时就不会丢失内容。 - 当图片文件路径不存在时,当前行为是向用户发送可见的
[图片读取失败: path]消息;可能更安全的做法是只在内部记录日志,并保留原始 CQ 文本或直接省略损坏的图片,而不是在消息中暴露文件系统路径。
给 AI Agent 的提示词
Please address the comments from this code review:
## Overall Comments
- 目前 CQ 解析只处理 `at` 和 `image` 类型,并且会静默丢弃其他任何 `[CQ:...]` 段;建议把未知的 CQ 代码以纯文本的形式保留下来,这样在出现新的 CQ 类型时就不会丢失内容。
- 当图片文件路径不存在时,当前行为是向用户发送可见的 `[图片读取失败: path]` 消息;可能更安全的做法是只在内部记录日志,并保留原始 CQ 文本或直接省略损坏的图片,而不是在消息中暴露文件系统路径。
## Individual Comments
### Comment 1
<location path="core/parse_cq_to_chain.py" line_range="18-19" />
<code_context>
+ if plain_text:
+ chain.append(Plain(plain_text))
+
+ cq_type = match.group(1)
+ params_str = match.group(2)
+
+ # 解析参数:file=D:\xxx...
</code_context>
<issue_to_address>
**issue (bug_risk):** 未识别的 CQ 类型会被静默丢弃,而不是保留为文本。
当 `cq_type` 不是 `at` 或 `image` 时,这个分支只会向前移动 `last_pos`,而不会追加任何内容,因此该 CQ 段会丢失。为避免丢弃未知或未来可能出现的 CQ 类型,建议在类型未被识别时,将原始片段 `text[match.start():match.end()]` 作为一个 `Plain` 段追加到链中。
</issue_to_address>
### Comment 2
<location path="core/parse_cq_to_chain.py" line_range="29-30" />
<code_context>
+ params[k.strip()] = v.strip()
+
+ # 根据类型构造组件
+ if cq_type == "at":
+ chain.append(At(qq=params.get("qq", ""), name=""))
+ elif cq_type == "image":
+ file_path = params.get("file") or params.get("url")
</code_context>
<issue_to_address>
**suggestion:** 当缺少 `qq` 时创建 `At` 会退回到空字符串,这可能比较容易出错。
当 `qq` 缺失或格式不正确时,我们会得到 `At(qq="")`,它可能会静默失效或产生意外行为。建议将缺少 `qq` 的情况视为无效——要么将该段落保留为 `Plain`,要么跳过并插入一个可见的占位符,以便更容易发现配置问题。
Suggested implementation:
```python
# 根据类型构造组件
if cq_type == "at":
qq = (params.get("qq") or "").strip()
# qq 缺失或格式异常时,不创建空的 At,而是退回为原始文本,便于发现配置问题
if qq and qq.isdigit():
chain.append(At(qq=qq, name=""))
else:
chain.append(Plain(match.group(0)))
elif cq_type == "image":
```
This change assumes that `Plain` is already imported and available in this module (similar to `At` and `Image`). If not, you should import `Plain` from the same package where other segment classes (like `At`/`Image`) come from.
</issue_to_address>帮我变得更有用!请对每条评论点 👍 或 👎,我会根据这些反馈改进后续的 Review。
Original comment in English
Hey - I've found 2 issues, and left some high level feedback:
- The CQ parsing only handles
atandimagetypes and silently drops any other[CQ:...]segments; consider preserving unknown CQ codes as plain text so content is not lost if new types appear. - When an image file path does not exist, the current behavior sends a user-visible
[图片读取失败: path]message; it may be safer to log this internally and either keep the original CQ text or omit the broken image rather than exposing filesystem paths in the message.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The CQ parsing only handles `at` and `image` types and silently drops any other `[CQ:...]` segments; consider preserving unknown CQ codes as plain text so content is not lost if new types appear.
- When an image file path does not exist, the current behavior sends a user-visible `[图片读取失败: path]` message; it may be safer to log this internally and either keep the original CQ text or omit the broken image rather than exposing filesystem paths in the message.
## Individual Comments
### Comment 1
<location path="core/parse_cq_to_chain.py" line_range="18-19" />
<code_context>
+ if plain_text:
+ chain.append(Plain(plain_text))
+
+ cq_type = match.group(1)
+ params_str = match.group(2)
+
+ # 解析参数:file=D:\xxx...
</code_context>
<issue_to_address>
**issue (bug_risk):** Unrecognized CQ types are silently dropped instead of being preserved as text.
When `cq_type` is not `at` or `image`, this branch only moves `last_pos` forward and never appends anything, so that CQ segment is lost. To avoid dropping unknown or future CQ types, consider appending the raw slice `text[match.start():match.end()]` as a `Plain` segment when the type isn’t recognized.
</issue_to_address>
### Comment 2
<location path="core/parse_cq_to_chain.py" line_range="29-30" />
<code_context>
+ params[k.strip()] = v.strip()
+
+ # 根据类型构造组件
+ if cq_type == "at":
+ chain.append(At(qq=params.get("qq", ""), name=""))
+ elif cq_type == "image":
+ file_path = params.get("file") or params.get("url")
</code_context>
<issue_to_address>
**suggestion:** Creating an `At` with a missing `qq` falls back to an empty string, which may be error-prone.
When `qq` is missing or malformed, we end up with `At(qq="")`, which may silently do nothing or behave unexpectedly. Consider instead treating missing `qq` as invalid—either leave the segment as `Plain`, or skip it while inserting a visible placeholder so misconfigurations are easier to spot.
Suggested implementation:
```python
# 根据类型构造组件
if cq_type == "at":
qq = (params.get("qq") or "").strip()
# qq 缺失或格式异常时,不创建空的 At,而是退回为原始文本,便于发现配置问题
if qq and qq.isdigit():
chain.append(At(qq=qq, name=""))
else:
chain.append(Plain(match.group(0)))
elif cq_type == "image":
```
This change assumes that `Plain` is already imported and available in this module (similar to `At` and `Image`). If not, you should import `Plain` from the same package where other segment classes (like `At`/`Image`) come from.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| cq_type = match.group(1) | ||
| params_str = match.group(2) |
There was a problem hiding this comment.
issue (bug_risk): 未识别的 CQ 类型会被静默丢弃,而不是保留为文本。
当 cq_type 不是 at 或 image 时,这个分支只会向前移动 last_pos,而不会追加任何内容,因此该 CQ 段会丢失。为避免丢弃未知或未来可能出现的 CQ 类型,建议在类型未被识别时,将原始片段 text[match.start():match.end()] 作为一个 Plain 段追加到链中。
Original comment in English
issue (bug_risk): Unrecognized CQ types are silently dropped instead of being preserved as text.
When cq_type is not at or image, this branch only moves last_pos forward and never appends anything, so that CQ segment is lost. To avoid dropping unknown or future CQ types, consider appending the raw slice text[match.start():match.end()] as a Plain segment when the type isn’t recognized.
| if cq_type == "at": | ||
| chain.append(At(qq=params.get("qq", ""), name="")) |
There was a problem hiding this comment.
suggestion: 当缺少 qq 时创建 At 会退回到空字符串,这可能比较容易出错。
当 qq 缺失或格式不正确时,我们会得到 At(qq=""),它可能会静默失效或产生意外行为。建议将缺少 qq 的情况视为无效——要么将该段落保留为 Plain,要么跳过并插入一个可见的占位符,以便更容易发现配置问题。
Suggested implementation:
# 根据类型构造组件
if cq_type == "at":
qq = (params.get("qq") or "").strip()
# qq 缺失或格式异常时,不创建空的 At,而是退回为原始文本,便于发现配置问题
if qq and qq.isdigit():
chain.append(At(qq=qq, name=""))
else:
chain.append(Plain(match.group(0)))
elif cq_type == "image":This change assumes that Plain is already imported and available in this module (similar to At and Image). If not, you should import Plain from the same package where other segment classes (like At/Image) come from.
Original comment in English
suggestion: Creating an At with a missing qq falls back to an empty string, which may be error-prone.
When qq is missing or malformed, we end up with At(qq=""), which may silently do nothing or behave unexpectedly. Consider instead treating missing qq as invalid—either leave the segment as Plain, or skip it while inserting a visible placeholder so misconfigurations are easier to spot.
Suggested implementation:
# 根据类型构造组件
if cq_type == "at":
qq = (params.get("qq") or "").strip()
# qq 缺失或格式异常时,不创建空的 At,而是退回为原始文本,便于发现配置问题
if qq and qq.isdigit():
chain.append(At(qq=qq, name=""))
else:
chain.append(Plain(match.group(0)))
elif cq_type == "image":This change assumes that Plain is already imported and available in this module (similar to At and Image). If not, you should import Plain from the same package where other segment classes (like At/Image) come from.
1、如题
2、增加了uid替换{qq},format改成了replace避免不存在“{nickname}”时报错
#94
Summary by Sourcery
通过将格式化文本转换为消息链,在群欢迎消息中支持基于 CQ 码的提及和图片。
新功能:
增强:
Original summary in English
Summary by Sourcery
Support CQ code-based mentions and images in group join welcome messages by converting formatted text into a message chain.
New Features:
Enhancements: