Move postman and web inside src
This commit is contained in:
		
							
								
								
									
										231
									
								
								src/web/routes/dashboard/api/user/models.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								src/web/routes/dashboard/api/user/models.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,231 @@
 | 
			
		||||
use chrono::{naive::NaiveDateTime, Utc};
 | 
			
		||||
use futures::TryFutureExt;
 | 
			
		||||
use log::warn;
 | 
			
		||||
use rocket::serde::json::json;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use serenity::{client::Context, model::id::UserId};
 | 
			
		||||
use sqlx::types::Json;
 | 
			
		||||
 | 
			
		||||
use crate::web::{
 | 
			
		||||
    check_subscription,
 | 
			
		||||
    consts::{
 | 
			
		||||
        DAY, MAX_CONTENT_LENGTH, MAX_EMBED_AUTHOR_LENGTH, MAX_EMBED_DESCRIPTION_LENGTH,
 | 
			
		||||
        MAX_EMBED_FIELDS, MAX_EMBED_FIELD_TITLE_LENGTH, MAX_EMBED_FIELD_VALUE_LENGTH,
 | 
			
		||||
        MAX_EMBED_FOOTER_LENGTH, MAX_EMBED_TITLE_LENGTH, MAX_NAME_LENGTH, MAX_URL_LENGTH,
 | 
			
		||||
        MIN_INTERVAL,
 | 
			
		||||
    },
 | 
			
		||||
    guards::transaction::Transaction,
 | 
			
		||||
    routes::{
 | 
			
		||||
        dashboard::{create_database_channel, generate_uid, name_default, Attachment, EmbedField},
 | 
			
		||||
        JsonResult,
 | 
			
		||||
    },
 | 
			
		||||
    Error,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize)]
 | 
			
		||||
pub struct Reminder {
 | 
			
		||||
    pub attachment: Option<Attachment>,
 | 
			
		||||
    pub attachment_name: Option<String>,
 | 
			
		||||
    pub content: String,
 | 
			
		||||
    pub embed_author: String,
 | 
			
		||||
    pub embed_author_url: Option<String>,
 | 
			
		||||
    pub embed_color: u32,
 | 
			
		||||
    pub embed_description: String,
 | 
			
		||||
    pub embed_footer: String,
 | 
			
		||||
    pub embed_footer_url: Option<String>,
 | 
			
		||||
    pub embed_image_url: Option<String>,
 | 
			
		||||
    pub embed_thumbnail_url: Option<String>,
 | 
			
		||||
    pub embed_title: String,
 | 
			
		||||
    pub embed_fields: Option<Json<Vec<EmbedField>>>,
 | 
			
		||||
    pub enabled: bool,
 | 
			
		||||
    pub expires: Option<NaiveDateTime>,
 | 
			
		||||
    pub interval_seconds: Option<u32>,
 | 
			
		||||
    pub interval_days: Option<u32>,
 | 
			
		||||
    pub interval_months: Option<u32>,
 | 
			
		||||
    #[serde(default = "name_default")]
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub tts: bool,
 | 
			
		||||
    #[serde(default)]
 | 
			
		||||
    pub uid: String,
 | 
			
		||||
    pub utc_time: NaiveDateTime,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn create_reminder(
 | 
			
		||||
    ctx: &Context,
 | 
			
		||||
    transaction: &mut Transaction<'_>,
 | 
			
		||||
    user_id: UserId,
 | 
			
		||||
    reminder: Reminder,
 | 
			
		||||
) -> JsonResult {
 | 
			
		||||
    let channel = user_id
 | 
			
		||||
        .create_dm_channel(&ctx)
 | 
			
		||||
        .map_err(|e| Error::Serenity(e))
 | 
			
		||||
        .and_then(|dm_channel| create_database_channel(&ctx, dm_channel.id, transaction))
 | 
			
		||||
        .await;
 | 
			
		||||
 | 
			
		||||
    if let Err(e) = channel {
 | 
			
		||||
        warn!("`create_database_channel` returned an error code: {:?}", e);
 | 
			
		||||
 | 
			
		||||
        return Err(json!({"error": "Failed to configure channel for reminders."}));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let channel = channel.unwrap();
 | 
			
		||||
 | 
			
		||||
    // validate lengths
 | 
			
		||||
    check_length!(MAX_NAME_LENGTH, reminder.name);
 | 
			
		||||
    check_length!(MAX_CONTENT_LENGTH, reminder.content);
 | 
			
		||||
    check_length!(MAX_EMBED_DESCRIPTION_LENGTH, reminder.embed_description);
 | 
			
		||||
    check_length!(MAX_EMBED_TITLE_LENGTH, reminder.embed_title);
 | 
			
		||||
    check_length!(MAX_EMBED_AUTHOR_LENGTH, reminder.embed_author);
 | 
			
		||||
    check_length!(MAX_EMBED_FOOTER_LENGTH, reminder.embed_footer);
 | 
			
		||||
    check_length_opt!(MAX_EMBED_FIELDS, reminder.embed_fields);
 | 
			
		||||
    if let Some(fields) = &reminder.embed_fields {
 | 
			
		||||
        for field in &fields.0 {
 | 
			
		||||
            check_length!(MAX_EMBED_FIELD_VALUE_LENGTH, field.value);
 | 
			
		||||
            check_length!(MAX_EMBED_FIELD_TITLE_LENGTH, field.title);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    check_length_opt!(
 | 
			
		||||
        MAX_URL_LENGTH,
 | 
			
		||||
        reminder.embed_footer_url,
 | 
			
		||||
        reminder.embed_thumbnail_url,
 | 
			
		||||
        reminder.embed_author_url,
 | 
			
		||||
        reminder.embed_image_url
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // validate urls
 | 
			
		||||
    check_url_opt!(
 | 
			
		||||
        reminder.embed_footer_url,
 | 
			
		||||
        reminder.embed_thumbnail_url,
 | 
			
		||||
        reminder.embed_author_url,
 | 
			
		||||
        reminder.embed_image_url
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // validate time and interval
 | 
			
		||||
    if reminder.utc_time < Utc::now().naive_utc() {
 | 
			
		||||
        return Err(json!({"error": "Time must be in the future"}));
 | 
			
		||||
    }
 | 
			
		||||
    if reminder.interval_seconds.is_some()
 | 
			
		||||
        || reminder.interval_days.is_some()
 | 
			
		||||
        || reminder.interval_months.is_some()
 | 
			
		||||
    {
 | 
			
		||||
        if reminder.interval_months.unwrap_or(0) * 30 * DAY as u32
 | 
			
		||||
            + reminder.interval_days.unwrap_or(0) * DAY as u32
 | 
			
		||||
            + reminder.interval_seconds.unwrap_or(0)
 | 
			
		||||
            < *MIN_INTERVAL
 | 
			
		||||
        {
 | 
			
		||||
            return Err(json!({"error": "Interval too short"}));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // check patreon if necessary
 | 
			
		||||
    if reminder.interval_seconds.is_some()
 | 
			
		||||
        || reminder.interval_days.is_some()
 | 
			
		||||
        || reminder.interval_months.is_some()
 | 
			
		||||
    {
 | 
			
		||||
        if !check_subscription(&ctx, user_id).await {
 | 
			
		||||
            return Err(json!({"error": "Patreon is required to set intervals"}));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let name = if reminder.name.is_empty() { name_default() } else { reminder.name.clone() };
 | 
			
		||||
    let new_uid = generate_uid();
 | 
			
		||||
 | 
			
		||||
    // write to db
 | 
			
		||||
    match sqlx::query!(
 | 
			
		||||
        "INSERT INTO reminders (
 | 
			
		||||
         uid,
 | 
			
		||||
         attachment,
 | 
			
		||||
         attachment_name,
 | 
			
		||||
         channel_id,
 | 
			
		||||
         content,
 | 
			
		||||
         embed_author,
 | 
			
		||||
         embed_author_url,
 | 
			
		||||
         embed_color,
 | 
			
		||||
         embed_description,
 | 
			
		||||
         embed_footer,
 | 
			
		||||
         embed_footer_url,
 | 
			
		||||
         embed_image_url,
 | 
			
		||||
         embed_thumbnail_url,
 | 
			
		||||
         embed_title,
 | 
			
		||||
         embed_fields,
 | 
			
		||||
         enabled,
 | 
			
		||||
         expires,
 | 
			
		||||
         interval_seconds,
 | 
			
		||||
         interval_days,
 | 
			
		||||
         interval_months,
 | 
			
		||||
         name,
 | 
			
		||||
         tts,
 | 
			
		||||
         `utc_time`
 | 
			
		||||
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
 | 
			
		||||
        new_uid,
 | 
			
		||||
        reminder.attachment,
 | 
			
		||||
        reminder.attachment_name,
 | 
			
		||||
        channel,
 | 
			
		||||
        reminder.content,
 | 
			
		||||
        reminder.embed_author,
 | 
			
		||||
        reminder.embed_author_url,
 | 
			
		||||
        reminder.embed_color,
 | 
			
		||||
        reminder.embed_description,
 | 
			
		||||
        reminder.embed_footer,
 | 
			
		||||
        reminder.embed_footer_url,
 | 
			
		||||
        reminder.embed_image_url,
 | 
			
		||||
        reminder.embed_thumbnail_url,
 | 
			
		||||
        reminder.embed_title,
 | 
			
		||||
        reminder.embed_fields,
 | 
			
		||||
        reminder.enabled,
 | 
			
		||||
        reminder.expires,
 | 
			
		||||
        reminder.interval_seconds,
 | 
			
		||||
        reminder.interval_days,
 | 
			
		||||
        reminder.interval_months,
 | 
			
		||||
        name,
 | 
			
		||||
        reminder.tts,
 | 
			
		||||
        reminder.utc_time,
 | 
			
		||||
    )
 | 
			
		||||
    .execute(transaction.executor())
 | 
			
		||||
    .await
 | 
			
		||||
    {
 | 
			
		||||
        Ok(_) => 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
 | 
			
		||||
            WHERE uid = ?",
 | 
			
		||||
            new_uid
 | 
			
		||||
        )
 | 
			
		||||
        .fetch_one(transaction.executor())
 | 
			
		||||
        .await
 | 
			
		||||
        .map(|r| Ok(json!(r)))
 | 
			
		||||
        .unwrap_or_else(|e| {
 | 
			
		||||
            warn!("Failed to complete SQL query: {:?}", e);
 | 
			
		||||
 | 
			
		||||
            Err(json!({"error": "Could not load reminder"}))
 | 
			
		||||
        }),
 | 
			
		||||
 | 
			
		||||
        Err(e) => {
 | 
			
		||||
            warn!("Error in `create_reminder`: Could not execute query: {:?}", e);
 | 
			
		||||
 | 
			
		||||
            Err(json!({"error": "Unknown error"}))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user