tulpje_framework/module/
builder.rs1use 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}