tulpje_framework/module/
registry.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use std::collections::{HashMap, HashSet};

use twilight_gateway::EventType;
use twilight_model::application::command::Command;

use super::Module;
use crate::handler::{
    command_handler::CommandHandler, component_interaction_handler::ComponentInteractionHandler,
    event_handler::EventHandler, task_handler::TaskHandler,
};

#[derive(Clone)]
#[expect(
    clippy::partial_pub_fields,
    reason = "we need 'tasks' to be public for now to start the task scheduler"
)]
pub struct Registry<T: Clone + Send + Sync> {
    modules: HashMap<String, Module<T>>,

    pub(crate) commands: HashMap<String, CommandHandler<T>>,
    pub(crate) components: HashMap<String, ComponentInteractionHandler<T>>,
    pub(crate) events: HashMap<EventType, HashSet<EventHandler<T>>>,
    pub tasks: HashMap<String, TaskHandler<T>>,
}

impl<T: Clone + Send + Sync> Registry<T> {
    pub fn new() -> Self {
        Self {
            modules: HashMap::new(),
            commands: HashMap::new(),
            components: HashMap::new(),
            events: HashMap::new(),
            tasks: HashMap::new(),
        }
    }

    pub fn register(&mut self, module: Module<T>) {
        self.commands.extend(module.commands.clone());
        self.components.extend(module.components.clone());
        self.events.extend(module.events.clone());
        self.tasks.extend(module.tasks.clone());

        self.modules.insert(module.name.clone(), module);
    }

    pub fn global_commands(&self) -> Vec<Command> {
        self.modules
            .values()
            .filter(|m| !m.guild_scoped) // filter out guild scoped modules
            .flat_map(|m| m.commands.values().map(|ch| ch.definition.clone()))
            .collect()
    }

    pub fn module_commands(&self, module: &str) -> Option<Vec<Command>> {
        Some(
            self.modules
                .get(module)?
                .commands
                .values()
                .map(|ch| ch.definition.clone())
                .collect(),
        )
    }

    pub fn find_command(&self, name: &str) -> Option<&CommandHandler<T>> {
        self.commands.get(name)
    }

    pub fn guild_module_names(&self) -> Vec<String> {
        self.modules
            .values()
            .filter(|m| m.guild_scoped)
            .map(|m| m.name.clone())
            .collect()
    }
}

impl<T: Clone + Send + Sync> Default for Registry<T> {
    fn default() -> Self {
        Self::new()
    }
}