telexide_fork/framework/
framework.rs

1use super::types::{CommandTypes, TelegramCommand};
2use crate::{
3    client::Context,
4    model::{Message, MessageContent, MessageEntity, Update, UpdateContent},
5};
6use log::{debug, warn};
7
8/// A utility for easily managing commands.
9///
10/// Refer to the [module-level documentation](index.html) for more detail
11pub struct Framework {
12    commands: Vec<TelegramCommand>,
13    bot_name: String,
14}
15
16impl Framework {
17    /// Creates a new framework instance given the bot name
18    pub fn new(bot_name: &str) -> Self {
19        Self {
20            commands: Vec::new(),
21            bot_name: bot_name.to_owned(),
22        }
23    }
24
25    fn match_command(&self, message: &Message, name: &str) -> bool {
26        if let MessageContent::Text { entities, content } = &message.content {
27            for entity in entities {
28                if let MessageEntity::BotCommand(ref t) = entity {
29                    let t = t.get_text(content);
30                    return t == format!("/{name}")
31                        || t == format!("/{}@{}", name, &self.bot_name);
32                }
33            }
34        }
35        false
36    }
37
38    #[allow(clippy::needless_pass_by_value)]
39    fn fire_message_commands(&self, context: Context, message: Message) {
40        for command in &self.commands {
41            match command.command.clone() {
42                CommandTypes::Default(c) if self.match_command(&message, command.options.name) => {
43                    let ctx = context.clone();
44                    let msg = message.clone();
45                    let command_name = command.options.name;
46                    debug!("calling command {}", &command_name);
47
48                    tokio::spawn(async move {
49                        let res = c(ctx, msg).await;
50                        if res.is_err() {
51                            warn!(
52                                "command {} returned error: {}",
53                                &command_name,
54                                res.unwrap_err().0
55                            );
56                        }
57                    });
58                }
59                CommandTypes::Default(_) => (),
60            }
61        }
62    }
63
64    /// add a command to the registered commands
65    pub fn add_command(&mut self, command: &TelegramCommand) {
66        self.commands.push(command.clone());
67    }
68
69    /// get all registered commands
70    pub fn get_commands(&self) -> &Vec<TelegramCommand> {
71        &self.commands
72    }
73
74    /// fires off all commands matching the content in the update
75    pub fn fire_commands(&self, context: Context, update: Update) {
76        if let UpdateContent::Message(c) = update.content {
77            self.fire_message_commands(context, c);
78        }
79    }
80}