mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 08:48:54 +00:00
interaction_collector: rename from Paginator, implement Guard, is now generic
This commit is contained in:
parent
a35563801d
commit
e777d4d634
4 changed files with 97 additions and 72 deletions
90
youmubot-prelude/src/interaction_collector.rs
Normal file
90
youmubot-prelude/src/interaction_collector.rs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
use crate::{Context, Result};
|
||||||
|
use serenity::{
|
||||||
|
all::{CreateInteractionResponse, Interaction, MessageId},
|
||||||
|
prelude::TypeMapKey,
|
||||||
|
};
|
||||||
|
use std::{ops::Deref, sync::Arc};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
/// Handles distributing interaction to the handlers.
|
||||||
|
pub struct InteractionCollector {
|
||||||
|
pub(crate) channels: Arc<dashmap::DashMap<MessageId, flume::Sender<String>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps the interfaction receiver channel, automatically cleaning up upon drop.
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct InteractionCollectorGuard {
|
||||||
|
msg_id: MessageId,
|
||||||
|
ch: flume::Receiver<String>,
|
||||||
|
collector: InteractionCollector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for InteractionCollectorGuard {
|
||||||
|
type Target = flume::Receiver<String>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.ch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for InteractionCollectorGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.collector.channels.remove(&self.msg_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InteractionCollector {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
channels: Arc::new(dashmap::DashMap::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Create a new collector, returning a receiver.
|
||||||
|
pub fn create_collector(&self, msg: MessageId) -> impl Deref<Target = flume::Receiver<String>> {
|
||||||
|
let (send, recv) = flume::unbounded();
|
||||||
|
self.channels.insert(msg.clone(), send);
|
||||||
|
InteractionCollectorGuard {
|
||||||
|
msg_id: msg,
|
||||||
|
ch: recv,
|
||||||
|
collector: self.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new collector, returning a receiver.
|
||||||
|
pub(crate) async fn create(
|
||||||
|
ctx: &Context,
|
||||||
|
msg: MessageId,
|
||||||
|
) -> Result<impl Deref<Target = flume::Receiver<String>>> {
|
||||||
|
Ok(ctx
|
||||||
|
.data
|
||||||
|
.read()
|
||||||
|
.await
|
||||||
|
.get::<InteractionCollector>()
|
||||||
|
.unwrap()
|
||||||
|
.create_collector(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeMapKey for InteractionCollector {
|
||||||
|
type Value = InteractionCollector;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl crate::hook::InteractionHook for InteractionCollector {
|
||||||
|
async fn call(&self, ctx: &Context, interaction: &Interaction) -> Result<()> {
|
||||||
|
match interaction {
|
||||||
|
Interaction::Component(component_interaction) => {
|
||||||
|
if let Some(ch) = self.channels.get(&component_interaction.message.id) {
|
||||||
|
component_interaction
|
||||||
|
.create_response(ctx, CreateInteractionResponse::Acknowledge)
|
||||||
|
.await?;
|
||||||
|
ch.send_async(component_interaction.data.custom_id.clone())
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ pub use args::{ChannelId, Duration, RoleId, UserId, UsernameArg};
|
||||||
pub use debugging_ok::OkPrint;
|
pub use debugging_ok::OkPrint;
|
||||||
pub use flags::Flags;
|
pub use flags::Flags;
|
||||||
pub use hook::Hook;
|
pub use hook::Hook;
|
||||||
|
pub use interaction_collector::InteractionCollector;
|
||||||
pub use member_cache::MemberCache;
|
pub use member_cache::MemberCache;
|
||||||
pub use pagination::{paginate, paginate_from_fn, paginate_reply, CanEdit, Paginate};
|
pub use pagination::{paginate, paginate_from_fn, paginate_reply, CanEdit, Paginate};
|
||||||
pub use poise::CreateReply;
|
pub use poise::CreateReply;
|
||||||
|
@ -25,6 +26,7 @@ pub mod announcer;
|
||||||
pub mod args;
|
pub mod args;
|
||||||
pub mod flags;
|
pub mod flags;
|
||||||
pub mod hook;
|
pub mod hook;
|
||||||
|
pub mod interaction_collector;
|
||||||
pub mod member_cache;
|
pub mod member_cache;
|
||||||
pub mod pagination;
|
pub mod pagination;
|
||||||
pub mod ratelimit;
|
pub mod ratelimit;
|
||||||
|
|
|
@ -3,17 +3,11 @@ use futures_util::future::Future;
|
||||||
use poise::{CreateReply, ReplyHandle};
|
use poise::{CreateReply, ReplyHandle};
|
||||||
use serenity::{
|
use serenity::{
|
||||||
all::{
|
all::{
|
||||||
ComponentInteraction, CreateActionRow, CreateButton, CreateInteractionResponse,
|
ComponentInteraction, CreateActionRow, CreateButton, EditInteractionResponse, EditMessage,
|
||||||
EditInteractionResponse, EditMessage, Interaction, MessageId,
|
|
||||||
},
|
},
|
||||||
builder::CreateMessage,
|
builder::CreateMessage,
|
||||||
model::{
|
model::{channel::Message, id::ChannelId},
|
||||||
channel::{Message, ReactionType},
|
|
||||||
id::ChannelId,
|
|
||||||
},
|
|
||||||
prelude::TypeMapKey,
|
|
||||||
};
|
};
|
||||||
use std::{convert::TryFrom, sync::Arc};
|
|
||||||
use tokio::time as tokio_time;
|
use tokio::time as tokio_time;
|
||||||
|
|
||||||
// const ARROW_RIGHT: &str = "➡️";
|
// const ARROW_RIGHT: &str = "➡️";
|
||||||
|
@ -264,8 +258,7 @@ pub async fn paginate_with_first_message(
|
||||||
timeout: std::time::Duration,
|
timeout: std::time::Duration,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let msg_id = message.get_message().await?.id;
|
let msg_id = message.get_message().await?.id;
|
||||||
let (send, recv) = flume::unbounded::<String>();
|
let recv = crate::InteractionCollector::create(ctx, msg_id).await?;
|
||||||
Paginator::push(ctx, msg_id, send).await?;
|
|
||||||
|
|
||||||
do_render(&mut pager, 0, &mut message).await?;
|
do_render(&mut pager, 0, &mut message).await?;
|
||||||
// Just quit if there is only one page
|
// Just quit if there is only one page
|
||||||
|
@ -296,7 +289,6 @@ pub async fn paginate_with_first_message(
|
||||||
do_render_with_btns(&mut pager, page, &mut message, vec![])
|
do_render_with_btns(&mut pager, page, &mut message, vec![])
|
||||||
.await
|
.await
|
||||||
.pls_ok();
|
.pls_ok();
|
||||||
Paginator::pop(ctx, msg_id).await?;
|
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
@ -331,62 +323,3 @@ pub async fn handle_pagination_reaction(
|
||||||
page
|
page
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
/// Handles distributing pagination interaction to the handlers.
|
|
||||||
pub struct Paginator {
|
|
||||||
pub(crate) channels: Arc<dashmap::DashMap<MessageId, flume::Sender<String>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Paginator {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
channels: Arc::new(dashmap::DashMap::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async fn push(ctx: &Context, msg: MessageId, channel: flume::Sender<String>) -> Result<()> {
|
|
||||||
ctx.data
|
|
||||||
.read()
|
|
||||||
.await
|
|
||||||
.get::<Paginator>()
|
|
||||||
.unwrap()
|
|
||||||
.channels
|
|
||||||
.insert(msg, channel);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn pop(ctx: &Context, msg: MessageId) -> Result<()> {
|
|
||||||
ctx.data
|
|
||||||
.read()
|
|
||||||
.await
|
|
||||||
.get::<Paginator>()
|
|
||||||
.unwrap()
|
|
||||||
.channels
|
|
||||||
.remove(&msg);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TypeMapKey for Paginator {
|
|
||||||
type Value = Paginator;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl crate::hook::InteractionHook for Paginator {
|
|
||||||
async fn call(&self, ctx: &Context, interaction: &Interaction) -> Result<()> {
|
|
||||||
match interaction {
|
|
||||||
Interaction::Component(component_interaction) => {
|
|
||||||
if let Some(ch) = self.channels.get(&component_interaction.message.id) {
|
|
||||||
component_interaction
|
|
||||||
.create_response(ctx, CreateInteractionResponse::Acknowledge)
|
|
||||||
.await?;
|
|
||||||
ch.send_async(component_interaction.data.custom_id.clone())
|
|
||||||
.await
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -237,9 +237,9 @@ async fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Paginator
|
// Paginator
|
||||||
let paginator = youmubot_prelude::pagination::Paginator::new();
|
let paginator = youmubot_prelude::InteractionCollector::new();
|
||||||
handler.push_interaction_hook(paginator.clone());
|
handler.push_interaction_hook(paginator.clone());
|
||||||
data.insert::<youmubot_prelude::pagination::Paginator>(paginator);
|
data.insert::<youmubot_prelude::InteractionCollector>(paginator);
|
||||||
|
|
||||||
data.insert::<Env>(env.clone());
|
data.insert::<Env>(env.clone());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue