Skip to main content

stoat/ext/
message.rs

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