Skip to main content

stoat/ext/
channel.rs

1use std::collections::HashMap;
2
3use crate::{
4    HttpClient, Identifiable, Result,
5    builders::{EditChannelBuilder, FetchMessagesBuilder, SendMessageBuilder},
6    context::Events,
7    utils,
8};
9use async_trait::async_trait;
10use stoat_models::v0::{
11    Channel, CreateWebhookBody, DataDefaultChannelPermissions, DataSetRolePermissions, File,
12    Message, OptionsBulkDelete, VoiceInformation, Webhook,
13};
14use stoat_permissions::{Override, OverrideField};
15
16#[async_trait]
17pub trait ChannelExt: Identifiable {
18    fn user(&self) -> Option<&str>;
19    fn active(&self) -> Option<bool>;
20    fn recipients(&self) -> Option<&Vec<String>>;
21    fn last_message_id(&self) -> Option<&str>;
22    fn owner(&self) -> Option<&str>;
23    fn description(&self) -> Option<&str>;
24    fn permissions(&self) -> Option<i64>;
25    fn nsfw(&self) -> Option<bool>;
26    fn default_permissions(&self) -> Option<&OverrideField>;
27    fn role_permissions(&self) -> Option<&HashMap<String, OverrideField>>;
28    fn voice(&self) -> Option<&VoiceInformation>;
29    fn server(&self) -> Option<&str>;
30    fn name(&self) -> Option<&str>;
31    fn icon(&self) -> Option<&File>;
32
33    fn supports_voice(&self) -> bool;
34    fn mention(&self) -> String;
35
36    #[cfg(feature = "voice")]
37    fn voice_client(&self, cache: impl AsRef<crate::GlobalCache>)
38    -> Option<crate::VoiceConnection>;
39
40    async fn with_typing<Fut: Future<Output = R> + Send, R>(
41        &self,
42        events: impl AsRef<Events> + Send,
43        fut: Fut,
44    ) -> R;
45
46    fn send(&self, http: impl AsRef<HttpClient>) -> SendMessageBuilder;
47    async fn fetch_message(
48        &self,
49        http: impl AsRef<HttpClient> + Send,
50        message_id: &str,
51    ) -> Result<Message>;
52    fn fetch_messages(&self, http: impl AsRef<HttpClient>) -> FetchMessagesBuilder;
53    #[cfg(feature = "voice")]
54    async fn join_call(
55        &self,
56        http: impl AsRef<HttpClient> + Send,
57        cache: impl AsRef<crate::GlobalCache> + Send,
58        node: Option<String>,
59    ) -> Result<crate::VoiceConnection>;
60    async fn delete(&self, http: impl AsRef<HttpClient> + Send) -> Result<()>;
61    async fn edit(&self, http: impl AsRef<HttpClient> + Send) -> EditChannelBuilder;
62    async fn delete_messages(
63        &self,
64        http: impl AsRef<HttpClient> + Send,
65        options: &OptionsBulkDelete,
66    ) -> Result<()>;
67    async fn set_default_permissions(
68        &self,
69        http: impl AsRef<HttpClient> + Send,
70        data: &DataDefaultChannelPermissions,
71    ) -> Result<Channel>;
72    async fn set_role_permissions(
73        &self,
74        http: impl AsRef<HttpClient> + Send,
75        role_id: &str,
76        allow: u64,
77        deny: u64,
78    ) -> Result<Channel>;
79    async fn create_webhook(
80        &self,
81        http: impl AsRef<HttpClient> + Send,
82        data: &CreateWebhookBody,
83    ) -> Result<Webhook>;
84}
85
86#[async_trait]
87impl ChannelExt for Channel {
88    fn user(&self) -> Option<&str> {
89        match self {
90            Channel::SavedMessages { user, .. } => Some(user),
91            _ => None,
92        }
93    }
94
95    fn active(&self) -> Option<bool> {
96        match self {
97            Channel::DirectMessage { active, .. } => Some(*active),
98            _ => None,
99        }
100    }
101
102    fn recipients(&self) -> Option<&Vec<String>> {
103        match self {
104            Channel::DirectMessage { recipients, .. } | Channel::Group { recipients, .. } => {
105                Some(recipients)
106            }
107            _ => None,
108        }
109    }
110
111    fn last_message_id(&self) -> Option<&str> {
112        match self {
113            Channel::DirectMessage {
114                last_message_id, ..
115            }
116            | Channel::TextChannel {
117                last_message_id, ..
118            }
119            | Channel::Group {
120                last_message_id, ..
121            } => last_message_id.as_deref(),
122            _ => None,
123        }
124    }
125
126    fn owner(&self) -> Option<&str> {
127        match self {
128            Channel::Group { owner, .. } => Some(owner),
129            _ => None,
130        }
131    }
132
133    fn description(&self) -> Option<&str> {
134        match self {
135            Channel::TextChannel { description, .. } | Channel::Group { description, .. } => {
136                description.as_deref()
137            }
138            _ => None,
139        }
140    }
141
142    fn permissions(&self) -> Option<i64> {
143        match self {
144            Channel::Group { permissions, .. } => *permissions,
145            _ => None,
146        }
147    }
148
149    fn nsfw(&self) -> Option<bool> {
150        match self {
151            Channel::TextChannel { nsfw, .. } | Channel::Group { nsfw, .. } => Some(*nsfw),
152            _ => None,
153        }
154    }
155
156    fn default_permissions(&self) -> Option<&OverrideField> {
157        match self {
158            Channel::TextChannel {
159                default_permissions,
160                ..
161            } => default_permissions.as_ref(),
162            _ => None,
163        }
164    }
165
166    fn role_permissions(&self) -> Option<&HashMap<String, OverrideField>> {
167        match self {
168            Channel::TextChannel {
169                role_permissions, ..
170            } => Some(role_permissions),
171            _ => None,
172        }
173    }
174
175    fn voice(&self) -> Option<&VoiceInformation> {
176        match self {
177            Channel::TextChannel { voice, .. } => voice.as_ref(),
178            _ => None,
179        }
180    }
181
182    fn supports_voice(&self) -> bool {
183        match self {
184            Channel::DirectMessage { .. }
185            | Channel::Group { .. }
186            | Channel::SavedMessages { .. } => true,
187            Channel::TextChannel { voice, .. } => voice.is_some(),
188        }
189    }
190
191    fn server(&self) -> Option<&str> {
192        match self {
193            Channel::TextChannel { server, .. } => Some(server),
194            _ => None,
195        }
196    }
197
198    fn name(&self) -> Option<&str> {
199        match self {
200            Channel::SavedMessages { .. } => Some("Saved Messages"),
201            Channel::DirectMessage { .. } => None,
202            Channel::Group { name, .. } | Channel::TextChannel { name, .. } => Some(name),
203        }
204    }
205
206    fn icon(&self) -> Option<&File> {
207        match self {
208            Channel::Group { icon, .. } | Channel::TextChannel { icon, .. } => icon.as_ref(),
209            _ => None,
210        }
211    }
212
213    fn mention(&self) -> String {
214        format!("<#{}>", self.id())
215    }
216
217    #[cfg(feature = "voice")]
218    fn voice_client(
219        &self,
220        cache: impl AsRef<crate::GlobalCache>,
221    ) -> Option<crate::VoiceConnection> {
222        cache.as_ref().get_voice_connection(self.id())
223    }
224
225    async fn with_typing<Fut: Future<Output = R> + Send, R>(
226        &self,
227        events: impl AsRef<Events> + Send,
228        fut: Fut,
229    ) -> R {
230        utils::with_typing(events.as_ref(), self.id().to_string(), fut).await
231    }
232
233    fn send(&self, http: impl AsRef<HttpClient>) -> SendMessageBuilder {
234        SendMessageBuilder::new(http.as_ref().clone(), self.id().to_string())
235    }
236
237    async fn fetch_message(
238        &self,
239        http: impl AsRef<HttpClient> + Send,
240        message_id: &str,
241    ) -> Result<Message> {
242        http.as_ref().fetch_message(self.id(), message_id).await
243    }
244
245    fn fetch_messages(&self, http: impl AsRef<HttpClient>) -> FetchMessagesBuilder {
246        FetchMessagesBuilder::new(http.as_ref().clone(), self.id().to_string())
247    }
248
249    #[cfg(feature = "voice")]
250    async fn join_call(
251        &self,
252        http: impl AsRef<HttpClient> + Send,
253        cache: impl AsRef<crate::GlobalCache> + Send,
254        node: Option<String>,
255    ) -> Result<crate::VoiceConnection> {
256        let response = http
257            .as_ref()
258            .join_call(
259                self.id(),
260                &stoat_models::v0::DataJoinCall {
261                    node,
262                    force_disconnect: None,
263                    recipients: None,
264                },
265            )
266            .await?;
267
268        crate::VoiceConnection::connect(cache.as_ref(), &response.url, &response.token).await
269    }
270
271    async fn delete(&self, http: impl AsRef<HttpClient> + Send) -> Result<()> {
272        http.as_ref().delete_channel(self.id()).await
273    }
274
275    async fn edit(&self, http: impl AsRef<HttpClient> + Send) -> EditChannelBuilder {
276        EditChannelBuilder::new(http.as_ref().clone(), self.id().to_string())
277    }
278
279    async fn delete_messages(
280        &self,
281        http: impl AsRef<HttpClient> + Send,
282        options: &OptionsBulkDelete,
283    ) -> Result<()> {
284        http.as_ref().delete_messages(self.id(), options).await
285    }
286
287    async fn set_default_permissions(
288        &self,
289        http: impl AsRef<HttpClient> + Send,
290        data: &DataDefaultChannelPermissions,
291    ) -> Result<Channel> {
292        http.as_ref()
293            .set_default_channel_permissions(self.id(), data)
294            .await
295    }
296
297    async fn set_role_permissions(
298        &self,
299        http: impl AsRef<HttpClient> + Send,
300        role_id: &str,
301        allow: u64,
302        deny: u64,
303    ) -> Result<Channel> {
304        http.as_ref()
305            .set_role_channel_permissions(
306                self.id(),
307                role_id,
308                &DataSetRolePermissions {
309                    permissions: Override { allow, deny },
310                },
311            )
312            .await
313    }
314
315    async fn create_webhook(
316        &self,
317        http: impl AsRef<HttpClient> + Send,
318        data: &CreateWebhookBody,
319    ) -> Result<Webhook> {
320        http.as_ref().create_webhook(self.id(), data).await
321    }
322}
323
324impl Identifiable for Channel {
325    fn id(&self) -> &str {
326        Channel::id(&self)
327    }
328}