Skip to content
Clone
b7cd2b1
181 lines 7.0 KB Rust
use export::http::{Json, Path, Query, State};
use export::rest::{AppResponseData, NoData};
use jwt::Session;
use jwt::share::session;
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<ThreadDto>),
(status = 404, description = "not found", body = AppResponseData<NoData>),
(status = 409, description = "resource already exists", body = AppResponseData<NoData>),
(status = 400, description = "request failed validation", body = AppResponseData<NoData>),
(status = 401, description = "authentication required", body = AppResponseData<NoData>)
)
)]
pub async fn create_thread(
State(service): State<ChatService>,
session: Session,
Path((room_id, message_id)): Path<(Uuid, Uuid)>,
Json(cmd): Json<CreateThreadCmd>,
) -> Result<AppResponseData<ThreadDto>, ApiError> {
let uid = session::require_uid(&session)?;
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<ThreadPage>),
(status = 404, description = "not found", body = AppResponseData<NoData>),
(status = 401, description = "authentication required", body = AppResponseData<NoData>)
)
)]
pub async fn list_threads(
State(service): State<ChatService>,
session: Session,
Path(room_id): Path<Uuid>,
Query(q): Query<ListThreadQuery>,
) -> Result<AppResponseData<ThreadPage>, ApiError> {
let uid = session::require_uid(&session)?;
let page = service.list_threads(uid, room_id, q).await?;
Ok(AppResponseData::ok(page))
}
#[utoipa::path(
get,
path = "/chat/threads",
tag = "chat",
description = "列出当前用户参与的最近话题。",
params(export::pagination::PageQuery),
responses(
(status = 200, description = "my threads", body = AppResponseData<export::pagination::Page<ThreadDto>>),
(status = 401, description = "unauthorized", body = AppResponseData<NoData>),
(status = 404, description = "resource not found", body = AppResponseData<NoData>)
)
)]
pub async fn list_my_threads(
State(service): State<ChatService>,
session: Session,
Query(page): Query<export::pagination::PageQuery>,
) -> Result<AppResponseData<export::pagination::Page<ThreadDto>>, ApiError> {
let uid = session::require_uid(&session)?;
let threads = service.list_my_threads(uid).await?;
Ok(AppResponseData::ok(export::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<ThreadDto>),
(status = 404, description = "not found", body = AppResponseData<NoData>),
(status = 401, description = "authentication required", body = AppResponseData<NoData>)
)
)]
pub async fn get_thread(
State(service): State<ChatService>,
session: Session,
Path(thread_id): Path<Uuid>,
) -> Result<AppResponseData<ThreadDto>, ApiError> {
let uid = session::require_uid(&session)?;
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<ThreadDto>),
(status = 403, description = "forbidden", body = AppResponseData<NoData>),
(status = 400, description = "request failed validation", body = AppResponseData<NoData>),
(status = 401, description = "authentication required", body = AppResponseData<NoData>)
)
)]
pub async fn update_thread(
State(service): State<ChatService>,
session: Session,
Path(thread_id): Path<Uuid>,
Json(cmd): Json<UpdateThreadCmd>,
) -> Result<AppResponseData<ThreadDto>, ApiError> {
let uid = session::require_uid(&session)?;
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<NoData>),
(status = 404, description = "not found", body = AppResponseData<NoData>),
(status = 400, description = "request failed validation", body = AppResponseData<NoData>),
(status = 401, description = "authentication required", body = AppResponseData<NoData>)
)
)]
pub async fn follow_thread(
State(service): State<ChatService>,
session: Session,
Path(thread_id): Path<Uuid>,
Json(cmd): Json<ThreadMemberCmd>,
) -> Result<AppResponseData<NoData>, ApiError> {
let uid = session::require_uid(&session)?;
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<NoData>),
(status = 404, description = "not found", body = AppResponseData<NoData>),
(status = 401, description = "authentication required", body = AppResponseData<NoData>)
)
)]
pub async fn unfollow_thread(
State(service): State<ChatService>,
session: Session,
Path(thread_id): Path<Uuid>,
) -> Result<AppResponseData<NoData>, ApiError> {
let uid = session::require_uid(&session)?;
service.leave_thread(uid, thread_id).await?;
Ok(AppResponseData::empty())
}