aboutsummaryrefslogtreecommitdiff
path: root/src/model/channel/channel_id.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/model/channel/channel_id.rs')
-rw-r--r--src/model/channel/channel_id.rs511
1 files changed, 511 insertions, 0 deletions
diff --git a/src/model/channel/channel_id.rs b/src/model/channel/channel_id.rs
new file mode 100644
index 0000000..2d09367
--- /dev/null
+++ b/src/model/channel/channel_id.rs
@@ -0,0 +1,511 @@
+use serde_json::builder::ObjectBuilder;
+use std::fmt::{Display, Formatter, Result as FmtResult, Write as FmtWrite};
+use std::io::Read;
+use ::client::{CACHE, rest};
+use ::model::*;
+use ::utils::builder::{CreateMessage, EditChannel, GetMessages, Search};
+
+impl ChannelId {
+ /// Marks a [`Channel`] as being read up to a certain [`Message`].
+ ///
+ /// Refer to the documentation for [`rest::ack_message`] for more
+ /// information.
+ ///
+ /// [`Channel`]: enum.Channel.html
+ /// [`Message`]: struct.Message.html
+ /// [`rest::ack_message`]: rest/fn.ack_message.html
+ #[inline]
+ pub fn ack<M: Into<MessageId>>(&self, message_id: M) -> Result<()> {
+ rest::ack_message(self.0, message_id.into().0)
+ }
+
+ /// Broadcasts that the current user is typing to a channel for the next 5
+ /// seconds.
+ ///
+ /// After 5 seconds, another request must be made to continue broadcasting
+ /// that the current user is typing.
+ ///
+ /// This should rarely be used for bots, and should likely only be used for
+ /// signifying that a long-running command is still being executed.
+ ///
+ /// **Note**: Requires the [Send Messages] permission.
+ ///
+ /// # Examples
+ ///
+ /// ```rust,ignore
+ /// use serenity::model::ChannelId;
+ ///
+ /// let _successful = ChannelId(7).broadcast_typing();
+ /// ```
+ ///
+ /// [Send Messages]: permissions/constant.SEND_MESSAGES.html
+ #[inline]
+ pub fn broadcast_typing(&self) -> Result<()> {
+ rest::broadcast_typing(self.0)
+ }
+
+ /// Creates a [permission overwrite][`PermissionOverwrite`] for either a
+ /// single [`Member`] or [`Role`] within the channel.
+ ///
+ /// Refer to the documentation for [`GuildChannel::create_permission`] for
+ /// more information.
+ ///
+ /// Requires the [Manage Channels] permission.
+ ///
+ /// [`GuildChannel::create_permission`]: struct.GuildChannel.html#method.create_permission
+ /// [`Member`]: struct.Member.html
+ /// [`PermissionOverwrite`]: struct.PermissionOverwrite.html
+ /// [`Role`]: struct.Role.html
+ /// [Manage Channels]: permissions/constant.MANAGE_CHANNELS.html
+ pub fn create_permission(&self, target: PermissionOverwrite)
+ -> Result<()> {
+ let (id, kind) = match target.kind {
+ PermissionOverwriteType::Member(id) => (id.0, "member"),
+ PermissionOverwriteType::Role(id) => (id.0, "role"),
+ };
+
+ let map = ObjectBuilder::new()
+ .insert("allow", target.allow.bits())
+ .insert("deny", target.deny.bits())
+ .insert("id", id)
+ .insert("type", kind)
+ .build();
+
+ rest::create_permission(self.0, id, &map)
+ }
+
+ /// React to a [`Message`] with a custom [`Emoji`] or unicode character.
+ ///
+ /// [`Message::react`] may be a more suited method of reacting in most
+ /// cases.
+ ///
+ /// Requires the [Add Reactions] permission, _if_ the current user is the
+ /// first user to perform a react with a certain emoji.
+ ///
+ /// [`Emoji`]: struct.Emoji.html
+ /// [`Message`]: struct.Message.html
+ /// [`Message::react`]: struct.Message.html#method.react
+ /// [Add Reactions]: permissions/constant.ADD_REACTIONS.html
+ #[inline]
+ pub fn create_reaction<M, R>(&self, message_id: M, reaction_type: R)
+ -> Result<()> where M: Into<MessageId>, R: Into<ReactionType> {
+ rest::create_reaction(self.0, message_id.into().0, &reaction_type.into())
+ }
+
+ /// Deletes this channel, returning the channel on a successful deletion.
+ #[inline]
+ pub fn delete(&self) -> Result<Channel> {
+ rest::delete_channel(self.0)
+ }
+
+ /// Deletes a [`Message`] given its Id.
+ ///
+ /// Refer to [`Message::delete`] for more information.
+ ///
+ /// Requires the [Manage Messages] permission, if the current user is not
+ /// the author of the message.
+ ///
+ /// [`Message`]: struct.Message.html
+ /// [`Message::delete`]: struct.Message.html#method.delete
+ /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
+ #[inline]
+ pub fn delete_message<M: Into<MessageId>>(&self, message_id: M) -> Result<()> {
+ rest::delete_message(self.0, message_id.into().0)
+ }
+
+ /// Deletes all messages by Ids from the given vector in the given channel.
+ ///
+ /// Refer to the documentation for [`Channel::delete_messages`] for more
+ /// information.
+ ///
+ /// Requires the [Manage Messages] permission.
+ ///
+ /// **Note**: This uses bulk delete endpoint which is not available
+ /// for user accounts.
+ ///
+ /// **Note**: Messages that are older than 2 weeks can't be deleted using this method.
+ ///
+ /// [`Channel::delete_messages`]: enum.Channel.html#method.delete_messages
+ /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
+ pub fn delete_messages(&self, message_ids: &[MessageId]) -> Result<()> {
+ let ids = message_ids.into_iter()
+ .map(|message_id| message_id.0)
+ .collect::<Vec<u64>>();
+
+ let map = ObjectBuilder::new().insert("messages", ids).build();
+
+ rest::delete_messages(self.0, &map)
+ }
+
+ /// Deletes all permission overrides in the channel from a member or role.
+ ///
+ /// **Note**: Requires the [Manage Channel] permission.
+ ///
+ /// [Manage Channel]: permissions/constant.MANAGE_CHANNELS.html
+ pub fn delete_permission(&self, permission_type: PermissionOverwriteType) -> Result<()> {
+ rest::delete_permission(self.0, match permission_type {
+ PermissionOverwriteType::Member(id) => id.0,
+ PermissionOverwriteType::Role(id) => id.0,
+ })
+ }
+
+ /// Deletes the given [`Reaction`] from the channel.
+ ///
+ /// **Note**: Requires the [Manage Messages] permission, _if_ the current
+ /// user did not perform the reaction.
+ ///
+ /// [`Reaction`]: struct.Reaction.html
+ /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
+ pub fn delete_reaction<M, R>(&self, message_id: M, user_id: Option<UserId>, reaction_type: R)
+ -> Result<()> where M: Into<MessageId>, R: Into<ReactionType> {
+ rest::delete_reaction(self.0,
+ message_id.into().0,
+ user_id.map(|uid| uid.0),
+ &reaction_type.into())
+ }
+
+
+ /// Edits the settings of a [`Channel`], optionally setting new values.
+ ///
+ /// Refer to `EditChannel`'s documentation for its methods.
+ ///
+ /// Requires the [Manage Channel] permission.
+ ///
+ /// # Examples
+ ///
+ /// Change a voice channel's name and bitrate:
+ ///
+ /// ```rust,ignore
+ /// // assuming a `channel_id` has been bound
+ ///
+ /// channel_id.edit(|c| c.name("test").bitrate(64000));
+ /// ```
+ ///
+ /// # Errors
+ ///
+ /// Returns a [`ClientError::NoChannelId`] if the current context is not
+ /// related to a channel.
+ ///
+ /// [`Channel`]: enum.Channel.html
+ /// [`ClientError::NoChannelId`]: ../client/enum.ClientError.html#variant.NoChannelId
+ /// [Manage Channel]: permissions/constant.MANAGE_CHANNELS.html
+ #[inline]
+ pub fn edit<F: FnOnce(EditChannel) -> EditChannel>(&self, f: F) -> Result<GuildChannel> {
+ rest::edit_channel(self.0, &f(EditChannel::default()).0.build())
+ }
+
+ /// Edits a [`Message`] in the channel given its Id.
+ ///
+ /// Message editing preserves all unchanged message data.
+ ///
+ /// Refer to the documentation for [`CreateMessage`] for more information
+ /// regarding message restrictions and requirements.
+ ///
+ /// **Note**: Requires that the current user be the author of the message.
+ ///
+ /// # Errors
+ ///
+ /// Returns a [`ClientError::MessageTooLong`] if the content of the message
+ /// is over the [`the limit`], containing the number of unicode code points
+ /// over the limit.
+ ///
+ /// [`ClientError::MessageTooLong`]: ../client/enum.ClientError.html#variant.MessageTooLong
+ /// [`CreateMessage`]: ../utils/builder/struct.CreateMessage.html
+ /// [`Message`]: struct.Message.html
+ /// [`the limit`]: ../utils/builder/struct.CreateMessage.html#method.content
+ pub fn edit_message<F, M>(&self, message_id: M, f: F) -> Result<Message>
+ where F: FnOnce(CreateMessage) -> CreateMessage, M: Into<MessageId> {
+ let map = f(CreateMessage::default()).0;
+
+ if let Some(content) = map.get("content") {
+ if let Value::String(ref content) = *content {
+ if let Some(length_over) = Message::overflow_length(content) {
+ return Err(Error::Client(ClientError::MessageTooLong(length_over)));
+ }
+ }
+ }
+
+ rest::edit_message(self.0, message_id.into().0, &Value::Object(map))
+ }
+
+ /// Search the cache for the channel with the Id.
+ #[cfg(feature="cache")]
+ pub fn find(&self) -> Option<Channel> {
+ CACHE.read().unwrap().get_channel(*self)
+ }
+
+ /// Search the cache for the channel. If it can't be found, the channel is
+ /// requested over REST.
+ pub fn get(&self) -> Result<Channel> {
+ #[cfg(feature="cache")]
+ {
+ if let Some(channel) = CACHE.read().unwrap().get_channel(*self) {
+ return Ok(channel);
+ }
+ }
+
+ rest::get_channel(self.0)
+ }
+
+ /// Gets all of the channel's invites.
+ ///
+ /// Requires the [Manage Channels] permission.
+ /// [Manage Channels]: permissions/constant.MANAGE_CHANNELS.html
+ #[inline]
+ pub fn get_invites(&self) -> Result<Vec<RichInvite>> {
+ rest::get_channel_invites(self.0)
+ }
+
+ /// Gets a message from the channel.
+ ///
+ /// Requires the [Read Message History] permission.
+ ///
+ /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
+ #[inline]
+ pub fn get_message<M: Into<MessageId>>(&self, message_id: M) -> Result<Message> {
+ rest::get_message(self.0, message_id.into().0)
+ }
+
+ /// Gets messages from the channel.
+ ///
+ /// Refer to [`Channel::get_messages`] for more information.
+ ///
+ /// Requires the [Read Message History] permission.
+ ///
+ /// [`Channel::get_messages`]: enum.Channel.html#method.get_messages
+ /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
+ pub fn get_messages<F>(&self, f: F) -> Result<Vec<Message>>
+ where F: FnOnce(GetMessages) -> GetMessages {
+ let mut map = f(GetMessages::default()).0;
+ let mut query = format!("?limit={}", map.remove("limit").unwrap_or(50));
+
+ if let Some(after) = map.remove("after") {
+ write!(query, "&after={}", after)?;
+ } else if let Some(around) = map.remove("around") {
+ write!(query, "&around={}", around)?;
+ } else if let Some(before) = map.remove("before") {
+ write!(query, "&before={}", before)?;
+ }
+
+ rest::get_messages(self.0, &query)
+ }
+
+ /// Gets the list of [`User`]s who have reacted to a [`Message`] with a
+ /// certain [`Emoji`].
+ ///
+ /// Refer to [`Channel::get_reaction_users`] for more information.
+ ///
+ /// **Note**: Requires the [Read Message History] permission.
+ ///
+ /// [`Channel::get_reaction_users`]: enum.Channel.html#variant.get_reaction_users
+ /// [`Emoji`]: struct.Emoji.html
+ /// [`Message`]: struct.Message.html
+ /// [`User`]: struct.User.html
+ /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
+ pub fn get_reaction_users<M, R, U>(&self,
+ message_id: M,
+ reaction_type: R,
+ limit: Option<u8>,
+ after: Option<U>)
+ -> Result<Vec<User>> where M: Into<MessageId>, R: Into<ReactionType>, U: Into<UserId> {
+ let limit = limit.map_or(50, |x| if x > 100 { 100 } else { x });
+
+ rest::get_reaction_users(self.0,
+ message_id.into().0,
+ &reaction_type.into(),
+ limit,
+ after.map(|u| u.into().0))
+ }
+
+ /// Retrieves the channel's webhooks.
+ ///
+ /// **Note**: Requires the [Manage Webhooks] permission.
+ ///
+ /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html
+ #[inline]
+ pub fn get_webhooks(&self) -> Result<Vec<Webhook>> {
+ rest::get_channel_webhooks(self.0)
+ }
+
+ /// Pins a [`Message`] to the channel.
+ ///
+ /// [`Message`]: struct.Message.html
+ #[inline]
+ pub fn pin<M: Into<MessageId>>(&self, message_id: M) -> Result<()> {
+ rest::pin_message(self.0, message_id.into().0)
+ }
+
+ /// Gets the list of [`Message`]s which are pinned to the channel.
+ ///
+ /// [`Message`]: struct.Message.html
+ #[inline]
+ pub fn pins(&self) -> Result<Vec<Message>> {
+ rest::get_pins(self.0)
+ }
+
+ /// Sends a message with just the given message content in the channel.
+ ///
+ /// # Errors
+ ///
+ /// Returns a [`ClientError::MessageTooLong`] if the content of the message
+ /// is over the above limit, containing the number of unicode code points
+ /// over the limit.
+ ///
+ /// [`ChannelId`]: ../model/struct.ChannelId.html
+ /// [`ClientError::MessageTooLong`]: enum.ClientError.html#variant.MessageTooLong
+ #[inline]
+ pub fn say(&self, content: &str) -> Result<Message> {
+ self.send_message(|m| m.content(content))
+ }
+
+ /// Searches the channel's messages by providing query parameters via the
+ /// search builder.
+ ///
+ /// Refer to the documentation for the [`Search`] builder for restrictions
+ /// and defaults parameters, as well as potentially advanced usage.
+ ///
+ /// **Note**: Bot users can not search.
+ ///
+ /// # Examples
+ ///
+ /// Refer to the [`Search`] builder's documentation for examples,
+ /// specifically the section on [searching a channel][search channel].
+ ///
+ /// [`Search`]: ../utils/builder/struct.Search.html
+ #[inline]
+ pub fn search<F: FnOnce(Search) -> Search>(&self, f: F) -> Result<SearchResult> {
+ rest::search_channel_messages(self.0, f(Search::default()).0)
+ }
+
+ /// Sends a file along with optional message contents. The filename _must_
+ /// be specified.
+ ///
+ /// Message contents may be passed by using the [`CreateMessage::content`]
+ /// method.
+ ///
+ /// An embed can _not_ be sent when sending a file. If you set one, it will
+ /// be automatically removed.
+ ///
+ /// The [Attach Files] and [Send Messages] permissions are required.
+ ///
+ /// **Note**: Message contents must be under 2000 unicode code points.
+ ///
+ /// # Examples
+ ///
+ /// Send a file with the filename `my_file.jpg`:
+ ///
+ /// ```rust,no_run
+ /// use serenity::model::ChannelId;
+ /// use std::fs::File;
+ ///
+ /// let channel_id = ChannelId(7);
+ /// let filename = "my_file.jpg";
+ /// let file = File::open(filename).unwrap();
+ ///
+ /// let _ = channel_id.send_file(file, filename, |m| m.content("a file"));
+ /// ```
+ ///
+ /// # Errors
+ ///
+ /// If the content of the message is over the above limit, then a
+ /// [`ClientError::MessageTooLong`] will be returned, containing the number
+ /// of unicode code points over the limit.
+ ///
+ /// [`ClientError::MessageTooLong`]: ../client/enum.ClientError.html#variant.MessageTooLong
+ /// [`CreateMessage::content`]: ../utils/builder/struct.CreateMessage.html#method.content
+ /// [`GuildChannel`]: struct.GuildChannel.html
+ /// [Attach Files]: permissions/constant.ATTACH_FILES.html
+ /// [Send Messages]: permissions/constant.SEND_MESSAGES.html
+ pub fn send_file<F, R>(&self, file: R, filename: &str, f: F) -> Result<Message>
+ where F: FnOnce(CreateMessage) -> CreateMessage, R: Read {
+ let mut map = f(CreateMessage::default()).0;
+
+ if let Some(content) = map.get("content") {
+ if let Value::String(ref content) = *content {
+ if let Some(length_over) = Message::overflow_length(content) {
+ return Err(Error::Client(ClientError::MessageTooLong(length_over)));
+ }
+ }
+ }
+
+ let _ = map.remove("embed");
+
+ rest::send_file(self.0, file, filename, map)
+ }
+
+ /// Sends a message to the channel.
+ ///
+ /// Refer to the documentation for [`CreateMessage`] for more information
+ /// regarding message restrictions and requirements.
+ ///
+ /// Requires the [Send Messages] permission.
+ ///
+ /// **Note**: Message contents must be under 2000 unicode code points.
+ ///
+ /// # Errors
+ ///
+ /// Returns a [`ClientError::MessageTooLong`] if the content of the message
+ /// is over the above limit, containing the number of unicode code points
+ /// over the limit.
+ ///
+ /// [`Channel`]: enum.Channel.html
+ /// [`ClientError::MessageTooLong`]: ../client/enum.ClientError.html#variant.MessageTooLong
+ /// [`CreateMessage`]: ../utils/builder/struct.CreateMessage.html
+ /// [Send Messages]: permissions/constant.SEND_MESSAGES.html
+ pub fn send_message<F>(&self, f: F) -> Result<Message>
+ where F: FnOnce(CreateMessage) -> CreateMessage {
+ let map = f(CreateMessage::default()).0;
+
+ if let Some(content) = map.get(&"content".to_owned()) {
+ if let Value::String(ref content) = *content {
+ if let Some(length_over) = Message::overflow_length(content) {
+ return Err(Error::Client(ClientError::MessageTooLong(length_over)));
+ }
+ }
+ }
+
+ rest::send_message(self.0, &Value::Object(map))
+ }
+
+ /// Unpins a [`Message`] in the channel given by its Id.
+ ///
+ /// Requires the [Manage Messages] permission.
+ ///
+ /// [`Message`]: struct.Message.html
+ /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
+ #[inline]
+ pub fn unpin<M: Into<MessageId>>(&self, message_id: M) -> Result<()> {
+ rest::unpin_message(self.0, message_id.into().0)
+ }
+}
+
+impl From<Channel> for ChannelId {
+ /// Gets the Id of a `Channel`.
+ fn from(channel: Channel) -> ChannelId {
+ match channel {
+ Channel::Group(group) => group.read().unwrap().channel_id,
+ Channel::Guild(ch) => ch.read().unwrap().id,
+ Channel::Private(ch) => ch.read().unwrap().id,
+ }
+ }
+}
+
+impl From<PrivateChannel> for ChannelId {
+ /// Gets the Id of a private channel.
+ fn from(private_channel: PrivateChannel) -> ChannelId {
+ private_channel.id
+ }
+}
+
+impl From<GuildChannel> for ChannelId {
+ /// Gets the Id of a guild channel.
+ fn from(public_channel: GuildChannel) -> ChannelId {
+ public_channel.id
+ }
+}
+
+impl Display for ChannelId {
+ fn fmt(&self, f: &mut Formatter) -> FmtResult {
+ Display::fmt(&self.0, f)
+ }
+}