165 lines
4.5 KiB
Rust

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<String>,
use_browser_timezone: Option<bool>,
dashboard_color_scheme: Option<String>,
reset_inputs_on_create: Option<bool>,
}
#[get("/api/user")]
pub async fn get_user_info(
cookies: &CookieJar<'_>,
ctx: &State<Context>,
pool: &State<Pool<MySql>>,
) -> 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::<u64>().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 = "<preferences>")]
pub async fn update_user_info(
cookies: &CookieJar<'_>,
preferences: Json<UpdateUserPreferences>,
mut transaction: Transaction<'_>,
) -> JsonValue {
if let Some(user_id) =
cookies.get_private("userid").map(|u| u.value().parse::<u64>().ok()).flatten()
{
if let Some(timezone) = &preferences.timezone {
if timezone.parse::<Tz>().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"})
}
}