gitdataai/lib/channel/http/handler/search.rs

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 }))
}
}