doxing_emulator/commands/
mod.rs

1//! Extracts commands from messages and execution.
2
3mod dox;
4mod help;
5
6use super::dox_impl;
7pub use dox::Dox;
8use frankenstein::{client_reqwest::Bot, types::Message};
9pub use help::Help;
10use log::info;
11
12/// A command.
13pub trait Command {
14    /// Trigger word.
15    const TRIGGER: &'static str;
16    /// Help message.
17    const HELP: &'static str;
18    /// Execute the command.
19    fn execute(self, bot: &Bot, msg: Message, username: &str) -> impl Future<Output = String> + Send;
20}
21
22/// Available commands.
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum Commands {
25    /// The help command.
26    Help(Help),
27    /// The dox command.
28    Dox(Dox),
29}
30
31impl Commands {
32    /// Try to parse the given text to a command.
33    ///
34    /// # Arguments
35    ///
36    /// - `text` - The text to check.
37    /// - `username` - The username of the bot.
38    #[must_use]
39    pub fn parse(text: Option<&String>, username: &str) -> Option<Self> {
40        let text = text?.trim();
41        let (command, arg) = text.split_once(' ').unwrap_or((text, ""));
42
43        // Two possible command formats:
44        // 1. /command <arg>
45        // 2. /command@bot_username <arg>
46
47        // Trim the leading slash
48        let slash = command.starts_with('/');
49        if !slash {
50            return None;
51        }
52        let command = &command[1..];
53
54        // Split out the mention and check if it's the bot
55        let (command, mention) = command.split_once('@').unwrap_or((command, ""));
56        if !mention.is_empty() && mention != username {
57            return None;
58        }
59
60        // Match the command
61        match command {
62            Dox::TRIGGER => {
63                let arg = arg.trim();
64                let doxee = if arg.is_empty() {
65                    None
66                } else {
67                    Some(arg.to_string())
68                };
69                Some(Self::Dox(Dox { doxee }))
70            }
71            Help::TRIGGER | "start" => Some(Self::Help(Help)),
72            _ => None,
73        }
74    }
75
76    /// Execute the command.
77    pub async fn execute(self, bot: &Bot, msg: Message, username: &str) -> String {
78        info!("Executing command: {self:?}");
79        match self {
80            Self::Help(help) => help.execute(bot, msg, username).await,
81            Self::Dox(dox) => dox.execute(bot, msg, username).await,
82        }
83    }
84}
85
86/// A list of available commands and descriptions.
87pub const LIST: [(&str, &str); 2] = [(Dox::TRIGGER, Dox::HELP), (Help::TRIGGER, Help::HELP)];