#discord-api #discord #twilight #event-stream

twilight-standby

用于过滤并等待 Twilight 生态系统中的特定事件的实用工具

40 个版本

0.16.0-rc.12024 年 2 月 21 日
0.15.4 2023 年 9 月 10 日
0.15.2 2023 年 4 月 27 日
0.15.1 2023 年 2 月 26 日
0.2.1 2020 年 11 月 29 日

#74异步

Download history 36/week @ 2024-03-16 18/week @ 2024-03-23 106/week @ 2024-03-30 27/week @ 2024-04-06 285/week @ 2024-04-13 45/week @ 2024-04-20 63/week @ 2024-04-27 27/week @ 2024-05-04 23/week @ 2024-05-11 32/week @ 2024-05-18 36/week @ 2024-05-25 135/week @ 2024-06-01 58/week @ 2024-06-08 62/week @ 2024-06-15 45/week @ 2024-06-22 6/week @ 2024-06-29

192 每月下载
twilight 中使用

ISC 许可证

1.5MB
31K SLoC

twilight-standby

codecov badge discord badge github badge license badge rust badge

Standby 是一个基于谓词检查等待事件发生的实用工具。例如,你可能有一个带有 ✅ 和 ❌ 反应菜单的命令。如果你想要处理对这些反应的处理,使用类似于应用程序级状态或事件流可能不适合你的用例。等待反应可能更干净地直接在你的函数中进行。这就是 Twilight Standby 的作用。

Standby 允许你等待诸如特定公会中的事件(Standby::wait_for)、频道中的新消息(Standby::wait_for_message)、消息上的新反应(Standby::wait_for_reaction)以及可能不在公会中发生的事件,例如新的 Ready 事件(Standby::wait_for_event)。每个方法都有一个流变体。

要使用 Standby,它必须处理事件,例如在网关接收的事件事件循环中。查看 Standby::process 方法。

何时使用 futures 和 streams

Standby 拥有两种方法变体:future 变体和 stream 变体。例如 Standby::wait_for_message,它还有一个 Standby::wait_for_message_stream 变体。future 变体在需要等待事件时非常有用。这意味着,如果您只需在通道中等待一条消息,则应使用 future 变体。如果您需要等待多条消息,例如可能在一分钟内的所有消息,则应使用 Standby::wait_for_message_stream 方法。

差异在于,如果您在一个循环中使用 futures 变体,那么在处理接收事件时可能会错过一些事件。通过使用流,您不会错过任何事件。

超时

Standby 并不直接提供 futures 的超时功能。futures 可以通过例如 tokio::time::timeout 的 crate 来实现超时。有关此例的详细说明请参阅 Standby 类型。

示例

快速浏览

等待用户 456 在通道 123 发送的包含内容 "test" 的消息

use twilight_model::{
    gateway::payload::incoming::MessageCreate,
    id::Id,
};
use twilight_standby::Standby;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let standby = Standby::new();

    let channel_id = Id::new(123);

    let message = standby.wait_for_message(channel_id, |event: &MessageCreate| {
        event.author.id.get() == 456 && event.content == "test"
    }).await?;

    Ok(())
}

完整示例

完整示例:连接到网关,处理事件,并包括一个等待反应的处理程序

use std::{env, sync::Arc};
use twilight_gateway::{Event, EventTypeFlags, Intents, Shard, ShardId, StreamExt as _};
use twilight_model::{
    channel::Message,
    gateway::payload::incoming::ReactionAdd,
};
use twilight_standby::Standby;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let token = env::var("DISCORD_TOKEN")?;

    // Start a shard connected to the gateway to receive events.
    let intents = Intents::GUILD_MESSAGES | Intents::GUILD_MESSAGE_REACTIONS;
    let mut shard = Shard::new(ShardId::ONE, token, intents);

    let standby = Arc::new(Standby::new());

    while let Some(item) = shard.next_event(EventTypeFlags::all()).await {
        let Ok(event) = item else {
            tracing::warn!(source = ?item.unwrap_err(), "error receiving event");

            continue;
        };

        // Have standby process the event, which will fulfill any futures
        // that are waiting for an event.
        standby.process(&event);

        match event {
            Event::MessageCreate(msg) if msg.content == "!react" => {
                tokio::spawn(react(msg.0, Arc::clone(&standby)));
            },
            _ => {},
        }
    }

    Ok(())
}

// Wait for a reaction from the user who sent the message, and then print it
// once they react.
async fn react(msg: Message, standby: Arc<Standby>) -> anyhow::Result<()> {
    let author_id = msg.author.id;

    let reaction = standby.wait_for_reaction(msg.id, move |event: &ReactionAdd| {
        event.user_id == author_id
    }).await?;

    println!("user reacted with {:?}", reaction.emoji);

    Ok(())
}

更多示例,请查看 Standby 上的每个方法。

依赖关系

~5–12MB
~116K SLoC