feat(core/database): implement server member
This commit is contained in:
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -342,7 +342,7 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"futures",
|
"futures",
|
||||||
"handlebars",
|
"handlebars",
|
||||||
"iso8601-timestamp",
|
"iso8601-timestamp 0.1.10",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lettre",
|
"lettre",
|
||||||
"log",
|
"log",
|
||||||
@@ -1605,6 +1605,17 @@ dependencies = [
|
|||||||
"time 0.3.17",
|
"time 0.3.17",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iso8601-timestamp"
|
||||||
|
version = "0.2.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "368d05885f276773b79b4578869a60ab91e880415d17fb2a8d193aea74188a29"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array 0.14.5",
|
||||||
|
"serde",
|
||||||
|
"time 0.3.17",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
@@ -2851,6 +2862,7 @@ dependencies = [
|
|||||||
"authifier",
|
"authifier",
|
||||||
"bson",
|
"bson",
|
||||||
"futures",
|
"futures",
|
||||||
|
"iso8601-timestamp 0.2.10",
|
||||||
"log",
|
"log",
|
||||||
"mongodb",
|
"mongodb",
|
||||||
"nanoid",
|
"nanoid",
|
||||||
@@ -2956,7 +2968,7 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"impl_ops",
|
"impl_ops",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"iso8601-timestamp",
|
"iso8601-timestamp 0.1.10",
|
||||||
"linkify 0.8.1",
|
"linkify 0.8.1",
|
||||||
"log",
|
"log",
|
||||||
"lru",
|
"lru",
|
||||||
@@ -3129,7 +3141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d4554a81937341d8c3cd3e43431ac2d23624444dc3a88e7ffd3ff66593779293"
|
checksum = "d4554a81937341d8c3cd3e43431ac2d23624444dc3a88e7ffd3ff66593779293"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"authifier",
|
"authifier",
|
||||||
"iso8601-timestamp",
|
"iso8601-timestamp 0.1.10",
|
||||||
"revolt_okapi",
|
"revolt_okapi",
|
||||||
"revolt_rocket_okapi",
|
"revolt_rocket_okapi",
|
||||||
"rocket",
|
"rocket",
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ once_cell = "1.17"
|
|||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
revolt_optional_struct = "0.2.0"
|
revolt_optional_struct = "0.2.0"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
iso8601-timestamp = { version = "0.2.10", features = ["serde", "bson"] }
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
bson = { optional = true, version = "2.1.0" }
|
bson = { optional = true, version = "2.1.0" }
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::{collections::HashMap, sync::Arc};
|
|||||||
|
|
||||||
use futures::lock::Mutex;
|
use futures::lock::Mutex;
|
||||||
|
|
||||||
use crate::{Bot, File, Server, User, UserSettings};
|
use crate::{Bot, File, Member, MemberCompositeKey, Server, User, UserSettings};
|
||||||
|
|
||||||
database_derived!(
|
database_derived!(
|
||||||
/// Reference implementation
|
/// Reference implementation
|
||||||
@@ -11,11 +11,11 @@ database_derived!(
|
|||||||
pub bots: Arc<Mutex<HashMap<String, Bot>>>,
|
pub bots: Arc<Mutex<HashMap<String, Bot>>>,
|
||||||
pub user_settings: Arc<Mutex<HashMap<String, UserSettings>>>,
|
pub user_settings: Arc<Mutex<HashMap<String, UserSettings>>>,
|
||||||
pub users: Arc<Mutex<HashMap<String, User>>>,
|
pub users: Arc<Mutex<HashMap<String, User>>>,
|
||||||
|
pub server_members: Arc<Mutex<HashMap<MemberCompositeKey, Member>>>,
|
||||||
pub servers: Arc<Mutex<HashMap<String, Server>>>,
|
pub servers: Arc<Mutex<HashMap<String, Server>>>,
|
||||||
pub files: Arc<Mutex<HashMap<String, File>>>,
|
pub files: Arc<Mutex<HashMap<String, File>>>,
|
||||||
|
|
||||||
pub server_bans: 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_reports: Arc<Mutex<HashMap<String, ()>>>,
|
||||||
pub safety_snapshots: Arc<Mutex<HashMap<String, ()>>>,
|
pub safety_snapshots: Arc<Mutex<HashMap<String, ()>>>,
|
||||||
pub emoji: Arc<Mutex<HashMap<String, ()>>>,
|
pub emoji: Arc<Mutex<HashMap<String, ()>>>,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
mod admin_migrations;
|
mod admin_migrations;
|
||||||
mod bots;
|
mod bots;
|
||||||
mod files;
|
mod files;
|
||||||
|
mod server_members;
|
||||||
mod servers;
|
mod servers;
|
||||||
mod user_settings;
|
mod user_settings;
|
||||||
mod users;
|
mod users;
|
||||||
@@ -8,6 +9,7 @@ mod users;
|
|||||||
pub use admin_migrations::*;
|
pub use admin_migrations::*;
|
||||||
pub use bots::*;
|
pub use bots::*;
|
||||||
pub use files::*;
|
pub use files::*;
|
||||||
|
pub use server_members::*;
|
||||||
pub use servers::*;
|
pub use servers::*;
|
||||||
pub use user_settings::*;
|
pub use user_settings::*;
|
||||||
pub use users::*;
|
pub use users::*;
|
||||||
@@ -20,6 +22,7 @@ pub trait AbstractDatabase:
|
|||||||
+ admin_migrations::AbstractMigrations
|
+ admin_migrations::AbstractMigrations
|
||||||
+ bots::AbstractBots
|
+ bots::AbstractBots
|
||||||
+ files::AbstractAttachments
|
+ files::AbstractAttachments
|
||||||
|
+ server_members::AbstractServerMembers
|
||||||
+ servers::AbstractServers
|
+ servers::AbstractServers
|
||||||
+ user_settings::AbstractUserSettings
|
+ user_settings::AbstractUserSettings
|
||||||
+ users::AbstractUsers
|
+ users::AbstractUsers
|
||||||
|
|||||||
5
crates/core/database/src/models/server_members/mod.rs
Normal file
5
crates/core/database/src/models/server_members/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
mod model;
|
||||||
|
mod ops;
|
||||||
|
|
||||||
|
pub use model::*;
|
||||||
|
pub use ops::*;
|
||||||
118
crates/core/database/src/models/server_members/model.rs
Normal file
118
crates/core/database/src/models/server_members/model.rs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
use iso8601_timestamp::Timestamp;
|
||||||
|
use revolt_result::Result;
|
||||||
|
|
||||||
|
use crate::{Database, File, Server};
|
||||||
|
|
||||||
|
auto_derived_partial!(
|
||||||
|
/// Server Member
|
||||||
|
pub struct Member {
|
||||||
|
/// Unique member id
|
||||||
|
#[serde(rename = "_id")]
|
||||||
|
pub id: MemberCompositeKey,
|
||||||
|
|
||||||
|
/// Time at which this user joined the server
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub joined_at: Option<Timestamp>,
|
||||||
|
|
||||||
|
/// Member's nickname
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub nickname: Option<String>,
|
||||||
|
/// Avatar attachment
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub avatar: Option<File>,
|
||||||
|
|
||||||
|
/// Member's roles
|
||||||
|
#[serde(skip_serializing_if = "Vec::is_empty", default)]
|
||||||
|
pub roles: Vec<String>,
|
||||||
|
/// Timestamp this member is timed out until
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub timeout: Option<Timestamp>,
|
||||||
|
},
|
||||||
|
"PartialMember"
|
||||||
|
);
|
||||||
|
|
||||||
|
auto_derived!(
|
||||||
|
/// Composite primary key consisting of server and user id
|
||||||
|
#[derive(Hash, Default)]
|
||||||
|
pub struct MemberCompositeKey {
|
||||||
|
/// Server Id
|
||||||
|
pub server: String,
|
||||||
|
/// User Id
|
||||||
|
pub user: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Optional fields on server member object
|
||||||
|
pub enum FieldsMember {
|
||||||
|
Nickname,
|
||||||
|
Avatar,
|
||||||
|
Roles,
|
||||||
|
Timeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Member removal intention
|
||||||
|
pub enum RemovalIntention {
|
||||||
|
Leave,
|
||||||
|
Kick,
|
||||||
|
Ban,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl Member {
|
||||||
|
/// Update member data
|
||||||
|
pub async fn update<'a>(
|
||||||
|
&mut self,
|
||||||
|
db: &Database,
|
||||||
|
partial: PartialMember,
|
||||||
|
remove: Vec<FieldsMember>,
|
||||||
|
) -> Result<()> {
|
||||||
|
for field in &remove {
|
||||||
|
self.remove_field(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.apply_options(partial.clone());
|
||||||
|
|
||||||
|
db.update_member(&self.id, &partial, remove.clone()).await?;
|
||||||
|
|
||||||
|
/* // TODO: EventV1::ServerMemberUpdate {
|
||||||
|
id: self.id.clone(),
|
||||||
|
data: partial,
|
||||||
|
clear: remove,
|
||||||
|
}
|
||||||
|
.p(self.id.server.clone())
|
||||||
|
.await; */
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_field(&mut self, field: &FieldsMember) {
|
||||||
|
match field {
|
||||||
|
FieldsMember::Avatar => self.avatar = None,
|
||||||
|
FieldsMember::Nickname => self.nickname = None,
|
||||||
|
FieldsMember::Roles => self.roles.clear(),
|
||||||
|
FieldsMember::Timeout => self.timeout = None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get this user's current ranking
|
||||||
|
pub fn get_ranking(&self, server: &Server) -> i64 {
|
||||||
|
let mut value = i64::MAX;
|
||||||
|
for role in &self.roles {
|
||||||
|
if let Some(role) = server.roles.get(role) {
|
||||||
|
if role.rank < value {
|
||||||
|
value = role.rank;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether this member is in timeout
|
||||||
|
pub fn in_timeout(&self) -> bool {
|
||||||
|
if let Some(timeout) = self.timeout {
|
||||||
|
*timeout > *Timestamp::now_utc()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
crates/core/database/src/models/server_members/ops.rs
Normal file
41
crates/core/database/src/models/server_members/ops.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
use revolt_result::Result;
|
||||||
|
|
||||||
|
use crate::{FieldsMember, Member, MemberCompositeKey, PartialMember};
|
||||||
|
|
||||||
|
mod mongodb;
|
||||||
|
mod reference;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait AbstractServerMembers: Sync + Send {
|
||||||
|
/// Insert a new server member into the database
|
||||||
|
async fn insert_member(&self, member: &Member) -> Result<()>;
|
||||||
|
|
||||||
|
/// Fetch a server member by their id
|
||||||
|
async fn fetch_member(&self, server_id: &str, user_id: &str) -> Result<Member>;
|
||||||
|
|
||||||
|
/// Fetch all members in a server
|
||||||
|
async fn fetch_all_members<'a>(&self, server_id: &str) -> Result<Vec<Member>>;
|
||||||
|
|
||||||
|
/// Fetch all memberships for a user
|
||||||
|
async fn fetch_all_memberships<'a>(&self, user_id: &str) -> Result<Vec<Member>>;
|
||||||
|
|
||||||
|
/// Fetch multiple members by their ids
|
||||||
|
async fn fetch_members<'a>(&self, server_id: &str, ids: &'a [String]) -> Result<Vec<Member>>;
|
||||||
|
|
||||||
|
/// Fetch member count of a server
|
||||||
|
async fn fetch_member_count(&self, server_id: &str) -> Result<usize>;
|
||||||
|
|
||||||
|
/// Fetch server count of a user
|
||||||
|
async fn fetch_server_count(&self, user_id: &str) -> Result<usize>;
|
||||||
|
|
||||||
|
/// Update information for a server member
|
||||||
|
async fn update_member(
|
||||||
|
&self,
|
||||||
|
id: &MemberCompositeKey,
|
||||||
|
partial: &PartialMember,
|
||||||
|
remove: Vec<FieldsMember>,
|
||||||
|
) -> Result<()>;
|
||||||
|
|
||||||
|
/// Delete a server member by their id
|
||||||
|
async fn delete_member(&self, id: &MemberCompositeKey) -> Result<()>;
|
||||||
|
}
|
||||||
178
crates/core/database/src/models/server_members/ops/mongodb.rs
Normal file
178
crates/core/database/src/models/server_members/ops/mongodb.rs
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
use futures::StreamExt;
|
||||||
|
use revolt_result::Result;
|
||||||
|
|
||||||
|
use crate::{FieldsMember, Member, MemberCompositeKey, PartialMember};
|
||||||
|
use crate::{IntoDocumentPath, MongoDb};
|
||||||
|
|
||||||
|
use super::AbstractServerMembers;
|
||||||
|
|
||||||
|
static COL: &str = "server_members";
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AbstractServerMembers for MongoDb {
|
||||||
|
/// Insert a new server member into the database
|
||||||
|
async fn insert_member(&self, member: &Member) -> Result<()> {
|
||||||
|
query!(self, insert_one, COL, &member).map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch a server member by their id
|
||||||
|
async fn fetch_member(&self, server_id: &str, user_id: &str) -> Result<Member> {
|
||||||
|
query!(
|
||||||
|
self,
|
||||||
|
find_one,
|
||||||
|
COL,
|
||||||
|
doc! {
|
||||||
|
"_id.server": server_id,
|
||||||
|
"_id.user": user_id
|
||||||
|
}
|
||||||
|
)?
|
||||||
|
.ok_or_else(|| create_error!(NotFound))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch all members in a server
|
||||||
|
async fn fetch_all_members<'a>(&self, server_id: &str) -> Result<Vec<Member>> {
|
||||||
|
Ok(self
|
||||||
|
.col::<Member>(COL)
|
||||||
|
.find(
|
||||||
|
doc! {
|
||||||
|
"_id.server": server_id
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|_| create_database_error!("find", COL))?
|
||||||
|
.filter_map(|s| async {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
Some(s.unwrap())
|
||||||
|
} else {
|
||||||
|
s.ok()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
.await)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch all memberships for a user
|
||||||
|
async fn fetch_all_memberships<'a>(&self, user_id: &str) -> Result<Vec<Member>> {
|
||||||
|
Ok(self
|
||||||
|
.col::<Member>(COL)
|
||||||
|
.find(
|
||||||
|
doc! {
|
||||||
|
"_id.user": user_id
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|_| create_database_error!("find", COL))?
|
||||||
|
.filter_map(|s| async {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
Some(s.unwrap())
|
||||||
|
} else {
|
||||||
|
s.ok()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
.await)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch multiple members by their ids
|
||||||
|
async fn fetch_members<'a>(&self, server_id: &str, ids: &'a [String]) -> Result<Vec<Member>> {
|
||||||
|
Ok(self
|
||||||
|
.col::<Member>(COL)
|
||||||
|
.find(
|
||||||
|
doc! {
|
||||||
|
"_id.server": server_id,
|
||||||
|
"_id.user": {
|
||||||
|
"$in": ids
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|_| create_database_error!("find", COL))?
|
||||||
|
.filter_map(|s| async {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
Some(s.unwrap())
|
||||||
|
} else {
|
||||||
|
s.ok()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
.await)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch member count of a server
|
||||||
|
async fn fetch_member_count(&self, server_id: &str) -> Result<usize> {
|
||||||
|
self.col::<Member>(COL)
|
||||||
|
.count_documents(
|
||||||
|
doc! {
|
||||||
|
"_id.server": server_id
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map(|c| c as usize)
|
||||||
|
.map_err(|_| create_database_error!("count_documents", COL))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch server count of a user
|
||||||
|
async fn fetch_server_count(&self, user_id: &str) -> Result<usize> {
|
||||||
|
self.col::<Member>(COL)
|
||||||
|
.count_documents(
|
||||||
|
doc! {
|
||||||
|
"_id.user": user_id
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map(|c| c as usize)
|
||||||
|
.map_err(|_| create_database_error!("count_documents", COL))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update information for a server member
|
||||||
|
async fn update_member(
|
||||||
|
&self,
|
||||||
|
id: &MemberCompositeKey,
|
||||||
|
partial: &PartialMember,
|
||||||
|
remove: Vec<FieldsMember>,
|
||||||
|
) -> Result<()> {
|
||||||
|
query!(
|
||||||
|
self,
|
||||||
|
update_one,
|
||||||
|
COL,
|
||||||
|
doc! {
|
||||||
|
"_id.server": &id.server,
|
||||||
|
"_id.user": &id.user
|
||||||
|
},
|
||||||
|
partial,
|
||||||
|
remove.iter().map(|x| x as &dyn IntoDocumentPath).collect(),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete a server member by their id
|
||||||
|
async fn delete_member(&self, id: &MemberCompositeKey) -> Result<()> {
|
||||||
|
query!(
|
||||||
|
self,
|
||||||
|
delete_one,
|
||||||
|
COL,
|
||||||
|
doc! {
|
||||||
|
"_id.server": &id.server,
|
||||||
|
"_id.user": &id.user
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoDocumentPath for FieldsMember {
|
||||||
|
fn as_path(&self) -> Option<&'static str> {
|
||||||
|
Some(match self {
|
||||||
|
FieldsMember::Avatar => "avatar",
|
||||||
|
FieldsMember::Nickname => "nickname",
|
||||||
|
FieldsMember::Roles => "roles",
|
||||||
|
FieldsMember::Timeout => "timeout",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
117
crates/core/database/src/models/server_members/ops/reference.rs
Normal file
117
crates/core/database/src/models/server_members/ops/reference.rs
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
use revolt_result::Result;
|
||||||
|
|
||||||
|
use crate::ReferenceDb;
|
||||||
|
use crate::{FieldsMember, Member, MemberCompositeKey, PartialMember};
|
||||||
|
|
||||||
|
use super::AbstractServerMembers;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AbstractServerMembers for ReferenceDb {
|
||||||
|
/// Insert a new server member into the database
|
||||||
|
async fn insert_member(&self, member: &Member) -> Result<()> {
|
||||||
|
let mut server_members = self.server_members.lock().await;
|
||||||
|
if server_members.contains_key(&member.id) {
|
||||||
|
Err(create_database_error!("insert", "member"))
|
||||||
|
} else {
|
||||||
|
server_members.insert(member.id.clone(), member.clone());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch a server member by their id
|
||||||
|
async fn fetch_member(&self, server_id: &str, user_id: &str) -> Result<Member> {
|
||||||
|
let server_members = self.server_members.lock().await;
|
||||||
|
server_members
|
||||||
|
.get(&MemberCompositeKey {
|
||||||
|
server: server_id.to_string(),
|
||||||
|
user: user_id.to_string(),
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.ok_or_else(|| create_error!(NotFound))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch all members in a server
|
||||||
|
async fn fetch_all_members<'a>(&self, server_id: &str) -> Result<Vec<Member>> {
|
||||||
|
let server_members = self.server_members.lock().await;
|
||||||
|
Ok(server_members
|
||||||
|
.values()
|
||||||
|
.filter(|member| member.id.server == server_id)
|
||||||
|
.cloned()
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch all memberships for a user
|
||||||
|
async fn fetch_all_memberships<'a>(&self, user_id: &str) -> Result<Vec<Member>> {
|
||||||
|
let server_members = self.server_members.lock().await;
|
||||||
|
Ok(server_members
|
||||||
|
.values()
|
||||||
|
.filter(|member| member.id.user == user_id)
|
||||||
|
.cloned()
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch multiple members by their ids
|
||||||
|
async fn fetch_members<'a>(&self, server_id: &str, ids: &'a [String]) -> Result<Vec<Member>> {
|
||||||
|
let server_members = self.server_members.lock().await;
|
||||||
|
ids.iter()
|
||||||
|
.map(|id| {
|
||||||
|
server_members
|
||||||
|
.get(&MemberCompositeKey {
|
||||||
|
server: server_id.to_string(),
|
||||||
|
user: id.to_string(),
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.ok_or_else(|| create_error!(NotFound))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch member count of a server
|
||||||
|
async fn fetch_member_count(&self, server_id: &str) -> Result<usize> {
|
||||||
|
let server_members = self.server_members.lock().await;
|
||||||
|
Ok(server_members
|
||||||
|
.values()
|
||||||
|
.filter(|member| member.id.server == server_id)
|
||||||
|
.count())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch server count of a user
|
||||||
|
async fn fetch_server_count(&self, user_id: &str) -> Result<usize> {
|
||||||
|
let server_members = self.server_members.lock().await;
|
||||||
|
Ok(server_members
|
||||||
|
.values()
|
||||||
|
.filter(|member| member.id.user == user_id)
|
||||||
|
.count())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update information for a server member
|
||||||
|
async fn update_member(
|
||||||
|
&self,
|
||||||
|
id: &MemberCompositeKey,
|
||||||
|
partial: &PartialMember,
|
||||||
|
remove: Vec<FieldsMember>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut server_members = self.server_members.lock().await;
|
||||||
|
if let Some(member) = server_members.get_mut(id) {
|
||||||
|
for field in remove {
|
||||||
|
#[allow(clippy::disallowed_methods)]
|
||||||
|
member.remove_field(&field);
|
||||||
|
}
|
||||||
|
|
||||||
|
member.apply_options(partial.clone());
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(create_error!(NotFound))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete a server member by their id
|
||||||
|
async fn delete_member(&self, id: &MemberCompositeKey) -> Result<()> {
|
||||||
|
let mut server_members = self.server_members.lock().await;
|
||||||
|
if server_members.remove(id).is_some() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(create_error!(NotFound))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -406,6 +406,13 @@ impl Role {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove field from Role
|
||||||
|
pub fn remove_field(&mut self, field: &FieldsRole) {
|
||||||
|
match field {
|
||||||
|
FieldsRole::Colour => self.colour = None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Delete a role
|
/// Delete a role
|
||||||
pub async fn delete(self, db: &Database, server_id: &str, role_id: &str) -> Result<()> {
|
pub async fn delete(self, db: &Database, server_id: &str, role_id: &str) -> Result<()> {
|
||||||
/* // TODO: EventV1::ServerRoleDelete {
|
/* // TODO: EventV1::ServerRoleDelete {
|
||||||
@@ -417,13 +424,6 @@ impl Role {
|
|||||||
|
|
||||||
db.delete_role(server_id, role_id).await
|
db.delete_role(server_id, role_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove field from Role
|
|
||||||
pub fn remove_field(&mut self, field: &FieldsRole) {
|
|
||||||
match field {
|
|
||||||
FieldsRole::Colour => self.colour = None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemMessageChannels {
|
impl SystemMessageChannels {
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ impl AbstractUsers for MongoDb {
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| create_database_error!("find", "users"))?
|
.map_err(|_| create_database_error!("find", COL))?
|
||||||
.filter_map(|s| async {
|
.filter_map(|s| async {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
Some(s.unwrap())
|
Some(s.unwrap())
|
||||||
@@ -101,7 +101,7 @@ impl AbstractUsers for MongoDb {
|
|||||||
FindOptions::builder().projection(doc! { "_id": 1 }).build(),
|
FindOptions::builder().projection(doc! { "_id": 1 }).build(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| create_database_error!("find", "users"))?
|
.map_err(|_| create_database_error!("find", COL))?
|
||||||
.filter_map(|s| async { s.ok() })
|
.filter_map(|s| async { s.ok() })
|
||||||
.map(|user| user.id)
|
.map(|user| user.id)
|
||||||
.collect()
|
.collect()
|
||||||
@@ -278,7 +278,7 @@ impl AbstractUsers for MongoDb {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|_| create_database_error!("update_one", "user"))
|
.map_err(|_| create_database_error!("update_one", COL))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a user by their id
|
/// Delete a user by their id
|
||||||
|
|||||||
Reference in New Issue
Block a user