diff --git a/src/database/entities/user.rs b/src/database/entities/user.rs index 1d97b7f3323eb51217862e3cf66cf667be358ab7..53bd531e849c74b3bb438037c708d903a3626d97 100644 --- a/src/database/entities/user.rs +++ b/src/database/entities/user.rs @@ -1,10 +1,11 @@ -use crate::database::get_collection; +use crate::{database::get_collection, notifications::events::ClientboundNotification, util::result::{Error, Result}}; use crate::database::guards::reference::Ref; -use mongodb::bson::{doc, from_bson, Bson}; +use mongodb::{bson::{doc, from_bson, Bson}, options::FindOptions}; use rauth::auth::Session; use rocket::http::Status; use rocket::request::{self, FromRequest, Outcome, Request}; use serde::{Deserialize, Serialize}; +use futures::StreamExt; #[derive(Serialize, Deserialize, Debug, Clone)] pub enum RelationshipStatus { @@ -31,6 +32,10 @@ pub struct User { pub username: String, #[serde(skip_serializing_if = "Option::is_none")] pub relations: Option<Vec<Relationship>>, + + // ? This should never be pushed to the collection. + #[serde(skip_serializing_if = "Option::is_none")] + pub relationship: Option<RelationshipStatus> } #[rocket::async_trait] @@ -69,4 +74,51 @@ impl User { id: self.id.to_string(), } } + + pub async fn generate_ready_payload(self) -> Result<ClientboundNotification> { + let mut users = vec![]; + + if let Some(relationships) = &self.relations { + let user_ids: Vec<String> = relationships + .iter() + .map(|relationship| relationship.id.clone()) + .collect(); + + let mut cursor = get_collection("users") + .find( + doc! { + "_id": { + "$in": user_ids + } + }, + FindOptions::builder() + .projection(doc! { "_id": 1, "username": 1 }) + .build() + ) + .await + .map_err(|_| Error::DatabaseError { operation: "find", with: "users" })?; + + while let Some(result) = cursor.next().await { + if let Ok(doc) = result { + let mut user: User = from_bson(Bson::Document(doc)) + .map_err(|_| Error::DatabaseError { operation: "from_bson", with: "user" })?; + + user.relationship = Some( + relationships + .iter() + .find(|x| user.id == x.id) + .ok_or_else(|| Error::InternalError)? + .status + .clone() + ); + + users.push(user); + } + } + } + + users.push(self); + + Ok(ClientboundNotification::Ready { users }) + } } diff --git a/src/notifications/events.rs b/src/notifications/events.rs index 0cda3400772731fe015f2cd31b536eeb4f649c65..eb289fefc715c3932cd819dcf385d67a61b11465 100644 --- a/src/notifications/events.rs +++ b/src/notifications/events.rs @@ -33,7 +33,7 @@ pub enum ClientboundNotification { Error(WebSocketError), Authenticated, Ready { - user: User + users: Vec<User> }, /*MessageCreate { diff --git a/src/notifications/websocket.rs b/src/notifications/websocket.rs index dd472357229c6f162543893f612d74f799f3cba1..6bc89361104bd7091407aa160f25a3a4947abc4d 100644 --- a/src/notifications/websocket.rs +++ b/src/notifications/websocket.rs @@ -96,7 +96,19 @@ async fn accept(stream: TcpStream) { subscriptions::generate_subscriptions(&user), ) { send(ClientboundNotification::Authenticated); - send(ClientboundNotification::Ready { user }); + + match task::block_on( + user.generate_ready_payload() + ) { + Ok(payload) => { + send(payload); + } + Err(_) => { + send(ClientboundNotification::Error( + WebSocketError::InternalError, + )); + } + } } else { send(ClientboundNotification::Error( WebSocketError::InternalError,