Skip to main content

stoat/ext/
message.rs

1use crate::{
2    HttpClient, Identifiable, Result,
3    builders::{EditMessageBuilder, SendMessageBuilder},
4    types::StoatConfig,
5};
6use async_trait::async_trait;
7use stoat_models::v0::{Message, OptionsUnreact};
8
9#[async_trait]
10pub trait MessageExt {
11    fn reply(&self, http: impl AsRef<HttpClient>, mention: bool) -> SendMessageBuilder;
12    fn edit(&self, http: impl AsRef<HttpClient>) -> EditMessageBuilder;
13    async fn delete(&self, http: impl AsRef<HttpClient> + Send) -> Result<()>;
14    async fn clear_reactions(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()>;
15    async fn pin_message(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()>;
16    async fn unpin_message(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()>;
17    async fn react(&mut self, http: impl AsRef<HttpClient> + Send, emoji: &str) -> Result<()>;
18    async fn unreact(&mut self, http: impl AsRef<HttpClient> + Send, emoji: &str) -> Result<()>;
19    async fn remove_reaction(
20        &mut self,
21        http: impl AsRef<HttpClient> + Send,
22        emoji: &str,
23        options: &OptionsUnreact,
24    ) -> Result<()>;
25
26    fn jump_link(&self, config: impl AsRef<StoatConfig>) -> String;
27}
28
29#[async_trait]
30impl MessageExt for Message {
31    fn reply(&self, http: impl AsRef<HttpClient>, mention: bool) -> SendMessageBuilder {
32        let mut builder = SendMessageBuilder::new(http.as_ref().clone(), self.channel.clone());
33        builder.reply(self.id.clone(), mention);
34        builder
35    }
36
37    fn edit(&self, http: impl AsRef<HttpClient>) -> EditMessageBuilder {
38        EditMessageBuilder::new(http.as_ref().clone(), self.channel.clone(), self.id.clone())
39    }
40
41    async fn delete(&self, http: impl AsRef<HttpClient> + Send) -> Result<()> {
42        http.as_ref().delete_message(&self.channel, &self.id).await
43    }
44
45    async fn clear_reactions(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()> {
46        http.as_ref()
47            .clear_reactions(&self.channel, &self.id)
48            .await?;
49
50        self.reactions.clear();
51
52        Ok(())
53    }
54
55    async fn pin_message(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()> {
56        http.as_ref().pin_message(&self.channel, &self.id).await?;
57
58        self.pinned = Some(true);
59
60        Ok(())
61    }
62
63    async fn unpin_message(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()> {
64        http.as_ref().unpin_message(&self.channel, &self.id).await?;
65
66        self.pinned = None;
67
68        Ok(())
69    }
70
71    async fn react(&mut self, http: impl AsRef<HttpClient> + Send, emoji: &str) -> Result<()> {
72        http.as_ref()
73            .react_message(&self.channel, &self.id, emoji)
74            .await?;
75
76        if let Some(user_id) = http.as_ref().user_id.clone() {
77            self.reactions
78                .entry(emoji.to_string())
79                .or_default()
80                .insert(user_id);
81        };
82
83        Ok(())
84    }
85
86    async fn unreact(&mut self, http: impl AsRef<HttpClient> + Send, emoji: &str) -> Result<()> {
87        http.as_ref()
88            .unreact_message(
89                &self.channel,
90                &self.id,
91                emoji,
92                &OptionsUnreact {
93                    user_id: None,
94                    remove_all: None,
95                },
96            )
97            .await?;
98
99        if let Some(user_id) = &http.as_ref().user_id {
100            if let Some(users) = self.reactions.get_mut(emoji) {
101                users.remove(user_id);
102            };
103        };
104
105        Ok(())
106    }
107
108    async fn remove_reaction(
109        &mut self,
110        http: impl AsRef<HttpClient> + Send,
111        emoji: &str,
112        options: &OptionsUnreact,
113    ) -> Result<()> {
114        http.as_ref()
115            .unreact_message(&self.channel, &self.id, emoji, options)
116            .await?;
117
118        if options.remove_all == Some(true) {
119            self.reactions.remove(emoji);
120        } else if let Some(user_id) = &options.user_id {
121            if let Some(users) = self.reactions.get_mut(emoji) {
122                users.remove(user_id);
123            };
124        } else if let Some(user_id) = &http.as_ref().user_id {
125            if let Some(users) = self.reactions.get_mut(emoji) {
126                users.remove(user_id);
127            };
128        };
129
130        Ok(())
131    }
132
133    fn jump_link(&self, config: impl AsRef<StoatConfig>) -> String {
134        format!(
135            "{}/channel/{}/{}",
136            &config.as_ref().app,
137            &self.channel,
138            &self.id
139        )
140    }
141}
142
143impl Identifiable for Message {
144    fn id(&self) -> &str {
145        &self.id
146    }
147}