mod common;
mod prefix;
mod slash;
pub use common::*;
pub use prefix::*;
pub use slash::*;
use crate::serenity_prelude as serenity;
pub struct FrameworkContext<'a, U, E> {
pub bot_id: serenity::UserId,
pub options: &'a crate::FrameworkOptions<U, E>,
pub user_data: &'a U,
pub shard_manager: &'a std::sync::Arc<serenity::ShardManager>,
}
impl<U, E> Copy for FrameworkContext<'_, U, E> {}
impl<U, E> Clone for FrameworkContext<'_, U, E> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, U, E> FrameworkContext<'a, U, E> {
pub fn options(&self) -> &'a crate::FrameworkOptions<U, E> {
self.options
}
pub fn shard_manager(&self) -> std::sync::Arc<serenity::ShardManager> {
self.shard_manager.clone()
}
#[allow(clippy::unused_async)] pub async fn user_data(&self) -> &'a U {
self.user_data
}
}
pub async fn dispatch_event<U: Send + Sync, E>(
framework: crate::FrameworkContext<'_, U, E>,
ctx: &serenity::Context,
event: serenity::FullEvent,
) {
match &event {
serenity::FullEvent::Message { new_message } => {
let invocation_data = tokio::sync::Mutex::new(Box::new(()) as _);
let mut parent_commands = Vec::new();
let trigger = crate::MessageDispatchTrigger::MessageCreate;
if let Err(error) = prefix::dispatch_message(
framework,
ctx,
new_message,
trigger,
&invocation_data,
&mut parent_commands,
)
.await
{
error.handle(framework.options).await;
}
}
serenity::FullEvent::MessageUpdate { event, .. } => {
if let Some(edit_tracker) = &framework.options.prefix_options.edit_tracker {
let msg = edit_tracker.write().unwrap().process_message_update(
event,
framework
.options()
.prefix_options
.ignore_edits_if_not_yet_responded,
);
if let Some((msg, previously_tracked)) = msg {
let invocation_data = tokio::sync::Mutex::new(Box::new(()) as _);
let mut parent_commands = Vec::new();
let trigger = match previously_tracked {
true => crate::MessageDispatchTrigger::MessageEdit,
false => crate::MessageDispatchTrigger::MessageEditFromInvalid,
};
if let Err(error) = prefix::dispatch_message(
framework,
ctx,
&msg,
trigger,
&invocation_data,
&mut parent_commands,
)
.await
{
error.handle(framework.options).await;
}
}
}
}
serenity::FullEvent::MessageDelete {
deleted_message_id, ..
} => {
if let Some(edit_tracker) = &framework.options.prefix_options.edit_tracker {
let bot_response = edit_tracker
.write()
.unwrap()
.process_message_delete(*deleted_message_id);
if let Some(bot_response) = bot_response {
if let Err(e) = bot_response.delete(ctx).await {
tracing::warn!("failed to delete bot response: {}", e);
}
}
}
}
serenity::FullEvent::InteractionCreate {
interaction: serenity::Interaction::Command(interaction),
} => {
let invocation_data = tokio::sync::Mutex::new(Box::new(()) as _);
let mut parent_commands = Vec::new();
if let Err(error) = slash::dispatch_interaction(
framework,
ctx,
interaction,
&std::sync::atomic::AtomicBool::new(false),
&invocation_data,
&interaction.data.options(),
&mut parent_commands,
)
.await
{
error.handle(framework.options).await;
}
}
serenity::FullEvent::InteractionCreate {
interaction: serenity::Interaction::Autocomplete(interaction),
} => {
let invocation_data = tokio::sync::Mutex::new(Box::new(()) as _);
let mut parent_commands = Vec::new();
if let Err(error) = slash::dispatch_autocomplete(
framework,
ctx,
interaction,
&std::sync::atomic::AtomicBool::new(false),
&invocation_data,
&interaction.data.options(),
&mut parent_commands,
)
.await
{
error.handle(framework.options).await;
}
}
_ => {}
}
if let Err(error) =
(framework.options.event_handler)(ctx, &event, framework, framework.user_data).await
{
let error = crate::FrameworkError::EventHandler {
error,
ctx,
event: &event,
framework,
};
(framework.options.on_error)(error).await;
}
}