use actix_web::{HttpRequest, HttpResponse, web}; use channel::ChannelBus; use channel::http::{WsHandler, WsInMessage}; use serde::Deserialize; use uuid::Uuid; use super::rest::{channel_err, created_json, extract_user, ok_json}; use crate::error::ApiError; #[derive(Debug, Deserialize, utoipa::ToSchema)] pub struct CreateMessageRequest { pub content: String, pub content_type: Option, pub thread: Option, pub in_reply_to: Option, } #[derive(Debug, Deserialize, utoipa::ToSchema)] pub struct UpdateMessageRequest { pub content: String, } #[derive(Debug, Deserialize, utoipa::IntoParams)] pub struct MessageListParams { pub before_seq: Option, pub after_seq: Option, pub limit: Option, } #[derive(Debug, Deserialize, utoipa::IntoParams)] pub struct MessageAroundParams { pub seq: i64, pub limit: Option, pub thread: Option, } #[derive(Debug, Deserialize, utoipa::IntoParams)] pub struct MissedMessagesParams { pub after_seq: i64, pub limit: Option, } #[derive(Debug, Deserialize, utoipa::IntoParams)] pub struct SearchParams { pub q: String, pub room: Option, pub limit: Option, pub offset: Option, } #[utoipa::path( post, path = "/api/v1/ws/rooms/{room_id}/messages", request_body = CreateMessageRequest, responses((status = 201, description = "Message created")), tag = "channel", )] pub async fn create_message( req: HttpRequest, room_id: web::Path, body: web::Json, bus: web::Data, ) -> Result { let user_id = extract_user(&req)?; let msg = WsInMessage::MessageCreate { room: room_id.into_inner(), content: body.content.clone(), content_type: body.content_type.clone(), thread: body.thread, in_reply_to: body.in_reply_to, }; let result = WsHandler::handle(&bus, user_id, msg) .await .map_err(channel_err)?; Ok(created_json(result)) } #[utoipa::path( patch, path = "/api/v1/ws/messages/{message_id}", request_body = UpdateMessageRequest, responses((status = 200, description = "Message updated")), tag = "channel", )] pub async fn update_message( req: HttpRequest, message_id: web::Path, body: web::Json, bus: web::Data, ) -> Result { let user_id = extract_user(&req)?; let msg = WsInMessage::MessageUpdate { message: message_id.into_inner(), content: body.content.clone(), }; let result = WsHandler::handle(&bus, user_id, msg) .await .map_err(channel_err)?; Ok(ok_json(result)) } #[utoipa::path( delete, path = "/api/v1/ws/messages/{message_id}", responses((status = 200, description = "Message revoked")), tag = "channel", )] pub async fn revoke_message( req: HttpRequest, message_id: web::Path, bus: web::Data, ) -> Result { let user_id = extract_user(&req)?; let msg = WsInMessage::MessageRevoke { message: message_id.into_inner(), }; let result = WsHandler::handle(&bus, user_id, msg) .await .map_err(channel_err)?; Ok(ok_json(result)) } #[utoipa::path( get, path = "/api/v1/ws/rooms/{room_id}/messages", params(MessageListParams), responses((status = 200, description = "Message list")), tag = "channel", )] pub async fn list_messages( req: HttpRequest, room_id: web::Path, params: web::Query, bus: web::Data, ) -> Result { let user_id = extract_user(&req)?; let msg = WsInMessage::MessageList { room: room_id.into_inner(), before_seq: params.before_seq, after_seq: params.after_seq, limit: params.limit, }; let result = WsHandler::handle(&bus, user_id, msg) .await .map_err(channel_err)?; Ok(ok_json(result)) } #[utoipa::path( get, path = "/api/v1/ws/rooms/{room_id}/messages/around", params(MessageAroundParams), responses((status = 200, description = "Messages around seq")), tag = "channel", )] pub async fn messages_around( req: HttpRequest, room_id: web::Path, params: web::Query, bus: web::Data, ) -> Result { let user_id = extract_user(&req)?; let msg = WsInMessage::MessageAround { room: room_id.into_inner(), seq: params.seq, limit: params.limit, thread: params.thread, }; let result = WsHandler::handle(&bus, user_id, msg) .await .map_err(channel_err)?; Ok(ok_json(result)) } #[utoipa::path( get, path = "/api/v1/ws/rooms/{room_id}/messages/missed", params(MissedMessagesParams), responses((status = 200, description = "Missed messages")), tag = "channel", )] pub async fn missed_messages( req: HttpRequest, room_id: web::Path, params: web::Query, bus: web::Data, ) -> Result { let user_id = extract_user(&req)?; let msg = WsInMessage::MissedMessages { room: room_id.into_inner(), after_seq: params.after_seq, limit: params.limit, }; let result = WsHandler::handle(&bus, user_id, msg) .await .map_err(channel_err)?; Ok(ok_json(result)) } #[utoipa::path( get, path = "/api/v1/ws/search", params(SearchParams), responses((status = 200, description = "Search results")), tag = "channel", )] pub async fn search( req: HttpRequest, params: web::Query, bus: web::Data, ) -> Result { let user_id = extract_user(&req)?; let msg = WsInMessage::Search { q: params.q.clone(), room: params.room, start_time: None, end_time: None, sender_id: None, content_type: None, limit: params.limit, offset: params.offset, }; let result = WsHandler::handle(&bus, user_id, msg) .await .map_err(channel_err)?; Ok(ok_json(result)) }