diff options
| author | Austin Hellyer <[email protected]> | 2016-11-10 20:25:32 -0700 |
|---|---|---|
| committer | Austin Hellyer <[email protected]> | 2016-12-29 11:55:10 -0800 |
| commit | 0359f512a8aada5ae0371049eb7c66ecd8d68d84 (patch) | |
| tree | f88dd9b362a2d349d0cdcd13b0859c4cc3329f46 /src/client | |
| parent | Rework some event handles (diff) | |
| download | serenity-0359f512a8aada5ae0371049eb7c66ecd8d68d84.tar.xz serenity-0359f512a8aada5ae0371049eb7c66ecd8d68d84.zip | |
Add guild and channel search
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/context.rs | 83 | ||||
| -rw-r--r-- | src/client/error.rs | 3 | ||||
| -rw-r--r-- | src/client/rest/mod.rs | 69 | ||||
| -rw-r--r-- | src/client/rest/ratelimiting.rs | 2 |
4 files changed, 155 insertions, 2 deletions
diff --git a/src/client/context.rs b/src/client/context.rs index 8bbdfbe..d6d9ef9 100644 --- a/src/client/context.rs +++ b/src/client/context.rs @@ -16,7 +16,8 @@ use ::utils::builder::{ EditMember, EditProfile, EditRole, - GetMessages + GetMessages, + Search, }; use ::internal::prelude::*; use ::model::*; @@ -1444,6 +1445,86 @@ impl Context { } } + /// Searches a [`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]. + /// + /// # 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`]: ../model/enum.Channel.html + /// [`Search`]: ../utils/builder/struct.Search.html + /// [search channel]: ../../utils/builder/struct.Search.html#searching-a-channel + pub fn search_channel<C, F>(&self, channel_id: C, f: F) + -> Result<SearchResult> where C: Into<ChannelId>, + F: FnOnce(Search) -> Search { + #[cfg(feature="cache")] + { + if CACHE.read().unwrap().user.bot { + return Err(Error::Client(ClientError::InvalidOperationAsBot)); + } + } + + let map = f(Search::default()).0; + + rest::search_channel_messages(channel_id.into().0, map) + } + + /// Searches a [`Guild`]'s messages by providing query parameters via the + /// search builder, with the ability to narrow down channels to search. + /// + /// Refer to the documentation for the [`Search`] builder for restrictions + /// and default parameters, as well as potentially advanced usage. + /// + /// **Note**: Bot users can not search. + /// + /// # Examples + /// + /// Refer to the [`Search`] builder's documentation for more examples, + /// specifically the section on + /// [searching a guild's channels][search guild]. + /// + /// # 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 + /// [`Guild`]: ../model/struct.Guild.html + /// [`Search`]: ../utils/builder/struct.Search.html + /// [search guild]: ../../utils/builder/struct.Search.html#searching-a-guilds-channels + pub fn search_guild<F, G>(&self, + guild_id: G, + channel_ids: Vec<ChannelId>, + f: F) + -> Result<SearchResult> + where F: FnOnce(Search) -> Search, + G: Into<GuildId> { + #[cfg(feature="cache")] + { + if CACHE.read().unwrap().user.bot { + return Err(Error::Client(ClientError::InvalidOperationAsBot)); + } + } + + let map = f(Search::default()).0; + let ids = channel_ids.iter().map(|ch| ch.0).collect::<Vec<u64>>(); + + rest::search_guild_messages(guild_id.into().0, &ids, map) + } + /// Sends a file along with optional message contents. The filename _must_ /// be specified. /// diff --git a/src/client/error.rs b/src/client/error.rs index 0ed3bd8..14818d9 100644 --- a/src/client/error.rs +++ b/src/client/error.rs @@ -1,4 +1,5 @@ use hyper::status::StatusCode; +use ::constants::ErrorCode; use ::model::{ChannelType, Permissions}; /// An error returned from the [`Client`] or the [`Context`], or model instance. @@ -46,6 +47,7 @@ use ::model::{ChannelType, Permissions}; /// [`Context`]: struct.Context.html /// [`Context::ban`]: struct.Context.html#method.ban /// [`Error::Client`]: ../enum.Error.html#variant.Client +#[allow(enum_variant_names)] #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum Error { /// When attempting to delete below or above the minimum and maximum allowed @@ -54,6 +56,7 @@ pub enum Error { /// When attempting to delete a number of days' worth of messages that is /// not allowed. DeleteMessageDaysAmount(u8), + ErrorCode(ErrorCode), /// When there was an error retrieving the gateway URI from the REST API. Gateway, /// An indication that a [guild][`Guild`] could not be found by diff --git a/src/client/rest/mod.rs b/src/client/rest/mod.rs index 5a03f37..1af067d 100644 --- a/src/client/rest/mod.rs +++ b/src/client/rest/mod.rs @@ -44,7 +44,7 @@ use std::default::Default; use std::fmt::Write as FmtWrite; use std::io::{ErrorKind as IoErrorKind, Read}; use std::sync::{Arc, Mutex}; -use ::constants; +use ::constants::{self, ErrorCode}; use ::internal::prelude::*; use ::model::*; use ::utils::decode_array; @@ -1429,6 +1429,73 @@ pub fn remove_group_recipient(group_id: u64, user_id: u64) user_id)) } +/// Searches a [`Channel`] for [`Message`]s that meet provided requirements. +/// +/// **Note**: Bot users can not search. +/// +/// [`Channel`]: ../../model/enum.Channel.html +/// [`Message`]: ../../model/struct.Message.html +pub fn search_channel_messages(channel_id: u64, map: BTreeMap<&str, String>) + -> Result<SearchResult> { + let mut uri = format!("/channels/{}/messages/search?", channel_id); + + for (k, v) in map { + uri.push('&'); + uri.push_str(k); + uri.push('='); + uri.push_str(&v); + } + + let response = request!(Route::ChannelsIdMessagesSearch(channel_id), + get, + "{}", + uri); + + if response.status == StatusCode::Accepted { + return Err(Error::Client(ClientError::ErrorCode(ErrorCode::SearchIndexUnavailable))); + } + + let content = try!(serde_json::from_reader(response)); + + SearchResult::decode(content) +} + +/// Searches a [`Guild`] - and optionally specific [channel][`GuildChannel`]s +/// within it - for messages that meet provided requirements. +/// +/// **Note**: Bot users can not search. +/// +/// [`Guild`]: ../../model/struct.Guild.html +/// [`GuildChannel`]: ../../model/struct.GuildChannel.html +pub fn search_guild_messages(guild_id: u64, + channel_ids: &[u64], + map: BTreeMap<&str, String>) + -> Result<SearchResult> { + let mut uri = format!("/guilds/{}/messages/search?", guild_id); + + for (k, v) in map { + uri.push('&'); + uri.push_str(k); + uri.push('='); + uri.push_str(&v); + } + + for channel_id in channel_ids { + write!(uri, "&channel_id={}", channel_id)?; + } + + let response = request!(Route::GuildsIdMessagesSearch(guild_id), + get, + "{}", + uri); + + if response.status == StatusCode::Accepted { + return Err(Error::Client(ClientError::ErrorCode(ErrorCode::SearchIndexUnavailable))); + } + + SearchResult::decode(try!(serde_json::from_reader(response))) +} + /// Sends a file to a channel. pub fn send_file<R: Read>(channel_id: u64, mut file: R, diff --git a/src/client/rest/ratelimiting.rs b/src/client/rest/ratelimiting.rs index ac085eb..a404310 100644 --- a/src/client/rest/ratelimiting.rs +++ b/src/client/rest/ratelimiting.rs @@ -64,6 +64,7 @@ pub enum Route { ChannelsIdMessagesIdAck(u64), ChannelsIdMessagesIdReactions(u64), ChannelsIdMessagesIdReactionsUserIdType(u64), + ChannelsIdMessagesSearch(u64), ChannelsIdPermissionsOverwriteId(u64), ChannelsIdPins(u64), ChannelsIdPinsMessageId(u64), @@ -87,6 +88,7 @@ pub enum Route { GuildsIdMembersId(u64), GuildsIdMembersIdRolesId(u64), GuildsIdMembersMeNick(u64), + GuildsIdMessagesSearch(u64), GuildsIdPrune(u64), GuildsIdRegions(u64), GuildsIdRoles(u64), |