forked from jmug/stoatchat
feat(core/database): implement user settings model
This commit is contained in:
@@ -2,14 +2,26 @@ use std::{collections::HashMap, sync::Arc};
|
|||||||
|
|
||||||
use futures::lock::Mutex;
|
use futures::lock::Mutex;
|
||||||
|
|
||||||
use crate::{Bot, File, User};
|
use crate::{Bot, File, User, UserSettings};
|
||||||
|
|
||||||
database_derived!(
|
database_derived!(
|
||||||
/// Reference implementation
|
/// Reference implementation
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ReferenceDb {
|
pub struct ReferenceDb {
|
||||||
pub bots: Arc<Mutex<HashMap<String, Bot>>>,
|
pub bots: Arc<Mutex<HashMap<String, Bot>>>,
|
||||||
|
pub user_settings: Arc<Mutex<HashMap<String, UserSettings>>>,
|
||||||
pub users: Arc<Mutex<HashMap<String, User>>>,
|
pub users: Arc<Mutex<HashMap<String, User>>>,
|
||||||
pub files: Arc<Mutex<HashMap<String, File>>>,
|
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, ()>>>,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
mod admin_migrations;
|
mod admin_migrations;
|
||||||
mod bots;
|
mod bots;
|
||||||
mod files;
|
mod files;
|
||||||
|
mod user_settings;
|
||||||
mod users;
|
mod users;
|
||||||
|
|
||||||
pub use admin_migrations::*;
|
pub use admin_migrations::*;
|
||||||
pub use bots::*;
|
pub use bots::*;
|
||||||
pub use files::*;
|
pub use files::*;
|
||||||
|
pub use user_settings::*;
|
||||||
pub use users::*;
|
pub use users::*;
|
||||||
|
|
||||||
use crate::{Database, MongoDb, ReferenceDb};
|
use crate::{Database, MongoDb, ReferenceDb};
|
||||||
@@ -16,6 +18,7 @@ pub trait AbstractDatabase:
|
|||||||
+ admin_migrations::AbstractMigrations
|
+ admin_migrations::AbstractMigrations
|
||||||
+ bots::AbstractBots
|
+ bots::AbstractBots
|
||||||
+ files::AbstractAttachments
|
+ files::AbstractAttachments
|
||||||
|
+ user_settings::AbstractUserSettings
|
||||||
+ users::AbstractUsers
|
+ users::AbstractUsers
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
5
crates/core/database/src/models/user_settings/mod.rs
Normal file
5
crates/core/database/src/models/user_settings/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
mod model;
|
||||||
|
mod ops;
|
||||||
|
|
||||||
|
pub use model::*;
|
||||||
|
pub use ops::*;
|
||||||
28
crates/core/database/src/models/user_settings/model.rs
Normal file
28
crates/core/database/src/models/user_settings/model.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
18
crates/core/database/src/models/user_settings/ops.rs
Normal file
18
crates/core/database/src/models/user_settings/ops.rs
Normal 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<()>;
|
||||||
|
}
|
||||||
67
crates/core/database/src/models/user_settings/ops/mongodb.rs
Normal file
67
crates/core/database/src/models/user_settings/ops/mongodb.rs
Normal 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(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user