use uuid::Uuid; use crate::event::{RoomInfo, forward}; use crate::{ChannelBus, ChannelResult}; use super::WsHandler; use super::WsOutEvent; impl WsHandler { pub(super) async fn message_forward( bus: &ChannelBus, user_id: Uuid, source_message_id: Uuid, target_room: Uuid, ) -> ChannelResult> { let source = Self::load_message(bus, source_message_id).await?; Self::ensure_room_access(bus, user_id, source.room).await?; Self::ensure_room_access(bus, user_id, target_room).await?; let seq = bus.inner.seq.seq(target_room).await?; let sender = bus.lookup_user(user_id).await?; let source_room_info = bus .lookup_room(source.room) .await .unwrap_or_else(|_| RoomInfo::unknown(source.room)); let forward_content = format!( "> Forwarded from {}:\n\n{}", source_room_info.name, source.content ); let metadata = serde_json::json!({ "source_room_id": source.room, "source_message_id": source.id, "source_room_name": source_room_info.name, "forwarded_by": user_id, }); let row = db::sqlx::query_as::<_, model::channel::RoomMessageModel>( "INSERT INTO room_message \ (room, seq, thread, parent, author, content, content_type, system_type, metadata) \ VALUES ($1, $2, NULL, NULL, $3, $4, 'forward', NULL, $5) \ RETURNING id, room, seq, thread, parent, author, content, content_type, pinned, \ system_type, metadata, edited_at, created_at, updated_at, deleted_at", ) .bind(target_room) .bind(seq) .bind(user_id) .bind(&forward_content) .bind(&metadata) .fetch_one(bus.inner.db.writer()) .await?; let target_room_info = bus .lookup_room(target_room) .await .unwrap_or_else(|_| RoomInfo::unknown(target_room)); let fwd_id = row.id; let fwd_seq = row.seq; let fwd_content = row.content.clone(); let fwd_content_type = row.content_type.clone(); let fwd_created_at = row.created_at; bus.publish_room_message(row, Some(bus.lookup_user(user_id).await?)) .await?; let data = forward::MessageForwardedService { id: fwd_id, seq: fwd_seq, room: target_room_info.clone(), sender, content: fwd_content, content_type: fwd_content_type, source_room: source_room_info, source_message_id: source.id, forwarded_at: fwd_created_at, }; Ok(Some(WsOutEvent::MessageForwarded { room: target_room_info, data, })) } }