revolt_database/models/server_members/
ops.rs

1#[cfg(feature = "mongodb")]
2use ::mongodb::{ClientSession, SessionCursor};
3
4use revolt_result::Result;
5
6use crate::{FieldsMember, Member, MemberCompositeKey, PartialMember};
7
8#[cfg(feature = "mongodb")]
9mod mongodb;
10mod reference;
11
12#[derive(Debug)]
13#[allow(clippy::large_enum_variant)]
14pub enum ChunkedServerMembersGenerator {
15    #[cfg(feature = "mongodb")]
16    MongoDb {
17        session: ClientSession,
18        cursor: Option<SessionCursor<Member>>,
19    },
20
21    Reference {
22        offset: i32,
23        data: Option<Vec<Member>>,
24    },
25}
26
27impl ChunkedServerMembersGenerator {
28    #[cfg(feature = "mongodb")]
29    pub fn new_mongo(session: ClientSession, cursor: SessionCursor<Member>) -> Self {
30        ChunkedServerMembersGenerator::MongoDb {
31            session,
32            cursor: Some(cursor),
33        }
34    }
35
36    pub fn new_reference(data: Vec<Member>) -> Self {
37        ChunkedServerMembersGenerator::Reference {
38            offset: 0,
39            data: Some(data),
40        }
41    }
42
43    pub async fn next(&mut self) -> Option<Member> {
44        match self {
45            #[cfg(feature = "mongodb")]
46            ChunkedServerMembersGenerator::MongoDb { session, cursor } => {
47                if let Some(cursor) = cursor {
48                    let value = cursor.next(session).await;
49                    value.map(|val| val.expect("Failed to fetch the next member"))
50                } else {
51                    warn!("Attempted to access a (MongoDb) server member generator without first setting a cursor");
52                    None
53                }
54            }
55            ChunkedServerMembersGenerator::Reference { offset, data } => {
56                if let Some(data) = data {
57                    if data.len() as i32 >= *offset {
58                        None
59                    } else {
60                        let resp = &data[*offset as usize];
61                        *offset += 1;
62                        Some(resp.clone())
63                    }
64                } else {
65                    warn!("Attempted to access a (Reference) server member generator without first providing data");
66                    None
67                }
68            }
69        }
70    }
71}
72
73#[async_trait]
74pub trait AbstractServerMembers: Sync + Send {
75    /// Insert a new server member into the database
76    async fn insert_or_merge_member(&self, member: &Member) -> Result<Option<Member>>;
77
78    /// Fetch a server member by their id
79    async fn fetch_member(&self, server_id: &str, user_id: &str) -> Result<Member>;
80
81    /// Fetch all members in a server
82    async fn fetch_all_members(&self, server_id: &str) -> Result<Vec<Member>>;
83
84    /// Fetch all members in a server as an iterator
85    async fn fetch_all_members_chunked(
86        &self,
87        server_id: &str,
88    ) -> Result<ChunkedServerMembersGenerator>;
89
90    async fn fetch_all_members_with_roles(
91        &self,
92        server_id: &str,
93        roles: &[String],
94    ) -> Result<Vec<Member>>;
95
96    async fn fetch_all_members_with_roles_chunked(
97        &self,
98        server_id: &str,
99        roles: &[String],
100    ) -> Result<ChunkedServerMembersGenerator>;
101
102    /// Fetch all memberships for a user
103    async fn fetch_all_memberships(&self, user_id: &str) -> Result<Vec<Member>>;
104
105    /// Fetch multiple members by their ids
106    async fn fetch_members(&self, server_id: &str, ids: &[String]) -> Result<Vec<Member>>;
107
108    /// Fetch member count of a server
109    async fn fetch_member_count(&self, server_id: &str) -> Result<usize>;
110
111    /// Fetch server count of a user
112    async fn fetch_server_count(&self, user_id: &str) -> Result<usize>;
113
114    /// Update information for a server member
115    async fn update_member(
116        &self,
117        id: &MemberCompositeKey,
118        partial: &PartialMember,
119        remove: Vec<FieldsMember>,
120    ) -> Result<()>;
121
122    /// Marks a user as no longer a member of a server, while retaining the database value.
123    /// This is used to keep information such as timeouts in place, but will remove information such as join date and applied roles.
124    async fn soft_delete_member(&self, id: &MemberCompositeKey) -> Result<()>;
125
126    /// Forcibly delete a server member by their id.
127    /// This will cancel any pending timeouts or other longer term actions, and they will not be reapplied on rejoin.
128    async fn force_delete_member(&self, id: &MemberCompositeKey) -> Result<()>;
129
130    /// Fetch all members who have been marked for deletion.
131    async fn remove_dangling_members(&self) -> Result<()>;
132}