spectacles_rest/views/
channel.rs

1use futures::future::Future;
2use reqwest::Method;
3use reqwest::r#async::multipart::{Form, Part};
4
5use spectacles_model::channel::{Channel, ModifyChannelOptions};
6use spectacles_model::invite::{CreateInviteOptions, Invite};
7use spectacles_model::message::{GetReactionsOptions, Message, MessageResponse};
8use spectacles_model::snowflake::Snowflake;
9use spectacles_model::User;
10
11use crate::Endpoint;
12use crate::Error;
13use crate::RestClient;
14
15/// A view for interfacing with a Discord channel.
16pub struct ChannelView {
17    id: u64,
18    /// A view for interfacing with a channel's messages.
19    pub messages: ChannelMessagesView,
20    client: RestClient,
21}
22
23impl ChannelView {
24    pub(crate) fn new(id: u64, client: RestClient) -> Self {
25        Self {
26            id,
27            messages: ChannelMessagesView::new(id, client.clone()),
28            client,
29        }
30    }
31
32    /// Creates a message in the current channel.
33    /// This endpoint requires the Create Messages permission on Discord.
34    pub fn create_message<M: MessageResponse>(&self, payload: M) -> impl Future<Item=Message, Error=Error> {
35        let endpt = Endpoint::new(
36            Method::POST,
37            format!("/channels/{}/messages", self.id),
38        );
39        let create = payload.as_message();
40        let json = serde_json::to_string(&create).expect("Failed to serialize message");
41
42        if let Some((name, file)) = create.file {
43            self.client.request(endpt.multipart(
44                Form::new()
45                    .part("file", Part::bytes(file).file_name(name))
46                    .part("payload_json", Part::text(json))
47            ))
48        } else {
49            self.client.request(endpt.json(create))
50        }
51    }
52
53    /// Returns a view representing the messages in this channel.
54    pub fn messages(&self) -> ChannelMessagesView {
55        ChannelMessagesView::new(self.id, self.client.clone())
56    }
57
58    /// Creates an invite for the current channel.
59    /// Requires the Create Invite permission on Discord.
60    pub fn create_invite(&self, inv: CreateInviteOptions) -> impl Future<Item=Invite, Error=Error> {
61        self.client.request(
62            Endpoint::new(
63                Method::POST,
64                format!("/channels/{}/invites", self.id),
65            ).json(inv)
66        )
67    }
68
69    /// Edits a permission overwrite for a given channel.
70    pub fn edit_overwrite(&self, id: &Snowflake) -> impl Future<Item=(), Error=Error> {
71        self.client.request_empty(Endpoint::new(
72            Method::PUT,
73            format!("/channels/{}/permissions/{}", self.id, id.0),
74        ))
75    }
76
77    /// Deletes a permission overwrite for the current channel.
78    pub fn delete_overwrite(&self, id: &Snowflake) -> impl Future<Item=(), Error=Error> {
79        self.client.request_empty(Endpoint::new(
80            Method::DELETE,
81            format!("/channels/{}/permissions/{}", self.id, id.0),
82        ))
83    }
84
85    /// Gets a collection of all invites created for this channel.
86    pub fn get_invites(&self) -> impl Future<Item=Vec<Invite>, Error=Error> {
87        self.client.request(Endpoint::new(
88            Method::GET,
89            format!("/channels/{}/invites", self.id),
90        ))
91    }
92
93    /// Gets a list of all pinned messages in the channel.
94    pub fn get_pins(&self) -> impl Future<Item=Vec<Message>, Error=Error> {
95        self.client.request(Endpoint::new(
96            Method::GET,
97            format!("/channels/{}/pins", self.id))
98        )
99    }
100
101    /// Fetches a Channel object using the provided ID.
102    pub fn fetch(&self) -> impl Future<Item=Channel, Error=Error> {
103        self.client.request(Endpoint::new(
104            Method::GET,
105            format!("/channels/{}", self.id))
106        )
107    }
108
109    /// Deletes this channel from Discord, or in the case of a direct messages, closes the channel.
110    pub fn delete(&self) -> impl Future<Item=Channel, Error=Error> {
111        self.client.request(Endpoint::new(
112            Method::DELETE,
113            format!("/channels/{}", self.id))
114        )
115    }
116
117    /// Deletes a pinned message from this channel.
118    pub fn delete_pin(&self, mid: &Snowflake) -> impl Future<Item=(), Error=Error> {
119        self.client.request_empty(Endpoint::new(
120            Method::DELETE,
121            format!("/channels/{}/pins/{}", self.id, mid),
122        ))
123    }
124
125    /// Edits the message in this channel, with the given message ID.
126    pub fn edit_message(&self, mid: &Snowflake, payload: impl MessageResponse) -> impl Future<Item=Message, Error=Error> {
127        self.client.request(
128            Endpoint::new(
129                Method::PATCH,
130                format!("/channels/{}/messages/{}", self.id, mid),
131            ).json(payload.as_message())
132        )
133    }
134
135    /// Modifies this channel.
136    pub fn modify(&self, payload: ModifyChannelOptions) -> impl Future<Item=Channel, Error=Error> {
137        self.client.request(
138            Endpoint::new(
139                Method::PATCH,
140                format!("/channels/{}", self.id),
141            ).json(payload)
142        )
143    }
144
145    /// Triggers the typing indicator, authored by the client user, in the current channel.
146    pub fn trigger_typing(&self) -> impl Future<Item=(), Error=Error> {
147        self.client.request_empty(Endpoint::new(
148            Method::POST,
149            format!("/channels/{}/typing", self.id),
150        ))
151    }
152
153    /// Adds a pinned message to this channel.
154    pub fn pin_message(&self, mid: &Snowflake) -> impl Future<Item=(), Error=Error> {
155        self.client.request_empty(Endpoint::new(
156            Method::PUT,
157            format!("/channels/{}/pins/{}", self.id, mid),
158        ))
159    }
160}
161
162/// A view for managing a channel's messages.
163pub struct ChannelMessagesView {
164    id: u64,
165    client: RestClient,
166}
167
168impl ChannelMessagesView {
169    fn new(id: u64, client: RestClient) -> Self {
170        Self {
171            id,
172            client,
173        }
174    }
175
176    /// Fetches all messages in this channel.
177    pub fn get_all(&self) -> impl Future<Item=Vec<Message>, Error=Error> {
178        self.client.request(Endpoint::new(
179            Method::GET,
180            format!("/channels/{}/messages", self.id),
181        ))
182    }
183
184    /// Gets a single message in this channel, with the provided ID.
185    pub fn get(&self, mid: &Snowflake) -> impl Future<Item=Message, Error=Error> {
186        self.client.request(Endpoint::new(
187            Method::GET,
188            format!("/channels/{}/messages/{}", self.id, mid.0),
189        ))
190    }
191
192    /// Deletes a message from this channel.
193    pub fn delete(&self, mid: Snowflake) -> impl Future<Item=Message, Error=Error> {
194        self.client.request(Endpoint::new(
195            Method::DELETE,
196            format!("/channels/{}/messages/{}", self.id, mid.0),
197        ))
198    }
199
200    /// Deletes multiple messages in one request for a single channel.
201    pub fn bulk_delete(&self, ids: Vec<Snowflake>) -> impl Future<Item=(), Error=Error> {
202        let json = json!({
203            "messages": ids
204        });
205
206        self.client.request_empty(
207            Endpoint::new(
208                Method::POST,
209                format!("/channels/{}/messages/bulk-delete", self.id),
210            ).json(json)
211        )
212    }
213
214    /// A view for managing a message's reactions.
215    pub fn reactions(&self, mid: Snowflake) -> ChannelMessageReactionsView {
216        ChannelMessageReactionsView::new(self.id, mid.0, self.client.clone())
217    }
218}
219
220/// A view for working with a a message's reactions.
221pub struct ChannelMessageReactionsView {
222    id: u64,
223    message_id: u64,
224    client: RestClient,
225}
226
227impl ChannelMessageReactionsView {
228    fn new(id: u64, message_id: u64, client: RestClient) -> Self {
229        Self {
230            id,
231            message_id,
232            client
233        }
234    }
235    /// Get a list of users who have reacted to this message with the provided emoji.
236    pub fn get(&self, id: &Snowflake, opts: GetReactionsOptions) -> impl Future<Item=Vec<User>, Error=Error> {
237        self.client.request(
238            Endpoint::new(
239                Method::GET,
240                format!("/channels/{}/messages/{}/reactions/{}", self.id, self.message_id, id.0),
241            ).query(opts)
242        )
243    }
244
245    pub fn delete_all(&self) -> impl Future<Item=(), Error=Error> {
246        self.client.request_empty(Endpoint::new(
247            Method::DELETE,
248            format!("/channels/{}/messages/{}/reactions", self.id, self.message_id),
249        ))
250    }
251}