gitdataai/libs/transport/handler/dispatch.rs

134 lines
5.1 KiB
Rust

use models::RoomId;
use queue::{ReactionGroup, RoomMessageEvent, RoomMessageStreamChunkEvent, TypingEvent};
use room::types::NotificationEvent;
use super::types::WsOutEvent;
use crate::event::{member, message, notify, reaction};
pub struct EventDispatcher;
impl EventDispatcher {
pub fn dispatch_message(event: &RoomMessageEvent) -> WsOutEvent {
WsOutEvent::MessageNew {
room_id: event.room_id,
data: message::MessageNewService {
id: event.id,
seq: event.seq,
room: event.room_id,
sender_type: event.sender_type.clone(),
sender_id: event.sender_id,
display_name: event.display_name.clone(),
thread: event.thread_id,
in_reply_to: event.in_reply_to,
content: event.content.clone(),
content_type: event.content_type.clone(),
thinking_content: event.thinking_content.clone(),
thinking_is_chunked: false,
send_at: event.send_at,
reactions: None,
},
}
}
/// Dispatch MessageStreamStart — WS only sends message_id + SSE URL.
/// Full chunk content is delivered via dedicated SSE endpoint.
pub fn dispatch_stream_start(event: &RoomMessageStreamChunkEvent) -> WsOutEvent {
WsOutEvent::MessageStreamStart {
room_id: event.room_id,
data: message::MessageStreamStartService {
message_id: event.message_id,
room: event.room_id,
sse_url: format!("/ws/ai-stream/{}/{}", event.room_id, event.message_id),
display_name: event.display_name.clone(),
},
}
}
/// Dispatch MessageStreamDone — WS notifies client that SSE stream ended.
pub fn dispatch_stream_done(event: &RoomMessageStreamChunkEvent) -> WsOutEvent {
WsOutEvent::MessageStreamDone {
room_id: event.room_id,
data: message::MessageStreamDoneService {
message_id: event.message_id,
room: event.room_id,
content: event.content.clone(),
thinking_content: None,
display_name: event.display_name.clone(),
error: event.error.clone(),
},
}
}
pub fn dispatch_typing(event: &TypingEvent) -> WsOutEvent {
match event.action.as_str() {
"start" => WsOutEvent::TypingStart {
room_id: event.room_id,
data: member::TypingStartService {
room: event.room_id,
user: event.user_id,
username: event.username.clone(),
avatar_url: event.avatar_url.clone(),
sender_type: event.sender_type.clone(),
},
},
_ => WsOutEvent::TypingStop {
room_id: event.room_id,
data: member::TypingStopService {
room: event.room_id,
user: event.user_id,
username: event.username.clone(),
avatar_url: event.avatar_url.clone(),
sender_type: event.sender_type.clone(),
},
},
}
}
pub fn dispatch_notification(event: &NotificationEvent) -> WsOutEvent {
WsOutEvent::NotifyCreated {
data: notify::NotifyCreatedService {
id: event.notification.id,
room: event.notification.room,
project: event.notification.project,
user_id: event.notification.user_id,
notification_type: event.event_type.clone(),
title: event.notification.title.clone(),
content: event.notification.content.clone(),
related_message_id: event.notification.related_message_id,
related_user_id: event.notification.related_user_id,
related_room_id: event.notification.related_room_id,
metadata: event.notification.metadata.clone(),
created_at: event.timestamp,
deep_link_url: event.deep_link_url.clone(),
},
}
}
pub fn dispatch_reactions(
room_id: RoomId,
message_id: uuid::Uuid,
reactions: &[ReactionGroup],
) -> WsOutEvent {
WsOutEvent::ReactionBatchUpdated {
room_id,
data: reaction::ReactionBatchUpdatedService {
room: room_id,
message: message_id,
reactions: reactions
.iter()
.map(|g| reaction::ReactionGroup {
emoji: g.emoji.clone(),
count: g.count as i64,
reacted_by_me: g.reacted_by_me,
users: g
.users
.iter()
.filter_map(|u| u.parse::<uuid::Uuid>().ok())
.collect(),
})
.collect(),
},
}
}
}