feat(core/database): implement user settings model

This commit is contained in:
Paul Makles
2023-04-26 17:53:46 +01:00
parent 08ccc43f8d
commit b5863c0104
7 changed files with 180 additions and 1 deletions

View File

@@ -2,14 +2,26 @@ use std::{collections::HashMap, sync::Arc};
use futures::lock::Mutex;
use crate::{Bot, File, User};
use crate::{Bot, File, User, UserSettings};
database_derived!(
/// Reference implementation
#[derive(Default)]
pub struct ReferenceDb {
pub bots: Arc<Mutex<HashMap<String, Bot>>>,
pub user_settings: Arc<Mutex<HashMap<String, UserSettings>>>,
pub users: Arc<Mutex<HashMap<String, User>>>,
pub files: Arc<Mutex<HashMap<String, File>>>,
pub servers: Arc<Mutex<HashMap<String, ()>>>,
pub server_bans: Arc<Mutex<HashMap<String, ()>>>,
pub server_members: Arc<Mutex<HashMap<String, ()>>>,
pub safety_reports: Arc<Mutex<HashMap<String, ()>>>,
pub safety_snapshots: Arc<Mutex<HashMap<String, ()>>>,
pub emoji: Arc<Mutex<HashMap<String, ()>>>,
pub messages: Arc<Mutex<HashMap<String, ()>>>,
pub channels: Arc<Mutex<HashMap<String, ()>>>,
pub channel_invites: Arc<Mutex<HashMap<String, ()>>>,
pub channel_unreads: Arc<Mutex<HashMap<String, ()>>>,
}
);

View File

@@ -1,11 +1,13 @@
mod admin_migrations;
mod bots;
mod files;
mod user_settings;
mod users;
pub use admin_migrations::*;
pub use bots::*;
pub use files::*;
pub use user_settings::*;
pub use users::*;
use crate::{Database, MongoDb, ReferenceDb};
@@ -16,6 +18,7 @@ pub trait AbstractDatabase:
+ admin_migrations::AbstractMigrations
+ bots::AbstractBots
+ files::AbstractAttachments
+ user_settings::AbstractUserSettings
+ users::AbstractUsers
{
}

View File

@@ -0,0 +1,5 @@
mod model;
mod ops;
pub use model::*;
pub use ops::*;

View File

@@ -0,0 +1,28 @@
use std::collections::HashMap;
use crate::Database;
use revolt_result::Result;
pub type UserSettings = HashMap<String, (i64, String)>;
#[async_trait]
pub trait UserSettingsImpl {
async fn set(self, db: &Database, user: &str) -> Result<()>;
}
#[async_trait]
impl UserSettingsImpl for UserSettings {
async fn set(self, db: &Database, user: &str) -> Result<()> {
db.set_user_settings(user, &self).await?;
/* // TODO: EventV1::UserSettingsUpdate {
id: user.to_string(),
update: self,
}
.private(user.to_string())
.await; */
Ok(())
}
}

View File

@@ -0,0 +1,18 @@
use revolt_result::Result;
use crate::UserSettings;
mod mongodb;
mod reference;
#[async_trait]
pub trait AbstractUserSettings: Sync + Send {
/// Fetch a subset of user settings
async fn fetch_user_settings(&'_ self, id: &str, filter: &'_ [String]) -> Result<UserSettings>;
/// Update a subset of user settings
async fn set_user_settings(&self, id: &str, settings: &UserSettings) -> Result<()>;
/// Delete all user settings
async fn delete_user_settings(&self, id: &str) -> Result<()>;
}

View File

@@ -0,0 +1,67 @@
use ::mongodb::options::FindOneOptions;
use bson::to_bson;
use bson::Document;
use mongodb::options::UpdateOptions;
use revolt_result::Result;
use crate::MongoDb;
use crate::UserSettings;
use super::AbstractUserSettings;
static COL: &str = "user_settings";
#[async_trait]
impl AbstractUserSettings for MongoDb {
/// Fetch a subset of user settings
async fn fetch_user_settings(&'_ self, id: &str, filter: &'_ [String]) -> Result<UserSettings> {
let mut projection = doc! {
"_id": 0,
};
for key in filter {
projection.insert(key, 1);
}
Ok(query!(
self,
find_one_with_options,
COL,
doc! {
"_id": id
},
FindOneOptions::builder().projection(projection).build()
)?
.unwrap_or_default())
}
/// Update a subset of user settings
async fn set_user_settings(&self, id: &str, settings: &UserSettings) -> Result<()> {
let mut set = doc! {};
for (key, data) in settings {
set.insert(
key,
vec![to_bson(&data.0).unwrap(), to_bson(&data.1).unwrap()],
);
}
self.col::<Document>(COL)
.update_one(
doc! {
"_id": id
},
doc! {
"$set": set
},
UpdateOptions::builder().upsert(true).build(),
)
.await
.map(|_| ())
.map_err(|_| create_database_error!("update_one", "user_settings"))
}
/// Delete all user settings
async fn delete_user_settings(&self, id: &str) -> Result<()> {
query!(self, delete_one_by_id, COL, id).map(|_| ())
}
}

View File

@@ -0,0 +1,46 @@
use revolt_result::Result;
use crate::ReferenceDb;
use crate::UserSettings;
use super::AbstractUserSettings;
#[async_trait]
impl AbstractUserSettings for ReferenceDb {
/// Fetch a subset of user settings
async fn fetch_user_settings(&'_ self, id: &str, filter: &'_ [String]) -> Result<UserSettings> {
let user_settings = self.user_settings.lock().await;
user_settings
.get(id)
.cloned()
.map(|settings| {
settings
.into_iter()
.filter(|(key, _)| filter.contains(key))
.collect()
})
.ok_or_else(|| create_error!(NotFound))
}
/// Update a subset of user settings
async fn set_user_settings(&self, id: &str, settings: &UserSettings) -> Result<()> {
let mut user_settings = self.user_settings.lock().await;
if let Some(settings) = user_settings.get_mut(id) {
settings.extend(settings.clone());
} else {
user_settings.insert(id.to_string(), settings.clone());
}
Ok(())
}
/// Delete all user settings
async fn delete_user_settings(&self, id: &str) -> Result<()> {
let mut user_settings = self.user_settings.lock().await;
if user_settings.remove(id).is_some() {
Ok(())
} else {
Err(create_error!(NotFound))
}
}
}