Skip to main content

revolt_database/models/users/ops/
reference.rs

1use revolt_result::Result;
2
3use crate::{FieldsUser, PartialUser, RelationshipStatus, User};
4use crate::{ReferenceDb, Relationship};
5
6use super::AbstractUsers;
7
8#[async_trait]
9impl AbstractUsers for ReferenceDb {
10    /// Insert a new user into the database
11    async fn insert_user(&self, user: &User) -> Result<()> {
12        let mut users = self.users.lock().await;
13        if users.contains_key(&user.id) {
14            Err(create_database_error!("insert", "user"))
15        } else {
16            users.insert(user.id.to_string(), user.clone());
17            Ok(())
18        }
19    }
20
21    /// Fetch a user from the database
22    async fn fetch_user(&self, id: &str) -> Result<User> {
23        let users = self.users.lock().await;
24        users
25            .get(id)
26            .cloned()
27            .ok_or_else(|| create_error!(NotFound))
28    }
29
30    /// Fetch a user from the database by their username
31    async fn fetch_user_by_username(&self, username: &str, discriminator: &str) -> Result<User> {
32        let users = self.users.lock().await;
33        let lowercase = username.to_lowercase();
34        users
35            .values()
36            .find(|user| {
37                user.username.to_lowercase() == lowercase && user.discriminator == discriminator
38            })
39            .cloned()
40            .ok_or_else(|| create_error!(NotFound))
41    }
42
43    /// Fetch multiple users by their ids
44    async fn fetch_users<'a>(&self, ids: &'a [String]) -> Result<Vec<User>> {
45        let users = self.users.lock().await;
46        ids.iter()
47            .map(|id| {
48                users
49                    .get(id)
50                    .cloned()
51                    .ok_or_else(|| create_error!(NotFound))
52            })
53            .collect()
54    }
55
56    /// Fetch all discriminators in use for a username
57    async fn fetch_discriminators_in_use(&self, username: &str) -> Result<Vec<String>> {
58        let users = self.users.lock().await;
59        let lowercase = username.to_lowercase();
60        Ok(users
61            .values()
62            .filter(|user| user.username.to_lowercase() == lowercase)
63            .map(|user| &user.discriminator)
64            .cloned()
65            .collect())
66    }
67
68    /// Fetch ids of users that both users are friends with
69    async fn fetch_mutual_user_ids(&self, _user_a: &str, _user_b: &str) -> Result<Vec<String>> {
70        todo!()
71    }
72
73    /// Fetch ids of channels that both users are in
74    async fn fetch_mutual_channel_ids(&self, _user_a: &str, _user_b: &str) -> Result<Vec<String>> {
75        todo!()
76    }
77
78    /// Fetch ids of servers that both users share
79    async fn fetch_mutual_server_ids(&self, _user_a: &str, _user_b: &str) -> Result<Vec<String>> {
80        todo!()
81    }
82
83    /// Update a user by their id given some data
84    async fn update_user(
85        &self,
86        id: &str,
87        partial: &PartialUser,
88        remove: Vec<FieldsUser>,
89    ) -> Result<()> {
90        let mut users = self.users.lock().await;
91        if let Some(user) = users.get_mut(id) {
92            for field in remove {
93                #[allow(clippy::disallowed_methods)]
94                user.remove_field(&field);
95            }
96
97            user.apply_options(partial.clone());
98            Ok(())
99        } else {
100            Err(create_error!(NotFound))
101        }
102    }
103
104    /// Set relationship with another user
105    ///
106    /// This should use pull_relationship if relationship is None or User.
107    async fn set_relationship(
108        &self,
109        user_id: &str,
110        target_id: &str,
111        relationship: &RelationshipStatus,
112    ) -> Result<()> {
113        if let RelationshipStatus::User | RelationshipStatus::None = &relationship {
114            self.pull_relationship(user_id, target_id).await
115        } else {
116            let mut users = self.users.lock().await;
117            let user = users
118                .get_mut(user_id)
119                .ok_or_else(|| create_error!(NotFound))?;
120
121            let relation = Relationship {
122                id: target_id.to_string(),
123                status: relationship.clone(),
124            };
125
126            if let Some(relations) = &mut user.relations {
127                relations.retain(|relation| relation.id != target_id);
128                relations.push(relation);
129            } else {
130                user.relations = Some(vec![relation]);
131            }
132
133            Ok(())
134        }
135    }
136
137    /// Remove relationship with another user
138    async fn pull_relationship(&self, user_id: &str, target_id: &str) -> Result<()> {
139        let mut users = self.users.lock().await;
140        let user = users
141            .get_mut(user_id)
142            .ok_or_else(|| create_error!(NotFound))?;
143
144        if let Some(relations) = &mut user.relations {
145            relations.retain(|relation| relation.id != target_id);
146        }
147
148        Ok(())
149    }
150
151    /// Delete a user by their id
152    async fn delete_user(&self, id: &str) -> Result<()> {
153        let mut users = self.users.lock().await;
154        if users.remove(id).is_some() {
155            Ok(())
156        } else {
157            Err(create_error!(NotFound))
158        }
159    }
160
161    /// Removes all relationships with the user from the list of users
162    async fn clear_user_relationships(
163        &self,
164        target_id: &str,
165        user_ids: Vec<String>,
166    ) -> Result<()> {
167        let mut users = self.users.lock().await;
168
169        for user_id in user_ids {
170            if let Some(user) = users.get_mut(&user_id) {
171                if let Some(relations) = &mut user.relations {
172                    relations.retain(|relation| relation.id != target_id);
173                }
174            }
175        }
176
177        Ok(())
178    }
179}