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}