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#[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 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}