diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs index 9487100..833ff16 100644 --- a/src/api/channels/messages.rs +++ b/src/api/channels/messages.rs @@ -1,13 +1,15 @@ use http::header::CONTENT_DISPOSITION; use http::HeaderMap; use reqwest::{multipart, Client}; -use serde_json::to_string; +use serde_json::{from_str, to_string, to_value}; use crate::api::LimitType; -use crate::errors::ChorusResult; +use crate::errors::{ChorusError, ChorusResult}; use crate::instance::UserMeta; use crate::ratelimiter::ChorusRequest; -use crate::types::{Message, MessageSendSchema, Snowflake}; +use crate::types::{ + Message, MessageSearchEndpoint, MessageSearchQuery, MessageSendSchema, Snowflake, +}; impl Message { /// Sends a message in the channel with the provided channel_id. @@ -70,6 +72,89 @@ impl Message { chorus_request.deserialize_response::(user).await } } + + /// Returns messages without the reactions key that match a search query in the guild or channel. + /// The messages that are direct results will have an extra hit key set to true. + /// If operating on a guild channel, this endpoint requires the `READ_MESSAGE_HISTORY` + /// permission to be present on the current user. + /// + /// If the guild/channel you are searching is not yet indexed, the endpoint will return a 202 accepted response. + /// In this case, the method will return a [`ChorusError::InvalidResponse`] error. + /// + /// # Reference: + /// See + pub(crate) async fn search( + endpoint: MessageSearchEndpoint, + query: MessageSearchQuery, + user: &mut UserMeta, + ) -> ChorusResult> { + let limit_type = match &endpoint { + MessageSearchEndpoint::Channel(id) => LimitType::Channel(*id), + MessageSearchEndpoint::GuildChannel(id) => LimitType::Guild(*id), + }; + let request = ChorusRequest { + limit_type, + request: Client::new() + .get(format!( + "{}/{}/messages/search", + &user.belongs_to.borrow().urls.api, + endpoint + )) + .header("Authorization", user.token()) + .body(to_string(&query).unwrap()), + }; + let result = request.send_request(user).await?; + let result_text = result.text().await.unwrap(); + if let Ok(response) = from_str::>(&result_text) { + return Ok(response); + } + if to_value(result_text.clone()).is_err() { + return Err(search_error(result_text)); + } + let result_value = to_value(result_text.clone()).unwrap(); + if !result_value.is_object() { + return Err(search_error(result_text)); + } + let value_map = result_value.as_object().unwrap(); + if !value_map.contains_key("code") || !value_map.contains_key("retry_after") { + return Err(search_error(result_text)); + } + let code = value_map.get("code").unwrap().as_u64().unwrap(); + let retry_after = value_map.get("retry_after").unwrap().as_u64().unwrap(); + Err(ChorusError::NotFound { + error: format!( + "Index not yet available. Try again later. Code: {}. Retry after {}s", + code, retry_after + ), + }) + } + + /// Returns messages without the reactions key that match a search query in the channel. + /// The messages that are direct results will have an extra hit key set to true. + /// If operating on a guild channel, this endpoint requires the `READ_MESSAGE_HISTORY` + /// permission to be present on the current user. + /// + /// If the guild/channel you are searching is not yet indexed, the endpoint will return a 202 accepted response. + /// In this case, the method will return a [`ChorusError::InvalidResponse`] error. + /// + /// # Reference: + /// See + pub async fn search_messages( + channel_id: Snowflake, + query: MessageSearchQuery, + user: &mut UserMeta, + ) -> ChorusResult> { + Message::search(MessageSearchEndpoint::Channel(channel_id), query, user).await + } +} + +fn search_error(result_text: String) -> ChorusError { + ChorusError::InvalidResponse { + error: format!( + "Got unexpected Response, or Response which is not valid JSON. Response: \n{}", + result_text + ), + } } impl UserMeta { diff --git a/src/api/guilds/messages.rs b/src/api/guilds/messages.rs new file mode 100644 index 0000000..72d886c --- /dev/null +++ b/src/api/guilds/messages.rs @@ -0,0 +1,28 @@ +use crate::errors::ChorusResult; +use crate::instance::UserMeta; +use crate::types::{Guild, Message, MessageSearchQuery, Snowflake}; + +impl Guild { + /// Returns messages without the reactions key that match a search query in the guild. + /// The messages that are direct results will have an extra hit key set to true. + /// If operating on a guild channel, this endpoint requires the `READ_MESSAGE_HISTORY` + /// permission to be present on the current user. + /// + /// If the guild/channel you are searching is not yet indexed, the endpoint will return a 202 accepted response. + /// In this case, the method will return a [`ChorusError::InvalidResponse`] error. + /// + /// # Reference: + /// See + pub async fn search_messages( + guild_id: Snowflake, + query: MessageSearchQuery, + user: &mut UserMeta, + ) -> ChorusResult> { + Message::search( + crate::types::MessageSearchEndpoint::GuildChannel(guild_id), + query, + user, + ) + .await + } +} diff --git a/src/api/guilds/mod.rs b/src/api/guilds/mod.rs index 7577479..f1fa039 100644 --- a/src/api/guilds/mod.rs +++ b/src/api/guilds/mod.rs @@ -1,7 +1,9 @@ pub use guilds::*; +pub use messages::*; pub use roles::*; pub use roles::*; pub mod guilds; pub mod member; +pub mod messages; pub mod roles;