use ::session::AuthedUser; use api::http::{Json, Path, Query, State}; use api::rest::{AppResponseData, NoData}; use uuid::Uuid; use crate::errors::ApiError; use crate::services::service::ChatService; use crate::services::threads::{ CreateThreadCmd, ListThreadQuery, ThreadDto, ThreadMemberCmd, ThreadPage, UpdateThreadCmd, }; #[utoipa::path( post, path = "/chat/rooms/{room_id}/messages/{message_id}/threads", tag = "chat", description = "基于指定根消息创建房间话题;已存在时返回既有线程。", params( ("room_id" = Uuid, Path, description = "room id"), ("message_id" = Uuid, Path, description = "root message id") ), request_body = CreateThreadCmd, responses( (status = 200, description = "thread created", body = AppResponseData), (status = 404, description = "not found", body = AppResponseData), (status = 409, description = "resource already exists", body = AppResponseData), (status = 400, description = "request failed validation", body = AppResponseData), (status = 401, description = "authentication required", body = AppResponseData) ) )] pub async fn create_thread( State(service): State, AuthedUser(uid): AuthedUser, Path((room_id, message_id)): Path<(Uuid, Uuid)>, Json(cmd): Json, ) -> Result, ApiError> { let dto = service.create_thread(uid, room_id, message_id, cmd).await?; Ok(AppResponseData::ok(dto)) } #[utoipa::path( get, path = "/chat/rooms/{room_id}/threads", tag = "chat", description = "分页列出房间话题,可按归档状态过滤。", params(("room_id" = Uuid, Path, description = "room id"), ListThreadQuery), responses( (status = 200, description = "thread page", body = AppResponseData>), (status = 404, description = "not found", body = AppResponseData), (status = 401, description = "authentication required", body = AppResponseData) ) )] pub async fn list_threads( State(service): State, AuthedUser(uid): AuthedUser, Path(room_id): Path, Query(q): Query, ) -> Result, ApiError> { let page = service.list_threads(uid, room_id, q).await?; Ok(AppResponseData::ok(page)) } #[utoipa::path( get, path = "/chat/threads", tag = "chat", description = "列出当前用户参与的最近话题。", params(api::pagination::PageQuery), responses( (status = 200, description = "my threads", body = AppResponseData>), (status = 401, description = "unauthorized", body = AppResponseData), (status = 404, description = "resource not found", body = AppResponseData) ) )] pub async fn list_my_threads( State(service): State, AuthedUser(uid): AuthedUser, Query(page): Query, ) -> Result>, ApiError> { let threads = service.list_my_threads(uid).await?; Ok(AppResponseData::ok(api::pagination::paginate( threads, &page, )?)) } #[utoipa::path( get, path = "/chat/threads/{thread_id}", tag = "chat", description = "读取指定话题的标题、回复计数和参与状态。", params(("thread_id" = Uuid, Path, description = "thread id")), responses( (status = 200, description = "thread detail", body = AppResponseData), (status = 404, description = "not found", body = AppResponseData), (status = 401, description = "authentication required", body = AppResponseData) ) )] pub async fn get_thread( State(service): State, AuthedUser(uid): AuthedUser, Path(thread_id): Path, ) -> Result, ApiError> { let dto = service.get_thread(uid, thread_id).await?; Ok(AppResponseData::ok(dto)) } #[utoipa::path( patch, path = "/chat/threads/{thread_id}", tag = "chat", description = "话题所有者或空间管理员重命名、归档或锁定话题。", params(("thread_id" = Uuid, Path, description = "thread id")), request_body = UpdateThreadCmd, responses( (status = 200, description = "thread updated", body = AppResponseData), (status = 403, description = "forbidden", body = AppResponseData), (status = 400, description = "request failed validation", body = AppResponseData), (status = 401, description = "authentication required", body = AppResponseData) ) )] pub async fn update_thread( State(service): State, AuthedUser(uid): AuthedUser, Path(thread_id): Path, Json(cmd): Json, ) -> Result, ApiError> { let dto = service.update_thread(uid, thread_id, cmd).await?; Ok(AppResponseData::ok(dto)) } #[utoipa::path( put, path = "/chat/threads/{thread_id}/members/@me", tag = "chat", description = "让当前用户关注话题并设置通知级别。", params(("thread_id" = Uuid, Path, description = "thread id")), request_body = ThreadMemberCmd, responses( (status = 200, description = "followed", body = AppResponseData), (status = 404, description = "not found", body = AppResponseData), (status = 400, description = "request failed validation", body = AppResponseData), (status = 401, description = "authentication required", body = AppResponseData) ) )] pub async fn follow_thread( State(service): State, AuthedUser(uid): AuthedUser, Path(thread_id): Path, Json(cmd): Json, ) -> Result, ApiError> { service.set_thread_membership(uid, thread_id, cmd).await?; Ok(AppResponseData::empty()) } #[utoipa::path( delete, path = "/chat/threads/{thread_id}/members/@me", tag = "chat", description = "取消当前用户的话题关注并减少参与者计数。", params(("thread_id" = Uuid, Path, description = "thread id")), responses( (status = 200, description = "unfollowed", body = AppResponseData), (status = 404, description = "not found", body = AppResponseData), (status = 401, description = "authentication required", body = AppResponseData) ) )] pub async fn unfollow_thread( State(service): State, AuthedUser(uid): AuthedUser, Path(thread_id): Path, ) -> Result, ApiError> { service.leave_thread(uid, thread_id).await?; Ok(AppResponseData::empty()) }