use room::ws_context::WsUserContext; use uuid::Uuid; use crate::error::AppTransportError; use crate::event::reaction; use crate::handler::session::TransportSession; use crate::handler::types::WsOutEvent; pub(crate) async fn reaction_add( session: &TransportSession, room: models::RoomId, message: Uuid, emoji: String, ) -> Result, AppTransportError> { let ctx = WsUserContext::new(session.user.user_id); let rxs = session .service .room .message_reaction_add(message, emoji, &ctx) .await .map_err(|e| { tracing::warn!(error = %e, "message_reaction_add failed"); AppTransportError::Internal })?; Ok(Some(build_reaction_batch(room, message, rxs.reactions))) } pub(crate) async fn reaction_remove( session: &TransportSession, room: models::RoomId, message: Uuid, emoji: String, ) -> Result, AppTransportError> { let ctx = WsUserContext::new(session.user.user_id); let rxs = session .service .room .message_reaction_remove(message, emoji, &ctx) .await .map_err(|e| { tracing::warn!(error = %e, "message_reaction_remove failed"); AppTransportError::Internal })?; Ok(Some(build_reaction_batch(room, message, rxs.reactions))) } fn build_reaction_batch( room: models::RoomId, message: Uuid, reactions: Vec, ) -> WsOutEvent { WsOutEvent::ReactionBatchUpdated { room_id: room, data: reaction::ReactionBatchUpdatedService { room, message, reactions: reactions .into_iter() .map(|g| reaction::ReactionGroup { emoji: g.emoji, count: g.count as i64, reacted_by_me: g.reacted_by_me, users: g .users .iter() .filter_map(|u| u.parse::().ok()) .collect(), }) .collect(), }, } } pub(crate) async fn thread_create( session: &TransportSession, room: models::RoomId, parent: i64, ) -> Result, AppTransportError> { let ctx = WsUserContext::new(session.user.user_id); session .service .room .room_thread_create( room, room::RoomThreadCreateRequest { parent_seq: parent }, &ctx, ) .await .map_err(|e| { tracing::warn!(error = %e, "room_thread_create failed"); AppTransportError::Internal })?; Ok(None) } pub(crate) async fn thread_resolve( thread_id: models::RoomThreadId, ) -> Result, AppTransportError> { tracing::info!(%thread_id, "Thread resolved"); Ok(None) } pub(crate) async fn thread_archive( thread_id: models::RoomThreadId, ) -> Result, AppTransportError> { tracing::info!(%thread_id, "Thread archived"); Ok(None) } pub(crate) async fn pin_add( session: &TransportSession, message: Uuid, ) -> Result, AppTransportError> { let ctx = WsUserContext::new(session.user.user_id); session .service .room .room_pin_add(message, &ctx) .await .map_err(|e| { tracing::warn!(error = %e, "room_pin_add failed"); AppTransportError::Internal })?; Ok(None) } pub(crate) async fn pin_remove( session: &TransportSession, message: Uuid, ) -> Result, AppTransportError> { let ctx = WsUserContext::new(session.user.user_id); session .service .room .room_pin_remove(message, &ctx) .await .map_err(|e| { tracing::warn!(error = %e, "room_pin_remove failed"); AppTransportError::Internal })?; Ok(None) } pub(crate) async fn draft_save( session: &TransportSession, room: models::RoomId, content: String, ) -> Result, AppTransportError> { let ctx = WsUserContext::new(session.user.user_id); let draft = session .service .room .draft_save(room, content, &ctx) .await .map_err(|e| { tracing::warn!(error = %e, "draft_save failed"); AppTransportError::Internal })?; Ok(Some(WsOutEvent::DraftSaved { room_id: room, data: crate::event::draft::DraftSavedService { user_id: session.user.user_id, room: draft.room_id, content: draft.content, saved_at: draft.saved_at, }, })) } pub(crate) async fn draft_clear( session: &TransportSession, room: models::RoomId, ) -> Result, AppTransportError> { let ctx = WsUserContext::new(session.user.user_id); session .service .room .draft_clear(room, &ctx) .await .map_err(|e| { tracing::warn!(error = %e, "draft_clear failed"); AppTransportError::Internal })?; Ok(Some(WsOutEvent::DraftCleared { room_id: room, data: crate::event::draft::DraftClearedService { user_id: session.user.user_id, room, cleared_at: chrono::Utc::now(), }, })) }