Change reminder sending behaviour to keep reminders but flag them as sent

This commit is contained in:
jude 2023-07-31 18:39:27 +01:00
parent db1a53a797
commit 902b7e1b4a
7 changed files with 67 additions and 22 deletions

View File

@ -5,7 +5,7 @@ export $(grep -v '^#' /etc/reminder-rs/config.env | xargs -d '\n')
REGEX='mysql://([A-Za-z]+)@(.+)/(.+)' REGEX='mysql://([A-Za-z]+)@(.+)/(.+)'
[[ $DATABASE_URL =~ $REGEX ]] [[ $DATABASE_URL =~ $REGEX ]]
VAR=$(mysql -u "${BASH_REMATCH[1]}" -h "${BASH_REMATCH[2]}" -N -D "${BASH_REMATCH[3]}" -e "SELECT COUNT(1) FROM reminders WHERE utc_time < NOW() - INTERVAL 10 MINUTE AND enabled = 1") VAR=$(mysql -u "${BASH_REMATCH[1]}" -h "${BASH_REMATCH[2]}" -N -D "${BASH_REMATCH[3]}" -e "SELECT COUNT(1) FROM reminders WHERE utc_time < NOW() - INTERVAL 10 MINUTE AND enabled = 1 AND status = 'pending'")
if [ "$VAR" -gt 0 ] if [ "$VAR" -gt 0 ]
then then

View File

@ -0,0 +1,2 @@
ALTER TABLE reminders ADD COLUMN `status` ENUM ('pending', 'sent', 'failed', 'deleted') NOT NULL DEFAULT 'pending';
ALTER TABLE reminders ADD COLUMN `status_message` TEXT;

View File

@ -302,6 +302,7 @@ INNER JOIN
ON ON
reminders.channel_id = channels.id reminders.channel_id = channels.id
WHERE WHERE
reminders.`status` = 'pending' AND
reminders.`id` IN ( reminders.`id` IN (
SELECT SELECT
MIN(id) MIN(id)
@ -358,7 +359,7 @@ WHERE
&& self.interval_days == Some(0) && self.interval_days == Some(0)
&& self.interval_months == Some(0) && self.interval_months == Some(0)
{ {
self.force_delete(pool).await; self.set_sent(pool).await;
} }
let now = Utc::now(); let now = Utc::now();
@ -408,9 +409,9 @@ WHERE
None::<&'static str>, None::<&'static str>,
) )
.await; .await;
self.force_delete(pool).await; self.set_failed(pool, "Failed to update 4 times and so is being deleted").await;
} else if self.expires.map_or(false, |expires| updated_reminder_time > expires) { } else if self.expires.map_or(false, |expires| updated_reminder_time > expires) {
self.force_delete(pool).await; self.set_sent(pool).await;
} else { } else {
sqlx::query!( sqlx::query!(
"UPDATE reminders SET `utc_time` = ? WHERE `id` = ?", "UPDATE reminders SET `utc_time` = ? WHERE `id` = ?",
@ -422,7 +423,7 @@ WHERE
.expect(&format!("Could not update time on Reminder {}", self.id)); .expect(&format!("Could not update time on Reminder {}", self.id));
} }
} else { } else {
self.force_delete(pool).await; self.set_sent(pool).await;
} }
} }
@ -468,13 +469,28 @@ WHERE
} }
} }
async fn force_delete(&self, pool: impl Executor<'_, Database = Database> + Copy) { async fn set_sent(&self, pool: impl Executor<'_, Database = Database> + Copy) {
sqlx::query!("DELETE FROM reminders WHERE `id` = ?", self.id) sqlx::query!("UPDATE reminders SET `status` = 'sent' WHERE `id` = ?", self.id)
.execute(pool) .execute(pool)
.await .await
.expect(&format!("Could not delete Reminder {}", self.id)); .expect(&format!("Could not delete Reminder {}", self.id));
} }
async fn set_failed(
&self,
pool: impl Executor<'_, Database = Database> + Copy,
message: &'static str,
) {
sqlx::query!(
"UPDATE reminders SET `status` = 'failed', `status_message` = ? WHERE `id` = ?",
message,
self.id
)
.execute(pool)
.await
.expect(&format!("Could not delete Reminder {}", self.id));
}
async fn pin_message<M: Into<u64>>(&self, message_id: M, http: impl AsRef<Http>) { async fn pin_message<M: Into<u64>>(&self, message_id: M, http: impl AsRef<Http>) {
let _ = http.as_ref().pin_message(self.channel_id, message_id.into(), None).await; let _ = http.as_ref().pin_message(self.channel_id, message_id.into(), None).await;
} }
@ -649,7 +665,11 @@ WHERE
None::<&'static str>, None::<&'static str>,
) )
.await; .await;
self.force_delete(pool).await; self.set_failed(
pool,
"Could not be sent as channel does not exist",
)
.await;
} }
10004 => { 10004 => {
self.log_error( self.log_error(
@ -658,7 +678,8 @@ WHERE
None::<&'static str>, None::<&'static str>,
) )
.await; .await;
self.force_delete(pool).await; self.set_failed(pool, "Could not be sent as guild does not exist")
.await;
} }
50001 => { 50001 => {
self.log_error( self.log_error(
@ -667,7 +688,11 @@ WHERE
None::<&'static str>, None::<&'static str>,
) )
.await; .await;
self.force_delete(pool).await; self.set_failed(
pool,
"Could not be sent as permissions are invalid",
)
.await;
} }
50007 => { 50007 => {
self.log_error( self.log_error(
@ -676,7 +701,8 @@ WHERE
None::<&'static str>, None::<&'static str>,
) )
.await; .await;
self.force_delete(pool).await; self.set_failed(pool, "Could not be sent as user has DMs disabled")
.await;
} }
_ => { _ => {
self.log_error( self.log_error(

View File

@ -168,10 +168,13 @@ impl ComponentDataModel {
ComponentDataModel::DelSelector(selector) => { ComponentDataModel::DelSelector(selector) => {
let selected_id = component.data.values.join(","); let selected_id = component.data.values.join(",");
sqlx::query!("DELETE FROM reminders WHERE FIND_IN_SET(id, ?)", selected_id) sqlx::query!(
.execute(&data.database) "UPDATE reminders SET `status` = 'pending' WHERE FIND_IN_SET(id, ?)",
.await selected_id
.unwrap(); )
.execute(&data.database)
.await
.unwrap();
let reminders = Reminder::from_guild( let reminders = Reminder::from_guild(
&ctx, &ctx,

View File

@ -159,6 +159,7 @@ LEFT JOIN
ON ON
reminders.set_by = users.id reminders.set_by = users.id
WHERE WHERE
`status` = 'pending' AND
channels.channel = ? AND channels.channel = ? AND
FIND_IN_SET(reminders.enabled, ?) FIND_IN_SET(reminders.enabled, ?)
ORDER BY ORDER BY
@ -217,6 +218,7 @@ LEFT JOIN
ON ON
reminders.set_by = users.id reminders.set_by = users.id
WHERE WHERE
`status` = 'pending' AND
FIND_IN_SET(channels.channel, ?) FIND_IN_SET(channels.channel, ?)
", ",
channels channels
@ -251,6 +253,7 @@ LEFT JOIN
ON ON
reminders.set_by = users.id reminders.set_by = users.id
WHERE WHERE
`status` = 'pending' AND
channels.guild_id = (SELECT id FROM guilds WHERE guild = ?) channels.guild_id = (SELECT id FROM guilds WHERE guild = ?)
", ",
guild_id.as_u64() guild_id.as_u64()
@ -286,6 +289,7 @@ LEFT JOIN
ON ON
reminders.set_by = users.id reminders.set_by = users.id
WHERE WHERE
`status` = 'pending' AND
channels.id = (SELECT dm_channel FROM users WHERE user = ?) channels.id = (SELECT dm_channel FROM users WHERE user = ?)
", ",
user.as_u64() user.as_u64()
@ -300,7 +304,10 @@ WHERE
&self, &self,
db: impl Executor<'_, Database = Database>, db: impl Executor<'_, Database = Database>,
) -> Result<(), sqlx::Error> { ) -> Result<(), sqlx::Error> {
sqlx::query!("DELETE FROM reminders WHERE uid = ?", self.uid).execute(db).await.map(|_| ()) sqlx::query!("UPDATE reminders SET `status` = 'deleted' WHERE uid = ?", self.uid)
.execute(db)
.await
.map(|_| ())
} }
pub fn display_content(&self) -> &str { pub fn display_content(&self) -> &str {

View File

@ -45,7 +45,7 @@ pub async fn bot_data(cookies: &CookieJar<'_>, pool: &State<Pool<MySql>>) -> Jso
} }
let backlog = sqlx::query!( let backlog = sqlx::query!(
"SELECT COUNT(1) AS backlog FROM reminders WHERE `utc_time` < NOW() AND enabled = 1" "SELECT COUNT(1) AS backlog FROM reminders WHERE `utc_time` < NOW() AND enabled = 1 AND `status` = 'pending'"
) )
.fetch_one(pool.inner()) .fetch_one(pool.inner())
.await .await
@ -61,6 +61,7 @@ pub async fn bot_data(cookies: &CookieJar<'_>, pool: &State<Pool<MySql>>) -> Jso
`utc_time` < DATE_ADD(NOW(), INTERVAL 1 DAY) AND `utc_time` < DATE_ADD(NOW(), INTERVAL 1 DAY) AND
`utc_time` >= NOW() AND `utc_time` >= NOW() AND
`enabled` = 1 AND `enabled` = 1 AND
`status` = 'pending' AND
`interval_seconds` IS NULL AND `interval_seconds` IS NULL AND
`interval_months` IS NULL AND `interval_months` IS NULL AND
`interval_days` IS NULL `interval_days` IS NULL
@ -80,6 +81,7 @@ pub async fn bot_data(cookies: &CookieJar<'_>, pool: &State<Pool<MySql>>) -> Jso
WHERE WHERE
`utc_time` < DATE_ADD(NOW(), INTERVAL 1 DAY) AND `utc_time` < DATE_ADD(NOW(), INTERVAL 1 DAY) AND
`utc_time` >= NOW() AND `utc_time` >= NOW() AND
`status` = 'pending' AND
`enabled` = 1 AND ( `enabled` = 1 AND (
`interval_seconds` IS NOT NULL OR `interval_seconds` IS NOT NULL OR
`interval_months` IS NOT NULL OR `interval_months` IS NOT NULL OR
@ -102,6 +104,7 @@ pub async fn bot_data(cookies: &CookieJar<'_>, pool: &State<Pool<MySql>>) -> Jso
`utc_time` < DATE_ADD(NOW(), INTERVAL 31 DAY) AND `utc_time` < DATE_ADD(NOW(), INTERVAL 31 DAY) AND
`utc_time` >= NOW() AND `utc_time` >= NOW() AND
`enabled` = 1 AND `enabled` = 1 AND
`status` = 'pending' AND
`interval_seconds` IS NULL AND `interval_seconds` IS NULL AND
`interval_months` IS NULL AND `interval_months` IS NULL AND
`interval_days` IS NULL `interval_days` IS NULL
@ -121,6 +124,7 @@ pub async fn bot_data(cookies: &CookieJar<'_>, pool: &State<Pool<MySql>>) -> Jso
WHERE WHERE
`utc_time` < DATE_ADD(NOW(), INTERVAL 31 DAY) AND `utc_time` < DATE_ADD(NOW(), INTERVAL 31 DAY) AND
`utc_time` >= NOW() AND `utc_time` >= NOW() AND
`status` = 'pending' AND
`enabled` = 1 AND ( `enabled` = 1 AND (
`interval_seconds` IS NOT NULL OR `interval_seconds` IS NOT NULL OR
`interval_months` IS NOT NULL OR `interval_months` IS NOT NULL OR
@ -169,9 +173,11 @@ pub async fn bot_data(cookies: &CookieJar<'_>, pool: &State<Pool<MySql>>) -> Jso
"SELECT COUNT(1) AS count "SELECT COUNT(1) AS count
FROM reminders FROM reminders
WHERE WHERE
`interval_seconds` IS NOT NULL OR `status` = 'pending' AND (
`interval_months` IS NOT NULL OR `interval_seconds` IS NOT NULL OR
`interval_days` IS NOT NULL" `interval_months` IS NOT NULL OR
`interval_days` IS NOT NULL
)"
) )
.fetch_one(pool.inner()) .fetch_one(pool.inner())
.await .await
@ -181,6 +187,7 @@ pub async fn bot_data(cookies: &CookieJar<'_>, pool: &State<Pool<MySql>>) -> Jso
"SELECT COUNT(1) AS count "SELECT COUNT(1) AS count
FROM reminders FROM reminders
WHERE WHERE
`status` = 'pending' AND
`interval_seconds` IS NULL AND `interval_seconds` IS NULL AND
`interval_months` IS NULL AND `interval_months` IS NULL AND
`interval_days` IS NULL" `interval_days` IS NULL"

View File

@ -362,7 +362,7 @@ pub async fn get_reminders(
reminders.utc_time reminders.utc_time
FROM reminders FROM reminders
LEFT JOIN channels ON channels.id = reminders.channel_id LEFT JOIN channels ON channels.id = reminders.channel_id
WHERE FIND_IN_SET(channels.channel, ?)", WHERE `status` = 'pending' AND FIND_IN_SET(channels.channel, ?)",
channels channels
) )
.fetch_all(pool.inner()) .fetch_all(pool.inner())
@ -602,7 +602,7 @@ pub async fn delete_reminder(
reminder: Json<DeleteReminder>, reminder: Json<DeleteReminder>,
pool: &State<Pool<MySql>>, pool: &State<Pool<MySql>>,
) -> JsonResult { ) -> JsonResult {
match sqlx::query!("DELETE FROM reminders WHERE uid = ?", reminder.uid) match sqlx::query!("UPDATE reminders SET `status` = 'deleted' WHERE uid = ?", reminder.uid)
.execute(pool.inner()) .execute(pool.inner())
.await .await
{ {