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}