pikadick/commands/
cmd.rs

1use crate::{
2    checks::{
3        ADMIN_CHECK,
4        ENABLED_CHECK,
5    },
6    ClientDataKey,
7};
8use serenity::{
9    framework::standard::{
10        macros::command,
11        Args,
12        CommandResult,
13    },
14    model::prelude::*,
15    prelude::*,
16};
17use std::fmt::Write;
18use tracing::error;
19
20// Broken in help:
21// #[required_permissions("ADMINISTRATOR")]
22
23#[command]
24#[description("Disable a command")]
25#[usage("<enable/disable> <cmd>")]
26#[example("disable ping")]
27#[min_args(2)]
28#[max_args(2)]
29#[sub_commands(list)]
30#[checks(Admin, Enabled)]
31#[bucket("default")]
32pub async fn cmd(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
33    let guild_id = match msg.guild_id {
34        Some(id) => id,
35        None => {
36            msg.channel_id
37                .say(&ctx.http, "You cannot use this in a DM.")
38                .await?;
39            return Ok(());
40        }
41    };
42
43    let data_lock = ctx.data.read().await;
44    let client_data = data_lock.get::<ClientDataKey>().unwrap();
45    let data = client_data.enabled_check_data.clone();
46    let db = client_data.db.clone();
47    drop(data_lock);
48
49    let disable = match args.current().expect("invalid arg") {
50        "enable" => false,
51        "disable" => true,
52        _ => {
53            msg.channel_id
54                .say(&ctx.http, "Invalid Arg. Choose \"enable\" or \"disable\".")
55                .await?;
56            return Ok(());
57        }
58    };
59
60    args.advance();
61
62    let cmd_name = args.current().expect("missing cmd name");
63
64    let is_valid_command = {
65        let names = data.get_command_names();
66        names.iter().any(|name| name == cmd_name)
67    };
68
69    if !is_valid_command {
70        msg.channel_id
71            .say(
72                &ctx.http,
73                "Invalid Command. Use `cmd list` to list valid commands.",
74            )
75            .await?;
76        return Ok(());
77    }
78
79    match db.set_disabled_command(guild_id, cmd_name, disable).await {
80        Ok(_old_value) => {
81            let status_str = status_to_str(disable);
82
83            // TODO: Tell user if the command is already disabled/enabled
84            msg.channel_id
85                .say(&ctx.http, format!("Command '{}' {}.", cmd_name, status_str))
86                .await?;
87        }
88        Err(e) => {
89            error!("failed to disable command '{}': {:?}", cmd_name, e);
90            msg.channel_id
91                .say(
92                    &ctx.http,
93                    format!("Failed to disable command '{}' ", cmd_name),
94                )
95                .await?;
96        }
97    }
98
99    Ok(())
100}
101
102#[command]
103#[description("List commands that can be enabled/disabled")]
104pub async fn list(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
105    let guild_id = match msg.guild_id {
106        Some(id) => id,
107        None => {
108            msg.channel_id
109                .say(&ctx.http, "You cannot use this in a DM.")
110                .await?;
111            return Ok(());
112        }
113    };
114
115    let data_lock = ctx.data.read().await;
116    let client_data = data_lock.get::<ClientDataKey>().expect("client data");
117    let data = client_data.enabled_check_data.clone();
118    let db = client_data.db.clone();
119    drop(data_lock);
120
121    let res = {
122        let mut res = "Commands:\n".to_string();
123
124        let names = data.get_command_names().clone();
125
126        for name in names.iter() {
127            let state = if db.is_command_disabled(guild_id, name).await? {
128                "DISABLED"
129            } else {
130                "ENABLED"
131            };
132            writeln!(res, "{}: **{}**", name, state)?;
133        }
134
135        res
136    };
137
138    msg.channel_id.say(&ctx.http, res).await?;
139    Ok(())
140}
141
142fn status_to_str(status: bool) -> &'static str {
143    if status {
144        "disabled"
145    } else {
146        "enabled"
147    }
148}