Skip to main content

stoat/ext/
user.rs

1use std::time::SystemTime;
2
3use async_trait::async_trait;
4use bytes::Bytes;
5use stoat_models::v0::{
6    DataEditUser, FlagResponse, MutualResponse, User, UserProfile, UserVoiceState,
7};
8
9use crate::{
10    GlobalCache, HttpClient, Identifiable, Result, builders::SendMessageBuilder, created_at,
11};
12
13#[async_trait]
14pub trait UserExt {
15    fn mention(&self) -> String;
16    fn name(&self) -> &str;
17
18    fn voice(&self, cache: impl AsRef<GlobalCache>) -> Vec<(String, UserVoiceState)>;
19
20    async fn send(&self, http: impl AsRef<HttpClient> + Send) -> Result<SendMessageBuilder>;
21    async fn edit(
22        &mut self,
23        http: impl AsRef<HttpClient> + Send,
24        data: &DataEditUser,
25    ) -> Result<()>;
26    async fn fetch_profile(&self, http: impl AsRef<HttpClient> + Send) -> Result<UserProfile>;
27    async fn fetch_flags(&self, http: impl AsRef<HttpClient> + Send) -> Result<FlagResponse>;
28    async fn fetch_mutuals(&self, http: impl AsRef<HttpClient> + Send) -> Result<MutualResponse>;
29    async fn fetch_default_avatar(&self, http: impl AsRef<HttpClient> + Send) -> Result<Bytes>;
30}
31
32#[async_trait]
33impl UserExt for User {
34    fn mention(&self) -> String {
35        format!("<@{}>", &self.id)
36    }
37
38    fn name(&self) -> &str {
39        self.display_name.as_deref().unwrap_or(&self.username)
40    }
41
42    fn voice(&self, cache: impl AsRef<GlobalCache>) -> Vec<(String, UserVoiceState)> {
43        let mut states = Vec::new();
44
45        cache.as_ref().servers.iter_sync(|_, server| {
46            for channel in &server.channels {
47                if let Some(channel_voice_state) = cache.as_ref().voice_states.get_sync(channel) {
48                    if let Some(user_voice_state) = channel_voice_state
49                        .participants
50                        .iter()
51                        .find(|s| &s.id == &self.id)
52                    {
53                        states.push((channel.clone(), user_voice_state.clone()));
54                    }
55                }
56            }
57
58            true
59        });
60
61        states
62    }
63
64    async fn send(&self, http: impl AsRef<HttpClient> + Send) -> Result<SendMessageBuilder> {
65        let dm_channel = http.as_ref().open_dm(&self.id).await?;
66
67        Ok(SendMessageBuilder::new(
68            http.as_ref().clone(),
69            dm_channel.id().to_string(),
70        ))
71    }
72
73    async fn edit(
74        &mut self,
75        http: impl AsRef<HttpClient> + Send,
76        data: &DataEditUser,
77    ) -> Result<()> {
78        let user = http.as_ref().edit_user(&self.id, data).await?;
79
80        *self = user;
81
82        Ok(())
83    }
84
85    async fn fetch_profile(&self, http: impl AsRef<HttpClient> + Send) -> Result<UserProfile> {
86        http.as_ref().fetch_user_profile(&self.id).await
87    }
88
89    async fn fetch_flags(&self, http: impl AsRef<HttpClient> + Send) -> Result<FlagResponse> {
90        http.as_ref().fetch_user_flags(&self.id).await
91    }
92
93    async fn fetch_mutuals(&self, http: impl AsRef<HttpClient> + Send) -> Result<MutualResponse> {
94        http.as_ref().fetch_user_mutuals(&self.id).await
95    }
96
97    async fn fetch_default_avatar(&self, http: impl AsRef<HttpClient> + Send) -> Result<Bytes> {
98        http.as_ref().fetch_default_avatar(&self.id).await
99    }
100}
101
102impl Identifiable for User {
103    fn created_at(&self) -> SystemTime {
104        created_at(&self.id)
105    }
106}