jude/orphan-reminders #1
@ -472,10 +472,17 @@ WHERE
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn set_sent(&self, pool: impl Executor<'_, Database = Database> + Copy) {
|
async fn set_sent(&self, pool: impl Executor<'_, Database = Database> + Copy) {
|
||||||
sqlx::query!("UPDATE reminders SET `status` = 'sent' WHERE `id` = ?", self.id)
|
sqlx::query!(
|
||||||
.execute(pool)
|
"
|
||||||
.await
|
UPDATE reminders
|
||||||
.expect(&format!("Could not delete Reminder {}", self.id));
|
SET `status` = 'sent', `status_change_time` = NOW()
|
||||||
|
WHERE `id` = ?
|
||||||
|
",
|
||||||
|
self.id
|
||||||
|
)
|
||||||
|
.execute(pool)
|
||||||
|
.await
|
||||||
|
.expect(&format!("Could not delete Reminder {}", self.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_failed(
|
async fn set_failed(
|
||||||
|
@ -23,7 +23,11 @@ impl ChannelData {
|
|||||||
|
|
||||||
if let Ok(c) = sqlx::query_as_unchecked!(
|
if let Ok(c) = sqlx::query_as_unchecked!(
|
||||||
Self,
|
Self,
|
||||||
"SELECT id, name, nudge, blacklisted, webhook_id, webhook_token, paused, paused_until, guild_id AS db_guild_id FROM channels WHERE channel = ?",
|
"
|
||||||
|
SELECT id, name, nudge, blacklisted, webhook_id, webhook_token, paused, paused_until,
|
||||||
|
guild_id AS db_guild_id
|
||||||
|
FROM channels WHERE channel = ?
|
||||||
|
",
|
||||||
channel_id
|
channel_id
|
||||||
)
|
)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
@ -31,12 +35,18 @@ impl ChannelData {
|
|||||||
{
|
{
|
||||||
Ok(c)
|
Ok(c)
|
||||||
} else {
|
} else {
|
||||||
let props = channel.to_owned().guild().map(|g| (g.guild_id.as_u64().to_owned(), g.name));
|
let props =
|
||||||
|
channel.to_owned().guild().map(|g| (g.guild_id.as_u64().to_owned(), g.name));
|
||||||
|
|
||||||
let (guild_id, channel_name) = if let Some((a, b)) = props { (Some(a), Some(b)) } else { (None, None) };
|
let (guild_id, channel_name) =
|
||||||
|
if let Some((a, b)) = props { (Some(a), Some(b)) } else { (None, None) };
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"INSERT IGNORE INTO channels (channel, name, guild_id) VALUES (?, ?, (SELECT id FROM guilds WHERE guild = ?))",
|
"
|
||||||
|
INSERT IGNORE INTO channels
|
||||||
|
(channel, name, guild_id)
|
||||||
|
VALUES (?, ?, (SELECT id FROM guilds WHERE guild = ?))
|
||||||
|
",
|
||||||
channel_id,
|
channel_id,
|
||||||
channel_name,
|
channel_name,
|
||||||
guild_id
|
guild_id
|
||||||
@ -47,7 +57,10 @@ impl ChannelData {
|
|||||||
Ok(sqlx::query_as_unchecked!(
|
Ok(sqlx::query_as_unchecked!(
|
||||||
Self,
|
Self,
|
||||||
"
|
"
|
||||||
SELECT id, name, nudge, blacklisted, webhook_id, webhook_token, paused, paused_until, guild_id AS db_guild_id FROM channels WHERE channel = ?
|
SELECT id, name, nudge, blacklisted, webhook_id, webhook_token, paused,
|
||||||
|
paused_until, guild_id AS db_guild_id
|
||||||
|
FROM channels
|
||||||
|
WHERE channel = ?
|
||||||
",
|
",
|
||||||
channel_id
|
channel_id
|
||||||
)
|
)
|
||||||
@ -59,9 +72,10 @@ SELECT id, name, nudge, blacklisted, webhook_id, webhook_token, paused, paused_u
|
|||||||
pub async fn commit_changes(&self, pool: &MySqlPool) {
|
pub async fn commit_changes(&self, pool: &MySqlPool) {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
UPDATE channels SET name = ?, nudge = ?, blacklisted = ?, webhook_id = ?, webhook_token = ?, paused = ?, paused_until \
|
UPDATE channels
|
||||||
= ? WHERE id = ?
|
SET name = ?, nudge = ?, blacklisted = ?, webhook_id = ?, webhook_token = ?,
|
||||||
",
|
paused = ?, paused_until = ?
|
||||||
|
WHERE id = ?",
|
||||||
self.name,
|
self.name,
|
||||||
self.nudge,
|
self.nudge,
|
||||||
self.blacklisted,
|
self.blacklisted,
|
||||||
|
@ -145,7 +145,7 @@ pub async fn import_reminders(
|
|||||||
attachment: record.attachment,
|
attachment: record.attachment,
|
||||||
attachment_name: record.attachment_name,
|
attachment_name: record.attachment_name,
|
||||||
avatar: record.avatar,
|
avatar: record.avatar,
|
||||||
channel: channel_id,
|
channel: Some(channel_id),
|
||||||
content: record.content,
|
content: record.content,
|
||||||
embed_author: record.embed_author,
|
embed_author: record.embed_author,
|
||||||
embed_author_url: record.embed_author_url,
|
embed_author_url: record.embed_author_url,
|
||||||
|
@ -332,7 +332,8 @@ pub async fn get_reminders(
|
|||||||
|
|
||||||
sqlx::query_as_unchecked!(
|
sqlx::query_as_unchecked!(
|
||||||
Reminder,
|
Reminder,
|
||||||
"SELECT
|
"
|
||||||
|
SELECT
|
||||||
reminders.attachment,
|
reminders.attachment,
|
||||||
reminders.attachment_name,
|
reminders.attachment_name,
|
||||||
reminders.avatar,
|
reminders.avatar,
|
||||||
|
@ -124,8 +124,8 @@ pub struct Reminder {
|
|||||||
attachment: Option<Vec<u8>>,
|
attachment: Option<Vec<u8>>,
|
||||||
attachment_name: Option<String>,
|
attachment_name: Option<String>,
|
||||||
avatar: Option<String>,
|
avatar: Option<String>,
|
||||||
#[serde(with = "string")]
|
#[serde(with = "string_opt")]
|
||||||
channel: u64,
|
channel: Option<u64>,
|
||||||
content: String,
|
content: String,
|
||||||
embed_author: String,
|
embed_author: String,
|
||||||
embed_author_url: Option<String>,
|
embed_author_url: Option<String>,
|
||||||
@ -310,6 +310,34 @@ mod string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod string_opt {
|
||||||
|
use std::{fmt::Display, str::FromStr};
|
||||||
|
|
||||||
|
use serde::{de, Deserialize, Deserializer, Serializer};
|
||||||
|
|
||||||
|
pub fn serialize<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
Some(value) => serializer.collect_str(value),
|
||||||
|
None => serializer.serialize_none(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
|
||||||
|
where
|
||||||
|
T: FromStr,
|
||||||
|
T::Err: Display,
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
Option::deserialize(deserializer)?
|
||||||
|
.map(|d: String| d.parse().map_err(de::Error::custom))
|
||||||
|
.transpose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod base64s {
|
mod base64s {
|
||||||
use serde::{de, Deserialize, Deserializer, Serializer};
|
use serde::{de, Deserialize, Deserializer, Serializer};
|
||||||
|
|
||||||
@ -374,7 +402,7 @@ pub async fn create_reminder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validate channel
|
// validate channel
|
||||||
let channel = ChannelId(reminder.channel).to_channel_cached(&ctx);
|
let channel = reminder.channel.map(|c| ChannelId(c).to_channel_cached(&ctx)).flatten();
|
||||||
let channel_exists = channel.is_some();
|
let channel_exists = channel.is_some();
|
||||||
|
|
||||||
let channel_matches_guild =
|
let channel_matches_guild =
|
||||||
@ -382,14 +410,14 @@ pub async fn create_reminder(
|
|||||||
|
|
||||||
if !channel_matches_guild || !channel_exists {
|
if !channel_matches_guild || !channel_exists {
|
||||||
warn!(
|
warn!(
|
||||||
"Error in `create_reminder`: channel {} not found for guild {} (channel exists: {})",
|
"Error in `create_reminder`: channel {:?} not found for guild {} (channel exists: {})",
|
||||||
reminder.channel, guild_id, channel_exists
|
reminder.channel, guild_id, channel_exists
|
||||||
);
|
);
|
||||||
|
|
||||||
return Err(json!({"error": "Channel not found"}));
|
return Err(json!({"error": "Channel not found"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let channel = create_database_channel(&ctx, ChannelId(reminder.channel), pool).await;
|
let channel = create_database_channel(&ctx, ChannelId(reminder.channel.unwrap()), pool).await;
|
||||||
|
|
||||||
if let Err(e) = channel {
|
if let Err(e) = channel {
|
||||||
warn!("`create_database_channel` returned an error code: {:?}", e);
|
warn!("`create_database_channel` returned an error code: {:?}", e);
|
||||||
|
@ -16,6 +16,10 @@ document.addEventListener("paneLoad", (ev) => {
|
|||||||
|
|
||||||
loadErrors()
|
loadErrors()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
res = res
|
||||||
|
.filter((r) => r.status_change_time !== null)
|
||||||
|
.sort((a, b) => a.status_change_time < b.status_change_time);
|
||||||
|
|
||||||
for (const reminder of res) {
|
for (const reminder of res) {
|
||||||
const newRow = template.content.cloneNode(true);
|
const newRow = template.content.cloneNode(true);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user