serenity/model/channel/private_channel.rs
1use std::fmt;
2#[cfg(feature = "model")]
3use std::sync::Arc;
4
5#[cfg(feature = "model")]
6use crate::builder::{CreateAttachment, CreateMessage, EditMessage, GetMessages};
7#[cfg(feature = "model")]
8use crate::http::CacheHttp;
9#[cfg(feature = "model")]
10use crate::http::{Http, Typing};
11use crate::model::prelude::*;
12use crate::model::utils::single_recipient;
13
14/// A Direct Message text channel with another user.
15///
16/// [Discord docs](https://discord.com/developers/docs/resources/channel#channel-object).
17#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
18#[derive(Clone, Debug, Default, Deserialize, Serialize)]
19#[non_exhaustive]
20pub struct PrivateChannel {
21 /// The unique Id of the private channel.
22 ///
23 /// Can be used to calculate the first message's creation date.
24 pub id: ChannelId,
25 /// The Id of the last message sent.
26 pub last_message_id: Option<MessageId>,
27 /// Timestamp of the last time a [`Message`] was pinned.
28 pub last_pin_timestamp: Option<Timestamp>,
29 /// Indicator of the type of channel this is.
30 ///
31 /// This should always be [`ChannelType::Private`].
32 #[serde(rename = "type")]
33 pub kind: ChannelType,
34 /// The recipient to the private channel.
35 #[serde(with = "single_recipient", rename = "recipients")]
36 pub recipient: User,
37}
38
39#[cfg(feature = "model")]
40impl PrivateChannel {
41 /// Broadcasts that the current user is typing to the recipient.
42 ///
43 /// See [ChannelId::broadcast_typing] for more details.
44 #[allow(clippy::missing_errors_doc)]
45 #[inline]
46 pub async fn broadcast_typing(&self, http: impl AsRef<Http>) -> Result<()> {
47 self.id.broadcast_typing(http).await
48 }
49
50 /// React to a [`Message`] with a custom [`Emoji`] or unicode character.
51 ///
52 /// [`Message::react`] may be a more suited method of reacting in most cases.
53 ///
54 /// # Errors
55 ///
56 /// Returns [`Error::Http`] if the reaction cannot be added, or if a message with that Id does
57 /// not exist.
58 #[inline]
59 pub async fn create_reaction(
60 &self,
61 http: impl AsRef<Http>,
62 message_id: impl Into<MessageId>,
63 reaction_type: impl Into<ReactionType>,
64 ) -> Result<()> {
65 self.id.create_reaction(http, message_id, reaction_type).await
66 }
67
68 /// Deletes the channel. This does not delete the contents of the channel, and is equivalent to
69 /// closing a private channel on the client, which can be re-opened.
70 #[allow(clippy::missing_errors_doc)]
71 #[inline]
72 pub async fn delete(&self, http: impl AsRef<Http>) -> Result<PrivateChannel> {
73 self.id.delete(http).await?.private().ok_or(Error::Model(ModelError::InvalidChannelType))
74 }
75
76 /// Deletes all messages by Ids from the given vector in the channel.
77 ///
78 /// The minimum amount of messages is 2 and the maximum amount is 100.
79 ///
80 /// Requires the [Manage Messages] permission.
81 ///
82 /// **Note**: Messages that are older than 2 weeks can't be deleted using this method.
83 ///
84 /// # Errors
85 ///
86 /// Returns [`ModelError::BulkDeleteAmount`] if an attempt was made to delete either 0 or more
87 /// than 100 messages.
88 ///
89 /// [Manage Messages]: Permissions::MANAGE_MESSAGES
90 #[inline]
91 pub async fn delete_messages<T: AsRef<MessageId>>(
92 &self,
93 http: impl AsRef<Http>,
94 message_ids: impl IntoIterator<Item = T>,
95 ) -> Result<()> {
96 self.id.delete_messages(http, message_ids).await
97 }
98
99 /// Deletes all permission overrides in the channel from a member or role.
100 ///
101 /// **Note**: Requires the [Manage Channel] permission.
102 ///
103 /// [Manage Channel]: Permissions::MANAGE_CHANNELS
104 #[allow(clippy::missing_errors_doc)]
105 #[inline]
106 pub async fn delete_permission(
107 &self,
108 http: impl AsRef<Http>,
109 permission_type: PermissionOverwriteType,
110 ) -> Result<()> {
111 self.id.delete_permission(http, permission_type).await
112 }
113
114 /// Deletes the given [`Reaction`] from the channel.
115 ///
116 /// **Note**: In private channels, the current user may only delete it's own reactions.
117 ///
118 /// # Errors
119 ///
120 /// Returns [`Error::Http`] if the reaction is not from the current user.
121 #[inline]
122 pub async fn delete_reaction(
123 &self,
124 http: impl AsRef<Http>,
125 message_id: impl Into<MessageId>,
126 user_id: Option<UserId>,
127 reaction_type: impl Into<ReactionType>,
128 ) -> Result<()> {
129 self.id.delete_reaction(http, message_id, user_id, reaction_type).await
130 }
131
132 /// Edits a [`Message`] in the channel given its Id.
133 ///
134 /// Message editing preserves all unchanged message data, with some exceptions for embeds and
135 /// attachments.
136 ///
137 /// **Note**: In most cases requires that the current user be the author of the message.
138 ///
139 /// Refer to the documentation for [`EditMessage`] for information regarding content
140 /// restrictions and requirements.
141 ///
142 /// # Errors
143 ///
144 /// See [`EditMessage::execute`] for a list of possible errors, and their corresponding
145 /// reasons.
146 ///
147 /// [`EditMessage::execute`]: ../../builder/struct.EditMessage.html#method.execute
148 #[inline]
149 pub async fn edit_message(
150 &self,
151 cache_http: impl CacheHttp,
152 message_id: impl Into<MessageId>,
153 builder: EditMessage,
154 ) -> Result<Message> {
155 self.id.edit_message(cache_http, message_id, builder).await
156 }
157
158 /// Determines if the channel is NSFW.
159 #[inline]
160 #[must_use]
161 #[allow(clippy::unused_self)]
162 #[deprecated = "This always returns false"]
163 pub fn is_nsfw(&self) -> bool {
164 false
165 }
166
167 /// Gets a message from the channel.
168 ///
169 /// # Errors
170 ///
171 /// Returns [`Error::Http`] if a message with that Id does not exist in this channel.
172 #[inline]
173 pub async fn message(
174 &self,
175 cache_http: impl CacheHttp,
176 message_id: impl Into<MessageId>,
177 ) -> Result<Message> {
178 self.id.message(cache_http, message_id).await
179 }
180
181 /// Gets messages from the channel.
182 ///
183 /// **Note**: If the user does not have the [Read Message History] permission, returns an empty
184 /// [`Vec`].
185 ///
186 /// # Errors
187 ///
188 /// Returns [`Error::Http`] if the current user lacks permission.
189 ///
190 /// [Read Message History]: Permissions::READ_MESSAGE_HISTORY
191 #[inline]
192 pub async fn messages(
193 &self,
194 cache_http: impl CacheHttp,
195 builder: GetMessages,
196 ) -> Result<Vec<Message>> {
197 self.id.messages(cache_http, builder).await
198 }
199
200 /// Returns "DM with $username#discriminator".
201 #[must_use]
202 pub fn name(&self) -> String {
203 format!("DM with {}", self.recipient.tag())
204 }
205
206 /// Gets the list of [`User`]s who have reacted to a [`Message`] with a certain [`Emoji`].
207 ///
208 /// The default `limit` is `50` - specify otherwise to receive a different maximum number of
209 /// users. The maximum that may be retrieve at a time is `100`, if a greater number is provided
210 /// then it is automatically reduced.
211 ///
212 /// The optional `after` attribute is to retrieve the users after a certain user. This is
213 /// useful for pagination.
214 ///
215 /// # Errors
216 ///
217 /// Returns [`Error::Http`] if a message with the given Id does not exist in the channel.
218 #[inline]
219 pub async fn reaction_users(
220 &self,
221 http: impl AsRef<Http>,
222 message_id: impl Into<MessageId>,
223 reaction_type: impl Into<ReactionType>,
224 limit: Option<u8>,
225 after: impl Into<Option<UserId>>,
226 ) -> Result<Vec<User>> {
227 self.id.reaction_users(http, message_id, reaction_type, limit, after).await
228 }
229
230 /// Pins a [`Message`] to the channel.
231 ///
232 /// # Errors
233 ///
234 /// Returns [`Error::Http`] if the number of pinned messages would exceed the 50 message limit.
235 #[inline]
236 pub async fn pin(
237 &self,
238 http: impl AsRef<Http>,
239 message_id: impl Into<MessageId>,
240 ) -> Result<()> {
241 self.id.pin(http, message_id).await
242 }
243
244 /// Retrieves the list of messages that have been pinned in the private channel.
245 #[allow(clippy::missing_errors_doc)]
246 #[inline]
247 pub async fn pins(&self, http: impl AsRef<Http>) -> Result<Vec<Message>> {
248 self.id.pins(http).await
249 }
250
251 /// Sends a message with just the given message content in the channel.
252 ///
253 /// **Note**: Message content must be under 2000 unicode code points.
254 ///
255 /// # Errors
256 ///
257 /// Returns a [`ModelError::MessageTooLong`] if the content length is over the above limit. See
258 /// [`CreateMessage::execute`] for more details.
259 ///
260 /// [`CreateMessage::execute`]: ../../builder/struct.CreateMessage.html#method.execute
261 #[inline]
262 pub async fn say(
263 &self,
264 cache_http: impl CacheHttp,
265 content: impl Into<String>,
266 ) -> Result<Message> {
267 self.id.say(cache_http, content).await
268 }
269
270 /// Sends file(s) along with optional message contents.
271 ///
272 /// Refer to [`ChannelId::send_files`] for examples and more information.
273 ///
274 /// # Errors
275 ///
276 /// See [`CreateMessage::execute`] for a list of possible errors, and their corresponding
277 /// reasons.
278 ///
279 /// [`CreateMessage::execute`]: ../../builder/struct.CreateMessage.html#method.execute
280 #[inline]
281 pub async fn send_files(
282 self,
283 cache_http: impl CacheHttp,
284 files: impl IntoIterator<Item = CreateAttachment>,
285 builder: CreateMessage,
286 ) -> Result<Message> {
287 self.id.send_files(cache_http, files, builder).await
288 }
289
290 /// Sends a message to the channel.
291 ///
292 /// Refer to the documentation for [`CreateMessage`] for information regarding content
293 /// restrictions and requirements.
294 ///
295 /// # Errors
296 ///
297 /// See [`CreateMessage::execute`] for a list of possible errors, and their corresponding
298 /// reasons.
299 ///
300 /// [`CreateMessage::execute`]: ../../builder/struct.CreateMessage.html#method.execute
301 #[inline]
302 pub async fn send_message(
303 &self,
304 cache_http: impl CacheHttp,
305 builder: CreateMessage,
306 ) -> Result<Message> {
307 self.id.send_message(cache_http, builder).await
308 }
309
310 /// Starts typing in the channel for an indefinite period of time.
311 ///
312 /// Returns [`Typing`] that is used to trigger the typing. [`Typing::stop`] must be called on
313 /// the returned struct to stop typing. Note that on some clients, typing may persist for a few
314 /// seconds after [`Typing::stop`] is called. Typing is also stopped when the struct is
315 /// dropped.
316 ///
317 /// If a message is sent while typing is triggered, the user will stop typing for a brief
318 /// period of time and then resume again until either [`Typing::stop`] is called or the struct
319 /// is dropped.
320 ///
321 /// This should rarely be used for bots, although it is a good indicator that a long-running
322 /// command is still being processed.
323 ///
324 /// ## Examples
325 ///
326 /// ```rust,no_run
327 /// # #[cfg(feature = "cache")]
328 /// # async fn run() {
329 /// # use serenity::{cache::Cache, http::Http, model::channel::PrivateChannel, Result};
330 /// # use std::sync::Arc;
331 /// #
332 /// # fn long_process() {}
333 /// # let http: Arc<Http> = unimplemented!();
334 /// # let cache = Cache::default();
335 /// # let channel: PrivateChannel = unimplemented!();
336 /// // Initiate typing (assuming http is `Arc<Http>` and `channel` is bound)
337 /// let typing = channel.start_typing(&http);
338 ///
339 /// // Run some long-running process
340 /// long_process();
341 ///
342 /// // Stop typing
343 /// typing.stop();
344 /// # }
345 /// ```
346 ///
347 /// # Errors
348 ///
349 /// May return [`Error::Http`] if the current user cannot send a direct message to this user.
350 pub fn start_typing(self, http: &Arc<Http>) -> Typing {
351 http.start_typing(self.id)
352 }
353
354 /// Unpins a [`Message`] in the channel given by its Id.
355 ///
356 /// # Errors
357 ///
358 /// Returns [`Error::Http`] if the current user lacks permission, if the message was deleted,
359 /// or if the channel already has the limit of 50 pinned messages.
360 #[inline]
361 pub async fn unpin(
362 &self,
363 http: impl AsRef<Http>,
364 message_id: impl Into<MessageId>,
365 ) -> Result<()> {
366 self.id.unpin(http, message_id).await
367 }
368}
369
370impl fmt::Display for PrivateChannel {
371 /// Formats the private channel, displaying the recipient's username.
372 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
373 f.write_str(&self.recipient.name)
374 }
375}