Skip to content

Conversation

@shangxueink
Copy link
Contributor

@shangxueink shangxueink commented Sep 9, 2025

#2679 过来的咪

中途遇到一些奇奇怪怪的问题

Git 历史记录的丢失了

重新拉取项目 重新PR咪!


如果有有关此适配器的issues,请at我,我来对接咪。

Motivation

引用消息 无法正确识别
id 配置项 设置了 但是不生效
ark卡片元素支持

Modifications

  • 解决了 Satori适配器引用消息 无法正确识别的问题
  • 根据配置项更新平台元数据
  • 统一http和ws地址的host为localhost
  • 配置项描述使用简体中文呈现
  • ark卡片元素支持

Check

  • 😊 我的 Commit Message 符合良好的规范
  • 👀 我的更改经过良好的测试
  • 🤓 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到了 requirements.txtpyproject.toml 文件相应位置。
  • 😮 我的更改没有引入恶意代码

Sourcery 总结

增强 Satori 适配器,使其能够正确解析和表示引用消息和 ARK 卡片,统一端点主机,尊重为平台元数据配置的 ID,并提高 XML 解析的健壮性,同时将配置文本更新为中文。

新功能:

  • 在 Satori 适配器中支持 ARK 卡片元素
  • 识别并转换引用消息(<quote> 标签)为 Reply 组件
  • 允许从配置或登录用户信息中设置平台元数据 ID

错误修复:

  • 修复引用消息未被正确识别的问题
  • 使 'id' 配置选项对平台元数据生效

改进:

  • 将 Satori HTTP 和 WebSocket 主机规范化为 localhost
  • 改进 XML 解析,以处理命名空间前缀,并将无法识别的标签和解析错误视为纯文本
  • 添加辅助函数以从解析的组件构建消息字符串

文档:

  • 将 Satori 适配器配置描述翻译为简体中文
Original summary in English

Summary by Sourcery

Enhance the Satori adapter to correctly parse and represent quote messages and ARK cards, unify endpoint hosts, respect the configured id for platform metadata, and improve XML parsing robustness, with configuration texts updated to Chinese.

New Features:

  • Support ARK card elements in the Satori adapter
  • Recognize and convert quoted messages ( tags) into Reply components
  • Allow setting platform metadata id from configuration or login user info

Bug Fixes:

  • Fix quote messages not being correctly identified
  • Make the 'id' config option take effect for platform metadata

Enhancements:

  • Normalize Satori HTTP and WebSocket hosts to localhost
  • Improve XML parsing to handle namespace prefixes and treat unrecognized tags and parse errors as plaintext
  • Add helper to build a message string from parsed components

Documentation:

  • Translate Satori adapter configuration descriptions into Simplified Chinese

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你好 - 我已经审阅了你的修改,它们看起来很棒!

AI 代理提示
请处理此代码审查中的评论:
## 个别评论

### 评论 1
<location> `astrbot/core/platform/sources/satori/satori_adapter.py:389` </location>
<code_context>
+    def _build_message_str(self, components: List[BaseMessageComponent]) -> str:
+        """构建消息文本表示"""
+        message_str = ""
+        for comp in components:
+            if isinstance(comp, Plain):
+                message_str += comp.text
+            elif isinstance(comp, Image):
+                message_str += "[图片]"
+            elif isinstance(comp, Record):
+                message_str += "[语音]"
+            elif isinstance(comp, File):
+                message_str += "[文件]"
+            elif isinstance(comp, At):
+                message_str += f"@{comp.name}"
+        return message_str
+
+    async def _convert_quote_message(self, quote: dict) -> Optional[AstrBotMessage]:
</code_context>

<issue_to_address>
_build_message_str 方法遗漏了对 Reply 组件的处理。

此遗漏可能导致消息字符串缺少 Reply 内容。请添加对 Reply 组件的处理,以确保所有消息类型都得到表示。

建议的实现:

```python
        for comp in components:
            if isinstance(comp, Plain):
                message_str += comp.text
            elif isinstance(comp, Image):
                message_str += "[图片]"
            elif isinstance(comp, Record):
                message_str += "[语音]"
            elif isinstance(comp, File):
                message_str += "[文件]"
            elif isinstance(comp, At):
                message_str += f"@{comp.name}"
            elif isinstance(comp, Reply):
                # 假设 Reply 组件有 message_str 属性
                message_str += f"[回复: {getattr(comp, 'message_str', '')}]"
        return message_str

```

如果 `Reply` 类没有 `message_str` 属性,你可能需要调整表示方式以使用可用的属性(例如 `comp.text` 或另一个相关字段)。
如果 `Reply` 类尚未在此文件中导入,请确保导入或定义它。
</issue_to_address>

Sourcery 对开源免费 - 如果你喜欢我们的评论,请考虑分享它们 ✨
帮助我更有用!请点击每个评论上的 👍 或 👎,我将使用这些反馈来改进你的评论。
Original comment in English

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `astrbot/core/platform/sources/satori/satori_adapter.py:389` </location>
<code_context>
+    def _build_message_str(self, components: List[BaseMessageComponent]) -> str:
+        """构建消息文本表示"""
+        message_str = ""
+        for comp in components:
+            if isinstance(comp, Plain):
+                message_str += comp.text
+            elif isinstance(comp, Image):
+                message_str += "[图片]"
+            elif isinstance(comp, Record):
+                message_str += "[语音]"
+            elif isinstance(comp, File):
+                message_str += "[文件]"
+            elif isinstance(comp, At):
+                message_str += f"@{comp.name}"
+        return message_str
+
+    async def _convert_quote_message(self, quote: dict) -> Optional[AstrBotMessage]:
</code_context>

<issue_to_address>
The _build_message_str method omits handling for Reply components.

This omission could result in message strings missing Reply content. Please add handling for Reply components to ensure all message types are represented.

Suggested implementation:

```python
        for comp in components:
            if isinstance(comp, Plain):
                message_str += comp.text
            elif isinstance(comp, Image):
                message_str += "[图片]"
            elif isinstance(comp, Record):
                message_str += "[语音]"
            elif isinstance(comp, File):
                message_str += "[文件]"
            elif isinstance(comp, At):
                message_str += f"@{comp.name}"
            elif isinstance(comp, Reply):
                # 假设 Reply 组件有 message_str 属性
                message_str += f"[回复: {getattr(comp, 'message_str', '')}]"
        return message_str

```

If the `Reply` class does not have a `message_str` attribute, you may need to adjust the representation to use available properties (e.g., `comp.text` or another relevant field).
Make sure to import or define the `Reply` class if it is not already imported in this file.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 389 to 398
for comp in components:
if isinstance(comp, Plain):
message_str += comp.text
elif isinstance(comp, Image):
message_str += "[图片]"
elif isinstance(comp, Record):
message_str += "[语音]"
elif isinstance(comp, File):
message_str += "[文件]"
elif isinstance(comp, At):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: _build_message_str 方法遗漏了对 Reply 组件的处理。

此遗漏可能导致消息字符串缺少 Reply 内容。请添加对 Reply 组件的处理,以确保所有消息类型都得到表示。

建议的实现:

        for comp in components:
            if isinstance(comp, Plain):
                message_str += comp.text
            elif isinstance(comp, Image):
                message_str += "[图片]"
            elif isinstance(comp, Record):
                message_str += "[语音]"
            elif isinstance(comp, File):
                message_str += "[文件]"
            elif isinstance(comp, At):
                message_str += f"@{comp.name}"
            elif isinstance(comp, Reply):
                # 假设 Reply 组件有 message_str 属性
                message_str += f"[回复: {getattr(comp, 'message_str', '')}]"
        return message_str

如果 Reply 类没有 message_str 属性,你可能需要调整表示方式以使用可用的属性(例如 comp.text 或另一个相关字段)。
如果 Reply 类尚未在此文件中导入,请确保导入或定义它。

Original comment in English

suggestion: The _build_message_str method omits handling for Reply components.

This omission could result in message strings missing Reply content. Please add handling for Reply components to ensure all message types are represented.

Suggested implementation:

        for comp in components:
            if isinstance(comp, Plain):
                message_str += comp.text
            elif isinstance(comp, Image):
                message_str += "[图片]"
            elif isinstance(comp, Record):
                message_str += "[语音]"
            elif isinstance(comp, File):
                message_str += "[文件]"
            elif isinstance(comp, At):
                message_str += f"@{comp.name}"
            elif isinstance(comp, Reply):
                # 假设 Reply 组件有 message_str 属性
                message_str += f"[回复: {getattr(comp, 'message_str', '')}]"
        return message_str

If the Reply class does not have a message_str attribute, you may need to adjust the representation to use available properties (e.g., comp.text or another relevant field).
Make sure to import or define the Reply class if it is not already imported in this file.

@anka-afk
Copy link
Member

其实我觉得message_str没必要加占位符, 就纯文本信息就好了, 毕竟是发给llm的

@shangxueink
Copy link
Contributor Author

其实我觉得message_str没必要加占位符, 就纯文本信息就好了, 毕竟是发给llm的

嗯,的确,我已经修改啦

adapter: "SatoriPlatformAdapter",
):
# 更新平台元数据
if adapter and hasattr(adapter, 'logins') and adapter.logins:
Copy link
Member

@Soulter Soulter Sep 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没看懂这里在做什么,可以解释一下嘛

Copy link
Contributor Author

@shangxueink shangxueink Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没看懂这里在做什么,可以解释一下嘛

这里是在Satori平台事件初始化时,根据适配器的登录信息 设置平台元数据的唯一标识符。

这样可以确保每个Satori平台实例都有一个唯一的ID,格式为"平台名(用户ID)",便于系统识别和管理不同的平台连接。

Satori适配器需要更新平台元数据 是因为它是一个通用协议适配器,支持多种平台和多个账号的动态连接。而其他适配器是单一平台适配器,平台信息在配置时就已经确定,不需要动态更新。


在satori协议里是可以有多个bot的,logins属性存储着平台的登录信息。

比如在koishi侧,开启了若干个适配器:adapter-qq、adapter-bilibili、adapter-telegram...

然后开启server-satori之后,就会有若干个bot实例。


当然,如果用的是liteloader onebot实现satori协议,那么就只会有一个bot实例了。

也就是说,如果仅考虑 liteloader onebot 实现 satori协议接入的情况下,的确也可以不需要这里的 更新平台元数据 的做法

# 提取<quote>标签
if "<quote" in content:
import re
quote_match = re.search(r'<quote\s+id="([^"]*)"[^>]*>(.*?)</quote>', content, re.DOTALL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些 xml 数据的解析可以使用 xml.etree 来解析吗?

Copy link
Contributor Author

@shangxueink shangxueink Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些 xml 数据的解析可以使用 xml.etree 来解析吗?

当然,这些 XML 数据完全可以用 xml.etree 来解析。

而且当前代码已经在这样做了。

from xml.etree import ElementTree as ET

-> https://github.com/AstrBotDevs/AstrBot/blob/master/astrbot/core/platform/sources/satori/satori_adapter.py#L21


我明白你在说什么 这些正则看起来,的确让人担心。。。

嗯!应该统一使用 XML 解析器来处理 <quote> 标签,而不是混合使用正则表达式。

@shangxueink
Copy link
Contributor Author

另外我发现,satori_adapter.py文件似乎没有通过PR更新,它仍然是此PR之前的状态。而satori_event.py文件却更新了。


我会在之后新的PR中与xml解析问题一并提交修改

@shangxueink
Copy link
Contributor Author

shangxueink commented Sep 16, 2025

另外我发现,satori_adapter.py文件似乎没有通过PR更新,它仍然是此PR之前的状态。而satori_event.py文件却更新了。

我是笨笨咪,

才注意到这个PR是open的,satori_event.py文件也没更新((()

我继续commit((((

@Soulter Soulter merged commit fc76665 into AstrBotDevs:master Sep 21, 2025
4 checks passed
@shangxueink shangxueink deleted the patch-0 branch October 14, 2025 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants