aboutsummaryrefslogtreecommitdiff
path: root/src/model/channel/mod.rs
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2017-03-25 15:41:47 -0700
committerZeyla Hellyer <[email protected]>2017-03-25 15:41:47 -0700
commit9114963daf708cfaeaf54d8c788206ccfbae5df8 (patch)
tree08d6aba5b8ad40189b312865ac776bb6fa30c45d /src/model/channel/mod.rs
parentAdd slightly more documentation (diff)
downloadserenity-9114963daf708cfaeaf54d8c788206ccfbae5df8.tar.xz
serenity-9114963daf708cfaeaf54d8c788206ccfbae5df8.zip
Rework the models directory
Diffstat (limited to 'src/model/channel/mod.rs')
-rw-r--r--src/model/channel/mod.rs415
1 files changed, 415 insertions, 0 deletions
diff --git a/src/model/channel/mod.rs b/src/model/channel/mod.rs
new file mode 100644
index 0000000..ff12084
--- /dev/null
+++ b/src/model/channel/mod.rs
@@ -0,0 +1,415 @@
+mod attachment;
+mod channel_id;
+mod embed;
+mod group;
+mod guild_channel;
+mod message;
+mod private_channel;
+mod reaction;
+
+pub use self::attachment::*;
+pub use self::channel_id::*;
+pub use self::embed::*;
+pub use self::group::*;
+pub use self::guild_channel::*;
+pub use self::message::*;
+pub use self::private_channel::*;
+pub use self::reaction::*;
+
+use std::fmt::{Display, Formatter, Result as FmtResult};
+use std::io::Read;
+use ::client::CACHE;
+use ::model::*;
+use ::utils::builder::{CreateMessage, GetMessages, Search};
+
+impl Channel {
+ /// Marks the channel as being read up to a certain [`Message`].
+ ///
+ /// Refer to the documentation for [`rest::ack_message`] for more
+ /// information.
+ ///
+ /// # Errors
+ ///
+ /// If the `cache` is enabled, returns a
+ /// [`ClientError::InvalidOperationAsBot`] if the current user is a bot
+ /// user.
+ ///
+ /// [`Channel`]: enum.Channel.html
+ /// [`ClientError::InvalidOperationAsBot`]: ../client/enum.ClientError.html#variant.InvalidOperationAsUser
+ /// [`Message`]: struct.Message.html
+ /// [`rest::ack_message`]: ../client/rest/fn.ack_message.html
+ pub fn ack<M: Into<MessageId>>(&self, message_id: M) -> Result<()> {
+ #[cfg(feature="cache")]
+ {
+ if CACHE.read().unwrap().user.bot {
+ return Err(Error::Client(ClientError::InvalidOperationAsBot));
+ }
+ }
+
+ self.id().ack(message_id)
+ }
+
+ /// 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> {
+ self.id().create_reaction(message_id, reaction_type)
+ }
+
+ #[doc(hidden)]
+ pub fn decode(value: Value) -> Result<Channel> {
+ let map = into_map(value)?;
+ match req!(map.get("type").and_then(|x| x.as_u64())) {
+ 0 | 2 => GuildChannel::decode(Value::Object(map))
+ .map(|x| Channel::Guild(Arc::new(RwLock::new(x)))),
+ 1 => PrivateChannel::decode(Value::Object(map))
+ .map(|x| Channel::Private(Arc::new(RwLock::new(x)))),
+ 3 => Group::decode(Value::Object(map))
+ .map(|x| Channel::Group(Arc::new(RwLock::new(x)))),
+ other => Err(Error::Decode("Expected value Channel type",
+ Value::U64(other))),
+ }
+ }
+
+ /// Deletes the inner channel.
+ ///
+ /// **Note**: There is no real function as _deleting_ a [`Group`]. The
+ /// closest functionality is leaving it.
+ ///
+ /// [`Group`]: struct.Group.html
+ pub fn delete(&self) -> Result<()> {
+ match *self {
+ Channel::Group(ref group) => {
+ let _ = group.read().unwrap().leave()?;
+ },
+ Channel::Guild(ref public_channel) => {
+ let _ = public_channel.read().unwrap().delete()?;
+ },
+ Channel::Private(ref private_channel) => {
+ let _ = private_channel.read().unwrap().delete()?;
+ },
+ }
+
+ Ok(())
+ }
+
+ /// 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<()> {
+ self.id().delete_message(message_id)
+ }
+
+ /// Deletes all messages by Ids from the given vector in the channel.
+ ///
+ /// The minimum amount of messages is 2 and the maximum amount is 100.
+ ///
+ /// 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.
+ ///
+ /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
+ #[inline]
+ pub fn delete_messages(&self, message_ids: &[MessageId]) -> Result<()> {
+ self.id().delete_messages(message_ids)
+ }
+
+ /// 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
+ #[inline]
+ pub fn delete_permission(&self, permission_type: PermissionOverwriteType) -> Result<()> {
+ self.id().delete_permission(permission_type)
+ }
+
+ /// 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
+ #[inline]
+ 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> {
+ self.id().delete_reaction(message_id, user_id, reaction_type)
+ }
+
+ /// 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
+ #[inline]
+ pub fn edit_message<F, M>(&self, message_id: M, f: F) -> Result<Message>
+ where F: FnOnce(CreateMessage) -> CreateMessage, M: Into<MessageId> {
+ self.id().edit_message(message_id, f)
+ }
+
+ /// 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> {
+ self.id().get_message(message_id)
+ }
+
+ /// Gets messages from the channel.
+ ///
+ /// Requires the [Read Message History] permission.
+ ///
+ /// # Examples
+ ///
+ /// ```rust,ignore
+ /// use serenity::model::MessageId;
+ ///
+ /// let id = MessageId(81392407232380928);
+ ///
+ /// // Maximum is 100.
+ /// let _messages = channel.get_messages(|g| g.after(id).limit(100));
+ /// ```
+ ///
+ /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
+ #[inline]
+ pub fn get_messages<F>(&self, f: F) -> Result<Vec<Message>>
+ where F: FnOnce(GetMessages) -> GetMessages {
+ self.id().get_messages(f)
+ }
+
+ /// Gets the list of [`User`]s who have reacted to a [`Message`] with a
+ /// certain [`Emoji`].
+ ///
+ /// The default `limit` is `50` - specify otherwise to receive a different
+ /// maximum number of users. The maximum that may be retrieve at a time is
+ /// `100`, if a greater number is provided then it is automatically reduced.
+ ///
+ /// The optional `after` attribute is to retrieve the users after a certain
+ /// user. This is useful for pagination.
+ ///
+ /// **Note**: Requires the [Read Message History] permission.
+ ///
+ /// [`Emoji`]: struct.Emoji.html
+ /// [`Message`]: struct.Message.html
+ /// [`User`]: struct.User.html
+ /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
+ #[inline]
+ 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> {
+ self.id().get_reaction_users(message_id, reaction_type, limit, after)
+ }
+
+ /// Retrieves the Id of the inner [`Group`], [`GuildChannel`], or
+ /// [`PrivateChannel`].
+ ///
+ /// [`Group`]: struct.Group.html
+ /// [`GuildChannel`]: struct.GuildChannel.html
+ /// [`PrivateChannel`]: struct.PrivateChannel.html
+ pub fn id(&self) -> ChannelId {
+ match *self {
+ Channel::Group(ref group) => group.read().unwrap().channel_id,
+ Channel::Guild(ref channel) => channel.read().unwrap().id,
+ Channel::Private(ref channel) => channel.read().unwrap().id,
+ }
+ }
+
+ /// 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.id().say(content)
+ }
+
+ /// Performs a search request to the API for the inner channel's
+ /// [`Message`]s.
+ ///
+ /// Refer to the documentation for the [`Search`] builder for examples and
+ /// more information.
+ ///
+ /// **Note**: Bot users can not search.
+ ///
+ /// # Errors
+ ///
+ /// If the `cache` is enabled, returns a
+ /// [`ClientError::InvalidOperationAsBot`] if the current user is a bot.
+ ///
+ /// [`ClientError::InvalidOperationAsBot`]: ../client/enum.ClientError.html#variant.InvalidOperationAsBot
+ /// [`Message`]: struct.Message.html
+ /// [`Search`]: ../utils/builder/struct.Search.html
+ pub fn search<F>(&self, f: F) -> Result<SearchResult>
+ where F: FnOnce(Search) -> Search {
+ #[cfg(feature="cache")]
+ {
+ if CACHE.read().unwrap().user.bot {
+ return Err(Error::Client(ClientError::InvalidOperationAsBot));
+ }
+ }
+
+ self.id().search(f)
+ }
+
+ /// Sends a file along with optional message contents. The filename _must_
+ /// be specified.
+ ///
+ /// Refer to [`ChannelId::send_file`] for examples and more information.
+ ///
+ /// The [Attach Files] and [Send Messages] permissions are required.
+ ///
+ /// **Note**: Message contents must be under 2000 unicode code points.
+ ///
+ /// # 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.
+ ///
+ /// [`ChannelId::send_file`]: struct.ChannelId.html#method.send_file
+ /// [`ClientError::MessageTooLong`]: ../client/enum.ClientError.html#variant.MessageTooLong
+ /// [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 {
+ self.id().send_file(file, filename, f)
+ }
+
+ /// Sends a message to the channel.
+ ///
+ /// Refer to the documentation for [`CreateMessage`] for more information
+ /// regarding message restrictions and requirements.
+ ///
+ /// The [Send Messages] permission is required.
+ ///
+ /// **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
+ #[inline]
+ pub fn send_message<F>(&self, f: F) -> Result<Message>
+ where F: FnOnce(CreateMessage) -> CreateMessage {
+ self.id().send_message(f)
+ }
+
+ /// 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<()> {
+ self.id().unpin(message_id)
+ }
+}
+
+impl Display for Channel {
+ /// Formats the channel into a "mentioned" string.
+ ///
+ /// This will return a different format for each type of channel:
+ ///
+ /// - [`Group`]s: the generated name retrievable via [`Group::name`];
+ /// - [`PrivateChannel`]s: the recipient's name;
+ /// - [`GuildChannel`]s: a string mentioning the channel that users who can
+ /// see the channel can click on.
+ ///
+ /// [`Group`]: struct.Group.html
+ /// [`Group::name`]: struct.Group.html#method.name
+ /// [`GuildChannel`]: struct.GuildChannel.html
+ /// [`PrivateChannel`]: struct.PrivateChannel.html
+ fn fmt(&self, f: &mut Formatter) -> FmtResult {
+ match *self {
+ Channel::Group(ref group) => {
+ Display::fmt(&group.read().unwrap().name(), f)
+ },
+ Channel::Guild(ref ch) => {
+ Display::fmt(&ch.read().unwrap().id.mention(), f)
+ },
+ Channel::Private(ref ch) => {
+ let channel = ch.read().unwrap();
+ let recipient = channel.recipient.read().unwrap();
+
+ Display::fmt(&recipient.name, f)
+ },
+ }
+ }
+}
+
+impl PermissionOverwrite {
+ #[doc(hidden)]
+ pub fn decode(value: Value) -> Result<PermissionOverwrite> {
+ let mut map = into_map(value)?;
+ let id = remove(&mut map, "id").and_then(decode_id)?;
+ let kind = remove(&mut map, "type").and_then(into_string)?;
+ let kind = match &*kind {
+ "member" => PermissionOverwriteType::Member(UserId(id)),
+ "role" => PermissionOverwriteType::Role(RoleId(id)),
+ _ => return Err(Error::Decode("Expected valid PermissionOverwrite type", Value::String(kind))),
+ };
+
+ Ok(PermissionOverwrite {
+ kind: kind,
+ allow: remove(&mut map, "allow").and_then(Permissions::decode)?,
+ deny: remove(&mut map, "deny").and_then(Permissions::decode)?,
+ })
+ }
+}