tulpje_framework/
lib.rs

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