use axum::{extract::{Path, State}, http::StatusCode, response::IntoResponse, Json}; use uuid::Uuid; use api_types::requests::{CreateThoughtRequest, EditThoughtRequest}; use application::use_cases::thoughts::{create_thought, delete_thought, edit_thought, get_thought, get_thread, CreateThoughtInput}; use domain::value_objects::ThoughtId; use crate::{errors::ApiError, extractors::{AuthUser, OptionalAuthUser}, handlers::auth::to_user_response, state::AppState}; fn thought_to_json(t: &domain::models::thought::Thought, author: &domain::models::user::User, like_count: i64, boost_count: i64, reply_count: i64) -> serde_json::Value { serde_json::json!({ "id": t.id.as_uuid(), "content": t.content.as_str(), "author": to_user_response(author), "in_reply_to_id": t.in_reply_to_id.as_ref().map(|x| x.as_uuid()), "visibility": t.visibility.as_str(), "content_warning": t.content_warning, "sensitive": t.sensitive, "like_count": like_count, "boost_count": boost_count, "reply_count": reply_count, "created_at": t.created_at, "updated_at": t.updated_at, }) } pub async fn post_thought(State(s): State, AuthUser(uid): AuthUser, Json(body): Json) -> Result { let in_reply_to = body.in_reply_to_id.map(ThoughtId::from_uuid); let out = create_thought(&*s.thoughts, &*s.users, &*s.events, CreateThoughtInput { user_id: uid.clone(), content: body.content, in_reply_to_id: in_reply_to, visibility: body.visibility, content_warning: body.content_warning, sensitive: body.sensitive.unwrap_or(false), }).await?; let author = s.users.find_by_id(&uid).await?.ok_or(domain::errors::DomainError::NotFound)?; Ok((StatusCode::CREATED, Json(thought_to_json(&out.thought, &author, 0, 0, 0)))) } pub async fn get_thought_handler(State(s): State, Path(id): Path, OptionalAuthUser(_viewer): OptionalAuthUser) -> Result, ApiError> { let thought = get_thought(&*s.thoughts, &ThoughtId::from_uuid(id)).await?; let author = s.users.find_by_id(&thought.user_id).await?.ok_or(domain::errors::DomainError::NotFound)?; Ok(Json(thought_to_json(&thought, &author, 0, 0, 0))) } pub async fn delete_thought_handler(State(s): State, AuthUser(uid): AuthUser, Path(id): Path) -> Result { delete_thought(&*s.thoughts, &*s.events, &ThoughtId::from_uuid(id), &uid).await?; Ok(StatusCode::NO_CONTENT) } pub async fn patch_thought(State(s): State, AuthUser(uid): AuthUser, Path(id): Path, Json(body): Json) -> Result { edit_thought(&*s.thoughts, &*s.events, &ThoughtId::from_uuid(id), &uid, body.content).await?; Ok(StatusCode::NO_CONTENT) } pub async fn get_thread_handler(State(s): State, Path(id): Path) -> Result>, ApiError> { let thoughts = get_thread(&*s.thoughts, &ThoughtId::from_uuid(id)).await?; let mut items = Vec::new(); for t in &thoughts { if let Ok(Some(author)) = s.users.find_by_id(&t.user_id).await { items.push(thought_to_json(t, &author, 0, 0, 0)); } } Ok(Json(items)) }