ErisPulse 会话类型标准
本文档定义了 ErisPulse 支持的会话类型标准,包括接收事件类型和发送目标类型。
1. 核心概念
1.1 接收类型 && 发送类型
ErisPulse 区分两种会话类型:
- 接收类型(Receive Type):用于接收的事件的
detail_type字段 - 发送类型(Send Type):用于发送消息时
Send.To()方法的目标类型
1.2 类型映射关系
接收类型 (detail_type) 发送类型 (Send.To)
───────────────── ────────────────
private → user
group → group
channel → channel
guild → guild
thread → thread
user → user
关键点:
private是接收时的类型,发送时必须使用usergroup、channel、guild、thread在接收和发送时类型相同- 系统会自动进行类型转换,无需手动处理(代表着你可以直接使用获得的接收类型进行发送),但实际上,你无需考虑这些,Event的包装类的存在,你可以直接使用event.reply()方法,而无需考虑类型转换
2. 标准会话类型
2.1 OneBot12 标准类型
private
- 接收类型:
private - 发送类型:
user - 说明:一对一私聊消息
- ID 字段:
user_id - 适用平台:所有支持私聊的平台
group
- 接收类型:
group - 发送类型:
group - 说明:群聊消息,包括各种形式的群组(如 Telegram supergroup)
- ID 字段:
group_id - 适用平台:所有支持群聊的平台
user
- 接收类型:
user - 发送类型:
user - 说明:用户类型,某些平台(如 Telegram)将私聊表示为 user 而非 private
- ID 字段:
user_id - 适用平台:Telegram 等平台
2.2 ErisPulse 扩展类型
channel
- 接收类型:
channel - 发送类型:
channel - 说明:频道消息,支持多个用户的广播式消息
- ID 字段:
channel_id - 适用平台:Discord, Telegram, Line 等
guild
- 接收类型:
guild - 发送类型:
guild - 说明:服务器/社区消息,通常用于 Discord Guild 级别的事件
- ID 字段:
guild_id - 适用平台:Discord 等
thread
- 接收类型:
thread - 发送类型:
thread - 说明:话题/子频道消息,用于社区中的子讨论区
- ID 字段:
thread_id - 适用平台:Discord Threads, Telegram Topics 等
3. 平台类型映射
3.1 映射原则
适配器负责将平台的原生类型映射到 ErisPulse 标准类型:
平台原生类型 → ErisPulse 标准类型 → 发送类型
3.2 常见平台映射示例
Telegram
Telegram 类型 ErisPulse 接收类型 发送类型
───────────────── ──────────────── ───────────
private private user
group group group
supergroup group group # 映射到 group
channel channel channel
Discord
Discord 类型 ErisPulse 接收类型 发送类型
───────────────── ──────────────── ───────────
Direct Message private user
Text Channel channel channel
Guild guild guild
Thread thread thread
OneBot11
OneBot11 类型 ErisPulse 接收类型 发送类型
───────────────── ──────────────── ───────────
private private user
group group group
discuss group group # 映射到 group
4. 自定义类型扩展
4.1 注册自定义类型
适配器可以注册自定义会话类型:
from ErisPulse.Core.Event import register_custom_type
# 注册自定义类型
register_custom_type(
receive_type="my_custom_type",
send_type="custom",
id_field="custom_id",
platform="MyPlatform"
)
4.2 使用自定义类型
注册后,系统会自动处理该类型的转换和推断:
# 自动推断
receive_type = infer_receive_type(event, platform="MyPlatform")
# 返回: "my_custom_type"
# 转换为发送类型
send_type = convert_to_send_type(receive_type, platform="MyPlatform")
# 返回: "custom"
# 获取对应ID
target_id = get_target_id(event, platform="MyPlatform")
# 返回: event["custom_id"]
4.3 注销自定义类型
from ErisPulse.Core.Event import unregister_custom_type
unregister_custom_type("my_custom_type", platform="MyPlatform")
5. 自动类型推断
当事件没有明确的 detail_type 字段时,系统会根据存在的 ID 字段自动推断类型:
Note
2.7.0+ 行为变更:detail_type 只有在是已知会话类型(标准或自定义)时才直接采用。notice/request 事件的 detail_type(如 group_member_increase、friend_increase)是语义子类型而非会话类型,会转而根据 ID 字段推断正确的会话类型。
5.1 推断优先级
优先级(从高到低):
1. group_id → group
2. channel_id → channel
3. guild_id → guild
4. thread_id → thread
5. user_id → private
5.2 使用示例
# 事件只有 group_id
event = {"group_id": "123", "user_id": "456"}
receive_type = infer_receive_type(event)
# 返回: "group"(优先使用 group_id)
# 事件只有 user_id
event = {"user_id": "123"}
receive_type = infer_receive_type(event)
# 返回: "private"
# notice 事件的 detail_type 是语义子类型,2.7.0+ 会从 ID 字段推断
event = {"type": "notice", "detail_type": "group_member_increase", "group_id": "123"}
receive_type = infer_receive_type(event)
# 返回: "group"(而非 "group_member_increase")
6. API 使用示例
6.1 发送消息
from ErisPulse import adapter
# 发送给用户
await adapter.myplatform.Send.To("user", "123").Text("Hello")
# 发送给群组
await adapter.myplatform.Send.To("group", "456").Text("Hello")
# 自动转换 private → user(不推荐,可能会有兼容性问题)
await adapter.myplatform.Send.To("private", "789").Text("Hello")
# 内部自动转换为: Send.To("user", "789") # 直接使用user作为会话类型是更优的选择
6.2 事件回复
from ErisPulse.Core.Event import Event
# Event.reply() 自动处理类型转换
await event.reply("回复内容")
# 内部自动使用正确的发送类型
6.3 命令处理
from ErisPulse.Core.Event import command
@command(name="test")
async def handle_test(event):
# 系统自动处理会话类型
# 无需手动判断 group_id 还是 user_id
await event.reply("命令执行成功")
7. 核心 API 参考
7.1 类型转换
from ErisPulse.Core.Event import convert_to_send_type, convert_to_receive_type
# 接收类型 → 发送类型
convert_to_send_type("private") # → "user"
convert_to_send_type("group") # → "group"
# 发送类型 → 接收类型
convert_to_receive_type("user") # → "private"
convert_to_receive_type("group") # → "group"
7.2 ID 字段查询
from ErisPulse.Core.Event import get_id_field, get_receive_type
get_id_field("group") # → "group_id"
get_id_field("private") # → "user_id"
get_receive_type("group_id") # → "group"
get_receive_type("user_id") # → "private"
7.3 一步获取发送信息
from ErisPulse.Core.Event import get_send_type_and_target_id
event = {"detail_type": "private", "user_id": "123"}
send_type, target_id = get_send_type_and_target_id(event)
# send_type = "user", target_id = "123"
# 直接用于 Send.To()
await adapter.Send.To(send_type, target_id).Text("Hello")
7.4 获取目标 ID
from ErisPulse.Core.Event import get_target_id
event = {"detail_type": "group", "group_id": "456"}
get_target_id(event) # → "456"
8. 工具方法
from ErisPulse.Core.Event import (
is_standard_type,
is_valid_send_type,
get_standard_types,
get_send_types,
clear_custom_types,
)
is_standard_type("private") # True
is_standard_type("custom_type") # False
is_valid_send_type("user") # True
is_valid_send_type("invalid") # False
get_standard_types() # {"private", "group", "channel", "guild", "thread", "user"}
get_send_types() # {"user", "group", "channel", "guild", "thread"}
clear_custom_types() # 清除所有
clear_custom_types(platform="discord") # 只清除指定平台的
9. 最佳实践
7.1 适配器开发者
- 使用标准映射:尽可能映射到标准类型,而非创建新类型
- 正确转换:确保接收类型和发送类型的映射关系正确
- 保留原始数据:在
{platform}_raw中保留原始事件类型 - 文档说明:在适配器文档中说明类型映射关系
7.2 模块开发者
- 使用工具方法:使用
get_send_type_and_target_id()等工具方法 - 避免硬编码:不要写
if group_id else "private"这样的代码 - 考虑所有类型:代码要支持所有标准类型,不仅是 private/group
- 灵活设计:使用事件包装器的方法,而非直接访问字段
7.3 类型推断
- 优先使用 detail_type:如果有明确字段,不进行推断
- 合理使用推断:只在没有明确类型时使用
- 注意优先级:了解推断优先级,避免意外结果
10. 常见问题
Q1: 为什么发送时 private 要转换为 user?
A: 这是 OneBot12 标准的要求。private 是接收时的概念,发送时使用 user 更符合语义。
Q2: 如何支持新的会话类型?
A: 通过 register_custom_type() 注册自定义类型,或直接使用标准类型中的 channel、guild 等。
Q3: 事件没有 detail_type 怎么办?
A: 系统会根据存在的 ID 字段自动推断。优先级为:group > channel > guild > thread > user。
Q4: 适配器如何映射 Telegram supergroup?
A: 在适配器的转换逻辑中,将 supergroup 映射为标准的 group 类型。
Q5: 邮箱等特殊平台如何处理?
A: 对于不通用或平台特有的类型,使用 {platform}_raw 和 {platform}_raw_type 保留原始数据,适配器自行处理。