ferris_bot/
cmd.rs

1/// core commands
2pub mod core {
3    use crate::config::{conf::Config, val};
4    use serenity::model::channel::Message;
5    /// respond with pong (left in for debug purposes)
6    pub fn ping() -> &'static str {
7        "**Pong!**"
8    }
9
10    /// send a small help page to the user
11    ///
12    /// # Arguments
13    ///
14    /// * `conf`: the config to use
15    ///
16    /// # Return
17    /// returns the help message as a String
18    pub fn help(conf: Config) -> String {
19        let mut help_string: String = String::from(
20            "**HELP**
21**core**
22`-ping`: sends pong (used for debug purposes)
23`-help`: sends this help message
24`-status`: show the status of the bot (which modules are loaded)
25`-getid [user]`: gets the user id of `user` or (if not specified) the sender",
26        );
27        match conf.moderation {
28            // feature has been enabled in the config file
29            Some(true) => {
30                help_string.push_str(
31                    "\n**moderation**
32`-kick <user> [reason]`: kicks a user
33`-ban <user> [reason]`: bans a user
34`-warn <user> [reason]`: warns a user
35`-mute <user> [reason]`: mutes a user
36a `<user>` is represented by his ID
37",
38                );
39            }
40            // if set to false or not specified (default value) don't do anything
41            // since the feature is disabled
42            Some(false) | None => {}
43        }
44        help_string.push_str(format!("\nversion: {}", val::VERSION).as_str());
45        help_string
46    }
47
48    /// get the ID of some user
49    ///
50    /// # Arguments
51    ///
52    /// * `msg`: the message to parse
53    ///
54    /// # Return
55    ///
56    /// returns the response content
57    pub fn get_id(msg: Message) -> String {
58        let components: Vec<&str> = msg.content.as_str().split_whitespace().collect();
59        if components.len() == 1 {
60            return format!("user ID of {}: {}", msg.author.name, msg.author.id.as_u64());
61        } else if components.len() > 1 {
62            if msg.mentions.len() > 0 {
63                let mut out: String = String::new();
64                for user in msg.mentions {
65                    out.push_str(
66                        format!("user ID of {}: {}\n", user.name, user.id.as_u64()).as_str(),
67                    );
68                }
69                return out;
70            } else {
71                return String::from("if you want the ID of some user @mention them");
72            }
73        } else {
74            return String::new();
75        }
76    }
77
78    /// function to report the status of the bot
79    ///
80    /// # Arguments
81    ///
82    /// * `config`: the config to use
83    ///
84    /// # Return
85    ///
86    /// returns the message to send as a String
87    pub fn status(config: Config) -> String {
88        let mut out: String = String::from("**core**: enabled (forced)");
89        match config.moderation {
90            Some(true) => out.push_str("\n**moderation**: enabled"),
91            Some(false) | None => out.push_str("\n**moderation**: disabled"),
92        }
93        out.push_str(format!("\n**version**: {}", val::VERSION).as_str());
94        out
95    }
96}
97
98/// moderation commands
99pub mod moderation {
100    use crate::config::conf::Config;
101    use serenity::{
102        client::Context,
103        model::{
104            channel::Message,
105            id::{GuildId, RoleId},
106            user::User,
107        },
108    };
109    /// warn a user
110    ///
111    /// # Arguments
112    ///
113    /// * `msg`: the message to parse
114    /// * `conf`: the configuration to use
115    /// * `ctx`: the context to use for some checking things
116    ///
117    /// # Return
118    ///
119    /// The message to send as a String
120    pub async fn warn(msg: Message, conf: Config, ctx: &Context) -> String {
121        let context: Context = ctx.clone();
122        let gid: GuildId = match msg.guild_id {
123            Some(n) => n,
124            None => {
125                return String::from("you need to send this message in a server");
126            }
127        };
128        let modrole: RoleId = match conf.moderating {
129            Some(n) => RoleId(n.modrole),
130            None => {
131                return String::from("Modrole not specified in the config file");
132            }
133        };
134        match msg.author.has_role(context, gid, modrole).await {
135            Ok(true) => {
136                if msg.mentions.len() != 1 {
137                    return String::from("you need to mention the person you want to warn");
138                } else {
139                    let user: &User = &msg.mentions[0];
140                    let parts: Vec<&str> = msg.content.as_str().split_whitespace().collect();
141                    if parts.len() > 2 {
142                        let reason_vec: Vec<&str> = parts[2..].to_vec();
143                        let mut reason: String = String::new();
144                        for i in reason_vec {
145                            reason = format!("{} {}", reason, i);
146                        }
147                        reason = reason[1..].to_string();
148                        return format!("{} has been warned. Reason: {}", user.name, reason);
149                    } else {
150                        return format!("{} has been warned", user.name);
151                    }
152                }
153            }
154
155            Ok(false) => {
156                return String::from("you need to be a moderator to execute this command");
157            }
158
159            Err(e) => {
160                return format!("Error while checking permissions: `{}`", e);
161            }
162        }
163    }
164
165    /// kick a user
166    ///
167    /// # Arguments
168    ///
169    /// * `msg`: the message to parse
170    /// * `conf`: the configuration to use
171    /// * `ctx`: the context to use for some checking things
172    ///
173    /// # Return
174    ///
175    /// The message to send as a String
176    pub async fn kick(msg: Message, conf: Config, ctx: &Context) -> String {
177        let context: Context = ctx.clone();
178        let gid: GuildId = match msg.guild_id {
179            Some(n) => n,
180            None => {
181                return String::from("you need to send this message in a server");
182            }
183        };
184        let modrole: RoleId = match conf.moderating {
185            Some(n) => RoleId(n.modrole),
186            None => {
187                return String::from("Modrole not specified in the config file");
188            }
189        };
190        match msg.author.has_role(&context, gid, modrole).await {
191            Ok(true) => {
192                if msg.mentions.len() != 1 {
193                    return String::from("you need to mention the person you want to kick");
194                } else {
195                    let user: &User = &msg.mentions[0];
196                    let parts: Vec<&str> = msg.content.as_str().split_whitespace().collect();
197                    if parts.len() > 2 {
198                        let reason_vec: Vec<&str> = parts[2..].to_vec();
199                        let mut reason: String = String::new();
200                        for i in reason_vec {
201                            reason = format!("{} {}", reason, i);
202                        }
203                        reason = reason[1..].to_string();
204                        if let Err(e) = gid.kick(&context, user.id).await {
205                            println!("failed to kick user: {:?}", e);
206                            return format!("failed to kick user: {}", e);
207                        }
208                        return format!("{} has been kicked. Reason: {}", user.name, reason);
209                    } else {
210                        if let Err(e) = gid.kick(&context, user.id).await {
211                            println!("failed to kick user: {:?}", e);
212                            return format!("failed to kick user: {}", e);
213                        }
214                        return format!("{} has been kicked", user.name);
215                    }
216                }
217            }
218
219            Ok(false) => {
220                return String::from("you need to be a moderator to execute this command");
221            }
222
223            Err(e) => {
224                return format!("Error while checking permissions: `{}`", e);
225            }
226        }
227    }
228}