104 lines
3.6 KiB
Rust
104 lines
3.6 KiB
Rust
use uuid::Uuid;
|
|
|
|
use crate::event::{RoomInfo, UserInfo};
|
|
use crate::{
|
|
ChannelBus, ChannelError, ChannelResult,
|
|
search::{SearchEngine, SearchQuery},
|
|
};
|
|
|
|
use super::WsHandler;
|
|
use super::WsOutEvent;
|
|
|
|
impl WsHandler {
|
|
pub(super) async fn search(
|
|
bus: &ChannelBus,
|
|
user_id: Uuid,
|
|
q: String,
|
|
room: Option<Uuid>,
|
|
limit: Option<u64>,
|
|
offset: Option<u64>,
|
|
) -> ChannelResult<Option<WsOutEvent>> {
|
|
if let Some(room_id) = room {
|
|
Self::ensure_room_access(bus, user_id, room_id).await?;
|
|
} else {
|
|
return Err(ChannelError::Validation(
|
|
"room is required for websocket search".to_string(),
|
|
));
|
|
}
|
|
let engine = SearchEngine::new(bus.inner.db.clone());
|
|
let result = engine
|
|
.search(SearchQuery {
|
|
query: q.clone(),
|
|
room_id: room,
|
|
user_id: None,
|
|
limit: limit.unwrap_or(50),
|
|
offset: offset.unwrap_or(0),
|
|
})
|
|
.await?;
|
|
|
|
let author_ids: Vec<Uuid> =
|
|
result.hits.iter().map(|h| h.sender_id).collect();
|
|
let message_ids: Vec<Uuid> =
|
|
result.hits.iter().map(|h| h.message_id).collect();
|
|
let user_map = bus.lookup_users(&author_ids).await.unwrap_or_default();
|
|
let reactions =
|
|
Self::reaction_groups_for_messages(bus, user_id, &message_ids)
|
|
.await
|
|
.unwrap_or_default();
|
|
|
|
let search_room = match room {
|
|
Some(r) => Some(
|
|
bus.lookup_room(r)
|
|
.await
|
|
.unwrap_or_else(|_| RoomInfo::unknown(r)),
|
|
),
|
|
None => None,
|
|
};
|
|
let search_msg_room = search_room
|
|
.clone()
|
|
.unwrap_or_else(|| RoomInfo::unknown(room.unwrap_or_default()));
|
|
let data = crate::event::search::SearchResultService {
|
|
q,
|
|
room: search_room,
|
|
messages: result
|
|
.hits
|
|
.into_iter()
|
|
.map(|h| {
|
|
let sender = user_map
|
|
.get(&h.sender_id)
|
|
.cloned()
|
|
.unwrap_or_else(|| UserInfo::unknown(h.sender_id));
|
|
crate::event::search::SearchMessageHitService {
|
|
message: crate::event::message::MessageNewService {
|
|
id: h.message_id,
|
|
seq: 0,
|
|
room: search_msg_room.clone(),
|
|
sender_type: "user".to_string(),
|
|
sender,
|
|
thread: None,
|
|
in_reply_to: None,
|
|
content: h.content.clone(),
|
|
content_type: "text".to_string(),
|
|
pinned: false,
|
|
system_type: None,
|
|
metadata: serde_json::Value::Null,
|
|
thinking_content: None,
|
|
thinking_is_chunked: None,
|
|
send_at: h.send_at,
|
|
reactions: reactions
|
|
.get(&h.message_id)
|
|
.cloned()
|
|
.unwrap_or_default(),
|
|
},
|
|
highlighted_content: h.highlighted,
|
|
}
|
|
})
|
|
.collect(),
|
|
total: result.total as i64,
|
|
took_ms: 0,
|
|
};
|
|
|
|
Ok(Some(WsOutEvent::SearchResult { data }))
|
|
}
|
|
}
|