tulpje_framework/module/
builder.rs

1use std::collections::{HashMap, HashSet};
2
3use async_cron_scheduler::cron::Schedule;
4use twilight_gateway::EventType;
5use twilight_model::application::command::Command;
6
7use super::{command_builder::CommandBuilder, Module};
8use crate::handler::{
9    command_handler::CommandHandler,
10    component_interaction_handler::{ComponentInteractionFunc, ComponentInteractionHandler},
11    event_handler::{EventFunc, EventHandler},
12    task_handler::{TaskFunc, TaskHandler},
13};
14
15pub struct ModuleBuilder<T: Clone + Send + Sync> {
16    name: String,
17    guild_scoped: bool,
18
19    commands: HashMap<String, CommandHandler<T>>,
20    command_definitions: Vec<Command>,
21
22    components: HashMap<String, ComponentInteractionHandler<T>>,
23    events: HashMap<EventType, HashSet<EventHandler<T>>>,
24    tasks: HashMap<String, TaskHandler<T>>,
25}
26
27impl<T: Clone + Send + Sync> ModuleBuilder<T> {
28    pub fn new(name: &str) -> Self {
29        Self {
30            name: name.into(),
31            guild_scoped: false,
32
33            commands: HashMap::new(),
34            command_definitions: Vec::new(),
35
36            components: HashMap::new(),
37            events: HashMap::new(),
38            tasks: HashMap::new(),
39        }
40    }
41
42    #[must_use]
43    pub fn build(self) -> Module<T> {
44        Module {
45            name: self.name,
46            guild_scoped: self.guild_scoped,
47
48            commands: self.commands,
49            command_definitions: self.command_definitions,
50
51            components: self.components,
52            events: self.events,
53            tasks: self.tasks,
54        }
55    }
56
57    #[must_use]
58    pub fn guild(mut self) -> Self {
59        self.guild_scoped = true;
60        self
61    }
62
63    #[must_use]
64    pub fn command(mut self, command: CommandBuilder<T>) -> Self {
65        self.command_definitions.push(command.clone().into());
66
67        for group in &command.groups {
68            for subcommand in &group.commands {
69                let command_name = format!("{} {} {}", command.name, group.name, subcommand.name);
70                let func = subcommand
71                    .func
72                    .unwrap_or_else(|| panic!("command '/{}' has no handler", command_name));
73
74                self.commands.insert(
75                    command_name.clone(),
76                    CommandHandler {
77                        module: self.name.clone(),
78                        name: command_name,
79                        func,
80                    },
81                );
82            }
83        }
84        for subcommand in &command.subcommands {
85            let command_name = format!("{} {}", command.name, subcommand.name);
86            let func = subcommand
87                .func
88                .unwrap_or_else(|| panic!("command /{} has no handler", command_name));
89
90            self.commands.insert(
91                command_name.clone(),
92                CommandHandler {
93                    module: self.name.clone(),
94                    name: command_name,
95                    func,
96                },
97            );
98        }
99
100        if command.subcommands.is_empty() && command.groups.is_empty() {
101            let func = command
102                .func
103                .unwrap_or_else(|| panic!("command /{} has no handler", command.name));
104
105            self.commands.insert(
106                command.name.clone(),
107                CommandHandler {
108                    module: self.name.clone(),
109                    name: command.name,
110                    func,
111                },
112            );
113        }
114
115        self
116    }
117
118    #[must_use]
119    pub fn component(mut self, custom_id: &str, func: ComponentInteractionFunc<T>) -> Self {
120        self.components.insert(
121            custom_id.to_string(),
122            ComponentInteractionHandler {
123                module: self.name.clone(),
124                custom_id: custom_id.to_string(),
125                func,
126            },
127        );
128        self
129    }
130
131    #[must_use]
132    pub fn event(mut self, event: EventType, func: EventFunc<T>) -> Self {
133        self.events.entry(event).or_default().insert(EventHandler {
134            module: self.name.clone(),
135            uuid: uuid::Uuid::now_v7().to_string(),
136            event,
137            func,
138        });
139        self
140    }
141
142    #[must_use]
143    pub fn task(mut self, name: &str, schedule: &str, func: TaskFunc<T>) -> Self {
144        self.tasks.insert(
145            name.to_string(),
146            TaskHandler {
147                module: self.name.clone(),
148                name: name.to_string(),
149                cron: Schedule::try_from(schedule).expect("failed to parse cron expression"),
150                func,
151            },
152        );
153        self
154    }
155}