aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2017-03-25 16:58:14 -0700
committerZeyla Hellyer <[email protected]>2017-03-25 16:58:14 -0700
commit3cd0e40e2b30a0452fd9ea5d22c65afbce321fc6 (patch)
tree0aa3308e604d9d6288977bd8eddeccea27a591c1 /src
parentRework the models directory (diff)
downloadserenity-3cd0e40e2b30a0452fd9ea5d22c65afbce321fc6.tar.xz
serenity-3cd0e40e2b30a0452fd9ea5d22c65afbce321fc6.zip
Update search params
Diffstat (limited to 'src')
-rw-r--r--src/client/rest/mod.rs14
-rw-r--r--src/utils/builder/mod.rs2
-rw-r--r--src/utils/builder/search.rs334
3 files changed, 139 insertions, 211 deletions
diff --git a/src/client/rest/mod.rs b/src/client/rest/mod.rs
index a9dc88c..c341bf2 100644
--- a/src/client/rest/mod.rs
+++ b/src/client/rest/mod.rs
@@ -1386,15 +1386,12 @@ pub fn remove_group_recipient(group_id: u64, user_id: u64) -> Result<()> {
///
/// [`Channel`]: ../../model/enum.Channel.html
/// [`Message`]: ../../model/struct.Message.html
-pub fn search_channel_messages(channel_id: u64, map: BTreeMap<&str, String>)
+pub fn search_channel_messages(channel_id: u64, map: BTreeMap<&str, Value>)
-> 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 _ = write!(uri, "&{}={}", k, v);
}
let response = request!(Route::ChannelsIdMessagesSearch(channel_id),
@@ -1420,15 +1417,12 @@ pub fn search_channel_messages(channel_id: u64, map: BTreeMap<&str, String>)
/// [`GuildChannel`]: ../../model/struct.GuildChannel.html
pub fn search_guild_messages(guild_id: u64,
channel_ids: &[u64],
- map: BTreeMap<&str, String>)
+ map: BTreeMap<&str, Value>)
-> 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);
+ let _ = write!(uri, "&{}={}", k, v);
}
for channel_id in channel_ids {
diff --git a/src/utils/builder/mod.rs b/src/utils/builder/mod.rs
index 9ded8b8..10a20d9 100644
--- a/src/utils/builder/mod.rs
+++ b/src/utils/builder/mod.rs
@@ -32,4 +32,4 @@ pub use self::edit_profile::EditProfile;
pub use self::edit_role::EditRole;
pub use self::execute_webhook::ExecuteWebhook;
pub use self::get_messages::GetMessages;
-pub use self::search::{Search, SortingMode, SortingOrder};
+pub use self::search::{Search, Has};
diff --git a/src/utils/builder/search.rs b/src/utils/builder/search.rs
index 904c580..5a4d4a9 100644
--- a/src/utils/builder/search.rs
+++ b/src/utils/builder/search.rs
@@ -1,71 +1,52 @@
+use serde_json::Value;
use std::collections::BTreeMap;
use ::model::{MessageId, UserId};
-/// An indicator of the type of sorting mode to use when searching for
-/// [`Message`]s via the [`Search`] builder.
+/// An indicator for filtering [`Message`]s that have a certain item or quality.
///
-/// [`Message`]: ../../model/struct.Message.html
-/// [`Search`]: struct.Search.html
-pub enum SortingMode {
- /// Search by messages' relevance to parameters.
- Relevance,
- /// Search by messages' timestamp, where results will match according to
- /// parameters. This is used in conjunction in the [`Search::sort_order`]
- /// method, and is used in conjunction with [`SortingOrder`].
- ///
- /// [`Search::sort_order`]: struct.Search.html#method.sort_order
- /// [`SortingOrder`]: enum.SortingOrder.html
- Timestamp,
-}
-
-impl SortingMode {
- /// Retrieves the name of the sorting mode. This is equivalent to a
- /// lowercase string version of each variant.
- pub fn name(&self) -> &str {
- match *self {
- SortingMode::Relevance => "relevance",
- SortingMode::Timestamp => "timestamp",
- }
- }
-}
-
-/// An indicator of how to sort results when searching for [`Message`]s via the
-/// [`Search`] builder.
+/// Used with [`Search::has`].
///
/// [`Message`]: ../../model/struct.Message.html
-/// [`Search`]: struct.Search.html
-pub enum SortingOrder {
- /// Search message results in ascending order.
- ///
- /// In the case of [`SortingMode::Relevance`], this will search from the
- /// least relevant to the most relevant.
- ///
- /// In the case of [`SortingMode::Timestamp`], this will indicate to search
- /// from the least recent to the most recent.
+/// [`Search::has`]: struct.Search.html#method.has
+pub enum Has {
+ /// Find messages that have an [`Embed`].
///
- /// [`SortingMode::Relevance`]: enum.SortingMode.html#variant.Relevance
- /// [`SortingMode::Timestamp`]: enum.SortingMode.html#variant.Timestamp
- Ascending,
- /// Search message results in descending order.
+ /// [`Embed`]: ../../model/struct.Embed.html
+ Embed,
+ /// Find messages that have an [`Attachment`].
///
- /// In the case of [`SortingMode::Relevance`], this will search from the
- /// most relevant to least relevant.
+ /// [`Attachment`]: ../../model/struct.Attachment.html
+ File,
+ /// Find messages that have an embed with an image.
+ Image,
+ /// Find messages with a link of any kind.
+ Link,
+ /// Find messages that have an [`Embed`] with a sound [`provider`].
///
- /// In the case of [`SortingMode::Timestamp`], this will search from the
- /// most recent to least recent.
+ /// [`Embed`]: ../../model/struct.Embed.html
+ /// [`provider`]: ../../model/struct.Embed.html#structfield.provider
+ Sound,
+ /// Find messages that have an [`Embed`] with a `video`
+ /// [type][`Embed::kind`].
///
- /// [`SortingMode::Relevance`]: enum.SortingMode.html#variant.Relevance
- /// [`SortingMode::Timestamp`]: enum.SortingMode.html#variant.Timestamp
- Descending,
+ /// [`Embed`]: ../../model/struct.Embed.html
+ /// [`Embed::kind`]: ../../model/struct.Embed.html#structfield.kind
+ Video,
}
-impl SortingOrder {
- /// Retrieves the name of the sorting order. This is equivalent to a
- /// lowercase string version of each variant.
+impl Has {
+ /// Returns the "name" of the variant.
+ #[doc(hidden)]
pub fn name(&self) -> &str {
+ use self::Has::*;
+
match *self {
- SortingOrder::Ascending => "asc",
- SortingOrder::Descending => "desc",
+ Embed => "embed",
+ File => "file",
+ Image => "image",
+ Link => "link",
+ Sound => "sound",
+ Video => "video",
}
}
}
@@ -73,32 +54,28 @@ impl SortingOrder {
/// A builder used to query a [`Channel`] or [`Guild`] for its [`Message`]s,
/// specifying certain parameters to narrow down the returned messages.
///
-/// Many methods are provided to narrow down the results, such as [`sort_by`] -
-/// which is used with the [`SortingMode`] enum to sort the results - or
-/// [`limit`], which can be used in conjunction with [`offset`] to paginate
-/// results.
+/// Many methods are provided to narrow down the results, such as [`limit`],
+/// which can be used in conjunction with [`offset`] to paginate results.
///
/// # Examples
///
/// Provided are multiple in-depth examples for searching through different
-/// means. Also see [example 08] for a fully runnable bot.
+/// means. Also see [example 08] for a fully runnable selfbot.
///
/// ### Searching a Channel
///
-/// Search for messages via [`Context::search_channel`] with the content
-/// `"rust"`, which have no embed, no attachment, searching by relevance in
-/// ascending order, and limiting to 5 results:
+/// Search for messages via [`Channel::search`] with the content `"rust"`, which
+/// have an embed, have a video, and limiting to 5 results:
///
/// ```rust,ignore
-/// // assuming a `channel_id` has been bound
+/// use serenity::utils::builder::Has;
+///
+/// // assuming a `channel` has been bound
///
-/// let res = channel_id.search(|s| s
+/// let search = channel.search(|s| s
/// .content("rust")
-/// .has_embed(false)
-/// .has_attachment(false)
-/// .limit(5)
-/// .sort_by(SortingMode::Relevance)
-/// .sort_order(SortingOrder::Ascending));
+/// .has(vec![Has::Embed, Has::Video])
+/// .limit(5));
/// ```
///
/// ### Searching a Guild's Channels
@@ -111,7 +88,6 @@ impl SortingOrder {
/// ```rust,ignore
/// use serenity::client::{Client, Context};
/// use serenity::model::Message;
-/// use serenity::utils::builder::{SortingMode, SortingOrder};
/// use std::env;
///
/// let mut client = Client::login_bot(&env::var("DISCORD_BOT_TOKEN").unwrap());
@@ -120,16 +96,16 @@ impl SortingOrder {
/// .configure(|c| c.prefix("~").on_mention(true))
/// .on("search", search));
///
-/// command!(search(context, message, args) {
+/// command!(search(ctx, msg, args) {
/// let query = args.join(" ");
///
/// if query.is_empty() {
-/// let _ = message.channel_id.say("You must provide a query");
+/// let _ = msg.channel_id.say("You must provide a query");
///
/// return Ok(());
/// }
///
-/// let guild = message.guild().unwrap();
+/// let guild = msg.guild().unwrap();
///
/// let channel_ids = guild
/// .channels
@@ -143,35 +119,23 @@ impl SortingOrder {
/// .context_size(0)
/// .has_attachment(true)
/// .has_embed(true)
-/// .max_id(message.id.0 - 1)
-/// .sort_by(SortingMode::Timestamp)
-/// .sort_order(SortingOrder::Descending));
+/// .max_id(msg.id.0 - 1))
+/// .unwrap();
///
-/// let mut messages = match search {
-/// Ok(messages) => messages,
-/// Err(why) => {
-/// println!("Error performing search '{}': {:?}", query, why);
-///
-/// let _ = message.channel_id.say("Error occurred while searching");
-///
-/// return Ok(());
-/// },
-/// };
-///
-/// let _ = message.channel_id.send_message(|m| m
+/// let _ = msg.channel_id.send_message(|m| m
/// .content(&format!("Found {} total results", messages.total))
/// .embed(|mut e| {
/// for (i, messages) in messages.results.iter_mut().enumerate() {
-/// let mut message = match messages.get_mut(i) {
-/// Some(message) => message,
+/// let mut found = match messages.get_mut(i) {
+/// Some(found) => found,
/// None => break,
/// };
///
-/// message.content.truncate(1000);
+/// found.content.truncate(1000);
///
/// e = e.field(|f| f
/// .name(&format!("Result {}", i))
-/// .value(&message.content));
+/// .value(&found.content));
/// }
///
/// e
@@ -183,110 +147,81 @@ impl SortingOrder {
/// [`Context::search_channel`]: ../../client/struct.Context.html#method.search_channel
/// [`Guild`]: ../../model/struct.Guild.html
/// [`Message`]: ../../model/struct.Message.html
-/// [`SortingMode`]: enum.SortingMode.html
/// [`limit`]: #method.limit
/// [`offset`]: #method.offset
-/// [`sort_by`]: #method.sort_by
/// [example 08]: https://github.com/zeyla/serenity/tree/master/examples/08_search
-pub struct Search(pub BTreeMap<&'static str, String>);
+pub struct Search(pub BTreeMap<&'static str, Value>);
impl Search {
- /// Sets the list of attachment extensions to search by.
- ///
- /// When providing a vector of extensions, do _not_ include the period (`.`)
- /// character as part of the search.
- ///
- /// This is sent to Discord as a comma-separated value list of extension
- /// names.
- pub fn attachment_extensions(mut self, attachment_extensions: &[&str]) -> Self {
- let list = attachment_extensions.join(" ");
-
- self.0.insert("attachment_extensions", list);
-
- self
- }
-
- /// Sets the filename of the attachments to search for.
- pub fn attachment_filename(mut self, attachment_filename: &str) -> Self {
- self.0.insert("attachment_filename", attachment_filename.to_owned());
-
- self
- }
-
- /// Sets the Id of the author of [`Message`]s to search for. This excludes
- /// all messages by other [`User`]s.
+ /// Filters [`Message`]s by the the Id of the author.
///
/// [`Message`]: ../../model/struct.Message.html
- /// [`User`]: ../../model/struct.User.html
pub fn author_id<U: Into<UserId>>(mut self, author_id: U) -> Self {
- self.0.insert("author_id", author_id.into().0.to_string());
+ self.0.insert("author_id", Value::U64(author_id.into().0));
self
}
- /// Sets the content of the [`Message`] to search for. This is a fuzzy
- /// search, and can partially match the given query content.
+ /// Filtes [`Message`] by content. This is a fuzzy search, and can partially
+ /// match the given query content.
///
/// [`Message`]: ../../model/struct.Message.html
- pub fn content(mut self, content: &str) -> Self {
- self.0.insert("content", content.to_owned());
+ pub fn content<S: Into<String>>(mut self, content: S) -> Self {
+ self.0.insert("content", Value::String(content.into()));
self
}
- /// Sets the amount of "context" [`Message`]s to provide, at maximum. This
- /// is the number of messages to provide around each side
+ /// Sets the amount of "contextual" [`Message`]s to provide, at maximum.
+ /// This is the number of messages to provide around each side
/// (ascending+descending) of the "hit" (aka found) message.
///
+ /// The number of returned contextual messages can be lower if there are
+ /// fewer messages in the order.
+ ///
/// The default value is `2`. The minimum value is `0`. The maximum value is
/// `2`.
///
/// [`Message`]: ../../model/struct.Message.html
- pub fn context_size(mut self, context_size: u8) -> Self {
- self.0.insert("context_size", context_size.to_string());
+ pub fn context_size(mut self, mut context_size: u8) -> Self {
+ if context_size > 2 {
+ context_size = 2;
+ }
+
+ self.0.insert("context_size", Value::U64(context_size as u64));
self
}
- /// Sets the embed providers to search by.
+ /// Filter [`Message`]s by whether they have a certain item.
///
- /// This is a list of the providers' names.
+ /// You can pass either one or more [`Has`] variants.
///
- /// This is sent to Discord as a comma-separated value list of provider
- /// names.
- pub fn embed_providers(mut self, embed_providers: &[&str]) -> Self {
- self.0.insert("embed_providers", embed_providers.join(" "));
-
- self
- }
-
- /// Sets the type of [`Embed`]s to search by.
+ /// # Examples
///
- /// An example of an [embed type][`Embed::kind`] is `"rich"`.
+ /// Passing a single variant:
///
- /// [`Embed`]: ../../model/struct.Embed.html
- /// [`Embed::kind`]: ../../model/struct.Embed.html#structfield.kind
- pub fn embed_types(mut self, embed_types: &[&str]) -> Self {
- self.0.insert("embed_types", embed_types.join(" "));
-
- self
- }
-
- /// Sets whether to search for methods that do - or do not - have an
- /// attachment.
+ /// ```rust,no_run
+ /// use serenity::model::ChannelId;
+ /// use serenity::utils::builder::Has;
///
- /// Do not specify to search for both.
- pub fn has_attachment(mut self, has_attachment: bool) -> Self {
- self.0.insert("has_attachment", has_attachment.to_string());
-
- self
- }
-
- /// Sets whether to search for methods that do - or do not - have an embed.
+ /// let _ = ChannelId(7).search(|s| s.has(vec![Has::Embed]));
+ /// ```
///
- /// Do not specify to search for both.
- pub fn has_embed(mut self, has_embed: bool) -> Self {
- self.0.insert("has_embed", has_embed.to_string());
+ /// Passing multiple:
+ ///
+ /// ```rust,no_run
+ /// use serenity::model::ChannelId;
+ /// use serenity::utils::builder::Has;
+ ///
+ /// let _ = ChannelId(7).search(|s| s.has(vec![Has::Embed, Has::Sound]));
+ /// ```
+ ///
+ /// [`Has`]: enum.Has.html
+ /// [`Message`]: ../../model/struct.Message.html
+ pub fn has(mut self, has: Vec<Has>) -> Self {
+ let names = has.into_iter().map(|h| Value::String(h.name().to_owned())).collect();
+ self.0.insert("has", Value::Array(names));
self
}
@@ -298,7 +233,7 @@ impl Search {
///
/// [`offset`]: #method.offset
pub fn limit(mut self, limit: u8) -> Self {
- self.0.insert("limit", limit.to_string());
+ self.0.insert("limit", Value::U64(limit as u64));
self
}
@@ -308,7 +243,39 @@ impl Search {
///
/// [`Message`]: ../../model/struct.Message.html
pub fn max_id<M: Into<MessageId>>(mut self, message_id: M) -> Self {
- self.0.insert("max_id", message_id.into().0.to_string());
+ self.0.insert("max_id", Value::U64(message_id.into().0));
+
+ self
+ }
+
+ /// Filter [`Message`]s by whether they mention one or more specific
+ /// [`User`]s.
+ ///
+ /// This is an OR statement.
+ ///
+ /// # Examples
+ ///
+ /// Search for only one mention:
+ ///
+ /// ```rust,no_run
+ /// use serenity::model::{ChannelId, UserId};
+ ///
+ /// let _ = ChannelId(7).search(|s| s.mentions(vec![UserId(8)]));
+ /// ```
+ ///
+ /// Search for two mentions:
+ ///
+ /// ```rust,no_run
+ /// use serenity::model::{ChannelId, UserId};
+ ///
+ /// let _ = ChannelId(7).search(|s| s.mentions(vec![UserId(8), UserId(9)]));
+ /// ```
+ ///
+ /// [`Message`]: ../../model/struct.Message.html
+ /// [`User`]: ../../model/struct.User.html
+ pub fn mentions(mut self, mentions: Vec<UserId>) -> Self {
+ let ids = mentions.into_iter().map(|m| Value::U64(m.0)).collect();
+ self.0.insert("mentions", Value::Array(ids));
self
}
@@ -318,7 +285,7 @@ impl Search {
///
/// [`Message`]: ../../model/struct.Message.html
pub fn min_id<M: Into<MessageId>>(mut self, message_id: M) -> Self {
- self.0.insert("min_id", message_id.into().0.to_string());
+ self.0.insert("min_id", Value::U64(message_id.into().0));
self
}
@@ -331,29 +298,7 @@ impl Search {
/// [`Message`]: ../../model/struct.Message.html
/// [`limit`]: #method.limit
pub fn offset(mut self, offset: u16) -> Self {
- self.0.insert("offset", offset.to_string());
-
- self
- }
-
- /// The sorting mode to use.
- ///
- /// Refer to [`SortingMode`] for more information.
- ///
- /// [`SortingMode`]: enum.SortingMode.html
- pub fn sort_by(mut self, sorting_mode: SortingMode) -> Self {
- self.0.insert("sort_by", sorting_mode.name().to_string());
-
- self
- }
-
- /// The order to sort results by.
- ///
- /// Refer to the documentation for [`SortingOrder`] for more information.
- ///
- /// [`SortingOrder`]: enum.SortingOrder.html
- pub fn sort_order(mut self, sorting_order: SortingOrder) -> Self {
- self.0.insert("sort_order", sorting_order.name().to_string());
+ self.0.insert("offset", Value::U64(offset as u64));
self
}
@@ -367,18 +312,7 @@ impl Default for Search {
/// The library does not provide defaults differently than what Discord
/// itself defaults to.
///
- /// This list of defaults is:
- ///
- /// - [`context_size`]: 2
- /// - [`limit`]: 25
- /// - [`offset`]: 0
- /// - [`sort_by`]: [`SortingMode::Timestamp`]
- ///
- /// [`SortingMode::Timestamp`]: enum.SortingMode.html#variant.Timestamp
- /// [`context_size`]: #method.context_size
- /// [`limit`]: #method.limit
- /// [`offset`]: #method.offset
- /// [`sort_by`]: #method.sort_by
+ /// [`Message`]: ../../model/struct.Message.html
fn default() -> Search {
Search(BTreeMap::default())
}