From e61546e442b81e7159dcd7ede5f6372ec1e7cf58 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Thu, 1 Jun 2023 21:14:02 +0200 Subject: [PATCH 01/11] Remove mod --- src/api/channels/messages.rs | 208 +++++++++++++++++------------------ 1 file changed, 103 insertions(+), 105 deletions(-) diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs index cd2b899..a181784 100644 --- a/src/api/channels/messages.rs +++ b/src/api/channels/messages.rs @@ -1,113 +1,111 @@ -pub mod messages { - use http::header::CONTENT_DISPOSITION; - use http::HeaderMap; - use reqwest::{multipart, Client}; - use serde_json::to_string; +use http::header::CONTENT_DISPOSITION; +use http::HeaderMap; +use reqwest::{multipart, Client}; +use serde_json::to_string; - use crate::instance::UserMeta; - use crate::limit::LimitedRequester; - use crate::types::{Message, MessageSendSchema, PartialDiscordFileAttachment}; +use crate::instance::UserMeta; +use crate::limit::LimitedRequester; +use crate::types::{Message, MessageSendSchema, PartialDiscordFileAttachment}; - impl Message { - /** - Sends a message to the Spacebar server. - # Arguments - * `url_api` - The URL of the Spacebar server's API. - * `message` - The [`Message`] that will be sent to the Spacebar server. - * `limits_user` - The [`Limits`] of the user. - * `limits_instance` - The [`Limits`] of the instance. - * `requester` - The [`LimitedRequester`] that will be used to make requests to the Spacebar server. - # Errors - * [`InstanceServerError`] - If the message cannot be sent. - */ - pub async fn send( - user: &mut UserMeta, - channel_id: String, - message: &mut MessageSendSchema, - files: Option>, - ) -> Result { - let mut belongs_to = user.belongs_to.borrow_mut(); - let url_api = belongs_to.urls.get_api(); - let mut requester = LimitedRequester::new().await; +impl Message { + /** + Sends a message to the Spacebar server. + # Arguments + * `url_api` - The URL of the Spacebar server's API. + * `message` - The [`Message`] that will be sent to the Spacebar server. + * `limits_user` - The [`Limits`] of the user. + * `limits_instance` - The [`Limits`] of the instance. + * `requester` - The [`LimitedRequester`] that will be used to make requests to the Spacebar server. + # Errors + * [`InstanceServerError`] - If the message cannot be sent. + */ + pub async fn send( + user: &mut UserMeta, + channel_id: String, + message: &mut MessageSendSchema, + files: Option>, + ) -> Result { + let mut belongs_to = user.belongs_to.borrow_mut(); + let url_api = belongs_to.urls.get_api(); + let mut requester = LimitedRequester::new().await; - if files.is_none() { - let message_request = Client::new() - .post(format!("{}/channels/{}/messages/", url_api, channel_id)) - .bearer_auth(user.token()) - .body(to_string(message).unwrap()); - requester - .send_request( - message_request, - crate::api::limits::LimitType::Channel, - &mut belongs_to.limits, - &mut user.limits, - ) - .await - } else { - for (index, attachment) in message.attachments.iter_mut().enumerate() { - attachment.get_mut(index).unwrap().set_id(index as i16); - } - let mut form = reqwest::multipart::Form::new(); - let payload_json = to_string(message).unwrap(); - let payload_field = reqwest::multipart::Part::text(payload_json); - - form = form.part("payload_json", payload_field); - - for (index, attachment) in files.unwrap().into_iter().enumerate() { - let (attachment_content, current_attachment) = attachment.move_content(); - let (attachment_filename, _) = current_attachment.move_filename(); - let part_name = format!("files[{}]", index); - let content_disposition = format!( - "form-data; name=\"{}\"'; filename=\"{}\"", - part_name, &attachment_filename - ); - let mut header_map = HeaderMap::new(); - header_map.insert(CONTENT_DISPOSITION, content_disposition.parse().unwrap()); - - let part = multipart::Part::bytes(attachment_content) - .file_name(attachment_filename) - .headers(header_map); - - form = form.part(part_name, part); - } - - let message_request = Client::new() - .post(format!("{}/channels/{}/messages/", url_api, channel_id)) - .bearer_auth(user.token()) - .multipart(form); - - requester - .send_request( - message_request, - crate::api::limits::LimitType::Channel, - &mut belongs_to.limits, - &mut user.limits, - ) - .await + if files.is_none() { + let message_request = Client::new() + .post(format!("{}/channels/{}/messages/", url_api, channel_id)) + .bearer_auth(user.token()) + .body(to_string(message).unwrap()); + requester + .send_request( + message_request, + crate::api::limits::LimitType::Channel, + &mut belongs_to.limits, + &mut user.limits, + ) + .await + } else { + for (index, attachment) in message.attachments.iter_mut().enumerate() { + attachment.get_mut(index).unwrap().set_id(index as i16); } - } - } + let mut form = reqwest::multipart::Form::new(); + let payload_json = to_string(message).unwrap(); + let payload_field = reqwest::multipart::Part::text(payload_json); - impl UserMeta { - /// Shorthand call for Message::send() - /** - Sends a message to the Spacebar server. - # Arguments - * `url_api` - The URL of the Spacebar server's API. - * `message` - The [`Message`] that will be sent to the Spacebar server. - * `limits_user` - The [`Limits`] of the user. - * `limits_instance` - The [`Limits`] of the instance. - * `requester` - The [`LimitedRequester`] that will be used to make requests to the Spacebar server. - # Errors - * [`InstanceServerError`] - If the message cannot be sent. - */ - pub async fn send_message( - &mut self, - message: &mut MessageSendSchema, - channel_id: String, - files: Option>, - ) -> Result { - Message::send(self, channel_id, message, files).await + form = form.part("payload_json", payload_field); + + for (index, attachment) in files.unwrap().into_iter().enumerate() { + let (attachment_content, current_attachment) = attachment.move_content(); + let (attachment_filename, _) = current_attachment.move_filename(); + let part_name = format!("files[{}]", index); + let content_disposition = format!( + "form-data; name=\"{}\"'; filename=\"{}\"", + part_name, &attachment_filename + ); + let mut header_map = HeaderMap::new(); + header_map.insert(CONTENT_DISPOSITION, content_disposition.parse().unwrap()); + + let part = multipart::Part::bytes(attachment_content) + .file_name(attachment_filename) + .headers(header_map); + + form = form.part(part_name, part); + } + + let message_request = Client::new() + .post(format!("{}/channels/{}/messages/", url_api, channel_id)) + .bearer_auth(user.token()) + .multipart(form); + + requester + .send_request( + message_request, + crate::api::limits::LimitType::Channel, + &mut belongs_to.limits, + &mut user.limits, + ) + .await } } } + +impl UserMeta { + /// Shorthand call for Message::send() + /** + Sends a message to the Spacebar server. + # Arguments + * `url_api` - The URL of the Spacebar server's API. + * `message` - The [`Message`] that will be sent to the Spacebar server. + * `limits_user` - The [`Limits`] of the user. + * `limits_instance` - The [`Limits`] of the instance. + * `requester` - The [`LimitedRequester`] that will be used to make requests to the Spacebar server. + # Errors + * [`InstanceServerError`] - If the message cannot be sent. + */ + pub async fn send_message( + &mut self, + message: &mut MessageSendSchema, + channel_id: String, + files: Option>, + ) -> Result { + Message::send(self, channel_id, message, files).await + } +} From e9d5384f02cba1e28b4743f22757855ea21e5dd7 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Thu, 1 Jun 2023 21:14:11 +0200 Subject: [PATCH 02/11] Create reactions.rs --- src/api/channels/mod.rs | 2 ++ src/api/channels/reactions.rs | 1 + 2 files changed, 3 insertions(+) create mode 100644 src/api/channels/reactions.rs diff --git a/src/api/channels/mod.rs b/src/api/channels/mod.rs index 72f4e3e..28a9dd3 100644 --- a/src/api/channels/mod.rs +++ b/src/api/channels/mod.rs @@ -1,5 +1,7 @@ pub mod channels; pub mod messages; +pub mod reactions; pub use channels::*; pub use messages::*; +pub use reactions::*; diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs new file mode 100644 index 0000000..cd53b7b --- /dev/null +++ b/src/api/channels/reactions.rs @@ -0,0 +1 @@ +use crate::types; From df6fcbd5ee2c46e383c3fe223120a9b092736a60 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 3 Jun 2023 15:21:49 +0200 Subject: [PATCH 03/11] Add ReactionMeta struct --- src/api/channels/reactions.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index cd53b7b..ac66337 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -1 +1,9 @@ use crate::types; + +/** +Extends the [`types::Reaction`] struct with useful metadata. + */ +pub struct ReactionMeta { + pub message_id: types::Snowflake, + pub reaction: types::Reaction, +} From da0726c538eae07246566faa3008251dbfe9f04c Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 3 Jun 2023 18:46:36 +0200 Subject: [PATCH 04/11] Implement reactions: delete all --- src/api/channels/reactions.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index ac66337..7f3f6d7 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -1,9 +1,37 @@ -use crate::types; +use reqwest::Client; + +use crate::{instance::UserMeta, limit::LimitedRequester, types}; /** Extends the [`types::Reaction`] struct with useful metadata. */ pub struct ReactionMeta { pub message_id: types::Snowflake, + pub channel_id: types::Snowflake, pub reaction: types::Reaction, } + +impl ReactionMeta { + pub async fn delete_all( + &self, + user: &mut UserMeta, + ) -> Result { + let mut belongs_to = user.belongs_to.borrow_mut(); + let url = format!( + "{}/channels/{}/messages/{}/reactions/", + belongs_to.urls.get_api(), + self.channel_id, + self.message_id + ); + let request = Client::new().delete(url).bearer_auth(user.token()); + LimitedRequester::new() + .await + .send_request( + request, + crate::api::limits::LimitType::Channel, + &mut belongs_to.limits, + &mut user.limits, + ) + .await + } +} From be512504c57789fc75d0a41c4303f3e584d1ab24 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 3 Jun 2023 18:53:53 +0200 Subject: [PATCH 05/11] Add reactions: get --- src/api/channels/reactions.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index 7f3f6d7..217912e 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -34,4 +34,29 @@ impl ReactionMeta { ) .await } + + pub async fn get( + &self, + emoji: &str, + user: &mut UserMeta, + ) -> Result { + let mut belongs_to = user.belongs_to.borrow_mut(); + let url = format!( + "{}/channels/{}/messages/{}/reactions/{}/", + belongs_to.urls.get_api(), + self.channel_id, + self.message_id, + emoji + ); + let request = Client::new().get(url).bearer_auth(user.token()); + LimitedRequester::new() + .await + .send_request( + request, + crate::api::limits::LimitType::Channel, + &mut belongs_to.limits, + &mut user.limits, + ) + .await + } } From 4d6ad1cd7bc2d53bccb21e5497ee69c806819ae1 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 3 Jun 2023 18:59:13 +0200 Subject: [PATCH 06/11] Add documentation --- src/api/channels/reactions.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index 217912e..1b4378f 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -12,6 +12,14 @@ pub struct ReactionMeta { } impl ReactionMeta { + /** + Deletes all reactions for a message. + # Arguments + * `user` - A mutable reference to a `UserMeta` instance. + + # Returns + A `Result` containing a `reqwest::Response` or a `crate::errors::InstanceServerError`. + */ pub async fn delete_all( &self, user: &mut UserMeta, @@ -35,6 +43,16 @@ impl ReactionMeta { .await } + /** + Gets a list of users that reacted with a specific emoji to a message. + + # Arguments + * `emoji` - A string slice containing the emoji to search for. + * `user` - A mutable reference to a `UserMeta` instance. + + # Returns + A `Result` containing a `reqwest::Response` or a `crate::errors::InstanceServerError`. + */ pub async fn get( &self, emoji: &str, From 33e0f75772a10c9a7ea613402aebb3e2308739dc Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 3 Jun 2023 20:17:21 +0200 Subject: [PATCH 07/11] Add delete_emoji method with documentation --- src/api/channels/reactions.rs | 51 +++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index 1b4378f..3186991 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -15,10 +15,10 @@ impl ReactionMeta { /** Deletes all reactions for a message. # Arguments - * `user` - A mutable reference to a `UserMeta` instance. + * `user` - A mutable reference to a [`UserMeta`] instance. # Returns - A `Result` containing a `reqwest::Response` or a `crate::errors::InstanceServerError`. + A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. */ pub async fn delete_all( &self, @@ -47,11 +47,13 @@ impl ReactionMeta { Gets a list of users that reacted with a specific emoji to a message. # Arguments - * `emoji` - A string slice containing the emoji to search for. - * `user` - A mutable reference to a `UserMeta` instance. + * `emoji` - A string slice containing the emoji to search for. The emoji must be URL Encoded or + the request will fail with 10014: Unknown Emoji. To use custom emoji, you must encode it in the + format name:id with the emoji name and emoji id. + * `user` - A mutable reference to a [`UserMeta`] instance. # Returns - A `Result` containing a `reqwest::Response` or a `crate::errors::InstanceServerError`. + A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. */ pub async fn get( &self, @@ -77,4 +79,43 @@ impl ReactionMeta { ) .await } + + /** + Deletes all the reactions for a given `emoji` on a message. This endpoint requires the + MANAGE_MESSAGES permission to be present on the current user. Fires a `Message Reaction + Remove Emoji` Gateway event. + + # Arguments + * `emoji` - A string slice containing the emoji to delete. The `emoji` must be URL Encoded or + the request will fail with 10014: Unknown Emoji. To use custom emoji, you must encode it in the + format name:id with the emoji name and emoji id. + * `user` - A mutable reference to a [`UserMeta`] instance. + + # Returns + A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. + */ + pub async fn delete_emoji( + &self, + emoji: &str, + user: &mut UserMeta, + ) -> Result { + let mut belongs_to = user.belongs_to.borrow_mut(); + let url = format!( + "{}/channels/{}/messages/{}/reactions/{}/", + belongs_to.urls.get_api(), + self.channel_id, + self.message_id, + emoji + ); + let request = Client::new().delete(url).bearer_auth(user.token()); + LimitedRequester::new() + .await + .send_request( + request, + crate::api::limits::LimitType::Channel, + &mut belongs_to.limits, + &mut user.limits, + ) + .await + } } From 065bb28c96c893aa21b4d81f3eb7e3eb46d5b09f Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 3 Jun 2023 22:07:37 +0200 Subject: [PATCH 08/11] Add create reaction with documentation --- src/api/channels/reactions.rs | 52 ++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index 3186991..5716697 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -1,6 +1,10 @@ use reqwest::Client; -use crate::{instance::UserMeta, limit::LimitedRequester, types}; +use crate::{ + instance::UserMeta, + limit::LimitedRequester, + types::{self, Snowflake}, +}; /** Extends the [`types::Reaction`] struct with useful metadata. @@ -118,4 +122,50 @@ impl ReactionMeta { ) .await } + + /* + Create a reaction for the message. + + This endpoint requires the READ_MESSAGE_HISTORY permission + to be present on the current user. Additionally, if nobody else has reacted to the message using + this emoji, this endpoint requires the ADD_REACTIONS permission to be present on the current + user. Returns a 204 empty response on success. Fires a Message Reaction Add Gateway event. + + # Arguments + * `emoji` - A string slice containing the emoji to delete. The `emoji` must be URL Encoded or + the request will fail with 10014: Unknown Emoji. To use custom emoji, you must encode it in the + format name:id with the emoji name and emoji id. + * `user` - A mutable reference to a [`UserMeta`] instance. + + # Returns + A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. + + # Reference + See https://discord.com/developers/docs/resources/channel#create-reaction + */ + pub async fn create( + channel_id: &Snowflake, + message_id: &Snowflake, + emoji: &str, + user: &mut UserMeta, + ) -> Result { + let mut belongs_to = user.belongs_to.borrow_mut(); + let url = format!( + "{}/channels/{}/messages/{}/reactions/{}/@me/", + belongs_to.urls.get_api(), + channel_id, + message_id, + emoji + ); + let request = Client::new().put(url).bearer_auth(user.token()); + LimitedRequester::new() + .await + .send_request( + request, + crate::api::limits::LimitType::Channel, + &mut belongs_to.limits, + &mut user.limits, + ) + .await + } } From b5de178a918cadaabeb7b43b7817049a4b5f9bdc Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 3 Jun 2023 22:08:56 +0200 Subject: [PATCH 09/11] Add references --- src/api/channels/reactions.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index 5716697..d911448 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -23,6 +23,9 @@ impl ReactionMeta { # Returns A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. + + # Reference + See https://discord.com/developers/docs/resources/channel#delete-all-reactions */ pub async fn delete_all( &self, @@ -58,6 +61,9 @@ impl ReactionMeta { # Returns A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. + + # Reference + See https://discord.com/developers/docs/resources/channel#get-reactions */ pub async fn get( &self, @@ -97,6 +103,9 @@ impl ReactionMeta { # Returns A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. + + # Reference + See https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji */ pub async fn delete_emoji( &self, From 9918b9a71ddd94854b7d30adcadc8bcc33420e53 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 3 Jun 2023 22:15:03 +0200 Subject: [PATCH 10/11] Make reference links clickable in cargo doc --- src/api/channels/reactions.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index d911448..04c80f7 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -25,7 +25,7 @@ impl ReactionMeta { A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. # Reference - See https://discord.com/developers/docs/resources/channel#delete-all-reactions + See [https://discord.com/developers/docs/resources/channel#delete-all-reactions](https://discord.com/developers/docs/resources/channel#delete-all-reactions) */ pub async fn delete_all( &self, @@ -63,7 +63,7 @@ impl ReactionMeta { A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. # Reference - See https://discord.com/developers/docs/resources/channel#get-reactions + See [https://discord.com/developers/docs/resources/channel#get-reactions](https://discord.com/developers/docs/resources/channel#get-reactions) */ pub async fn get( &self, @@ -105,7 +105,7 @@ impl ReactionMeta { A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. # Reference - See https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji + See [https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji](https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji) */ pub async fn delete_emoji( &self, @@ -131,8 +131,10 @@ impl ReactionMeta { ) .await } +} - /* +impl types::Reaction { + /** Create a reaction for the message. This endpoint requires the READ_MESSAGE_HISTORY permission @@ -150,8 +152,8 @@ impl ReactionMeta { A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. # Reference - See https://discord.com/developers/docs/resources/channel#create-reaction - */ + See [https://discord.com/developers/docs/resources/channel#create-reaction](https://discord.com/developers/docs/resources/channel#create-reaction) + */ pub async fn create( channel_id: &Snowflake, message_id: &Snowflake, From 5dd9d095cf2a9d79f6416c6892dad706b792ada6 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sat, 3 Jun 2023 22:34:03 +0200 Subject: [PATCH 11/11] Move some pieces of documentation to where they make the most sense --- src/api/channels/reactions.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs index 04c80f7..0fc265b 100644 --- a/src/api/channels/reactions.rs +++ b/src/api/channels/reactions.rs @@ -140,7 +140,7 @@ impl types::Reaction { This endpoint requires the READ_MESSAGE_HISTORY permission to be present on the current user. Additionally, if nobody else has reacted to the message using this emoji, this endpoint requires the ADD_REACTIONS permission to be present on the current - user. Returns a 204 empty response on success. Fires a Message Reaction Add Gateway event. + user. Fires a Message Reaction Add Gateway event. # Arguments * `emoji` - A string slice containing the emoji to delete. The `emoji` must be URL Encoded or @@ -150,6 +150,7 @@ impl types::Reaction { # Returns A `Result` containing a [`reqwest::Response`] or a [`crate::errors::InstanceServerError`]. + Returns a 204 empty response on success. # Reference See [https://discord.com/developers/docs/resources/channel#create-reaction](https://discord.com/developers/docs/resources/channel#create-reaction)