Skip to content

Commit 17d8868

Browse files
committed
feat(commands): implement status command with maintenance mode
1 parent 7f55763 commit 17d8868

4 files changed

Lines changed: 151 additions & 12 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use strum::EnumString;
2+
3+
#[derive(EnumString)]
4+
#[strum(serialize_all = "snake_case")]
5+
pub enum BotStatus {
6+
Online,
7+
Idle,
8+
Dnd,
9+
Invisible,
10+
Maintenance,
11+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
pub mod common;
12
pub mod slash_command;
23
pub mod text_command;
34

5+
pub use common::*;
46
pub use slash_command::*;
57
pub use text_command::*;

rustmail/src/commands/status/slash_command/status.rs

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1+
use crate::commands::status::BotStatus;
12
use crate::commands::{BoxFuture, RegistrableCommand};
23
use crate::config::Config;
34
use crate::errors::ModmailResult;
45
use crate::handlers::InteractionHandler;
56
use crate::i18n::get_translated_message;
6-
use futures::FutureExt;
7+
use crate::utils::{MessageBuilder, defer_response};
8+
use serenity::FutureExt;
79
use serenity::all::{
8-
CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption,
9-
ResolvedOption,
10+
ActivityData, CommandDataOptionValue, CommandInteraction, CommandOptionType, Context,
11+
CreateCommand, CreateCommandOption, ResolvedOption,
1012
};
13+
use std::str::FromStr;
1114
use std::sync::Arc;
15+
use std::sync::atomic::Ordering;
1216

1317
pub struct StatusCommand;
1418

@@ -102,10 +106,79 @@ impl RegistrableCommand for StatusCommand {
102106
&self,
103107
ctx: &Context,
104108
command: &CommandInteraction,
105-
options: &[ResolvedOption<'_>],
109+
_options: &[ResolvedOption<'_>],
106110
config: &Config,
107111
handler: Arc<InteractionHandler>,
108112
) -> BoxFuture<'_, ModmailResult<()>> {
109-
todo!()
113+
let ctx = ctx.clone();
114+
let command = command.clone();
115+
let config = config.clone();
116+
117+
Box::pin(async move {
118+
defer_response(&ctx, &command).await?;
119+
120+
let mode = command.data.options.iter().find_map(|opt| {
121+
if opt.name == "mode" {
122+
if let CommandDataOptionValue::String(s) = &opt.value {
123+
return Some(s.clone());
124+
}
125+
}
126+
None
127+
});
128+
129+
let mode = match mode {
130+
Some(m) => m,
131+
None => return Ok(()),
132+
};
133+
134+
let bot_status = match BotStatus::from_str(&mode) {
135+
Ok(status) => status,
136+
Err(_) => return Ok(()),
137+
};
138+
139+
let message_key = match bot_status {
140+
BotStatus::Online => {
141+
handler.maintenance_mode.store(false, Ordering::Relaxed);
142+
ctx.set_activity(Some(ActivityData::playing(&config.bot.status)));
143+
ctx.online();
144+
"status.status_online"
145+
}
146+
BotStatus::Idle => {
147+
ctx.idle();
148+
"status.status_idle"
149+
}
150+
BotStatus::Dnd => {
151+
ctx.dnd();
152+
"status.status_dnd"
153+
}
154+
BotStatus::Invisible => {
155+
ctx.invisible();
156+
"status.status_invisible"
157+
}
158+
BotStatus::Maintenance => {
159+
handler.maintenance_mode.store(true, Ordering::Relaxed);
160+
let maintenance_status = get_translated_message(
161+
&config,
162+
"status.maintenance_activity",
163+
None,
164+
None,
165+
None,
166+
None,
167+
)
168+
.await;
169+
ctx.set_activity(Some(ActivityData::playing(&maintenance_status)));
170+
ctx.dnd();
171+
"status.status_maintenance"
172+
}
173+
};
174+
175+
let _ = MessageBuilder::system_message(&ctx, &config)
176+
.translated_content(message_key, None, None, None)
177+
.await
178+
.send_interaction_followup(&command, true)
179+
.await;
180+
181+
Ok(())
182+
})
110183
}
111184
}
Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,72 @@
1+
use crate::commands::status::BotStatus;
12
use crate::config::Config;
2-
use crate::errors::{ModmailResult, database_connection_failed};
3+
use crate::errors::{CommandError, ModmailError, ModmailResult};
34
use crate::handlers::GuildMessagesHandler;
4-
use serenity::all::{Context, Message};
5+
use crate::i18n::get_translated_message;
6+
use crate::utils::{MessageBuilder, extract_reply_content};
7+
use serenity::all::{ActivityData, Context, Message};
8+
use std::str::FromStr;
59
use std::sync::Arc;
10+
use std::sync::atomic::Ordering;
611

712
pub async fn status_command(
813
ctx: Context,
914
msg: Message,
1015
config: &Config,
11-
_handler: Arc<GuildMessagesHandler>,
16+
handler: Arc<GuildMessagesHandler>,
1217
) -> ModmailResult<()> {
13-
let pool = config
14-
.db_pool
15-
.as_ref()
16-
.ok_or_else(database_connection_failed)?;
18+
let content = match extract_reply_content(&msg.content, &config.command.prefix, &["status"]) {
19+
Some(c) => c,
20+
None => return Err(ModmailError::Command(CommandError::StatusIsMissing)),
21+
};
22+
23+
let bot_status = match BotStatus::from_str(&content) {
24+
Ok(status) => status,
25+
Err(_) => return Err(ModmailError::Command(CommandError::InvalidStatusValue)),
26+
};
27+
28+
let message_key = match bot_status {
29+
BotStatus::Online => {
30+
handler.maintenance_mode.store(false, Ordering::Relaxed);
31+
ctx.set_activity(Some(ActivityData::playing(&config.bot.status)));
32+
ctx.online();
33+
"status.status_online"
34+
}
35+
BotStatus::Idle => {
36+
ctx.idle();
37+
"status.status_idle"
38+
}
39+
BotStatus::Dnd => {
40+
ctx.dnd();
41+
"status.status_dnd"
42+
}
43+
BotStatus::Invisible => {
44+
ctx.invisible();
45+
"status.status_invisible"
46+
}
47+
BotStatus::Maintenance => {
48+
handler.maintenance_mode.store(true, Ordering::Relaxed);
49+
let maintenance_status = get_translated_message(
50+
config,
51+
"status.maintenance_activity",
52+
None,
53+
None,
54+
None,
55+
None,
56+
)
57+
.await;
58+
ctx.set_activity(Some(ActivityData::playing(&maintenance_status)));
59+
ctx.dnd();
60+
"status.status_maintenance"
61+
}
62+
};
63+
64+
let _ = MessageBuilder::system_message(&ctx, config)
65+
.translated_content(message_key, None, None, None)
66+
.await
67+
.to_channel(msg.channel_id)
68+
.send(true)
69+
.await;
1770

1871
Ok(())
1972
}

0 commit comments

Comments
 (0)