Skip to content

Commit 3ad8ed4

Browse files
authored
Merge pull request #171 from Rustmail/169-add-reminder-command
feat(commands): add add_reminder command
2 parents 56e3c68 + eff396d commit 3ad8ed4

28 files changed

Lines changed: 839 additions & 9 deletions

.sqlx/query-1f2332afc3824ca0790ef097ff1d48074feaa48de9844e0e30d7e6fe96ad5e44.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-8d256f5308e9c3af3f409d5097302f9794287b06f89da6c7f4a86efcd37b151a.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-b9420d5d850bf8fc05beb8594611533139e47e3df927153e8cb15fe7451fdc4b.json

Lines changed: 62 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.lock

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ toml = "0.9.7"
1313
reqwest = "0.12.23"
1414
async-trait = "0.1.89"
1515
chrono = { version = "0.4.42", features = ["serde"] }
16+
regex = "1.11.3"
1617

1718
[dependencies.uuid]
1819
version = "1.18.1"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- Create reminders table
2+
3+
CREATE TABLE IF NOT EXISTS reminders (
4+
id INTEGER PRIMARY KEY AUTOINCREMENT,
5+
thread_id TEXT NOT NULL,
6+
user_id BIGINT NOT NULL,
7+
channel_id BIGINT NOT NULL,
8+
guild_id BIGINT NOT NULL,
9+
reminder_content TEXT NOT NULL,
10+
trigger_time INTEGER NOT NULL,
11+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
12+
completed BOOLEAN NOT NULL DEFAULT 0,
13+
FOREIGN KEY (thread_id) REFERENCES threads(id) ON DELETE CASCADE ON UPDATE CASCADE
14+
);
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
use crate::config::Config;
2+
use crate::db::reminders::{update_reminder_status, Reminder};
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, CommandInteraction, Context, Message, UserId};
7+
use sqlx::SqlitePool;
8+
use std::collections::HashMap;
9+
use std::time::Duration;
10+
use tokio::time::sleep;
11+
12+
pub async fn send_register_confirmation_from_message(
13+
reminder_id: i64,
14+
reminder_content: &str,
15+
ctx: &Context,
16+
msg: &Message,
17+
config: &Config,
18+
trigger_timestamp: i64,
19+
) {
20+
let mut params = HashMap::new();
21+
params.insert("time".to_string(), format!("<t:{}:F>", trigger_timestamp));
22+
params.insert(
23+
"remaining_time".to_string(),
24+
format!("<t:{}:R>", trigger_timestamp),
25+
);
26+
27+
if !reminder_content.is_empty() {
28+
params.insert("content".to_string(), reminder_content.to_string());
29+
}
30+
31+
if !reminder_content.is_empty() {
32+
let _ = MessageBuilder::system_message(&ctx, &config)
33+
.translated_content(
34+
"reminder.registered_with_content",
35+
Some(&params),
36+
None,
37+
None,
38+
)
39+
.await
40+
.to_channel(msg.channel_id)
41+
.footer(format!("{}: {}", "ID", reminder_id))
42+
.send()
43+
.await;
44+
} else {
45+
let _ = MessageBuilder::system_message(&ctx, &config)
46+
.translated_content(
47+
"reminder.registered_without_content",
48+
Some(&params),
49+
None,
50+
None,
51+
)
52+
.await
53+
.to_channel(msg.channel_id)
54+
.footer(format!("{}: {}", "ID", reminder_id))
55+
.send()
56+
.await;
57+
}
58+
}
59+
60+
pub async fn send_register_confirmation_from_command(
61+
reminder_id: i64,
62+
reminder_content: &str,
63+
ctx: &Context,
64+
command: &CommandInteraction,
65+
config: &Config,
66+
trigger_timestamp: i64,
67+
) {
68+
let mut params = HashMap::new();
69+
params.insert("time".to_string(), format!("<t:{}:F>", trigger_timestamp));
70+
params.insert(
71+
"remaining_time".to_string(),
72+
format!("<t:{}:R>", trigger_timestamp),
73+
);
74+
75+
if !reminder_content.is_empty() {
76+
params.insert("content".to_string(), reminder_content.to_string());
77+
}
78+
79+
if !reminder_content.is_empty() {
80+
let response = MessageBuilder::system_message(&ctx, &config)
81+
.translated_content(
82+
"reminder.registered_with_content",
83+
Some(&params),
84+
None,
85+
None,
86+
)
87+
.await
88+
.to_channel(command.channel_id)
89+
.footer(format!("{}: {}", "ID", reminder_id))
90+
.build_interaction_message_followup()
91+
.await;
92+
93+
let _ = command.create_followup(&ctx.http, response).await;
94+
} else {
95+
let response = MessageBuilder::system_message(&ctx, &config)
96+
.translated_content(
97+
"reminder.registered_without_content",
98+
Some(&params),
99+
None,
100+
None,
101+
)
102+
.await
103+
.to_channel(command.channel_id)
104+
.footer(format!("{}: {}", "ID", reminder_id))
105+
.build_interaction_message_followup()
106+
.await;
107+
108+
let _ = command.create_followup(&ctx.http, response).await;
109+
}
110+
}
111+
112+
pub fn spawn_reminder(reminder: &Reminder, ctx: &Context, config: &Config, pool: &SqlitePool) {
113+
let pool = pool.clone();
114+
let config = config.clone();
115+
let ctx = ctx.clone();
116+
let reminder = reminder.clone();
117+
118+
tokio::spawn(async move {
119+
let now = Local::now().timestamp();
120+
let delay_duration = if reminder.trigger_time > now {
121+
reminder.trigger_time - now
122+
} else {
123+
0
124+
};
125+
sleep(Duration::from_secs(delay_duration as u64)).await;
126+
127+
let mut params = HashMap::new();
128+
params.insert(
129+
"time".to_string(),
130+
format!("<t:{}:F>", reminder.trigger_time),
131+
);
132+
params.insert(
133+
"remaining_time".to_string(),
134+
format!("<t:{}:R>", reminder.trigger_time),
135+
);
136+
137+
params.insert("user".to_string(), reminder.user_id.to_string());
138+
params.insert("content".to_string(), reminder.reminder_content.to_string());
139+
140+
let mut mentions = Vec::<UserId>::new();
141+
mentions.push(UserId::new(reminder.user_id as u64));
142+
143+
if !reminder.reminder_content.is_empty() {
144+
let _ = MessageBuilder::system_message(&ctx, &config)
145+
.translated_content("reminder.show_with_content", Some(&params), None, None)
146+
.await
147+
.to_channel(ChannelId::new(reminder.channel_id as u64))
148+
.color(hex_string_to_int(&config.reminders.embed_color) as u32)
149+
.mention(mentions)
150+
.send()
151+
.await;
152+
} else {
153+
let _ = MessageBuilder::system_message(&ctx, &config)
154+
.translated_content("reminder.show_without_content", Some(&params), None, None)
155+
.await
156+
.to_channel(ChannelId::new(reminder.channel_id as u64))
157+
.color(hex_string_to_int(&config.reminders.embed_color) as u32)
158+
.mention(mentions)
159+
.send()
160+
.await;
161+
}
162+
163+
if let Err(e) = update_reminder_status(&reminder, true, &pool).await {
164+
eprintln!("Failed to update reminder status: {}", e);
165+
}
166+
});
167+
}

src/commands/add_reminder/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod common;
2+
pub mod slash_command;
3+
pub mod text_command;

0 commit comments

Comments
 (0)