Skip to main content

event_plugin/
event_plugin.rs

1//! bot 作者怎么接事件触发器:一个插件,其 handler 在*事件*(而非命令文本)上触发,受与
2//! `#[command]` 触发器相同的分层开关门控。
3//!
4//! 声明一个插件(`group_events`),带两个事件触发器:
5//!   * `#[event(MemberJoin, id = "welcome")]` —— 欢迎新成员;
6//!   * `#[event(Nudge, id = "petpet")]` —— 被戳时戳回去。
7//!
8//! 开关 key 遵循 `plugin!{}` + `#[event(id=…)]` 的层级:
9//!   * 插件 master 就是它的 `key` —— 这里是 `group_events`;
10//!   * 每个触发器是 `"<plugin_key>.<id>"` —— `group_events.welcome` /
11//!     `group_events.petpet`。
12//!
13//! 在某个 peer 禁用 `group_events` 会同时静默那里的两个事件 handler —— 开关对事件一视同仁,
14//! 无需内联判断。`Nudge` 提取器还会丢掉 bot 自己发起的戳(无反馈环),所以 bot 绝不戳自己。
15//!
16//! 运行(需要一个在线的 OneBot 端点):
17//!   cargo run --example event_plugin --features onebot
18
19use nagisa::prelude::*;
20
21// 一个插件。它的 master 开关 key 是 "group_events";下面两个事件触发器都挂在它下面。
22nagisa::plugin! { name = "群事件", category = Fun, key = "group_events" }
23
24// 在任意已启用群的每条入群通知上触发。`MemberJoin` 暴露入群的群 + 用户;我们 @ 新人欢迎他。
25#[event(MemberJoin, id = "welcome")]
26async fn welcome(j: MemberJoin, bot: Bot) -> HandlerResult {
27    bot.send(&Peer::group(j.group.0), &[Segment::at(j.user), Segment::text(" 欢迎入群!")]).await?;
28    Ok(())
29}
30
31// 有人戳一戳 bot 时触发。`Nudge` 把好友/群的戳统一成 `{ peer, sender, receiver }`,并自我
32// 过滤:bot 自己发的戳永远到不了这里,所以回复不会成环。
33#[event(Nudge, id = "petpet")]
34async fn petpet(n: Nudge, bot: Bot) -> HandlerResult {
35    bot.send(&n.peer, &[Segment::text("戳回去!")]).await?;
36    Ok(())
37}
38
39#[cfg(feature = "onebot")]
40#[tokio::main]
41async fn main() -> Result<()> {
42    let shutdown = ctrl_c_shutdown();
43    App::new().run_onebot(OneBotConfig::new("ws://127.0.0.1:8080/onebot/v11/ws"), shutdown).await
44}
45
46// 没有适配器 feature 时无可运行;用一个空操作的 `main` 让示例仍能编译(上面的 handler 也仍被
47// 类型检查)。
48#[cfg(not(feature = "onebot"))]
49fn main() {
50    println!("build with --features onebot to run this example against a OneBot endpoint");
51}