use super::get_collection; use lru::LruCache; use mongodb::bson::{doc, from_bson, Bson}; use rocket::http::RawStr; use rocket::request::FromParam; use rocket_contrib::json::JsonValue; use serde::{Deserialize, Serialize}; use std::sync::{Arc, Mutex}; use rocket::futures::StreamExt; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct LastMessage { // message id id: String, // author's id user_id: String, // truncated content with author's name prepended (for GDM / GUILD) short_content: String, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Channel { #[serde(rename = "_id")] pub id: String, #[serde(rename = "type")] pub channel_type: u8, // DM: whether the DM is active pub active: Option<bool>, // DM + GDM: last message in channel pub last_message: Option<LastMessage>, // DM + GDM: recipients for channel pub recipients: Option<Vec<String>>, // GDM: owner of group pub owner: Option<String>, // GUILD: channel parent pub guild: Option<String>, // GUILD + GDM: channel name pub name: Option<String>, // GUILD + GDM: channel description pub description: Option<String>, } impl Channel { pub fn serialise(self) -> JsonValue { match self.channel_type { 0 => json!({ "id": self.id, "type": self.channel_type, "last_message": self.last_message, "recipients": self.recipients, }), 1 => json!({ "id": self.id, "type": self.channel_type, "last_message": self.last_message, "recipients": self.recipients, "name": self.name, "owner": self.owner, "description": self.description, }), 2 => json!({ "id": self.id, "type": self.channel_type, "guild": self.guild, "name": self.name, "description": self.description, }), _ => unreachable!(), } } } lazy_static! { static ref CACHE: Arc<Mutex<LruCache<String, Channel>>> = Arc::new(Mutex::new(LruCache::new(4_000_000))); } pub async fn fetch_channel(id: &str) -> Result<Option<Channel>, String> { { if let Ok(mut cache) = CACHE.lock() { let existing = cache.get(&id.to_string()); if let Some(channel) = existing { return Ok(Some((*channel).clone())); } } else { return Err("Failed to lock cache.".to_string()); } } let col = get_collection("channels"); if let Ok(result) = col.find_one(doc! { "_id": id }, None).await { if let Some(doc) = result { if let Ok(channel) = from_bson(Bson::Document(doc)) as Result<Channel, _> { let mut cache = CACHE.lock().unwrap(); cache.put(id.to_string(), channel.clone()); Ok(Some(channel)) } else { Err("Failed to deserialize channel!".to_string()) } } else { Ok(None) } } else { Err("Failed to fetch channel from database.".to_string()) } } pub async fn fetch_channels(ids: &Vec<String>) -> Result<Vec<Channel>, String> { let mut missing = vec![]; let mut channels = vec![]; { if let Ok(mut cache) = CACHE.lock() { for id in ids { let existing = cache.get(id); if let Some(channel) = existing { channels.push((*channel).clone()); } else { missing.push(id); } } } else { return Err("Failed to lock cache.".to_string()); } } if missing.len() == 0 { return Ok(channels); } let col = get_collection("channels"); if let Ok(mut result) = col.find(doc! { "_id": { "$in": missing } }, None).await { while let Some(item) = result.next().await { let mut cache = CACHE.lock().unwrap(); if let Ok(doc) = item { if let Ok(channel) = from_bson(Bson::Document(doc)) as Result<Channel, _> { cache.put(channel.id.clone(), channel.clone()); channels.push(channel); } else { return Err("Failed to deserialize channel!".to_string()); } } else { return Err("Failed to fetch channel.".to_string()); } } Ok(channels) } else { Err("Failed to fetch channel from database.".to_string()) } } impl<'r> FromParam<'r> for Channel { type Error = &'r RawStr; fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> { Err(param) /*if let Ok(result) = fetch_channel(param).await { if let Some(channel) = result { Ok(channel) } else { Err(param) } } else { Err(param) }*/ } } /*use crate::notifications::events::Notification; pub fn process_event(event: &Notification) { match event { Notification::group_user_join(ev) => { let mut cache = CACHE.lock().unwrap(); if let Some(channel) = cache.peek_mut(&ev.id) { channel.recipients.as_mut().unwrap().push(ev.user.clone()); } } Notification::group_user_leave(ev) => { let mut cache = CACHE.lock().unwrap(); if let Some(channel) = cache.peek_mut(&ev.id) { let recipients = channel.recipients.as_mut().unwrap(); if let Some(pos) = recipients.iter().position(|x| *x == ev.user) { recipients.remove(pos); } } } Notification::guild_channel_create(ev) => { let mut cache = CACHE.lock().unwrap(); cache.put( ev.id.clone(), Channel { id: ev.channel.clone(), channel_type: 2, active: None, last_message: None, recipients: None, owner: None, guild: Some(ev.id.clone()), name: Some(ev.name.clone()), description: Some(ev.description.clone()), }, ); } Notification::guild_channel_delete(ev) => { let mut cache = CACHE.lock().unwrap(); cache.pop(&ev.channel); } _ => {} } }*/