From 6f0bdf985266e2656541008291b5733a050a63c1 Mon Sep 17 00:00:00 2001 From: jude Date: Sun, 3 Mar 2024 13:04:50 +0000 Subject: [PATCH] Support sending reminders to threads --- migrations/20240303125837_add_indexes.sql | 5 + postman/src/sender.rs | 119 ++++++++++++---------- src/models/reminder/mod.rs | 25 +++-- 3 files changed, 91 insertions(+), 58 deletions(-) create mode 100644 migrations/20240303125837_add_indexes.sql diff --git a/migrations/20240303125837_add_indexes.sql b/migrations/20240303125837_add_indexes.sql new file mode 100644 index 0000000..7aeea9e --- /dev/null +++ b/migrations/20240303125837_add_indexes.sql @@ -0,0 +1,5 @@ +-- Add migration script here +ALTER TABLE reminders + ADD INDEX `utc_time_index` (`utc_time`); +ALTER TABLE reminders + ADD INDEX `status_index` (`status`); diff --git a/postman/src/sender.rs b/postman/src/sender.rs index 2cdad51..6eecba7 100644 --- a/postman/src/sender.rs +++ b/postman/src/sender.rs @@ -232,6 +232,7 @@ pub struct Reminder { id: u32, channel_id: u64, + thread_id: Option, webhook_id: Option, webhook_token: Option, @@ -262,58 +263,59 @@ impl Reminder { match sqlx::query_as_unchecked!( Reminder, r#" -SELECT - reminders.`id` AS id, + SELECT + reminders.`id` AS id, - channels.`channel` AS channel_id, - channels.`webhook_id` AS webhook_id, - channels.`webhook_token` AS webhook_token, + channels.`channel` AS channel_id, + reminders.`thread_id` AS thread_id, + channels.`webhook_id` AS webhook_id, + channels.`webhook_token` AS webhook_token, - channels.`paused` AS 'channel_paused', - channels.`paused_until` AS 'channel_paused_until', - reminders.`enabled` AS 'enabled', + channels.`paused` AS 'channel_paused', + channels.`paused_until` AS 'channel_paused_until', + reminders.`enabled` AS 'enabled', - reminders.`tts` AS tts, - reminders.`pin` AS pin, - reminders.`content` AS content, - reminders.`attachment` AS attachment, - reminders.`attachment_name` AS attachment_name, + reminders.`tts` AS tts, + reminders.`pin` AS pin, + reminders.`content` AS content, + reminders.`attachment` AS attachment, + reminders.`attachment_name` AS attachment_name, - reminders.`utc_time` AS 'utc_time', - reminders.`timezone` AS timezone, - reminders.`restartable` AS restartable, - reminders.`expires` AS 'expires', - reminders.`interval_seconds` AS 'interval_seconds', - reminders.`interval_days` AS 'interval_days', - reminders.`interval_months` AS 'interval_months', + reminders.`utc_time` AS 'utc_time', + reminders.`timezone` AS timezone, + reminders.`restartable` AS restartable, + reminders.`expires` AS 'expires', + reminders.`interval_seconds` AS 'interval_seconds', + reminders.`interval_days` AS 'interval_days', + reminders.`interval_months` AS 'interval_months', - reminders.`avatar` AS avatar, - reminders.`username` AS username -FROM - reminders -INNER JOIN - channels -ON - reminders.channel_id = channels.id -WHERE - reminders.`status` = 'pending' AND - reminders.`id` IN ( - SELECT - MIN(id) - FROM - reminders - WHERE - reminders.`utc_time` <= NOW() AND - `status` = 'pending' AND - ( - reminders.`interval_seconds` IS NOT NULL - OR reminders.`interval_months` IS NOT NULL - OR reminders.`interval_days` IS NOT NULL - OR reminders.enabled - ) - GROUP BY channel_id - ) - "#, + reminders.`avatar` AS avatar, + reminders.`username` AS username + FROM + reminders + INNER JOIN + channels + ON + reminders.channel_id = channels.id + WHERE + reminders.`status` = 'pending' AND + reminders.`id` IN ( + SELECT + MIN(id) + FROM + reminders + WHERE + reminders.`utc_time` <= NOW() AND + `status` = 'pending' AND + ( + reminders.`interval_seconds` IS NOT NULL + OR reminders.`interval_months` IS NOT NULL + OR reminders.`interval_days` IS NOT NULL + OR reminders.enabled + ) + GROUP BY channel_id + ) + "#, ) .fetch_all(pool) .await @@ -337,7 +339,9 @@ WHERE async fn reset_webhook(&self, pool: impl Executor<'_, Database = Database> + Copy) { let _ = sqlx::query!( - "UPDATE channels SET webhook_id = NULL, webhook_token = NULL WHERE channel = ?", + " + UPDATE channels SET webhook_id = NULL, webhook_token = NULL WHERE channel = ? + ", self.channel_id ) .execute(pool) @@ -473,7 +477,11 @@ WHERE reminder: &Reminder, embed: Option, ) -> Result<()> { - let channel = ChannelId::new(reminder.channel_id).to_channel(&cache_http).await; + let channel = if let Some(thread_id) = reminder.thread_id { + ChannelId::new(thread_id).to_channel(&cache_http).await + } else { + ChannelId::new(reminder.channel_id).to_channel(&cache_http).await + }; let mut message = CreateMessage::new().content(&reminder.content).tts(reminder.tts); @@ -524,7 +532,14 @@ WHERE webhook: Webhook, embed: Option, ) -> Result<()> { - let mut builder = ExecuteWebhook::new().content(&reminder.content).tts(reminder.tts); + let mut builder = if let Some(thread_id) = reminder.thread_id { + ExecuteWebhook::new() + .content(&reminder.content) + .tts(reminder.tts) + .in_thread(thread_id) + } else { + ExecuteWebhook::new().content(&reminder.content).tts(reminder.tts) + }; if let Some(username) = &reminder.username { if !username.is_empty() { @@ -571,7 +586,9 @@ WHERE .map_or(true, |inner| inner >= Utc::now().naive_local())) { let _ = sqlx::query!( - "UPDATE `channels` SET paused = 0, paused_until = NULL WHERE `channel` = ?", + " + UPDATE `channels` SET paused = 0, paused_until = NULL WHERE `channel` = ? + ", self.channel_id ) .execute(pool) diff --git a/src/models/reminder/mod.rs b/src/models/reminder/mod.rs index 294c91e..a5c9439 100644 --- a/src/models/reminder/mod.rs +++ b/src/models/reminder/mod.rs @@ -13,7 +13,7 @@ use chrono_tz::Tz; use poise::{ serenity_prelude::{ model::id::{ChannelId, GuildId, UserId}, - ButtonStyle, Cache, CreateActionRow, CreateButton, CreateEmbed, ReactionType, + ButtonStyle, Cache, ChannelType, CreateActionRow, CreateButton, CreateEmbed, ReactionType, }, CreateReply, }; @@ -482,12 +482,23 @@ pub async fn create_reminder( let list = channels.map(|arg| parse_mention_list(&arg)).unwrap_or_default(); if list.is_empty() { - if ctx.guild_id().is_some() { - let channel_with_threads = ChannelWithThread { - channel_id: ctx.channel_id().get(), - thread_id: None, - }; - vec![ReminderScope::Channel(channel_with_threads)] + if let Some(channel) = ctx.guild_channel().await { + if channel.kind == ChannelType::PublicThread + || channel.kind == ChannelType::PrivateThread + { + let parent = channel.parent_id.unwrap(); + let channel_with_threads = ChannelWithThread { + channel_id: parent.get(), + thread_id: Some(ctx.channel_id().get()), + }; + vec![ReminderScope::Channel(channel_with_threads)] + } else { + let channel_with_threads = ChannelWithThread { + channel_id: ctx.channel_id().get(), + thread_id: None, + }; + vec![ReminderScope::Channel(channel_with_threads)] + } } else { vec![ReminderScope::User(ctx.author().id.get())] }