mod guilds; mod models; mod reminders; use std::env; use chrono_tz::Tz; pub use guilds::*; pub use reminders::*; use rocket::{ get, http::CookieJar, patch, serde::json::{json, Json, Value as JsonValue}, State, }; use serde::{Deserialize, Serialize}; use serenity::{ client::Context, model::id::{GuildId, RoleId}, }; use sqlx::{MySql, Pool}; use crate::web::guards::transaction::Transaction; #[derive(Serialize)] struct UserPreferences { timezone: String, use_browser_timezone: bool, dashboard_color_scheme: String, reset_inputs_on_create: bool, } #[derive(Serialize)] struct UserInfo { name: String, patreon: bool, preferences: UserPreferences, } #[derive(Deserialize)] pub struct UpdateUserPreferences { timezone: Option, use_browser_timezone: Option, dashboard_color_scheme: Option, reset_inputs_on_create: Option, } #[get("/api/user")] pub async fn get_user_info( cookies: &CookieJar<'_>, ctx: &State, pool: &State>, ) -> JsonValue { offline!(json!(UserInfo { name: "Discord".to_string(), patreon: true, preferences: UserPreferences { timezone: "UTC".to_string(), use_browser_timezone: false, dashboard_color_scheme: "system".to_string(), reset_inputs_on_create: false, } })); if let Some(user_id) = cookies.get_private("userid").map(|u| u.value().parse::().ok()).flatten() { let member_res = GuildId::new(env::var("PATREON_GUILD_ID").unwrap().parse().unwrap()) .member(&ctx.inner(), user_id) .await; let prefs = sqlx::query!( " SELECT IFNULL(timezone, 'UTC') AS timezone, use_browser_timezone, dashboard_color_scheme, reset_inputs_on_create FROM users WHERE id = ? ", user_id ) .fetch_one(pool.inner()) .await .map_or(None, |q| Some(q.timezone)); let user_info = UserInfo { name: cookies .get_private("username") .map_or("Discord User".to_string(), |c| c.value().to_string()), patreon: member_res.map_or(false, |member| { member .roles .contains(&RoleId::new(env::var("PATREON_ROLE_ID").unwrap().parse().unwrap())) }), preferences: UserPreferences { timezone: prefs.timezone, use_browser_timezone: prefs.use_browser_timezone, dashboard_color_scheme: prefs.dashboard_color_scheme, reset_inputs_on_create: prefs.reset_inputs_on_create, }, }; json!(user_info) } else { json!({"error": "Not authorized"}) } } #[patch("/api/user", data = "")] pub async fn update_user_info( cookies: &CookieJar<'_>, preferences: Json, mut transaction: Transaction<'_>, ) -> JsonValue { if let Some(user_id) = cookies.get_private("userid").map(|u| u.value().parse::().ok()).flatten() { if let Some(timezone) = &preferences.timezone { if timezone.parse::().is_ok() { let _ = sqlx::query!( " UPDATE users SET timezone = ? WHERE id = ? ", timezone, user_id, ) .execute(transaction.executor()) .await; } else { return json!({"error": "Timezone not recognised"}); } } if let Some(dashboard_color_scheme) = &preferences.dashboard_color_scheme { if vec!["system", "light", "dark"].contains(&dashboard_color_scheme.as_str()) { let _ = sqlx::query!( " UPDATE users SET dashboard_color_scheme = ? WHERE id = ? ", dashboard_color_scheme, user_id, ) .execute(transaction.executor()) .await; } else { return json!({"error": "Color scheme not recognised"}); } } // todo handle other two options transaction.commit().await; json!({}) } else { json!({"error": "Not authorized"}) } }