285 lines
8.7 KiB
Rust
285 lines
8.7 KiB
Rust
use log::warn;
|
|
use rocket::{
|
|
get,
|
|
http::CookieJar,
|
|
patch, post,
|
|
serde::json::{json, Json},
|
|
State,
|
|
};
|
|
use serenity::{client::Context, model::id::UserId};
|
|
use sqlx::{MySql, Pool};
|
|
|
|
use crate::web::{
|
|
check_subscription,
|
|
guards::transaction::Transaction,
|
|
routes::{
|
|
dashboard::{
|
|
api::user::models::{create_reminder, Reminder},
|
|
PatchReminder, MIN_INTERVAL,
|
|
},
|
|
JsonResult,
|
|
},
|
|
Database,
|
|
};
|
|
|
|
#[post("/api/user/reminders", data = "<reminder>")]
|
|
pub async fn create_user_reminder(
|
|
reminder: Json<Reminder>,
|
|
cookies: &CookieJar<'_>,
|
|
ctx: &State<Context>,
|
|
mut transaction: Transaction<'_>,
|
|
) -> JsonResult {
|
|
let user_id =
|
|
cookies.get_private("userid").map(|c| c.value().parse::<u64>().ok()).flatten().unwrap();
|
|
|
|
match create_reminder(
|
|
ctx.inner(),
|
|
&mut transaction,
|
|
UserId::new(user_id),
|
|
reminder.into_inner(),
|
|
)
|
|
.await
|
|
{
|
|
Ok(r) => match transaction.commit().await {
|
|
Ok(_) => Ok(r),
|
|
Err(e) => {
|
|
warn!("Couldn't commit transaction: {:?}", e);
|
|
json_err!("Couldn't commit transaction.")
|
|
}
|
|
},
|
|
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
|
|
#[get("/api/user/reminders")]
|
|
pub async fn get_reminders(
|
|
cookies: &CookieJar<'_>,
|
|
ctx: &State<Context>,
|
|
pool: &State<Pool<MySql>>,
|
|
) -> JsonResult {
|
|
let user_id =
|
|
cookies.get_private("userid").map(|c| c.value().parse::<u64>().ok()).flatten().unwrap();
|
|
let channel = UserId::new(user_id).create_dm_channel(ctx.inner()).await;
|
|
|
|
match channel {
|
|
Ok(channel) => sqlx::query_as_unchecked!(
|
|
Reminder,
|
|
"
|
|
SELECT
|
|
reminders.attachment,
|
|
reminders.attachment_name,
|
|
reminders.content,
|
|
reminders.embed_author,
|
|
reminders.embed_author_url,
|
|
reminders.embed_color,
|
|
reminders.embed_description,
|
|
reminders.embed_footer,
|
|
reminders.embed_footer_url,
|
|
reminders.embed_image_url,
|
|
reminders.embed_thumbnail_url,
|
|
reminders.embed_title,
|
|
IFNULL(reminders.embed_fields, '[]') AS embed_fields,
|
|
reminders.enabled,
|
|
reminders.expires,
|
|
reminders.interval_seconds,
|
|
reminders.interval_days,
|
|
reminders.interval_months,
|
|
reminders.name,
|
|
reminders.tts,
|
|
reminders.uid,
|
|
reminders.utc_time
|
|
FROM reminders
|
|
INNER JOIN channels ON channels.id = reminders.channel_id
|
|
WHERE `status` = 'pending' AND channels.channel = ?
|
|
",
|
|
channel.id.get()
|
|
)
|
|
.fetch_all(pool.inner())
|
|
.await
|
|
.map(|r| Ok(json!(r)))
|
|
.unwrap_or_else(|e| {
|
|
warn!("Failed to complete SQL query: {:?}", e);
|
|
|
|
json_err!("Could not load reminders")
|
|
}),
|
|
|
|
Err(e) => {
|
|
warn!("Couldn't get DM channel: {:?}", e);
|
|
|
|
json_err!("Could not find a DM channel")
|
|
}
|
|
}
|
|
}
|
|
|
|
#[patch("/api/user/reminders", data = "<reminder>")]
|
|
pub async fn edit_reminder(
|
|
reminder: Json<PatchReminder>,
|
|
ctx: &State<Context>,
|
|
mut transaction: Transaction<'_>,
|
|
pool: &State<Pool<Database>>,
|
|
cookies: &CookieJar<'_>,
|
|
) -> JsonResult {
|
|
let user_id_cookie =
|
|
cookies.get_private("userid").map(|c| c.value().parse::<u64>().ok()).flatten();
|
|
|
|
if user_id_cookie.is_none() {
|
|
return Err(json!({"error": "User not authorized"}));
|
|
}
|
|
|
|
let mut error = vec![];
|
|
let user_id = user_id_cookie.unwrap();
|
|
|
|
if reminder.message_ok() {
|
|
update_field!(transaction.executor(), error, reminder.[
|
|
content,
|
|
embed_author,
|
|
embed_description,
|
|
embed_footer,
|
|
embed_title,
|
|
embed_fields
|
|
]);
|
|
} else {
|
|
error.push("Message exceeds limits.".to_string());
|
|
}
|
|
|
|
update_field!(transaction.executor(), error, reminder.[
|
|
attachment,
|
|
attachment_name,
|
|
embed_author_url,
|
|
embed_color,
|
|
embed_footer_url,
|
|
embed_image_url,
|
|
embed_thumbnail_url,
|
|
enabled,
|
|
expires,
|
|
name,
|
|
tts,
|
|
utc_time
|
|
]);
|
|
|
|
if reminder.interval_days.flatten().is_some()
|
|
|| reminder.interval_months.flatten().is_some()
|
|
|| reminder.interval_seconds.flatten().is_some()
|
|
{
|
|
if check_subscription(&ctx.inner(), user_id).await {
|
|
let new_interval_length = match reminder.interval_days {
|
|
Some(interval) => interval.unwrap_or(0),
|
|
None => sqlx::query!(
|
|
"SELECT interval_days AS days FROM reminders WHERE uid = ?",
|
|
reminder.uid
|
|
)
|
|
.fetch_one(transaction.executor())
|
|
.await
|
|
.map_err(|e| {
|
|
warn!("Error updating reminder interval: {:?}", e);
|
|
json!({ "reminder": Option::<Reminder>::None, "errors": vec!["Unknown error"] })
|
|
})?
|
|
.days
|
|
.unwrap_or(0),
|
|
} * 86400 + match reminder.interval_months {
|
|
Some(interval) => interval.unwrap_or(0),
|
|
None => sqlx::query!(
|
|
"SELECT interval_months AS months FROM reminders WHERE uid = ?",
|
|
reminder.uid
|
|
)
|
|
.fetch_one(transaction.executor())
|
|
.await
|
|
.map_err(|e| {
|
|
warn!("Error updating reminder interval: {:?}", e);
|
|
json!({ "reminder": Option::<Reminder>::None, "errors": vec!["Unknown error"] })
|
|
})?
|
|
.months
|
|
.unwrap_or(0),
|
|
} * 2592000 + match reminder.interval_seconds {
|
|
Some(interval) => interval.unwrap_or(0),
|
|
None => sqlx::query!(
|
|
"SELECT interval_seconds AS seconds FROM reminders WHERE uid = ?",
|
|
reminder.uid
|
|
)
|
|
.fetch_one(transaction.executor())
|
|
.await
|
|
.map_err(|e| {
|
|
warn!("Error updating reminder interval: {:?}", e);
|
|
json!({ "reminder": Option::<Reminder>::None, "errors": vec!["Unknown error"] })
|
|
})?
|
|
.seconds
|
|
.unwrap_or(0),
|
|
};
|
|
|
|
if new_interval_length < *MIN_INTERVAL {
|
|
error.push(String::from("New interval is too short."));
|
|
} else {
|
|
update_field!(transaction.executor(), error, reminder.[
|
|
interval_days,
|
|
interval_months,
|
|
interval_seconds
|
|
]);
|
|
}
|
|
}
|
|
} else {
|
|
sqlx::query!(
|
|
"
|
|
UPDATE reminders
|
|
SET interval_seconds = NULL, interval_days = NULL, interval_months = NULL
|
|
WHERE uid = ?
|
|
",
|
|
reminder.uid
|
|
)
|
|
.execute(transaction.executor())
|
|
.await
|
|
.map_err(|e| {
|
|
warn!("Error updating reminder interval: {:?}", e);
|
|
json!({ "reminder": Option::<Reminder>::None, "errors": vec!["Unknown error"] })
|
|
})?;
|
|
}
|
|
|
|
if let Err(e) = transaction.commit().await {
|
|
warn!("Couldn't commit transaction: {:?}", e);
|
|
return json_err!("Couldn't commit transaction");
|
|
}
|
|
|
|
match sqlx::query_as_unchecked!(
|
|
Reminder,
|
|
"
|
|
SELECT reminders.attachment,
|
|
reminders.attachment_name,
|
|
reminders.content,
|
|
reminders.embed_author,
|
|
reminders.embed_author_url,
|
|
reminders.embed_color,
|
|
reminders.embed_description,
|
|
reminders.embed_footer,
|
|
reminders.embed_footer_url,
|
|
reminders.embed_image_url,
|
|
reminders.embed_thumbnail_url,
|
|
reminders.embed_title,
|
|
reminders.embed_fields,
|
|
reminders.enabled,
|
|
reminders.expires,
|
|
reminders.interval_seconds,
|
|
reminders.interval_days,
|
|
reminders.interval_months,
|
|
reminders.name,
|
|
reminders.tts,
|
|
reminders.uid,
|
|
reminders.utc_time
|
|
FROM reminders
|
|
LEFT JOIN channels ON channels.id = reminders.channel_id
|
|
WHERE uid = ?
|
|
",
|
|
reminder.uid
|
|
)
|
|
.fetch_one(pool.inner())
|
|
.await
|
|
{
|
|
Ok(reminder) => Ok(json!({"reminder": reminder, "errors": error})),
|
|
|
|
Err(e) => {
|
|
warn!("Error exiting `edit_reminder': {:?}", e);
|
|
|
|
Err(json!({"reminder": Option::<Reminder>::None, "errors": vec!["Unknown error"]}))
|
|
}
|
|
}
|
|
}
|