diff --git a/Backend/Remora.Discord.API.Abstractions/API/Rest/IDiscordRestEmojiAPI.cs b/Backend/Remora.Discord.API.Abstractions/API/Rest/IDiscordRestEmojiAPI.cs index ba2698960d..04635f5e9d 100644 --- a/Backend/Remora.Discord.API.Abstractions/API/Rest/IDiscordRestEmojiAPI.cs +++ b/Backend/Remora.Discord.API.Abstractions/API/Rest/IDiscordRestEmojiAPI.cs @@ -37,6 +37,88 @@ namespace Remora.Discord.API.Abstractions.Rest; [PublicAPI] public interface IDiscordRestEmojiAPI { + /// + /// Gets a list of emojis for the given application. + /// + /// The ID of the application. + /// The cancellation token for this operation. + /// A retrieval result which may or may not have succeeded. + Task>> ListApplicationEmojisAync + ( + Snowflake applicationID, + CancellationToken ct = default + ); + + /// + /// Gets the emoji on the given application with the given ID. + /// + /// The ID of the application. + /// The ID of the emoji. + /// The cancellation token for this operation. + /// A retrieval result which may or may not have succeeded. + Task> GetApplicationEmojiAsync + ( + Snowflake applicationID, + Snowflake emojiID, + CancellationToken ct = default + ); + + /// + /// Creates a new emoji for the given application with the given parameters. + /// + /// + /// Any streams passed to this method will be disposed of at the end of the call. If you want to reuse the streams + /// afterwards, ensure that what you pass is a copy that the method can take ownership of. + /// + /// The ID of the application. + /// The name of the new emoji. + /// The image data. + /// The reason to mark the action in the audit log with. + /// The cancellation token for this operation. + /// A creation result which may or may not have succeeded. + Task> CreateApplicationEmojiAsync + ( + Snowflake applicationID, + string name, + Stream image, + Optional reason = default, + CancellationToken ct = default + ); + + /// + /// Modifies the given emoji. + /// + /// The ID of the application. + /// The ID of the emoji. + /// The new name of the emoji. + /// The reason to mark the action in the audit log with. + /// The cancellation token for this operation. + /// A modification result which may or may not have succeeded. + Task> ModifyApplicationEmojiAsync + ( + Snowflake applicationID, + Snowflake emojiID, + Optional name = default, + Optional reason = default, + CancellationToken ct = default + ); + + /// + /// Deletes the given emoji. + /// + /// The ID of the application. + /// The ID of the emoji. + /// The reason to mark the action in the audit log with. + /// The cancellation token for this operation. + /// A deletion result which may or may not have succeeded. + Task DeleteApplicationEmojiAsync + ( + Snowflake applicationID, + Snowflake emojiID, + Optional reason = default, + CancellationToken ct = default + ); + /// /// Gets a list of emojis for the given guild. /// @@ -56,8 +138,7 @@ Task>> ListGuildEmojisAsync /// The ID of the emoji. /// The cancellation token for this operation. /// A retrieval result which may or may not have succeeded. - Task> GetGuildEmojiAsync - ( + Task> GetGuildEmojiAsync( Snowflake guildID, Snowflake emojiID, CancellationToken ct = default diff --git a/Backend/Remora.Discord.Rest/API/Emoji/DiscordRestEmojiAPI.cs b/Backend/Remora.Discord.Rest/API/Emoji/DiscordRestEmojiAPI.cs index 5afc2a4873..424b1abd46 100644 --- a/Backend/Remora.Discord.Rest/API/Emoji/DiscordRestEmojiAPI.cs +++ b/Backend/Remora.Discord.Rest/API/Emoji/DiscordRestEmojiAPI.cs @@ -58,6 +58,115 @@ ICacheProvider rateLimitCache { } + /// + public Task>> ListApplicationEmojisAync + ( + Snowflake applicationID, + CancellationToken ct = default + ) + { + return this.RestHttpClient.GetAsync> + ( + $"applications/{applicationID}/emojis", + "items", + b => b.WithRateLimitContext(this.RateLimitCache), + ct: ct + ); + } + + /// + public virtual Task> GetApplicationEmojiAsync + ( + Snowflake applicationID, + Snowflake emojiID, + CancellationToken ct = default + ) + { + return this.RestHttpClient.GetAsync + ( + $"applications/{applicationID}/emojis/{emojiID}", + b => b.WithRateLimitContext(this.RateLimitCache), + ct: ct + ); + } + + /// + public virtual async Task> CreateApplicationEmojiAsync + ( + Snowflake applicationID, + string name, + Stream image, + Optional reason = default, + CancellationToken ct = default + ) + { + if (image.Length > 256000) + { + return new NotSupportedError("Image too large (max 256k)."); + } + + var packImage = await ImagePacker.PackImageAsync(image, ct); + if (!packImage.IsSuccess) + { + return Result.FromError(packImage); + } + + var emojiData = packImage.Entity; + + return await this.RestHttpClient.PostAsync + ( + $"applications/{applicationID}/emojis", + b => b + .AddAuditLogReason(reason) + .WithJson + ( + json => + { + json.WriteString("name", name); + json.WriteString("image", emojiData); + } + ) + .WithRateLimitContext(this.RateLimitCache), + ct: ct + ); + } + + /// + public virtual Task> ModifyApplicationEmojiAsync + ( + Snowflake applicationID, + Snowflake emojiID, + Optional name = default, + Optional reason = default, + CancellationToken ct = default + ) + { + return this.RestHttpClient.PatchAsync + ( + $"applications/{applicationID}/emojis/{emojiID}", + b => b + .AddAuditLogReason(reason) + .WithJson( + json => + { + json.Write("name", name, this.JsonOptions); + } + ).WithRateLimitContext(this.RateLimitCache), + ct: ct + ); + } + + /// + public virtual Task DeleteApplicationEmojiAsync(Snowflake applicationID, Snowflake emojiID, Optional reason = default, CancellationToken ct = default) + { + return this.RestHttpClient.DeleteAsync + ( + $"applications/{applicationID}/emojis/{emojiID}", + b => b.AddAuditLogReason(reason).WithRateLimitContext(this.RateLimitCache), + ct: ct + ); + } + /// public virtual Task>> ListGuildEmojisAsync (