Skip to content

Commit 02eed0e

Browse files
committed
fix(commands): fixed mention that doesn't ping mentionned user
1 parent 01db53b commit 02eed0e

8 files changed

Lines changed: 116 additions & 122 deletions

File tree

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
use crate::config::Config;
2+
use crate::db::reminders::{update_reminder_status, Reminder};
23
use crate::utils::conversion::hex_string_to_int::hex_string_to_int;
34
use crate::utils::message::message_builder::MessageBuilder;
4-
use serenity::all::{Context, Message};
5+
use chrono::Local;
6+
use serenity::all::{ChannelId, Context, Message, UserId};
7+
use sqlx::SqlitePool;
58
use std::collections::HashMap;
9+
use std::time::Duration;
10+
use tokio::time::sleep;
611

712
pub async fn send_register_confirmation(
13+
reminder_id: i64,
814
reminder_content: &str,
915
ctx: &Context,
1016
msg: &Message,
@@ -32,6 +38,7 @@ pub async fn send_register_confirmation(
3238
)
3339
.await
3440
.to_channel(msg.channel_id)
41+
.footer(format!("{}: {}", "ID", reminder_id))
3542
.send()
3643
.await;
3744
} else {
@@ -44,44 +51,65 @@ pub async fn send_register_confirmation(
4451
)
4552
.await
4653
.to_channel(msg.channel_id)
54+
.footer(format!("{}: {}", "ID", reminder_id))
4755
.send()
4856
.await;
4957
}
5058
}
5159

52-
pub async fn send_reminder_content(
53-
reminder_content: &str,
54-
ctx: &Context,
55-
msg: &Message,
56-
config: &Config,
57-
trigger_timestamp: i64,
58-
) {
59-
let mut params = HashMap::new();
60-
params.insert("time".to_string(), format!("<t:{}:F>", trigger_timestamp));
61-
params.insert(
62-
"remaining_time".to_string(),
63-
format!("<t:{}:R>", trigger_timestamp),
64-
);
60+
pub fn spawn_reminder(reminder: &Reminder, ctx: &Context, config: &Config, pool: &SqlitePool) {
61+
let pool = pool.clone();
62+
let config = config.clone();
63+
let ctx = ctx.clone();
64+
let reminder = reminder.clone();
6565

66-
if !reminder_content.is_empty() {
67-
params.insert("content".to_string(), reminder_content.to_string());
68-
}
66+
tokio::spawn(async move {
67+
let now = Local::now().timestamp();
68+
let delay_duration = if reminder.trigger_time > now {
69+
reminder.trigger_time - now
70+
} else {
71+
0
72+
};
73+
sleep(Duration::from_secs(delay_duration as u64)).await;
6974

70-
if !reminder_content.is_empty() {
71-
let _ = MessageBuilder::system_message(&ctx, &config)
72-
.translated_content("reminder.show_with_content", Some(&params), None, None)
73-
.await
74-
.to_channel(msg.channel_id)
75-
.color(hex_string_to_int(&config.reminders.embed_color) as u32)
76-
.send()
77-
.await;
78-
} else {
79-
let _ = MessageBuilder::system_message(&ctx, &config)
80-
.translated_content("reminder.show_without_content", None, None, None)
81-
.await
82-
.to_channel(msg.channel_id)
83-
.color(hex_string_to_int(&config.reminders.embed_color) as u32)
84-
.send()
85-
.await;
86-
}
75+
let mut params = HashMap::new();
76+
params.insert(
77+
"time".to_string(),
78+
format!("<t:{}:F>", reminder.trigger_time),
79+
);
80+
params.insert(
81+
"remaining_time".to_string(),
82+
format!("<t:{}:R>", reminder.trigger_time),
83+
);
84+
85+
params.insert("user".to_string(), reminder.user_id.to_string());
86+
params.insert("content".to_string(), reminder.reminder_content.to_string());
87+
88+
let mut mentions = Vec::<UserId>::new();
89+
mentions.push(UserId::new(reminder.user_id as u64));
90+
91+
if !reminder.reminder_content.is_empty() {
92+
let _ = MessageBuilder::system_message(&ctx, &config)
93+
.translated_content("reminder.show_with_content", Some(&params), None, None)
94+
.await
95+
.to_channel(ChannelId::new(reminder.channel_id as u64))
96+
.color(hex_string_to_int(&config.reminders.embed_color) as u32)
97+
.mention(mentions)
98+
.send()
99+
.await;
100+
} else {
101+
let _ = MessageBuilder::system_message(&ctx, &config)
102+
.translated_content("reminder.show_without_content", Some(&params), None, None)
103+
.await
104+
.to_channel(ChannelId::new(reminder.channel_id as u64))
105+
.color(hex_string_to_int(&config.reminders.embed_color) as u32)
106+
.mention(mentions)
107+
.send()
108+
.await;
109+
}
110+
111+
if let Err(e) = update_reminder_status(&reminder, true, &pool).await {
112+
eprintln!("Failed to update reminder status: {}", e);
113+
}
114+
});
87115
}

src/commands/add_reminder/text_command/add_reminder.rs

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
use crate::commands::add_reminder::common::{send_register_confirmation, send_reminder_content};
1+
use crate::commands::add_reminder::common::{send_register_confirmation, spawn_reminder};
22
use crate::config::Config;
3-
use crate::db::reminders::{insert_reminder, update_reminder_status, Reminder};
3+
use crate::db::reminders::{insert_reminder, Reminder};
44
use crate::db::threads::get_thread_by_user_id;
5-
use crate::errors::{common, CommandError, ModmailError, ModmailResult, ThreadError};
5+
use crate::errors::{
6+
common, CommandError, DatabaseError, ModmailError, ModmailResult, ThreadError,
7+
};
68
use crate::utils::command::extract_reply_content::extract_reply_content;
79
use chrono::{Local, NaiveTime};
810
use regex::Regex;
911
use serenity::all::{Context, Message};
10-
use std::time::Duration;
11-
use tokio::time::sleep;
1212

1313
pub async fn add_reminder(ctx: &Context, msg: &Message, config: &Config) -> ModmailResult<()> {
1414
let pool = config
@@ -76,36 +76,29 @@ pub async fn add_reminder(ctx: &Context, msg: &Message, config: &Config) -> Modm
7676
completed: false,
7777
};
7878

79-
if let Err(e) = insert_reminder(&reminder, pool).await {
80-
eprintln!("Failed to insert reminder: {}", e);
81-
}
79+
let reminder_id = match insert_reminder(&reminder, pool).await {
80+
Ok(id) => id,
81+
Err(e) => {
82+
eprintln!("Failed to insert reminder: {}", e);
83+
return Err(ModmailError::Database(DatabaseError::InsertFailed(
84+
e.to_string(),
85+
)));
86+
}
87+
};
8288

83-
send_register_confirmation(reminder_content, ctx, msg, config, trigger_timestamp).await;
89+
send_register_confirmation(
90+
reminder_id,
91+
reminder_content,
92+
ctx,
93+
msg,
94+
config,
95+
trigger_timestamp,
96+
)
97+
.await;
8498

8599
let _ = msg.delete(&ctx.http).await;
86100

87-
let ctx = ctx.clone();
88-
let config = config.clone();
89-
let msg = msg.clone();
90-
let reminder_content = reminder_content.to_string();
91-
let pool = pool.clone();
92-
let reminder = reminder.clone();
93-
94-
tokio::spawn(async move {
95-
let now = Local::now().timestamp();
96-
let delay_duration = if trigger_timestamp > now {
97-
trigger_timestamp - now
98-
} else {
99-
0
100-
};
101-
sleep(Duration::from_secs(delay_duration as u64)).await;
102-
103-
send_reminder_content(&reminder_content, &ctx, &msg, &config, trigger_timestamp).await;
104-
105-
if let Err(e) = update_reminder_status(&reminder, true, &pool).await {
106-
eprintln!("Failed to update reminder status: {}", e);
107-
}
108-
});
101+
spawn_reminder(&reminder, &ctx, &config, &pool);
109102

110103
Ok(())
111104
}

src/db/operations/reminders.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ pub struct Reminder {
1313
pub async fn insert_reminder(
1414
reminder: &Reminder,
1515
pool: &sqlx::SqlitePool,
16-
) -> Result<(), sqlx::Error> {
16+
) -> Result<i64, sqlx::Error> {
1717
let user_id = reminder.user_id;
1818
let channel_id = &reminder.channel_id;
1919
let guild_id = &reminder.guild_id;
2020

21-
sqlx::query!(
21+
let result = sqlx::query!(
2222
r#"
2323
INSERT INTO reminders (thread_id, user_id, channel_id, guild_id, reminder_content, trigger_time, created_at, completed)
2424
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
@@ -34,7 +34,8 @@ pub async fn insert_reminder(
3434
)
3535
.execute(pool)
3636
.await?;
37-
Ok(())
37+
38+
Ok(result.last_insert_rowid())
3839
}
3940

4041
pub async fn update_reminder_status(

src/i18n/language/en.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -725,10 +725,10 @@ pub fn load_english_messages(dict: &mut ErrorDictionary) {
725725
);
726726
dict.messages.insert(
727727
"reminder.show_with_content".to_string(),
728-
DictionaryMessage::new("⏰ Reminder: \n\n{content} !"),
728+
DictionaryMessage::new("⏰ Reminder <@{user}>: \n\n{content} !"),
729729
);
730730
dict.messages.insert(
731731
"reminder.show_without_content".to_string(),
732-
DictionaryMessage::new("⏰ Reminder!"),
732+
DictionaryMessage::new("⏰ Reminder <@{user}>!"),
733733
);
734734
}

src/i18n/language/fr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -742,10 +742,10 @@ pub fn load_french_messages(dict: &mut ErrorDictionary) {
742742
);
743743
dict.messages.insert(
744744
"reminder.show_with_content".to_string(),
745-
DictionaryMessage::new("⏰ Rappel : \n\n{content} !"),
745+
DictionaryMessage::new("⏰ Rappel <@{user}> : \n\n{content} !"),
746746
);
747747
dict.messages.insert(
748748
"reminder.show_without_content".to_string(),
749-
DictionaryMessage::new("⏰ Rappel !"),
749+
DictionaryMessage::new("⏰ Rappel <@{user}> !"),
750750
);
751751
}

src/modules/reminders.rs

Lines changed: 4 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1+
use crate::commands::add_reminder::common::spawn_reminder;
12
use crate::config::Config;
2-
use crate::db::reminders::{get_all_pending_reminders, update_reminder_status};
3-
use crate::utils::conversion::hex_string_to_int::hex_string_to_int;
4-
use crate::utils::message::message_builder::MessageBuilder;
5-
use chrono::Local;
6-
use serenity::all::{ChannelId, Context};
7-
use std::collections::HashMap;
8-
use std::time::Duration;
9-
use tokio::time::sleep;
3+
use crate::db::reminders::get_all_pending_reminders;
4+
use serenity::all::Context;
105

116
pub async fn load_reminders(ctx: &Context, config: &Config, pool: &sqlx::SqlitePool) {
127
let reminders = get_all_pending_reminders(pool).await.unwrap_or_else(|e| {
@@ -15,47 +10,7 @@ pub async fn load_reminders(ctx: &Context, config: &Config, pool: &sqlx::SqliteP
1510
});
1611

1712
for reminder in reminders {
18-
let pool = pool.clone();
19-
let config = config.clone();
20-
let ctx = ctx.clone();
21-
22-
tokio::spawn(async move {
23-
let now = Local::now().timestamp();
24-
let delay_duration = if reminder.trigger_time > now {
25-
reminder.trigger_time - now
26-
} else {
27-
0
28-
};
29-
30-
sleep(Duration::from_secs(delay_duration as u64)).await;
31-
32-
let channel_id = ChannelId::new(reminder.channel_id as u64);
33-
34-
let mut params = HashMap::new();
35-
params.insert("content".to_string(), reminder.reminder_content.clone());
36-
37-
if !reminder.reminder_content.is_empty() {
38-
let _ = MessageBuilder::system_message(&ctx, &config)
39-
.translated_content("reminder.show_with_content", Some(&params), None, None)
40-
.await
41-
.to_channel(channel_id)
42-
.color(hex_string_to_int(&config.reminders.embed_color) as u32)
43-
.send()
44-
.await;
45-
} else {
46-
let _ = MessageBuilder::system_message(&ctx, &config)
47-
.translated_content("reminder.show_without_content", None, None, None)
48-
.await
49-
.to_channel(channel_id)
50-
.color(hex_string_to_int(&config.reminders.embed_color) as u32)
51-
.send()
52-
.await;
53-
}
54-
55-
if let Err(e) = update_reminder_status(&reminder, true, &pool).await {
56-
eprintln!("Failed to update reminder status: {}", e);
57-
}
58-
});
13+
spawn_reminder(&reminder, &ctx, &config, &pool);
5914
}
6015
println!("All pending reminders have been scheduled.");
6116
}

src/utils/message/message_builder.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub struct MessageBuilder<'a> {
5151
bot_user_id: UserId,
5252
components: Option<Vec<CreateActionRow>>,
5353
ephemeral: bool,
54+
mention: Vec<UserId>,
5455
}
5556

5657
impl<'a> MessageBuilder<'a> {
@@ -69,6 +70,7 @@ impl<'a> MessageBuilder<'a> {
6970
bot_user_id,
7071
components: None,
7172
ephemeral: false,
73+
mention: Vec::<UserId>::new(),
7274
}
7375
}
7476

@@ -124,6 +126,11 @@ impl<'a> MessageBuilder<'a> {
124126
self
125127
}
126128

129+
pub fn mention(mut self, mention: Vec<UserId>) -> Self {
130+
self.mention.extend(mention);
131+
self
132+
}
133+
127134
pub fn ephemeral(mut self, ephemeral: bool) -> Self {
128135
if ephemeral {
129136
self.ephemeral = ephemeral;
@@ -434,6 +441,13 @@ impl<'a> MessageBuilder<'a> {
434441

435442
if self.should_use_embed().await {
436443
message = message.embed(self.build_embed().await);
444+
445+
if !self.mention.is_empty() {
446+
let mentions: Vec<String> =
447+
self.mention.iter().map(|id| format!("<@{}>", id)).collect();
448+
let mention_str = mentions.join(" ");
449+
message = message.content(mention_str);
450+
}
437451
} else {
438452
let content = self.build_plain_message();
439453
if !content.is_empty() {

src/utils/thread/send_to_thread.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::db::operations::{
44
};
55
use crate::i18n::get_translated_message;
66
use crate::utils::message::message_builder::MessageBuilder;
7-
use serenity::all::{ChannelId, Context, CreateAttachment, GuildId, Message};
7+
use serenity::all::{ChannelId, Context, CreateAttachment, GuildId, Message, UserId};
88
use std::collections::HashMap;
99

1010
fn extract_message_content_with_media(msg: &Message) -> (String, Vec<String>) {
@@ -146,8 +146,10 @@ pub async fn send_to_thread(
146146
&& !alerts.is_empty()
147147
{
148148
let mut ping_mentions = String::new();
149+
let mut mentions = Vec::<UserId>::new();
149150
for staff_id in &alerts {
150151
ping_mentions.push_str(&format!("<@{}> ", staff_id));
152+
mentions.push(UserId::new(*staff_id as u64));
151153
}
152154

153155
let mut params = HashMap::new();
@@ -166,6 +168,7 @@ pub async fn send_to_thread(
166168

167169
let _ = MessageBuilder::system_message(ctx, config)
168170
.content(full_content)
171+
.mention(mentions)
169172
.to_channel(channel_id)
170173
.send()
171174
.await;

0 commit comments

Comments
 (0)