简体中文 English 繁體中文 日本語 Русский
本文为静态镜像,内容以交互版为准 在交互式文档中心打开 →

Event 包裝類詳解

Event 模組提供了功能強大的 Event 包裝類,簡化事件處理。

為 event 參數添加類型註解

事件處理器的 event 參數是 Event 包裝類(dict 子類)。強烈建議為它添加類型註解:

from ErisPulse.Core.Event import Event

@message.on_private_message()
async def handler(event: Event):
    text = event.get_text()   # IDE 自動補全所有便捷方法
    await event.reply(text)   # 拼寫錯誤在靜態檢查時即可發現

不加註解時 IDE 無法識別 Event 上的方法(get_text() / reply() / wait_reply() / 平台擴展方法均不提示),只能靠記憶拼寫。

注意區分:事件處理器回調的 event 是 Event 包裝類(註解為 Event);模組生命週期方法 on_load / on_unload 的 event 是普通 dict(註解為 dict),二者不要混淆。

核心特性

核心字段方法

from ErisPulse.Core.Event import command

@command("info")
async def info_command(event: Event):
    event_id = event.get_id()
    platform = event.get_platform()
    time = event.get_time()
    print(f"ID: {event_id}, 平台: {platform}, 時間: {time}")

消息事件方法

from ErisPulse.Core.Event import message

@message.on_private_message()
async def private_handler(event: Event):
    text = event.get_text()
    user_id = event.get_user_id()
    nickname = event.get_user_nickname()
    await event.reply(f"你好,{nickname}!")

消息類型判斷

from ErisPulse.Core.Event import message

@message.on_group_message()
async def group_handler(event: Event):
    is_private = event.is_private_message()
    is_group = event.is_group_message()
    is_at = event.is_at_message()
    await event.reply(f"類型: {'私聊' if is_private else '群聊'}")

回覆功能

from ErisPulse.Core.Event import command

@command("ask")
async def ask_command(event: Event):
    await event.reply("請輸入你的名字:")
    reply = await event.wait_reply(timeout=30)
    if reply:
        name = reply.get_text()
        await event.reply(f"你好,{name}!")

@command("price")
async def price_command(event: Event):
    await event.reply("請輸入金額(如:5元):")
    # 回覆必須符合正則,否則繼續等待直到超時
    reply = await event.wait_reply(timeout=30, regex=r"\d+\s*元")
    if reply:
        await event.reply(f"收到金額:{reply.get_text()}")

互動對話進階

Note

本節功能需要 ErisPulse **2.8.0+**。

# 會話定時提醒:5 分鐘無回覆則提醒,用戶回覆後自動取消
reminder = event.remind(300, "還在嗎?不想聊了回覆「退出」")
reminder.cancel()  # 也可手動取消

# 超時升級:到點必達(不被回覆取消),如長時間未處理通知主人
event.escalate(1800, lambda e: notify_master("工單超時"))

# 多路等待:同時等"同意"與"拒絕",先到先得
which, reply = await event.select(
    event.expect(pattern="同意*", user="10001"),
    event.expect(pattern="拒絕*", user="10002"),
    timeout=60,
)
if which is None:
    await event.reply("超時未收到審批")

# 會話級等待:同群任何人的回覆均可命中(群協作)
reply = await event.wait_reply(session=True, prompt="哪位大神幫忙答一下?")

# 會話收件箱:當前會話最近 20 條消息(含機器人,AI 上下文 / 防重複回覆底座)
messages = await event.history(20)

# 消息事務:異常時自動撤回事務內已發送的消息
async with event.message_tx():
    await event.reply("處理中,請稍候...")
    result = await do_something()
    await event.reply(f"完成:{result}")

命令資訊獲取

from ErisPulse.Core.Event import command

@command("cmdinfo")
async def cmdinfo_command(event: Event):
    cmd_name = event.get_command_name()
    cmd_args = event.get_command_args()
    await event.reply(f"命令: {cmd_name}, 參數: {cmd_args}")

通知事件方法

from ErisPulse.Core.Event import notice

@notice.on_friend_add()
async def friend_add_handler(event: Event):
    await event.reply("歡迎添加我為好友!")

方法速查表

核心方法

事件基礎資訊

機器人資訊

會話標識

消息事件方法

消息內容

發送者資訊

群組/頻道資訊

@消息相關

消息類型判斷

基礎判斷

通知事件方法

通知操作者

通知類型判斷

請求事件方法

請求資訊

請求類型判斷

回覆功能

基礎回覆

平台能力查詢

轉發功能

注意:轉發功能需要透過適配器的 Send DSL 實現,Event 包裝類本身不提供直接的轉發方法。

# 轉發消息到群組
adapter = sdk.adapter.get(event.get_platform())
target_id = event.get_group_id()  # 或指定其他群組ID
await adapter.Send.To("group", target_id).Text(event.get_text())

等待回覆功能

互動方法

互動方法示例

confirm() - 確認對話:

@command("delete", help="刪除數據")
async def delete_handler(event: Event):
    if await event.confirm("確定要刪除所有數據嗎?"):
        sdk.storage.delete("all_data")
        await event.reply("數據已刪除")
    else:
        await event.reply("已取消")

confirm() - 帶提示詞:

# hint=True 會在提示末尾追加 "(是/否)"
if await event.confirm("確定繼續?", hint=True):
    await event.reply("已繼續")
# 用戶看到:確定繼續?(是/否)

choose() - 選擇菜單:

@command("color", help="選擇顏色")
async def color_handler(event: Event):
    choice = await event.choose("請選擇顏色:", ["紅色", "綠色", "藍色"])
    if choice is not None:
        colors = ["紅色", "綠色", "藍色"]
        await event.reply(f"你選擇了:{colors[choice]}")

choose() - 選項格式化與消息合併:

# inline 格式:選項顯示在同一行
choice = await event.choose("請選擇:", ["A", "B", "C"], options_format="inline")
# 輸出:1.A | 2.B | 3.C

# 自定義格式
choice = await event.choose("請選擇:", ["貓", "狗"],
    options_format=lambda opts: " / ".join(opts))
# 輸出:貓 / 狗

# options_format="auto"(預設):根據 method 自動選擇內建樣式
# Markdown → 無序列表
choice = await event.choose(
    "## 請選擇", ["貓", "狗"],
    method="Markdown",  # auto 自動識別為 md 列表
)
# 輸出:
# ## 請選擇
# - 1. 貓
# - 2. 狗

# Html → 有序列表
choice = await event.choose(
    "<h2>請選擇</h2>", ["貓", "狗"],
    method="Html", merge_prompt=True,  # auto 自動識別為 html 列表
)
# 輸出:
# <h2>請選擇</h2>
# <ol><li>1. 貓</li><li>2. 狗</li></ol>

# 合併模式 + 占位符
choice = await event.choose(
    "## 請選擇\n{options}\n請回覆編號",
    ["貓", "狗"],
    method="Markdown", merge_prompt=True,
)

# 自定義占位符
choice = await event.choose(
    "請選擇: [choices]",
    ["貓", "狗"],
    placeholder="[choices]",
)

collect() - 表單收集:

@command("register", help="註冊")
async def register_handler(event: Event):
    data = await event.collect([
        {"key": "name", "prompt": "請輸入姓名:"},
        {"key": "age", "prompt": "請輸入年齡:",
         "validator": lambda e: e.get_text().isdigit()},
    ])
    if data:
        await event.reply(f"註冊成功!{data['name']},{data['age']}歲")

非 Text 方法的 reply:

await event.reply("http://example.com/img.jpg", method="Image")
await event.reply("http://example.com/audio.mp3", method="Voice")

from ErisPulse.Core.Event import MessageBuilder
segments = MessageBuilder.text("看這張圖:").image("http://example.com/img.jpg").build()
await event.reply_ob12(segments)

完整的 Conversation 多輪對話用法請參考 Conversation 多輪對話。

命令資訊

命令基礎

原始數據

平台擴展方法

適配器可以為 Event 包裝類註冊平台專有方法。方法僅在對應平台的 Event 實例上可用,其他平台訪問時拋出 AttributeError。

平台方法透過 Event.__getattribute__ 優先於內置方法生效,因此可以覆寫 confirm、choose、collect、wait_reply 等內置互動方法,提供平台特色實現(如按鈕、卡片等)。內置實現作為 _builtin_* 函數導出供覆寫方調用。

# 郵件事件 - 只有郵件方法
event = Event({"platform": "email", "email_raw": {"subject": "Hello"}})
event.get_subject()      # ✅ 返回 "Hello"
event.get_chat_type()    # ❌ AttributeError

# Telegram 事件 - 只有 Telegram 方法
event = Event({"platform": "telegram", "telegram_raw": {"chat": {"type": "private"}}})
event.get_chat_type()    # ✅ 返回 "private"
event.get_subject()      # ❌ AttributeError

# 內置方法始終可用
event.get_text()         # ✅ 任何平台
event.reply("hi")        # ✅ 任何平台

查詢已註冊方法

from ErisPulse.Core.Event import get_platform_event_methods

methods = get_platform_event_methods("email")
# ["get_subject", "get_from", ...]

hasattr 和 dir 支援

hasattr(event, "get_subject")   # 僅當 platform="email" 時返回 True
"get_subject" in dir(event)     # 同上

跨平台擴展(通配符)

register_event_method 和 register_event_mixin 支援傳 "*" 作為平台名,註冊的方法在所有平台的 Event 實例上都可用。適合 AI 對話、上下文管理等需要跨平台複用的功能。

from ErisPulse.Core.Event.wrapper import register_event_method

@register_event_method("*")
async def ai_chat(self, prompt: str):
    # self 為 Event 實例,可訪問事件數據和內置方法
    await self.reply(f"AI: {prompt}")

註冊後,任何平台的事件處理器都能調用 event.ai_chat(...)。

方法解析優先級(從高到低):平台特定方法 → 通配符方法 → 內置方法 → 字典鍵訪問。

適配器開發者註冊擴展方法的方式請參閱 事件系統 API - 跨平台擴展通配符。

相關文件