From ee455a035175cf6dc7d34a48482f361385c11c81 Mon Sep 17 00:00:00 2001 From: Michael Krasnitski <42564254+mkrasnitski@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:01:24 -0400 Subject: [PATCH] Add support for Application Emojis (#2920) --- src/client/context.rs | 66 ++++++++++++++++++++++++++ src/http/client.rs | 107 ++++++++++++++++++++++++++++++++++++++++-- src/http/routing.rs | 8 ++++ 3 files changed, 177 insertions(+), 4 deletions(-) diff --git a/src/client/context.rs b/src/client/context.rs index 40a84683e91..3a2de8ec3f4 100644 --- a/src/client/context.rs +++ b/src/client/context.rs @@ -308,6 +308,72 @@ impl Context { pub fn set_presence(&self, activity: Option, status: OnlineStatus) { self.shard.set_presence(activity, status); } + + /// Gets all emojis for the current application. + /// + /// # Errors + /// + /// Returns an error if the Application ID is not known. + pub async fn get_application_emojis(&self) -> Result> { + self.http.get_application_emojis().await + } + + /// Gets information about an application emoji. + /// + /// # Errors + /// + /// Returns an error if the emoji does not exist. + pub async fn get_application_emoji(&self, emoji_id: EmojiId) -> Result { + self.http.get_application_emoji(emoji_id).await + } + + /// Creates an application emoji with a name and base64-encoded image. + /// + /// # Errors + /// + /// See [`Guild::create_emoji`] for information about name and filesize requirements. This + /// method will error if said requirements are not met. + pub async fn create_application_emoji(&self, name: &str, image: &str) -> Result { + #[derive(serde::Serialize)] + struct CreateEmoji<'a> { + name: &'a str, + image: &'a str, + } + + let body = CreateEmoji { + name, + image, + }; + + self.http.create_application_emoji(&body).await + } + + /// Changes the name of an application emoji. + /// + /// # Errors + /// + /// Returns an error if the emoji does not exist. + pub async fn edit_application_emoji(&self, emoji_id: EmojiId, name: &str) -> Result { + #[derive(serde::Serialize)] + struct EditEmoji<'a> { + name: &'a str, + } + + let body = EditEmoji { + name, + }; + + self.http.edit_application_emoji(emoji_id, &body).await + } + + /// Deletes an application emoji. + /// + /// # Errors + /// + /// Returns an error if the emoji does not exist. + pub async fn delete_application_emoji(&self, emoji_id: EmojiId) -> Result<()> { + self.http.delete_application_emoji(emoji_id).await + } } impl AsRef for Context { diff --git a/src/http/client.rs b/src/http/client.rs index 4157b804fd5..b8a18cd08e3 100644 --- a/src/http/client.rs +++ b/src/http/client.rs @@ -487,7 +487,7 @@ impl Http { /// Creates an emoji in the given [`Guild`] with the given data. /// - /// View the source code for [`Guild::create_emoji`] method to see what fields this requires. + /// See [`Guild::create_emoji`] for required fields. /// /// **Note**: Requires the [Create Guild Expressions] permission. /// @@ -511,6 +511,25 @@ impl Http { .await } + /// Creates an application emoji with the given data. + /// + /// See [`Context::create_application_emoji`] for required fields. + /// + /// [`Context::create_application_emoji`]: crate::client::Context::create_application_emoji + pub async fn create_application_emoji(&self, map: &impl serde::Serialize) -> Result { + self.fire(Request { + body: Some(to_vec(map)?), + multipart: None, + headers: None, + method: LightMethod::Post, + route: Route::Emojis { + application_id: self.try_application_id()?, + }, + params: None, + }) + .await + } + /// Create a follow-up message for an Interaction. /// /// Functions the same as [`Self::execute_webhook`] @@ -1055,9 +1074,9 @@ impl Http { .await } - /// Deletes an emoji from a server. + /// Deletes an emoji from a guild. /// - /// See [`GuildId::edit_emoji`] for permissions requirements. + /// See [`GuildId::delete_emoji`] for permissions requirements. pub async fn delete_emoji( &self, guild_id: GuildId, @@ -1078,6 +1097,22 @@ impl Http { .await } + /// Deletes an application emoji. + pub async fn delete_application_emoji(&self, emoji_id: EmojiId) -> Result<()> { + self.wind(204, Request { + body: None, + multipart: None, + headers: None, + method: LightMethod::Delete, + route: Route::Emoji { + application_id: self.try_application_id()?, + emoji_id, + }, + params: None, + }) + .await + } + /// Deletes a follow-up message for an interaction. pub async fn delete_followup_message( &self, @@ -1583,7 +1618,7 @@ impl Http { .await } - /// Changes emoji information. + /// Changes guild emoji information. /// /// See [`GuildId::edit_emoji`] for permissions requirements. pub async fn edit_emoji( @@ -1609,6 +1644,30 @@ impl Http { .await } + /// Changes application emoji information. + /// + /// See [`Context::edit_application_emoji`] for required fields. + /// + /// [`Context::edit_application_emoji`]: crate::client::Context::edit_application_emoji + pub async fn edit_application_emoji( + &self, + emoji_id: EmojiId, + map: &impl serde::Serialize, + ) -> Result { + self.fire(Request { + body: Some(to_vec(map)?), + multipart: None, + headers: None, + method: LightMethod::Patch, + route: Route::Emoji { + application_id: self.try_application_id()?, + emoji_id, + }, + params: None, + }) + .await + } + /// Edits a follow-up message for an interaction. /// /// Refer to Discord's [docs] for Edit Webhook Message for field information. @@ -3263,6 +3322,46 @@ impl Http { .await } + /// Gets all emojis for the current application. + pub async fn get_application_emojis(&self) -> Result> { + // Why, discord... + #[derive(Deserialize)] + struct ApplicationEmojis { + items: Vec, + } + + let result: ApplicationEmojis = self + .fire(Request { + body: None, + multipart: None, + headers: None, + method: LightMethod::Get, + route: Route::Emojis { + application_id: self.try_application_id()?, + }, + params: None, + }) + .await?; + + Ok(result.items) + } + + /// Gets information about an application emoji. + pub async fn get_application_emoji(&self, emoji_id: EmojiId) -> Result { + self.fire(Request { + body: None, + multipart: None, + headers: None, + method: LightMethod::Get, + route: Route::Emoji { + application_id: self.try_application_id()?, + emoji_id, + }, + params: None, + }) + .await + } + #[allow(clippy::too_many_arguments)] /// Gets all entitlements for the current app, active and expired. pub async fn get_entitlements( diff --git a/src/http/routing.rs b/src/http/routing.rs index 13e047a47be..b3a04b02b44 100644 --- a/src/http/routing.rs +++ b/src/http/routing.rs @@ -470,6 +470,14 @@ routes! ('a, { api!("/applications/{}/skus", application_id), Some(RatelimitingKind::PathAndId(application_id.into())); + Emoji { application_id: ApplicationId, emoji_id: EmojiId }, + api!("/applications/{}/emojis/{}", application_id, emoji_id), + Some(RatelimitingKind::PathAndId(application_id.into())); + + Emojis { application_id: ApplicationId }, + api!("/applications/{}/emojis", application_id), + Some(RatelimitingKind::PathAndId(application_id.into())); + Entitlement { application_id: ApplicationId, entitlement_id: EntitlementId }, api!("/applications/{}/entitlements/{}", application_id, entitlement_id), Some(RatelimitingKind::PathAndId(application_id.into()));