aboutsummaryrefslogtreecommitdiff
path: root/src/model/guild.rs
diff options
context:
space:
mode:
authorAustin Hellyer <[email protected]>2017-01-23 12:16:06 -0800
committerAustin Hellyer <[email protected]>2017-01-23 12:16:06 -0800
commit651c618f17cb92d3ea9bbd1d5f5c92a015ff64e0 (patch)
treedcf452e8fe73411af331678a769cb769a32dd12e /src/model/guild.rs
parentFix no-framework compilation (diff)
downloadserenity-651c618f17cb92d3ea9bbd1d5f5c92a015ff64e0.tar.xz
serenity-651c618f17cb92d3ea9bbd1d5f5c92a015ff64e0.zip
Switch to a mostly-fully OOP approach
The context is now strictly in relation to the context of the current channel related to the event, if any. See Context::say for a list of events that the context can be used for.
Diffstat (limited to 'src/model/guild.rs')
-rw-r--r--src/model/guild.rs1718
1 files changed, 1482 insertions, 236 deletions
diff --git a/src/model/guild.rs b/src/model/guild.rs
index fa8df32..9af9e00 100644
--- a/src/model/guild.rs
+++ b/src/model/guild.rs
@@ -1,3 +1,4 @@
+use serde_json::builder::ObjectBuilder;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt;
@@ -13,23 +14,17 @@ use super::utils::{
remove,
};
use super::*;
+use ::client::rest;
use ::internal::prelude::*;
+use ::utils::builder::{EditGuild, EditMember, EditRole, Search};
use ::utils::decode_array;
-#[cfg(feature="methods")]
-use serde_json::builder::ObjectBuilder;
-#[cfg(all(feature="cache", feature = "methods"))]
+#[cfg(feature="cache")]
use std::mem;
-#[cfg(all(feature="cache", feature="methods"))]
-use ::utils::builder::EditMember;
-#[cfg(feature="methods")]
-use ::utils::builder::{EditGuild, EditRole, Search};
-#[cfg(feature = "methods")]
-use ::client::rest;
-#[cfg(all(feature="cache", feature="methods"))]
+#[cfg(feature="cache")]
use ::client::CACHE;
-#[cfg(all(feature="cache", feature="methods"))]
+#[cfg(feature="cache")]
use ::utils::Colour;
impl From<PartialGuild> for GuildContainer {
@@ -58,7 +53,7 @@ impl Emoji {
/// **Note**: Only user accounts may use this method.
///
/// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn delete(&self) -> Result<()> {
match self.find_guild_id() {
Some(guild_id) => rest::delete_emoji(guild_id.0, self.id.0),
@@ -73,7 +68,7 @@ impl Emoji {
/// **Note**: Only user accounts may use this method.
///
/// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn edit(&mut self, name: &str) -> Result<()> {
match self.find_guild_id() {
Some(guild_id) => {
@@ -97,7 +92,7 @@ impl Emoji {
/// Finds the [`Guild`] that owns the emoji by looking through the Cache.
///
/// [`Guild`]: struct.Guild.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn find_guild_id(&self) -> Option<GuildId> {
CACHE.read()
.unwrap()
@@ -108,7 +103,6 @@ impl Emoji {
}
/// Generates a URL to the emoji's image.
- #[cfg(feature="methods")]
#[inline]
pub fn url(&self) -> String {
format!(cdn!("/emojis/{}.png"), self.id)
@@ -129,141 +123,37 @@ impl fmt::Display for Emoji {
}
}
-impl GuildInfo {
- /// Returns the formatted URL of the guild's icon, if the guild has an icon.
- pub fn icon_url(&self) -> Option<String> {
- self.icon.as_ref().map(|icon|
- format!(cdn!("/icons/{}/{}.webp"), self.id, icon))
+impl fmt::Display for EmojiId {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.0, f)
}
}
-impl InviteGuild {
- /// Returns the formatted URL of the guild's splash image, if one exists.
- #[cfg(feature="methods")]
- pub fn splash_url(&self) -> Option<String> {
- self.icon.as_ref().map(|icon|
- format!(cdn!("/splashes/{}/{}.webp"), self.id, icon))
+impl From<Emoji> for EmojiId {
+ /// Gets the Id of an `Emoji`.
+ fn from(emoji: Emoji) -> EmojiId {
+ emoji.id
}
}
-impl PartialGuild {
- /// Edits the current user's nickname for the guild.
- ///
- /// Pass `None` to reset the nickname.
- ///
- /// **Note**: Requires the [Change Nickname] permission.
- ///
- /// [Change Nickname]: permissions/constant.CHANGE_NICKNAME.html
- #[cfg(feature="methods")]
- #[inline]
- pub fn edit_nickname(&self, new_nickname: Option<&str>) -> Result<()> {
- rest::edit_nickname(self.id.0, new_nickname)
- }
-
- /// Returns a formatted URL of the guild's icon, if the guild has an icon.
+impl GuildInfo {
+ /// Returns the formatted URL of the guild's icon, if the guild has an icon.
pub fn icon_url(&self) -> Option<String> {
self.icon.as_ref().map(|icon|
format!(cdn!("/icons/{}/{}.webp"), self.id, icon))
}
+}
- /// Performs a search request to the API for the guild's [`Message`]s.
- ///
- /// This will search all of the guild's [`Channel`]s at once, that you have
- /// the [Read Message History] permission to. Use [`search_channels`] to
- /// specify a list of [channel][`GuildChannel`]s to search, where all other
- /// channels will be excluded.
- ///
- /// 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
- /// [`Channel`]: enum.Channel.html
- /// [`GuildChannel`]: struct.GuildChannel.html
- /// [`Message`]: struct.Message.html
- /// [`Search`]: ../utils/builder/struct.Search.html
- /// [`search_channels`]: #method.search_channels
- /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
- #[cfg(feature="methods")]
- 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));
- }
- }
-
- rest::search_guild_messages(self.id.0, &[], f(Search::default()).0)
- }
-
- /// Performs a search request to the API for the guild's [`Message`]s in
- /// given channels.
- ///
- /// This will search all of the messages in the guild's provided
- /// [`Channel`]s by Id that you have the [Read Message History] permission
- /// to. Use [`search`] to search all of a guild's [channel][`GuildChannel`]s
- /// at once.
- ///
- /// 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
- /// [`Channel`]: enum.Channel.html
- /// [`GuildChannel`]: struct.GuildChannel.html
- /// [`Message`]: struct.Message.html
- /// [`Search`]: ../utils/builder/struct.Search.html
- /// [`search`]: #method.search
- /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
- #[cfg(feature="methods")]
- pub fn search_channels<F>(&self, channel_ids: &[ChannelId], f: F)
- -> Result<SearchResult> where F: FnOnce(Search) -> Search {
- #[cfg(feature="cache")]
- {
- if CACHE.read().unwrap().user.bot {
- return Err(Error::Client(ClientError::InvalidOperationAsBot));
- }
- }
-
- let ids = channel_ids.iter().map(|x| x.0).collect::<Vec<u64>>();
-
- rest::search_guild_messages(self.id.0, &ids, f(Search::default()).0)
- }
-
+impl InviteGuild {
/// Returns the formatted URL of the guild's splash image, if one exists.
- #[cfg(feature="methods")]
pub fn splash_url(&self) -> Option<String> {
self.icon.as_ref().map(|icon|
format!(cdn!("/splashes/{}/{}.webp"), self.id, icon))
}
-
- /// Retrieves the guild's webhooks.
- ///
- /// **Note**: Requires the [Manage Webhooks] permission.
- ///
- /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html
- #[cfg(feature="methods")]
- #[inline]
- pub fn webhooks(&self) -> Result<Vec<Webhook>> {
- rest::get_guild_webhooks(self.id.0)
- }
}
impl Guild {
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
fn has_perms(&self, mut permissions: Permissions) -> Result<bool> {
let member = match self.members.get(&CACHE.read().unwrap().user.id) {
Some(member) => member,
@@ -277,8 +167,9 @@ impl Guild {
}
/// Ban a [`User`] from the guild. All messages by the
- /// user within the last given number of days given will be deleted. This
- /// may be a range between `0` and `7`.
+ /// user within the last given number of days given will be deleted.
+ ///
+ /// Refer to the documentation for [`Guild::ban`] for more information.
///
/// **Note**: Requires the [Ban Members] permission.
///
@@ -301,9 +192,9 @@ impl Guild {
///
/// [`ClientError::DeleteMessageDaysAmount`]: ../client/enum.ClientError.html#variant.DeleteMessageDaysAmount
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
+ /// [`Guild::ban`]: struct.Guild.html#method.ban
/// [`User`]: struct.User.html
/// [Ban Members]: permissions/constant.BAN_MEMBERS.html
- #[cfg(feature="methods")]
pub fn ban<U: Into<UserId>>(&self, user: U, delete_message_days: u8)
-> Result<()> {
if delete_message_days > 7 {
@@ -319,7 +210,7 @@ impl Guild {
}
}
- rest::ban_user(self.id.0, user.into().0, delete_message_days)
+ self.id.ban(user.into(), delete_message_days)
}
/// Retrieves a list of [`Ban`]s for the guild.
@@ -334,7 +225,6 @@ impl Guild {
/// [`Ban`]: struct.Ban.html
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Ban Members]: permissions/constant.BAN_MEMBERS.html
- #[cfg(feature="methods")]
pub fn bans(&self) -> Result<Vec<Ban>> {
#[cfg(feature="cache")]
{
@@ -345,7 +235,43 @@ impl Guild {
}
}
- rest::get_bans(self.id.0)
+ self.id.get_bans()
+ }
+
+ /// Creates a guild with the data provided.
+ ///
+ /// Only a [`PartialGuild`] will be immediately returned, and a full
+ /// [`Guild`] will be received over a [`Shard`].
+ ///
+ /// **Note**: This endpoint is usually only available for user accounts.
+ /// Refer to Discord's information for the endpoint [here][whitelist] for
+ /// more information. If you require this as a bot, re-think what you are
+ /// doing and if it _really_ needs to be doing this.
+ ///
+ /// # Examples
+ ///
+ /// Create a guild called `"test"` in the [US West region] with no icon:
+ ///
+ /// ```rust,ignore
+ /// use serenity::model::{Guild, Region};
+ ///
+ /// let _guild = Guild::create_guild("test", Region::UsWest, None);
+ /// ```
+ ///
+ /// [`Guild`]: struct.Guild.html
+ /// [`PartialGuild`]: struct.PartialGuild.html
+ /// [`Shard`]: ../gateway/struct.Shard.html
+ /// [US West region]: enum.Region.html#variant.UsWest
+ /// [whitelist]: https://discordapp.com/developers/docs/resources/guild#create-guild
+ pub fn create(name: &str, region: Region, icon: Option<&str>)
+ -> Result<PartialGuild> {
+ let map = ObjectBuilder::new()
+ .insert("icon", icon)
+ .insert("name", name)
+ .insert("region", region.name())
+ .build();
+
+ rest::create_guild(map)
}
/// Creates a new [`Channel`] in the guild.
@@ -370,7 +296,6 @@ impl Guild {
/// [`Channel`]: struct.Channel.html
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Manage Channels]: permissions/constants.MANAGE_CHANNELS.html
- #[cfg(feature="methods")]
pub fn create_channel(&mut self, name: &str, kind: ChannelType)
-> Result<Channel> {
#[cfg(feature="cache")]
@@ -382,20 +307,58 @@ impl Guild {
}
}
- let map = ObjectBuilder::new()
- .insert("name", name)
- .insert("type", kind.name())
- .build();
+ self.id.create_channel(name, kind)
+ }
- rest::create_channel(self.id.0, map)
+ /// Creates an emoji in the guild with a name and base64-encoded image. The
+ /// [`utils::read_image`] function is provided for you as a simple method to
+ /// read an image and encode it into base64, if you are reading from the
+ /// filesystem.
+ ///
+ /// The name of the emoji must be at least 2 characters long and can only
+ /// contain alphanumeric characters and underscores.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// # Examples
+ ///
+ /// See the [`EditProfile::avatar`] example for an in-depth example as to
+ /// how to read an image from the filesystem and encode it as base64. Most
+ /// of the example can be applied similarly for this method.
+ ///
+ /// [`EditProfile::avatar`]: ../utils/builder/struct.EditProfile.html#method.avatar
+ /// [`utils::read_image`]: ../utils/fn.read_image.html
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn create_emoji(&self, name: &str, image: &str) -> Result<Emoji> {
+ self.id.create_emoji(name, image)
}
- /// Creates a new [`Role`] in the guild with the data set, if any.
+ /// Creates an integration for the guild.
+ ///
+ /// Requires the [Manage Guild] permission.
///
- /// See the documentation for [`Context::create_role`] on how to use this.
+ /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
+ #[inline]
+ pub fn create_integration<I>(&self, integration_id: I, kind: &str) -> Result<()>
+ where I: Into<IntegrationId> {
+ self.id.create_integration(integration_id, kind)
+ }
+
+ /// Creates a new role in the guild with the data set, if any.
///
/// **Note**: Requires the [Manage Roles] permission.
///
+ /// # Examples
+ ///
+ /// Create a role which can be mentioned, with the name 'test':
+ ///
+ /// ```rust,ignore
+ /// let role = context.create_role(guild_id, |r| r
+ /// .hoist(true)
+ /// .name("role"));
+ /// ```
+ ///
/// # Errors
///
/// If the `cache` is enabled, returns a [`ClientError::InvalidPermissions`]
@@ -405,7 +368,6 @@ impl Guild {
/// [`Context::create_role`]: ../client/struct.Context.html#method.create_role
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constants.MANAGE_ROLES.html
- #[cfg(feature="methods")]
pub fn create_role<F>(&self, f: F) -> Result<Role>
where F: FnOnce(EditRole) -> EditRole {
#[cfg(feature="cache")]
@@ -417,7 +379,7 @@ impl Guild {
}
}
- rest::create_role(self.id.0, f(EditRole::default()).0.build())
+ self.id.create_role(f)
}
#[doc(hidden)]
@@ -464,8 +426,7 @@ impl Guild {
})
}
-
- /// Deletes the current guild if the current account is the owner of the
+ /// Deletes the current guild if the current user is the owner of the
/// guild.
///
/// **Note**: Requires the current user to be the owner of the guild.
@@ -476,7 +437,6 @@ impl Guild {
/// if the current user is not the guild owner.
///
/// [`ClientError::InvalidUser`]: ../client/enum.ClientError.html#variant.InvalidUser
- #[cfg(feature="methods")]
pub fn delete(&self) -> Result<PartialGuild> {
#[cfg(feature="cache")]
{
@@ -487,15 +447,68 @@ impl Guild {
}
}
- rest::delete_guild(self.id.0)
+ self.id.delete()
+ }
+
+ /// Deletes an [`Emoji`] from the guild.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [`Emoji`]: struct.Emoji.html
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn delete_emoji<E: Into<EmojiId>>(&self, emoji_id: E) -> Result<()> {
+ self.id.delete_emoji(emoji_id)
+ }
+
+ /// Deletes an integration by Id from the guild.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
+ #[inline]
+ pub fn delete_integration<I: Into<IntegrationId>>(&self, integration_id: I) -> Result<()> {
+ self.id.delete_integration(integration_id)
+ }
+
+ /// Deletes a [`Role`] by Id from the guild.
+ ///
+ /// Also see [`Role::delete`] if you have the `cache` and `methods` features
+ /// enabled.
+ ///
+ /// Requires the [Manage Roles] permission.
+ ///
+ /// [`Role`]: struct.Role.html
+ /// [`Role::delete`]: struct.Role.html#method.delete
+ /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
+ #[inline]
+ pub fn delete_role<R: Into<RoleId>>(&self, role_id: R) -> Result<()> {
+ self.id.delete_role(role_id)
}
- /// Edits the current guild with new data where specified. See the
- /// documentation for [`Context::edit_guild`] on how to use this.
+ /// Edits the current guild with new data where specified.
+ ///
+ /// Refer to `EditGuild`'s documentation for a full list of methods.
+ ///
+ /// Also see [`Guild::edit`] if you have the `methods` feature enabled.
///
/// **Note**: Requires the current user to have the [Manage Guild]
/// permission.
///
+ /// # Examples
+ ///
+ /// Change a guild's icon using a file name "icon.png":
+ ///
+ /// ```rust,ignore
+ /// use serenity::utils;
+ ///
+ /// // We are using read_image helper function from utils.
+ /// let base64_icon = utils::read_image("./icon.png")
+ /// .expect("Failed to read image");
+ ///
+ /// guild.edit(|g| g.icon(base64_icon));
+ /// ```
+ ///
/// # Errors
///
/// If the `cache` is enabled, returns a [`ClientError::InvalidPermissions`]
@@ -504,7 +517,6 @@ impl Guild {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [`Context::edit_guild`]: ../client/struct.Context.html#method.edit_guild
/// [Manage Guild]: permissions/constants.MANAGE_GUILD.html
- #[cfg(feature="methods")]
pub fn edit<F>(&mut self, f: F) -> Result<()>
where F: FnOnce(EditGuild) -> EditGuild {
#[cfg(feature="cache")]
@@ -516,9 +528,7 @@ impl Guild {
}
}
- let map = f(EditGuild::default()).0.build();
-
- match rest::edit_guild(self.id.0, map) {
+ match self.id.edit(f) {
Ok(guild) => {
self.afk_channel_id = guild.afk_channel_id;
self.afk_timeout = guild.afk_timeout;
@@ -540,6 +550,42 @@ impl Guild {
}
}
+ /// Edits an [`Emoji`]'s name in the guild.
+ ///
+ /// Also see [`Emoji::edit`] if you have the `cache` and `methods` features
+ /// enabled.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [`Emoji`]: struct.Emoji.html
+ /// [`Emoji::edit`]: struct.Emoji.html#method.edit
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn edit_emoji<E: Into<EmojiId>>(&self, emoji_id: E, name: &str) -> Result<Emoji> {
+ self.id.edit_emoji(emoji_id, name)
+ }
+
+ /// Edits the properties of member of the guild, such as muting or
+ /// nicknaming them.
+ ///
+ /// Refer to `EditMember`'s documentation for a full list of methods and
+ /// permission restrictions.
+ ///
+ /// # Examples
+ ///
+ /// Mute a member and set their roles to just one role with a predefined Id:
+ ///
+ /// ```rust,ignore
+ /// guild.edit_member(user_id, |m| m
+ /// .mute(true)
+ /// .roles(&vec![role_id]));
+ /// ```
+ #[inline]
+ pub fn edit_member<F, U>(&self, user_id: U, f: F) -> Result<()>
+ where F: FnOnce(EditMember) -> EditMember, U: Into<UserId> {
+ self.id.edit_member(user_id, f)
+ }
+
/// Edits the current user's nickname for the guild.
///
/// Pass `None` to reset the nickname.
@@ -554,7 +600,6 @@ impl Guild {
///
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Change Nickname]: permissions/constant.CHANGE_NICKNAME.html
- #[cfg(feature="methods")]
pub fn edit_nickname(&self, new_nickname: Option<&str>) -> Result<()> {
#[cfg(feature="cache")]
{
@@ -565,7 +610,78 @@ impl Guild {
}
}
- rest::edit_nickname(self.id.0, new_nickname)
+ self.id.edit_nickname(new_nickname)
+ }
+
+ /// Edits a role, optionally setting its fields.
+ ///
+ /// Requires the [Manage Roles] permission.
+ ///
+ /// # Examples
+ ///
+ /// Make a role hoisted:
+ ///
+ /// ```rust,ignore
+ /// guild.edit_role(RoleId(7), |r| r.hoist(true));
+ /// ```
+ ///
+ /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
+ #[inline]
+ pub fn edit_role<F, R>(&self, role_id: R, f: F) -> Result<Role>
+ where F: FnOnce(EditRole) -> EditRole, R: Into<RoleId> {
+ self.id.edit_role(role_id, f)
+ }
+
+ /// Gets a partial amount of guild data by its Id.
+ ///
+ /// Requires that the current user be in the guild.
+ #[inline]
+ pub fn get<G: Into<GuildId>>(guild_id: G) -> Result<PartialGuild> {
+ guild_id.into().get()
+ }
+
+ /// Gets a list of the guild's bans.
+ ///
+ /// Requires the [Ban Members] permission.
+ #[inline]
+ pub fn get_bans(&self) -> Result<Vec<Ban>> {
+ self.id.get_bans()
+ }
+
+ /// Gets all of the guild's channels over the REST API.
+ ///
+ /// [`Guild`]: struct.Guild.html
+ #[inline]
+ pub fn get_channels(&self) -> Result<HashMap<ChannelId, GuildChannel>> {
+ self.id.get_channels()
+ }
+
+ /// Gets an emoji in the guild by Id.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn get_emoji<E: Into<EmojiId>>(&self, emoji_id: E) -> Result<Emoji> {
+ self.id.get_emoji(emoji_id)
+ }
+
+ /// Gets a list of all of the guild's emojis.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn get_emojis(&self) -> Result<Vec<Emoji>> {
+ self.id.get_emojis()
+ }
+
+ /// Gets all integration of the guild.
+ ///
+ /// This performs a request over the REST API.
+ #[inline]
+ pub fn get_integrations(&self) -> Result<Vec<Integration>> {
+ self.id.get_integrations()
}
/// Retrieves the active invites for the guild.
@@ -579,7 +695,6 @@ impl Guild {
///
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
- #[cfg(feature="methods")]
pub fn get_invites(&self) -> Result<Vec<RichInvite>> {
#[cfg(feature="cache")]
{
@@ -590,7 +705,29 @@ impl Guild {
}
}
- rest::get_guild_invites(self.id.0)
+ self.id.get_invites()
+ }
+
+ /// Gets a user's [`Member`] for the guild by Id.
+ ///
+ /// [`Guild`]: struct.Guild.html
+ /// [`Member`]: struct.Member.html
+ #[inline]
+ pub fn get_member<U: Into<UserId>>(&self, user_id: U) -> Result<Member> {
+ self.id.get_member(user_id)
+ }
+
+ /// Gets a list of the guild's members.
+ ///
+ /// Optionally pass in the `limit` to limit the number of results. Maximum
+ /// value is 1000. Optionally pass in `after` to offset the results by a
+ /// [`User`]'s Id.
+ ///
+ /// [`User`]: struct.User.html
+ #[inline]
+ pub fn get_members<U>(&self, limit: Option<u64>, after: Option<U>)
+ -> Result<Vec<Member>> where U: Into<UserId> {
+ self.id.get_members(limit, after)
}
/// Retrieves the first [`Member`] found that matches the name - with an
@@ -631,11 +768,40 @@ impl Guild {
};
name_matches && discrim_matches
- }).or(self.members.iter().find(|&(_member_id, member)| {
+ }).or_else(|| self.members.iter().find(|&(_member_id, member)| {
member.nick.as_ref().map_or(false, |nick| nick == name)
})).map(|(_member_id, member)| member)
}
+ /// Retrieves the count of the number of [`Member`]s that would be pruned
+ /// with the number of given days.
+ ///
+ /// See the documentation on [`GuildPrune`] for more information.
+ ///
+ /// **Note**: Requires the [Kick Members] permission.
+ ///
+ /// # Errors
+ ///
+ /// If the `cache` is enabled, returns a [`ClientError::InvalidPermissions`]
+ /// if the current user does not have permission to perform bans.
+ ///
+ /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
+ /// [`GuildPrune`]: struct.GuildPrune.html
+ /// [`Member`]: struct.Member.html
+ /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
+ pub fn get_prune_count(&self, days: u16) -> Result<GuildPrune> {
+ #[cfg(feature="cache")]
+ {
+ let req = permissions::KICK_MEMBERS;
+
+ if !self.has_perms(req)? {
+ return Err(Error::Client(ClientError::InvalidPermissions(req)));
+ }
+ }
+
+ self.id.get_prune_count(days)
+ }
+
/// Returns the formatted URL of the guild's icon, if one exists.
pub fn icon_url(&self) -> Option<String> {
self.icon.as_ref().map(|icon|
@@ -644,14 +810,37 @@ impl Guild {
/// Checks if the guild is 'large'. A guild is considered large if it has
/// more than 250 members.
+ #[inline]
pub fn is_large(&self) -> bool {
self.members.len() > 250
}
+ /// Kicks a [`Member`] from the guild.
+ ///
+ /// Requires the [Kick Members] permission.
+ ///
+ /// [`Member`]: struct.Member.html
+ /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
+ #[inline]
+ pub fn kick<U: Into<UserId>>(&self, user_id: U) -> Result<()> {
+ self.id.kick(user_id)
+ }
+
/// Leaves the guild.
- #[cfg(feature="methods")]
+ #[inline]
pub fn leave(&self) -> Result<PartialGuild> {
- rest::leave_guild(self.id.0)
+ self.id.leave()
+ }
+
+ /// Moves a member to a specific voice channel.
+ ///
+ /// Requires the [Move Members] permission.
+ ///
+ /// [Move Members]: permissions/constant.MOVE_MEMBERS.html
+ #[inline]
+ pub fn move_member<C, U>(&self, user_id: U, channel_id: C)
+ -> Result<()> where C: Into<ChannelId>, U: Into<UserId> {
+ self.id.move_member(user_id, channel_id)
}
/// Calculate a [`User`]'s permissions in a given channel in the guild.
@@ -770,40 +959,6 @@ impl Guild {
permissions
}
- /// Retrieves the count of the number of [`Member`]s that would be pruned
- /// with the number of given days.
- ///
- /// See the documentation on [`GuildPrune`] for more information.
- ///
- /// **Note**: Requires the [Kick Members] permission.
- ///
- /// # Errors
- ///
- /// If the `cache` is enabled, returns a [`ClientError::InvalidPermissions`]
- /// if the current user does not have permission to perform bans.
- ///
- /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
- /// [`GuildPrune`]: struct.GuildPrune.html
- /// [`Member`]: struct.Member.html
- /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
- #[cfg(feature="methods")]
- pub fn prune_count(&self, days: u16) -> Result<GuildPrune> {
- #[cfg(feature="cache")]
- {
- let req = permissions::KICK_MEMBERS;
-
- if !self.has_perms(req)? {
- return Err(Error::Client(ClientError::InvalidPermissions(req)));
- }
- }
-
- let map = ObjectBuilder::new()
- .insert("days", days)
- .build();
-
- rest::get_guild_prune_count(self.id.0, map)
- }
-
/// Performs a search request to the API for the guild's [`Message`]s.
///
/// This will search all of the guild's [`Channel`]s at once, that you have
@@ -828,9 +983,7 @@ impl Guild {
/// [`Search`]: ../utils/builder/struct.Search.html
/// [`search_channels`]: #method.search_channels
/// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
- #[cfg(feature="methods")]
- pub fn search<F>(&self, f: F) -> Result<SearchResult>
- where F: FnOnce(Search) -> Search {
+ pub fn search<F: FnOnce(Search) -> Search>(&self, f: F) -> Result<SearchResult> {
#[cfg(feature="cache")]
{
if CACHE.read().unwrap().user.bot {
@@ -866,7 +1019,6 @@ impl Guild {
/// [`Search`]: ../utils/builder/struct.Search.html
/// [`search`]: #method.search
/// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
- #[cfg(feature = "methods")]
pub fn search_channels<F>(&self, channel_ids: &[ChannelId], f: F)
-> Result<SearchResult> where F: FnOnce(Search) -> Search {
#[cfg(feature="cache")]
@@ -876,18 +1028,25 @@ impl Guild {
}
}
- let ids = channel_ids.iter().map(|x| x.0).collect::<Vec<u64>>();
-
- rest::search_guild_messages(self.id.0, &ids, f(Search::default()).0)
+ self.id.search_channels(channel_ids, f)
}
/// Returns the formatted URL of the guild's splash image, if one exists.
- #[cfg(feature="methods")]
pub fn splash_url(&self) -> Option<String> {
self.icon.as_ref().map(|icon|
format!(cdn!("/splashes/{}/{}.webp"), self.id, icon))
}
+ /// Starts an integration sync for the given integration Id.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
+ #[inline]
+ pub fn start_integration_sync<I: Into<IntegrationId>>(&self, integration_id: I) -> Result<()> {
+ self.id.start_integration_sync(integration_id)
+ }
+
/// Starts a prune of [`Member`]s.
///
/// See the documentation on [`GuildPrune`] for more information.
@@ -903,7 +1062,6 @@ impl Guild {
/// [`GuildPrune`]: struct.GuildPrune.html
/// [`Member`]: struct.Member.html
/// [Kick Members]: permissions/constant.KICK_MEMBERS.html
- #[cfg(feature="methods")]
pub fn start_prune(&self, days: u16) -> Result<GuildPrune> {
#[cfg(feature="cache")]
{
@@ -914,11 +1072,7 @@ impl Guild {
}
}
- let map = ObjectBuilder::new()
- .insert("days", days)
- .build();
-
- rest::start_guild_prune(self.id.0, map)
+ self.id.start_prune(days)
}
/// Unbans the given [`User`] from the guild.
@@ -933,8 +1087,7 @@ impl Guild {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [`User`]: struct.User.html
/// [Ban Members]: permissions/constant.BAN_MEMBERS.html
- #[cfg(feature="methods")]
- pub fn unban<U: Into<UserId>>(&self, user: U) -> Result<()> {
+ pub fn unban<U: Into<UserId>>(&self, user_id: U) -> Result<()> {
#[cfg(feature="cache")]
{
let req = permissions::BAN_MEMBERS;
@@ -944,7 +1097,494 @@ impl Guild {
}
}
- rest::remove_ban(self.id.0, user.into().0)
+ self.id.unban(user_id)
+ }
+
+ /// Retrieves the guild's webhooks.
+ ///
+ /// **Note**: Requires the [Manage Webhooks] permission.
+ ///
+ /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html
+ #[inline]
+ pub fn webhooks(&self) -> Result<Vec<Webhook>> {
+ self.id.webhooks()
+ }
+}
+
+impl GuildId {
+ /// Ban a [`User`] from the guild. All messages by the
+ /// user within the last given number of days given will be deleted.
+ ///
+ /// Refer to the documentation for [`Guild::ban`] for more information.
+ ///
+ /// **Note**: Requires the [Ban Members] permission.
+ ///
+ /// # Examples
+ ///
+ /// Ban a member and remove all messages they've sent in the last 4 days:
+ ///
+ /// ```rust,ignore
+ /// use serenity::model::GuildId;
+ ///
+ /// // assuming a `user` has already been bound
+ /// let _ = GuildId(81384788765712384).ban(user, 4);
+ /// ```
+ ///
+ /// # Errors
+ ///
+ /// Returns a [`ClientError::DeleteMessageDaysAmount`] if the number of
+ /// days' worth of messages to delete is over the maximum.
+ ///
+ /// [`ClientError::DeleteMessageDaysAmount`]: ../client/enum.ClientError.html#variant.DeleteMessageDaysAmount
+ /// [`Guild::ban`]: struct.Guild.html#method.ban
+ /// [`User`]: struct.User.html
+ /// [Ban Members]: permissions/constant.BAN_MEMBERS.html
+ pub fn ban<U: Into<UserId>>(&self, user: U, delete_message_days: u8)
+ -> Result<()> {
+ if delete_message_days > 7 {
+ return Err(Error::Client(ClientError::DeleteMessageDaysAmount(delete_message_days)));
+ }
+
+ rest::ban_user(self.0, user.into().0, delete_message_days)
+ }
+
+ /// Creates a [`GuildChannel`] in the the guild.
+ ///
+ /// Refer to [`rest::create_channel`] for more information.
+ ///
+ /// Requires the [Manage Channels] permission.
+ ///
+ /// # Examples
+ ///
+ /// Create a voice channel in a guild with the name `test`:
+ ///
+ /// ```rust,ignore
+ /// use serenity::model::{ChannelType, GuildId};
+ ///
+ /// let _channel = GuildId(7).create_channel("test", ChannelType::Voice);
+ /// ```
+ ///
+ /// [`GuildChannel`]: struct.GuildChannel.html
+ /// [`rest::create_channel`]: rest/fn.create_channel.html
+ /// [Manage Channels]: permissions/constant.MANAGE_CHANNELS.html
+ pub fn create_channel(&self, name: &str, kind: ChannelType) -> Result<Channel> {
+ let map = ObjectBuilder::new()
+ .insert("name", name)
+ .insert("type", kind.name())
+ .build();
+
+ rest::create_channel(self.0, map)
+ }
+
+ /// Creates an emoji in the guild with a name and base64-encoded image.
+ ///
+ /// Refer to the documentation for [`Guild::create_emoji`] for more
+ /// information.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// # Examples
+ ///
+ /// See the [`EditProfile::avatar`] example for an in-depth example as to
+ /// how to read an image from the filesystem and encode it as base64. Most
+ /// of the example can be applied similarly for this method.
+ ///
+ /// [`EditProfile::avatar`]: ../utils/builder/struct.EditProfile.html#method.avatar
+ /// [`Guild::create_emoji`]: struct.Guild.html#method.create_emoji
+ /// [`utils::read_image`]: ../utils/fn.read_image.html
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ pub fn create_emoji(&self, name: &str, image: &str) -> Result<Emoji> {
+ let map = ObjectBuilder::new()
+ .insert("name", name)
+ .insert("image", image)
+ .build();
+
+ rest::create_emoji(self.0, map)
+ }
+
+ /// Creates an integration for the guild.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
+ pub fn create_integration<I>(&self, integration_id: I, kind: &str)
+ -> Result<()> where I: Into<IntegrationId> {
+ let integration_id = integration_id.into();
+ let map = ObjectBuilder::new()
+ .insert("id", integration_id.0)
+ .insert("type", kind)
+ .build();
+
+ rest::create_guild_integration(self.0, integration_id.0, map)
+ }
+
+ /// Creates a new role in the guild with the data set, if any.
+ ///
+ /// See the documentation for [`Guild::create_role`] on how to use this.
+ ///
+ /// **Note**: Requires the [Manage Roles] permission.
+ ///
+ /// [`Guild::create_role`]: struct.Guild.html#method.create_role
+ /// [Manage Roles]: permissions/constants.MANAGE_ROLES.html
+ #[inline]
+ pub fn create_role<F: FnOnce(EditRole) -> EditRole>(&self, f: F) -> Result<Role> {
+ rest::create_role(self.0, f(EditRole::default()).0.build())
+ }
+
+ /// Deletes the current guild if the current account is the owner of the
+ /// guild.
+ ///
+ /// Refer to [`Guild::delete`] for more information.
+ ///
+ /// **Note**: Requires the current user to be the owner of the guild.
+ ///
+ /// [`Guild::delete`]: struct.Guild.html#method.delete
+ #[inline]
+ pub fn delete(&self) -> Result<PartialGuild> {
+ rest::delete_guild(self.0)
+ }
+
+ /// Deletes an [`Emoji`] from the guild.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [`Emoji`]: struct.Emoji.html
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn delete_emoji<E: Into<EmojiId>>(&self, emoji_id: E) -> Result<()> {
+ rest::delete_emoji(self.0, emoji_id.into().0)
+ }
+
+ /// Deletes an integration by Id from the guild.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
+ #[inline]
+ pub fn delete_integration<I: Into<IntegrationId>>(&self, integration_id: I) -> Result<()> {
+ rest::delete_guild_integration(self.0, integration_id.into().0)
+ }
+
+ /// Deletes a [`Role`] by Id from the guild.
+ ///
+ /// Also see [`Role::delete`] if you have the `cache` and `methods` features
+ /// enabled.
+ ///
+ /// Requires the [Manage Roles] permission.
+ ///
+ /// [`Role`]: struct.Role.html
+ /// [`Role::delete`]: struct.Role.html#method.delete
+ /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
+ #[inline]
+ pub fn delete_role<R: Into<RoleId>>(&self, role_id: R) -> Result<()> {
+ rest::delete_role(self.0, role_id.into().0)
+ }
+
+ /// Edits the current guild with new data where specified.
+ ///
+ /// Refer to [`Guild::edit`] for more information.
+ ///
+ /// **Note**: Requires the current user to have the [Manage Guild]
+ /// permission.
+ ///
+ /// [`Guild::edit`]: struct.Guild.html#method.edit
+ /// [Manage Guild]: permissions/constants.MANAGE_GUILD.html
+ #[inline]
+ pub fn edit<F: FnOnce(EditGuild) -> EditGuild>(&mut self, f: F) -> Result<PartialGuild> {
+ rest::edit_guild(self.0, f(EditGuild::default()).0.build())
+ }
+
+ /// Edits an [`Emoji`]'s name in the guild.
+ ///
+ /// Also see [`Emoji::edit`] if you have the `cache` and `methods` features
+ /// enabled.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [`Emoji`]: struct.Emoji.html
+ /// [`Emoji::edit`]: struct.Emoji.html#method.edit
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ pub fn edit_emoji<E: Into<EmojiId>>(&self, emoji_id: E, name: &str) -> Result<Emoji> {
+ let map = ObjectBuilder::new()
+ .insert("name", name)
+ .build();
+
+ rest::edit_emoji(self.0, emoji_id.into().0, map)
+ }
+
+ /// Edits the properties of member of the guild, such as muting or
+ /// nicknaming them.
+ ///
+ /// Refer to `EditMember`'s documentation for a full list of methods and
+ /// permission restrictions.
+ ///
+ /// # Examples
+ ///
+ /// Mute a member and set their roles to just one role with a predefined Id:
+ ///
+ /// ```rust,ignore
+ /// guild.edit_member(user_id, |m| m
+ /// .mute(true)
+ /// .roles(&vec![role_id]));
+ /// ```
+ #[inline]
+ pub fn edit_member<F, U>(&self, user_id: U, f: F) -> Result<()>
+ where F: FnOnce(EditMember) -> EditMember, U: Into<UserId> {
+ rest::edit_member(self.0, user_id.into().0, f(EditMember::default()).0.build())
+ }
+
+ /// Edits the current user's nickname for the guild.
+ ///
+ /// Pass `None` to reset the nickname.
+ ///
+ /// Requires the [Change Nickname] permission.
+ ///
+ /// [Change Nickname]: permissions/constant.CHANGE_NICKNAME.html
+ #[inline]
+ pub fn edit_nickname(&self, new_nickname: Option<&str>) -> Result<()> {
+ rest::edit_nickname(self.0, new_nickname)
+ }
+
+ /// Edits a [`Role`], optionally setting its new fields.
+ ///
+ /// Requires the [Manage Roles] permission.
+ ///
+ /// # Examples
+ ///
+ /// Make a role hoisted:
+ ///
+ /// ```rust,ignore
+ /// use serenity::model::{GuildId, RoleId};
+ ///
+ /// GuildId(7).edit_role(RoleId(8), |r| r.hoist(true));
+ /// ```
+ ///
+ /// [`Role`]: struct.Role.html
+ /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
+ #[inline]
+ pub fn edit_role<F, R>(&self, role_id: R, f: F) -> Result<Role>
+ where F: FnOnce(EditRole) -> EditRole, R: Into<RoleId> {
+ rest::edit_role(self.0, role_id.into().0, f(EditRole::default()).0.build())
+ }
+
+ /// Search the cache for the guild.
+ #[cfg(feature="cache")]
+ pub fn find(&self) -> Option<Guild> {
+ CACHE.read().unwrap().get_guild(*self).cloned()
+ }
+
+ /// Requests the guild over REST.
+ ///
+ /// Note that this will not be a complete guild, as REST does not send
+ /// all data with a guild retrieval.
+ #[inline]
+ pub fn get(&self) -> Result<PartialGuild> {
+ rest::get_guild(self.0)
+ }
+
+ /// Gets a list of the guild's bans.
+ ///
+ /// Requires the [Ban Members] permission.
+ #[inline]
+ pub fn get_bans(&self) -> Result<Vec<Ban>> {
+ rest::get_bans(self.0)
+ }
+
+ /// Gets all of the guild's channels over the REST API.
+ ///
+ /// [`Guild`]: struct.Guild.html
+ pub fn get_channels(&self) -> Result<HashMap<ChannelId, GuildChannel>> {
+ let mut channels = HashMap::new();
+
+ for channel in rest::get_channels(self.0)? {
+ channels.insert(channel.id, channel);
+ }
+
+ Ok(channels)
+ }
+
+ /// Gets an emoji in the guild by Id.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn get_emoji<E: Into<EmojiId>>(&self, emoji_id: E) -> Result<Emoji> {
+ rest::get_emoji(self.0, emoji_id.into().0)
+ }
+
+ /// Gets a list of all of the guild's emojis.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn get_emojis(&self) -> Result<Vec<Emoji>> {
+ rest::get_emojis(self.0)
+ }
+
+ /// Gets all integration of the guild.
+ ///
+ /// This performs a request over the REST API.
+ #[inline]
+ pub fn get_integrations(&self) -> Result<Vec<Integration>> {
+ rest::get_guild_integrations(self.0)
+ }
+
+ /// Gets all of the guild's invites.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/struct.MANAGE_GUILD.html
+ #[inline]
+ pub fn get_invites(&self) -> Result<Vec<RichInvite>> {
+ rest::get_guild_invites(self.0)
+ }
+
+ /// Gets a user's [`Member`] for the guild by Id.
+ ///
+ /// [`Guild`]: struct.Guild.html
+ /// [`Member`]: struct.Member.html
+ #[inline]
+ pub fn get_member<U: Into<UserId>>(&self, user_id: U) -> Result<Member> {
+ rest::get_member(self.0, user_id.into().0)
+ }
+
+ /// Gets a list of the guild's members.
+ ///
+ /// Optionally pass in the `limit` to limit the number of results. Maximum
+ /// value is 1000. Optionally pass in `after` to offset the results by a
+ /// [`User`]'s Id.
+ ///
+ /// [`User`]: struct.User.html
+ #[inline]
+ pub fn get_members<U>(&self, limit: Option<u64>, after: Option<U>)
+ -> Result<Vec<Member>> where U: Into<UserId> {
+ rest::get_guild_members(self.0, limit, after.map(|x| x.into().0))
+ }
+
+ /// Gets the number of [`Member`]s that would be pruned with the given
+ /// number of days.
+ ///
+ /// Requires the [Kick Members] permission.
+ ///
+ /// [`Member`]: struct.Member.html
+ /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
+ pub fn get_prune_count(&self, days: u16) -> Result<GuildPrune> {
+ let map = ObjectBuilder::new()
+ .insert("days", days)
+ .build();
+
+ rest::get_guild_prune_count(self.0, map)
+ }
+
+ /// Kicks a [`Member`] from the guild.
+ ///
+ /// Requires the [Kick Members] permission.
+ ///
+ /// [`Member`]: struct.Member.html
+ /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
+ #[inline]
+ pub fn kick<U: Into<UserId>>(&self, user_id: U) -> Result<()> {
+ rest::kick_member(self.0, user_id.into().0)
+ }
+
+ /// Leaves the guild.
+ #[inline]
+ pub fn leave(&self) -> Result<PartialGuild> {
+ rest::leave_guild(self.0)
+ }
+
+ /// Moves a member to a specific voice channel.
+ ///
+ /// Requires the [Move Members] permission.
+ ///
+ /// [Move Members]: permissions/constant.MOVE_MEMBERS.html
+ pub fn move_member<C, U>(&self, user_id: U, channel_id: C)
+ -> Result<()> where C: Into<ChannelId>, U: Into<UserId> {
+ let map = ObjectBuilder::new()
+ .insert("channel_id", channel_id.into().0)
+ .build();
+
+ rest::edit_member(self.0, user_id.into().0, map)
+ }
+
+ /// Performs a search request to the API for the guild's [`Message`]s.
+ ///
+ /// This will search all of the guild's [`Channel`]s at once, that you have
+ /// the [Read Message History] permission to. Use [`search_channels`] to
+ /// specify a list of [channel][`GuildChannel`]s to search, where all other
+ /// channels will be excluded.
+ ///
+ /// Refer to the documentation for the [`Search`] builder for examples and
+ /// more information.
+ ///
+ /// [`Channel`]: enum.Channel.html
+ /// [`GuildChannel`]: struct.GuildChannel.html
+ /// [`Message`]: struct.Message.html
+ /// [`Search`]: ../utils/builder/struct.Search.html
+ /// [`search_channels`]: #method.search_channels
+ /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
+ #[inline]
+ pub fn search<F: FnOnce(Search) -> Search>(&self, f: F) -> Result<SearchResult> {
+ rest::search_guild_messages(self.0, &[], f(Search::default()).0)
+ }
+
+ /// Performs a search request to the API for the guild's [`Message`]s in
+ /// given channels.
+ ///
+ /// Refer to [`Guild::search_channels`] for more information.
+ ///
+ /// Refer to the documentation for the [`Search`] builder for examples and
+ /// more information.
+ ///
+ /// **Note**: Bot users can not search.
+ ///
+ /// [`Guild::search_channels`]: struct.Guild.html#method.search_channels
+ /// [`Message`]: struct.Message.html
+ pub fn search_channels<F>(&self, channel_ids: &[ChannelId], f: F)
+ -> Result<SearchResult> where F: FnOnce(Search) -> Search {
+ let ids = channel_ids.iter().map(|x| x.0).collect::<Vec<u64>>();
+
+ rest::search_guild_messages(self.0, &ids, f(Search::default()).0)
+ }
+
+ /// Starts an integration sync for the given integration Id.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
+ #[inline]
+ pub fn start_integration_sync<I: Into<IntegrationId>>(&self, integration_id: I) -> Result<()> {
+ rest::start_integration_sync(self.0, integration_id.into().0)
+ }
+
+ /// Starts a prune of [`Member`]s.
+ ///
+ /// See the documentation on [`GuildPrune`] for more information.
+ ///
+ /// **Note**: Requires the [Kick Members] permission.
+ ///
+ /// [`GuildPrune`]: struct.GuildPrune.html
+ /// [`Member`]: struct.Member.html
+ /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
+ pub fn start_prune(&self, days: u16) -> Result<GuildPrune> {
+ let map = ObjectBuilder::new()
+ .insert("days", days)
+ .build();
+
+ rest::start_guild_prune(self.0, map)
+ }
+
+ /// Unbans a [`User`] from the guild.
+ ///
+ /// Requires the [Ban Members] permission.
+ ///
+ /// [`User`]: struct.User.html
+ /// [Ban Members]: permissions/constant.BAN_MEMBERS.html
+ #[inline]
+ pub fn unban<U: Into<UserId>>(&self, user_id: U) -> Result<()> {
+ rest::remove_ban(self.0, user_id.into().0)
}
/// Retrieves the guild's webhooks.
@@ -952,10 +1592,50 @@ impl Guild {
/// **Note**: Requires the [Manage Webhooks] permission.
///
/// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html
- #[cfg(feature="methods")]
#[inline]
pub fn webhooks(&self) -> Result<Vec<Webhook>> {
- rest::get_guild_webhooks(self.id.0)
+ rest::get_guild_webhooks(self.0)
+ }
+}
+
+impl fmt::Display for GuildId {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.0, f)
+ }
+}
+
+impl From<PartialGuild> for GuildId {
+ /// Gets the Id of a partial guild.
+ fn from(guild: PartialGuild) -> GuildId {
+ guild.id
+ }
+}
+
+impl From<GuildInfo> for GuildId {
+ /// Gets the Id of Guild information struct.
+ fn from(guild_info: GuildInfo) -> GuildId {
+ guild_info.id
+ }
+}
+
+impl From<InviteGuild> for GuildId {
+ /// Gets the Id of Invite Guild struct.
+ fn from(invite_guild: InviteGuild) -> GuildId {
+ invite_guild.id
+ }
+}
+
+impl From<Guild> for GuildId {
+ /// Gets the Id of Guild.
+ fn from(live_guild: Guild) -> GuildId {
+ live_guild.id
+ }
+}
+
+impl From<Integration> for IntegrationId {
+ /// Gets the Id of integration.
+ fn from(integration: Integration) -> IntegrationId {
+ integration.id
}
}
@@ -967,7 +1647,7 @@ impl Member {
///
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn add_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> {
let role_id = role_id.into();
@@ -994,7 +1674,7 @@ impl Member {
///
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn add_roles(&mut self, role_ids: &[RoleId]) -> Result<()> {
let guild_id = self.find_guild()?;
self.roles.extend_from_slice(role_ids);
@@ -1016,23 +1696,25 @@ impl Member {
///
/// **Note**: Requires the [Ban Members] role.
///
+ /// # Errors
+ ///
+ /// Returns a [`ClientError::GuildNotFound`] if the guild could not be
+ /// found.
+ ///
+ /// [`ClientError::GuildNotFound`]: ../client/enum.ClientError.html#variant.GuildNotFound
+ ///
/// [Ban Members]: permissions/constant.BAN_MEMBERS.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn ban(&self, delete_message_days: u8) -> Result<()> {
- let guild_id = self.find_guild()?;
-
- rest::ban_user(guild_id.0,
- self.user.id.0,
- delete_message_days)
+ rest::ban_user(self.find_guild()?.0, self.user.id.0, delete_message_days)
}
/// Determines the member's colour.
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn colour(&self) -> Option<Colour> {
- let default = Colour::default();
let guild_id = match self.find_guild() {
Ok(guild_id) => guild_id,
- Err(_why) => return None,
+ Err(_) => return None,
};
let cache = CACHE.read().unwrap();
@@ -1047,18 +1729,21 @@ impl Member {
.collect::<Vec<&Role>>();
roles.sort_by(|a, b| b.cmp(a));
+ let default = Colour::default();
+
roles.iter().find(|r| r.colour.0 != default.0).map(|r| r.colour)
}
/// Calculates the member's display name.
///
/// The nickname takes priority over the member's username if it exists.
+ #[inline]
pub fn display_name(&self) -> &str {
self.nick.as_ref().unwrap_or(&self.user.name)
}
/// Returns the DiscordTag of a Member, taking possible nickname into account.
- #[cfg(feature="methods")]
+ #[inline]
pub fn distinct(&self) -> String {
format!("{}#{}", self.display_name(), self.user.discriminator)
}
@@ -1071,7 +1756,7 @@ impl Member {
///
/// [`Context::edit_member`]: ../client/struct.Context.html#method.edit_member
/// [`EditMember`]: ../builder/struct.EditMember.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn edit<F>(&self, f: F) -> Result<()>
where F: FnOnce(EditMember) -> EditMember {
let guild_id = self.find_guild()?;
@@ -1082,8 +1767,14 @@ impl Member {
/// Finds the Id of the [`Guild`] that the member is in.
///
+ /// # Errors
+ ///
+ /// Returns a [`ClientError::GuildNotFound`] if the guild could not be
+ /// found.
+ ///
+ /// [`ClientError::GuildNotFound`]: ../client/enum.ClientError.html#variant.GuildNotFound
/// [`Guild`]: struct.Guild.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn find_guild(&self) -> Result<GuildId> {
CACHE.read()
.unwrap()
@@ -1110,7 +1801,7 @@ impl Member {
///
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn remove_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> {
let role_id = role_id.into();
@@ -1136,7 +1827,7 @@ impl Member {
///
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn remove_roles(&mut self, role_ids: &[RoleId]) -> Result<()> {
let guild_id = self.find_guild()?;
self.roles.retain(|r| !role_ids.contains(r));
@@ -1158,7 +1849,7 @@ impl Member {
/// This is shorthand for manually searching through the CACHE.
///
/// If role data can not be found for the member, then `None` is returned.
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn roles(&self) -> Option<Vec<Role>> {
CACHE.read().unwrap()
.guilds
@@ -1172,6 +1863,23 @@ impl Member {
.cloned()
.collect())
}
+
+ /// Unbans the [`User`] from the guild.
+ ///
+ /// **Note**: Requires the [Ban Members] permission.
+ ///
+ /// # Errors
+ ///
+ /// If the `cache` is enabled, returns a [`ClientError::InvalidPermissions`]
+ /// if the current user does not have permission to perform bans.
+ ///
+ /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
+ /// [`User`]: struct.User.html
+ /// [Ban Members]: permissions/constant.BAN_MEMBERS.html
+ #[cfg(feature="cache")]
+ pub fn unban(&self) -> Result<()> {
+ rest::remove_ban(self.find_guild()?.0, self.user.id.0)
+ }
}
impl fmt::Display for Member {
@@ -1190,6 +1898,489 @@ impl fmt::Display for Member {
}
}
+impl PartialGuild {
+ /// Ban a [`User`] from the guild. All messages by the
+ /// user within the last given number of days given will be deleted. This
+ /// may be a range between `0` and `7`.
+ ///
+ /// **Note**: Requires the [Ban Members] permission.
+ ///
+ /// # Examples
+ ///
+ /// Ban a member and remove all messages they've sent in the last 4 days:
+ ///
+ /// ```rust,ignore
+ /// // assumes a `user` and `guild` have already been bound
+ /// let _ = guild.ban(user, 4);
+ /// ```
+ ///
+ /// # Errors
+ ///
+ /// Returns a [`ClientError::DeleteMessageDaysAmount`] if the number of
+ /// days' worth of messages to delete is over the maximum.
+ ///
+ /// [`ClientError::DeleteMessageDaysAmount`]: ../client/enum.ClientError.html#variant.DeleteMessageDaysAmount
+ /// [`User`]: struct.User.html
+ /// [Ban Members]: permissions/constant.BAN_MEMBERS.html
+ pub fn ban<U: Into<UserId>>(&self, user: U, delete_message_days: u8)
+ -> Result<()> {
+ if delete_message_days > 7 {
+ return Err(Error::Client(ClientError::DeleteMessageDaysAmount(delete_message_days)));
+ }
+
+ self.id.ban(user.into(), delete_message_days)
+ }
+
+ /// Creates a [`GuildChannel`] in the guild.
+ ///
+ /// Refer to [`rest::create_channel`] for more information.
+ ///
+ /// Requires the [Manage Channels] permission.
+ ///
+ /// # Examples
+ ///
+ /// Create a voice channel in a guild with the name `test`:
+ ///
+ /// ```rust,ignore
+ /// use serenity::model::ChannelType;
+ ///
+ /// guild.create_channel("test", ChannelType::Voice);
+ /// ```
+ ///
+ /// [`GuildChannel`]: struct.GuildChannel.html
+ /// [`rest::create_channel`]: rest/fn.create_channel.html
+ /// [Manage Channels]: permissions/constant.MANAGE_CHANNELS.html
+ #[inline]
+ pub fn create_channel(&self, name: &str, kind: ChannelType) -> Result<Channel> {
+ self.id.create_channel(name, kind)
+ }
+
+ /// Creates an emoji in the guild with a name and base64-encoded image.
+ ///
+ /// Refer to the documentation for [`Guild::create_emoji`] for more
+ /// information.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// # Examples
+ ///
+ /// See the [`EditProfile::avatar`] example for an in-depth example as to
+ /// how to read an image from the filesystem and encode it as base64. Most
+ /// of the example can be applied similarly for this method.
+ ///
+ /// [`EditProfile::avatar`]: ../utils/builder/struct.EditProfile.html#method.avatar
+ /// [`Guild::create_emoji`]: struct.Guild.html#method.create_emoji
+ /// [`utils::read_image`]: ../utils/fn.read_image.html
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn create_emoji(&self, name: &str, image: &str) -> Result<Emoji> {
+ self.id.create_emoji(name, image)
+ }
+
+ /// Creates an integration for the guild.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
+ #[inline]
+ pub fn create_integration<I>(&self, integration_id: I, kind: &str) -> Result<()>
+ where I: Into<IntegrationId> {
+ self.id.create_integration(integration_id, kind)
+ }
+
+ /// Creates a new role in the guild with the data set, if any.
+ ///
+ /// See the documentation for [`Guild::create_role`] on how to use this.
+ ///
+ /// **Note**: Requires the [Manage Roles] permission.
+ ///
+ /// # Errors
+ ///
+ /// If the `cache` is enabled, returns a [`ClientError::InvalidPermissions`]
+ /// if the current user does not have permission to perform bans.
+ ///
+ /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
+ /// [`Guild::create_role`]: struct.Guild.html#method.create_role
+ /// [Manage Roles]: permissions/constants.MANAGE_ROLES.html
+ #[inline]
+ pub fn create_role<F: FnOnce(EditRole) -> EditRole>(&self, f: F) -> Result<Role> {
+ self.id.create_role(f)
+ }
+
+ /// Deletes the current guild if the current user is the owner of the
+ /// guild.
+ ///
+ /// **Note**: Requires the current user to be the owner of the guild.
+ #[inline]
+ pub fn delete(&self) -> Result<PartialGuild> {
+ self.id.delete()
+ }
+
+ /// Deletes an [`Emoji`] from the guild.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [`Emoji`]: struct.Emoji.html
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn delete_emoji<E: Into<EmojiId>>(&self, emoji_id: E) -> Result<()> {
+ self.id.delete_emoji(emoji_id)
+ }
+
+ /// Deletes an integration by Id from the guild.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
+ #[inline]
+ pub fn delete_integration<I: Into<IntegrationId>>(&self, integration_id: I) -> Result<()> {
+ self.id.delete_integration(integration_id)
+ }
+
+ /// Deletes a [`Role`] by Id from the guild.
+ ///
+ /// Also see [`Role::delete`] if you have the `cache` and `methods` features
+ /// enabled.
+ ///
+ /// Requires the [Manage Roles] permission.
+ ///
+ /// [`Role`]: struct.Role.html
+ /// [`Role::delete`]: struct.Role.html#method.delete
+ /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
+ #[inline]
+ pub fn delete_role<R: Into<RoleId>>(&self, role_id: R) -> Result<()> {
+ self.id.delete_role(role_id)
+ }
+
+ /// Edits the current guild with new data where specified.
+ ///
+ /// Refer to [`Guild::edit`] for more information.
+ ///
+ /// **Note**: Requires the current user to have the [Manage Guild]
+ /// permission.
+ ///
+ /// [`Context::edit_guild`]: ../client/struct.Context.html#method.edit_guild
+ /// [Manage Guild]: permissions/constants.MANAGE_GUILD.html
+ pub fn edit<F>(&mut self, f: F) -> Result<()>
+ where F: FnOnce(EditGuild) -> EditGuild {
+ match self.id.edit(f) {
+ Ok(guild) => {
+ self.afk_channel_id = guild.afk_channel_id;
+ self.afk_timeout = guild.afk_timeout;
+ self.default_message_notifications = guild.default_message_notifications;
+ self.emojis = guild.emojis;
+ self.features = guild.features;
+ self.icon = guild.icon;
+ self.mfa_level = guild.mfa_level;
+ self.name = guild.name;
+ self.owner_id = guild.owner_id;
+ self.region = guild.region;
+ self.roles = guild.roles;
+ self.splash = guild.splash;
+ self.verification_level = guild.verification_level;
+
+ Ok(())
+ },
+ Err(why) => Err(why),
+ }
+ }
+
+ /// Edits an [`Emoji`]'s name in the guild.
+ ///
+ /// Also see [`Emoji::edit`] if you have the `cache` and `methods` features
+ /// enabled.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [`Emoji`]: struct.Emoji.html
+ /// [`Emoji::edit`]: struct.Emoji.html#method.edit
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn edit_emoji<E: Into<EmojiId>>(&self, emoji_id: E, name: &str) -> Result<Emoji> {
+ self.id.edit_emoji(emoji_id, name)
+ }
+
+ /// Edits the properties of member of the guild, such as muting or
+ /// nicknaming them.
+ ///
+ /// Refer to `EditMember`'s documentation for a full list of methods and
+ /// permission restrictions.
+ ///
+ /// # Examples
+ ///
+ /// Mute a member and set their roles to just one role with a predefined Id:
+ ///
+ /// ```rust,ignore
+ /// use serenity::model::GuildId;
+ ///
+ /// GuildId(7).edit_member(user_id, |m| m
+ /// .mute(true)
+ /// .roles(&vec![role_id]));
+ /// ```
+ #[inline]
+ pub fn edit_member<F, U>(&self, user_id: U, f: F) -> Result<()>
+ where F: FnOnce(EditMember) -> EditMember, U: Into<UserId> {
+ self.id.edit_member(user_id, f)
+ }
+
+ /// Edits the current user's nickname for the guild.
+ ///
+ /// Pass `None` to reset the nickname.
+ ///
+ /// **Note**: Requires the [Change Nickname] permission.
+ ///
+ /// # Errors
+ ///
+ /// If the `cache` is enabled, returns a [`ClientError::InvalidPermissions`]
+ /// if the current user does not have permission to change their own
+ /// nickname.
+ ///
+ /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
+ /// [Change Nickname]: permissions/constant.CHANGE_NICKNAME.html
+ #[inline]
+ pub fn edit_nickname(&self, new_nickname: Option<&str>) -> Result<()> {
+ self.id.edit_nickname(new_nickname)
+ }
+
+ /// Gets a partial amount of guild data by its Id.
+ ///
+ /// Requires that the current user be in the guild.
+ #[inline]
+ pub fn get<G: Into<GuildId>>(guild_id: G) -> Result<PartialGuild> {
+ guild_id.into().get()
+ }
+
+ /// Gets a list of the guild's bans.
+ ///
+ /// Requires the [Ban Members] permission.
+ #[inline]
+ pub fn get_bans(&self) -> Result<Vec<Ban>> {
+ self.id.get_bans()
+ }
+
+ /// Gets all of the guild's channels over the REST API.
+ ///
+ /// [`Guild`]: struct.Guild.html
+ #[inline]
+ pub fn get_channels(&self) -> Result<HashMap<ChannelId, GuildChannel>> {
+ self.id.get_channels()
+ }
+
+ /// Gets an emoji in the guild by Id.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn get_emoji<E: Into<EmojiId>>(&self, emoji_id: E) -> Result<Emoji> {
+ self.id.get_emoji(emoji_id)
+ }
+
+ /// Gets a list of all of the guild's emojis.
+ ///
+ /// Requires the [Manage Emojis] permission.
+ ///
+ /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
+ #[inline]
+ pub fn get_emojis(&self) -> Result<Vec<Emoji>> {
+ self.id.get_emojis()
+ }
+
+ /// Gets all integration of the guild.
+ ///
+ /// This performs a request over the REST API.
+ #[inline]
+ pub fn get_integrations(&self) -> Result<Vec<Integration>> {
+ self.id.get_integrations()
+ }
+
+ /// Gets all of the guild's invites.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/struct.MANAGE_GUILD.html
+ #[inline]
+ pub fn get_invites(&self) -> Result<Vec<RichInvite>> {
+ self.id.get_invites()
+ }
+
+ /// Gets a user's [`Member`] for the guild by Id.
+ ///
+ /// [`Guild`]: struct.Guild.html
+ /// [`Member`]: struct.Member.html
+ pub fn get_member<U: Into<UserId>>(&self, user_id: U) -> Result<Member> {
+ self.id.get_member(user_id)
+ }
+
+ /// Gets a list of the guild's members.
+ ///
+ /// Optionally pass in the `limit` to limit the number of results. Maximum
+ /// value is 1000. Optionally pass in `after` to offset the results by a
+ /// [`User`]'s Id.
+ ///
+ /// [`User`]: struct.User.html
+ pub fn get_members<U>(&self, limit: Option<u64>, after: Option<U>)
+ -> Result<Vec<Member>> where U: Into<UserId> {
+ self.id.get_members(limit, after)
+ }
+
+ /// Gets the number of [`Member`]s that would be pruned with the given
+ /// number of days.
+ ///
+ /// Requires the [Kick Members] permission.
+ ///
+ /// [`Member`]: struct.Member.html
+ /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
+ #[inline]
+ pub fn get_prune_count(&self, days: u16) -> Result<GuildPrune> {
+ self.id.get_prune_count(days)
+ }
+
+ /// Kicks a [`Member`] from the guild.
+ ///
+ /// Requires the [Kick Members] permission.
+ ///
+ /// [`Member`]: struct.Member.html
+ /// [Kick Members]: permissions/constant.KICK_MEMBERS.html
+ #[inline]
+ pub fn kick<U: Into<UserId>>(&self, user_id: U) -> Result<()> {
+ self.id.kick(user_id)
+ }
+
+ /// Returns a formatted URL of the guild's icon, if the guild has an icon.
+ pub fn icon_url(&self) -> Option<String> {
+ self.icon.as_ref().map(|icon|
+ format!(cdn!("/icons/{}/{}.webp"), self.id, icon))
+ }
+
+ /// Leaves the guild.
+ #[inline]
+ pub fn leave(&self) -> Result<PartialGuild> {
+ self.id.leave()
+ }
+
+ /// Moves a member to a specific voice channel.
+ ///
+ /// Requires the [Move Members] permission.
+ ///
+ /// [Move Members]: permissions/constant.MOVE_MEMBERS.html
+ #[inline]
+ pub fn move_member<C, U>(&self, user_id: U, channel_id: C)
+ -> Result<()> where C: Into<ChannelId>, U: Into<UserId> {
+ self.id.move_member(user_id, channel_id)
+ }
+
+ /// Performs a search request to the API for the guild's [`Message`]s.
+ ///
+ /// This will search all of the guild's [`Channel`]s at once, that you have
+ /// the [Read Message History] permission to. Use [`search_channels`] to
+ /// specify a list of [channel][`GuildChannel`]s to search, where all other
+ /// channels will be excluded.
+ ///
+ /// 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
+ /// [`Channel`]: enum.Channel.html
+ /// [`GuildChannel`]: struct.GuildChannel.html
+ /// [`Message`]: struct.Message.html
+ /// [`Search`]: ../utils/builder/struct.Search.html
+ /// [`search_channels`]: #method.search_channels
+ /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.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)
+ }
+
+ /// Performs a search request to the API for the guild's [`Message`]s in
+ /// given channels.
+ ///
+ /// This will search all of the messages in the guild's provided
+ /// [`Channel`]s by Id that you have the [Read Message History] permission
+ /// to. Use [`search`] to search all of a guild's [channel][`GuildChannel`]s
+ /// at once.
+ ///
+ /// 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
+ /// [`Channel`]: enum.Channel.html
+ /// [`GuildChannel`]: struct.GuildChannel.html
+ /// [`Message`]: struct.Message.html
+ /// [`Search`]: ../utils/builder/struct.Search.html
+ /// [`search`]: #method.search
+ /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
+ pub fn search_channels<F>(&self, channel_ids: &[ChannelId], 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_channels(channel_ids, f)
+ }
+
+ /// Returns the formatted URL of the guild's splash image, if one exists.
+ pub fn splash_url(&self) -> Option<String> {
+ self.icon.as_ref().map(|icon|
+ format!(cdn!("/splashes/{}/{}.webp"), self.id, icon))
+ }
+
+ /// Starts an integration sync for the given integration Id.
+ ///
+ /// Requires the [Manage Guild] permission.
+ ///
+ /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
+ #[inline]
+ pub fn start_integration_sync<I: Into<IntegrationId>>(&self, integration_id: I) -> Result<()> {
+ self.id.start_integration_sync(integration_id)
+ }
+
+ /// Unbans a [`User`] from the guild.
+ ///
+ /// Requires the [Ban Members] permission.
+ ///
+ /// [`User`]: struct.User.html
+ /// [Ban Members]: permissions/constant.BAN_MEMBERS.html
+ #[inline]
+ pub fn unban<U: Into<UserId>>(&self, user_id: U) -> Result<()> {
+ self.id.unban(user_id)
+ }
+
+ /// Retrieves the guild's webhooks.
+ ///
+ /// **Note**: Requires the [Manage Webhooks] permission.
+ ///
+ /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html
+ #[inline]
+ pub fn webhooks(&self) -> Result<Vec<Webhook>> {
+ self.id.webhooks()
+ }
+}
+
impl PossibleGuild<Guild> {
#[doc(hidden)]
pub fn decode(value: Value) -> Result<Self> {
@@ -1240,13 +2431,36 @@ impl Role {
/// **Note** Requires the [Manage Roles] permission.
///
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn delete(&self) -> Result<()> {
let guild_id = self.find_guild()?;
rest::delete_role(guild_id.0, self.id.0)
}
+ /// Edits a [`Role`], optionally setting its new fields.
+ ///
+ /// Requires the [Manage Roles] permission.
+ ///
+ /// # Examples
+ ///
+ /// Make a role hoisted:
+ ///
+ /// ```rust,ignore
+ /// context.edit_role(guild_id, role_id, |r| r
+ /// .hoist(true));
+ /// ```
+ ///
+ /// [`Role`]: struct.Role.html
+ /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
+ #[cfg(feature="cache")]
+ pub fn edit_role<F: FnOnce(EditRole) -> EditRole>(&self, f: F) -> Result<Role> {
+ match self.find_guild() {
+ Ok(guild_id) => guild_id.edit_role(self.id, f),
+ Err(why) => Err(why),
+ }
+ }
+
/// Searches the cache for the guild that owns the role.
///
/// # Errors
@@ -1255,7 +2469,7 @@ impl Role {
/// that contains the role.
///
/// [`ClientError::GuildNotFound`]: ../client/enum.ClientError.html#variant.GuildNotFound
- #[cfg(all(feature="cache", feature="methods"))]
+ #[cfg(feature="cache")]
pub fn find_guild(&self) -> Result<GuildId> {
CACHE.read()
.unwrap()
@@ -1267,6 +2481,7 @@ impl Role {
}
/// Check that the role has the given permission.
+ #[inline]
pub fn has_permission(&self, permission: Permissions) -> bool {
self.permissions.contains(permission)
}
@@ -1317,3 +2532,34 @@ impl PartialOrd for Role {
Some(self.cmp(other))
}
}
+
+impl RoleId {
+ /// Search the cache for the role.
+ #[cfg(feature="cache")]
+ pub fn find(&self) -> Option<Role> {
+ CACHE.read()
+ .unwrap()
+ .guilds
+ .values()
+ .find(|guild| guild.roles.contains_key(self))
+ .map(|guild| guild.roles.get(self))
+ .and_then(|v| match v {
+ Some(v) => Some(v),
+ None => None,
+ })
+ .cloned()
+ }
+}
+
+impl fmt::Display for RoleId {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.0, f)
+ }
+}
+
+impl From<Role> for RoleId {
+ /// Gets the Id of a role.
+ fn from(role: Role) -> RoleId {
+ role.id
+ }
+}