/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin */ use super::ui::{account::session::Session, error::MyResult, node::DatabaseNodeUserDataExt}; use crate::routes::ui::node::rocket_uri_macro_r_library_node; use anyhow::anyhow; use jellybase::{ database::{redb::ReadableTable, DataAcid, Ser, TableExt, T_NODE, T_USER_NODE}, permission::NodePermissionExt, }; use jellycommon::user::{NodeUserData, WatchedState}; use rocket::{ form::Form, get, post, response::Redirect, serde::json::Json, FromForm, FromFormField, State, UriDisplayQuery, }; #[derive(Debug, FromFormField, UriDisplayQuery)] pub enum UrlWatchedState { None, Watched, Pending, } #[get("/n//userdata")] pub fn r_node_userdata( session: Session, db: &State, id: &str, ) -> MyResult> { let (_, _, u) = db.get_node_with_userdata(id, &session)?; Ok(Json(u)) } #[post("/n//watched?")] pub async fn r_node_userdata_watched( session: Session, db: &State, id: &str, state: UrlWatchedState, ) -> MyResult { T_NODE .get(db, id)? .only_if_permitted(&session.user.permissions) .ok_or(anyhow!("node does not exist"))?; let txn = db.begin_write()?; let mut user_nodes = txn.open_table(T_USER_NODE)?; let mut udata = user_nodes .get((session.user.name.as_str(), id))? .map(|x| x.value().0) .unwrap_or_default(); udata.watched = match state { UrlWatchedState::None => WatchedState::None, UrlWatchedState::Watched => WatchedState::Watched, UrlWatchedState::Pending => WatchedState::Pending, }; user_nodes.insert((session.user.name.as_str(), id), Ser(udata))?; drop(user_nodes); txn.commit()?; Ok(Redirect::found(rocket::uri!(r_library_node(id)))) } #[derive(FromForm)] pub struct UpdateRating { #[field(validate = range(-10..=10))] rating: i32, } #[post("/n//update_rating", data = "
")] pub async fn r_node_userdata_rating( session: Session, db: &State, id: &str, form: Form, ) -> MyResult { T_NODE .get(db, id)? .only_if_permitted(&session.user.permissions) .ok_or(anyhow!("node does not exist"))?; let txn = db.begin_write()?; let mut user_nodes = txn.open_table(T_USER_NODE)?; let mut udata = user_nodes .get((session.user.name.as_str(), id))? .map(|x| x.value().0) .unwrap_or_default(); udata.rating = form.rating; user_nodes.insert((session.user.name.as_str(), id), Ser(udata))?; drop(user_nodes); txn.commit()?; Ok(Redirect::found(rocket::uri!(r_library_node(id)))) } #[post("/n//progress?")] pub async fn r_node_userdata_progress( session: Session, db: &State, id: &str, t: f64, ) -> MyResult<()> { T_NODE .get(db, id)? .only_if_permitted(&session.user.permissions) .ok_or(anyhow!("node does not exist"))?; let txn = db.begin_write()?; let mut user_nodes = txn.open_table(T_USER_NODE)?; let mut udata = user_nodes .get((session.user.name.as_str(), id))? .map(|x| x.value().0) .unwrap_or_default(); udata.watched = match udata.watched { WatchedState::None | WatchedState::Pending | WatchedState::Progress(_) => { WatchedState::Progress(t) } WatchedState::Watched => WatchedState::Watched, }; user_nodes.insert((session.user.name.as_str(), id), Ser(udata))?; drop(user_nodes); txn.commit()?; Ok(()) }