40 个版本
0.16.0-rc.1 | 2024 年 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 在 异步
192 每月下载
在 twilight 中使用
1.5MB
31K SLoC
twilight-standby
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