1use twilight_gateway::Event;
2use twilight_model::gateway::payload::incoming::InteractionCreate;
3
4pub use context::{Context, EventContext, InteractionContext};
5pub use framework::Framework;
6pub use metadata::Metadata;
7pub use module::{Module, builder::ModuleBuilder, registry::Registry};
8
9pub mod color;
10pub mod context;
11pub mod framework;
12pub mod handler;
13pub mod interaction;
14pub mod macros;
15pub mod metadata;
16pub mod module;
17pub mod scheduler;
18
19pub type Error = Box<dyn std::error::Error + Send + Sync>;
20
21pub async fn handle_interaction<T: Clone + Send + Sync + 'static>(
22 event: InteractionCreate,
23 context: Context<T>,
24 meta: &Metadata,
25 registry: &Registry<T>,
26 processed: twilight_standby::ProcessResults,
27) -> Result<(), Error> {
28 match interaction::parse(&event, meta.clone(), context) {
29 Ok(InteractionContext::Command(ctx)) => {
30 let Some(command) = registry.find_command(&ctx.name) else {
31 return Err(format!("unknown command /{}", ctx.name).into());
32 };
33
34 if let Err(err) = command.run(ctx.clone()).await {
35 return Err(format!("error running command /{}: {}", ctx.name, err).into());
36 }
37 }
38 Ok(InteractionContext::ComponentInteraction(ctx)) => {
39 let Some(component_interaction) = registry.components.get(&ctx.interaction.custom_id)
40 else {
41 if processed.matched() > 0 {
44 return Ok(());
45 }
46
47 return Err(format!(
49 "no handler for component interaction {}",
50 ctx.interaction.custom_id
51 )
52 .into());
53 };
54
55 if let Err(err) = component_interaction.run(ctx.clone()).await {
56 return Err(format!(
57 "error handling component interaction {}: {}",
58 ctx.interaction.custom_id, err
59 )
60 .into());
61 }
62 }
63 Ok(InteractionContext::Modal(_modal_context)) => {
64 todo!()
65 }
66 Err(err) => return Err(format!("error handling interaction: {}", err).into()),
67 };
68
69 Ok(())
70}
71
72pub async fn handle<T: Clone + Send + Sync + 'static>(
73 meta: Metadata,
74 ctx: Context<T>,
75 registry: &Registry<T>,
76 event: Event,
77) {
78 let processed = ctx.standby.process(&event);
79
80 if let twilight_gateway::Event::InteractionCreate(event) = event.clone()
81 && let Err(err) = handle_interaction(*event, ctx.clone(), &meta, registry, processed).await
82 {
83 tracing::warn!(err);
84 }
85
86 if let Some(handlers) = registry.events.get(&event.kind()) {
87 tracing::debug!("running event handlers for {:?}", event.kind());
88
89 for handler in handlers {
90 let event_ctx = EventContext::from_context(ctx.clone(), meta.clone(), event.clone());
91
92 if let Err(err) = handler.run(event_ctx).await {
93 tracing::warn!(
94 "error running event handler {} for event {:?}: {}",
95 handler.uuid,
96 event.kind(),
97 err
98 );
99 }
100 }
101 }
102}