use std::{fmt::Debug, sync::Arc}; use futures::future::BoxFuture; use patricia_tree::StringPatriciaMap; use songbird::Songbird; use tokio_util::sync::CancellationToken; use twilight_model::{ application::{command::Command, interaction::Interaction}, id::{Id, marker::{ApplicationMarker, UserMarker}}, }; use crate::VCs; mod join; mod leave; mod opt_out; #[derive(Debug, Clone)] pub struct State { pub cancellation_token: CancellationToken, pub discord_application_id: Id, pub discord_client: Arc, pub discord_user_id: Id, pub songbird: Arc, pub vcs: Arc, } type Return = (); type BoxedHandler = Box BoxFuture<'static, Return>>; fn box_handler(handler: Handler) -> BoxedHandler where Fut: Future + Send + 'static, Handler: Send + Sync + Fn(State, Interaction) -> Fut + 'static, { Box::new(move |state, interaction| Box::pin(handler(state, interaction))) } pub fn all() -> Vec<(&'static Command, BoxedHandler)> { vec![ (&join::COMMAND, box_handler(join::handle)), (&leave::COMMAND, box_handler(leave::handle)), (&opt_out::COMMAND, box_handler(opt_out::handle)), ] } #[derive(Default)] pub struct Router { map: StringPatriciaMap, } impl Router { fn add_route(&mut self, name: &str, handler: Handler) where Fut: Future + Send + 'static, Handler: Send + Sync + Fn(State, Interaction) -> Fut + 'static, { self.add_route_already_boxed(name, box_handler(handler)); } fn add_route_already_boxed(&mut self, name: &str, boxed_handler: BoxedHandler) { self.map.insert(name, boxed_handler); } pub async fn handle( &self, state: State, command_name: &str, interaction: Interaction, ) -> Option { let handler = self.map.get(command_name)?; Some(handler(state, interaction).await) } } impl<'a> FromIterator<(&'a Command, BoxedHandler)> for Router { #[inline] fn from_iter>(iter: T) -> Self { let mut this = Self::default(); this.extend(iter); this } } impl<'a> Extend<(&'a Command, BoxedHandler)> for Router { #[inline] fn extend>(&mut self, iter: T) { for (command, boxed_handler) in iter { let name = &command.name; self.add_route_already_boxed(name, boxed_handler); } } }