uh yes pls (#2963)

This commit is contained in:
Mihail Gribkov
2024-07-20 23:35:19 +03:00
committed by GitHub
parent 8b6be640c7
commit 26bb789b0a
15 changed files with 254 additions and 11 deletions

View File

@@ -0,0 +1,12 @@
namespace Discord;
/// <summary>
/// Represents the properties for an application emote.
/// </summary>
public class ApplicationEmoteProperties
{
/// <summary>
/// Gets or sets the name of the emote.
/// </summary>
public string Name { get; set; }
}

View File

@@ -12,8 +12,10 @@ namespace Discord
{
/// <inheritdoc />
public string Name { get; }
/// <inheritdoc />
public ulong Id { get; }
/// <summary>
/// Gets whether this emote is animated.
/// </summary>
@@ -21,8 +23,10 @@ namespace Discord
/// A boolean that determines whether or not this emote is an animated one.
/// </returns>
public bool Animated { get; }
/// <inheritdoc />
public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
/// <summary>
/// Gets the image URL of this emote.
/// </summary>
@@ -31,6 +35,11 @@ namespace Discord
/// </returns>
public string Url => CDN.GetEmojiUrl(Id, Animated);
/// <summary>
/// Gets the user who created this emote. <see langword="null" /> if not available.
/// </summary>
public IUser User { get; private set; }
/// <summary>
/// Creates a new instance of <see cref="Emote" />.
/// </summary>
@@ -41,6 +50,14 @@ namespace Discord
Animated = animated;
}
internal Emote(ulong id, string name, bool animated = false, IUser user = null)
{
Id = id;
Name = name;
Animated = animated;
User = user;
}
/// <summary>
/// Determines whether the specified emote is equal to the current emote.
/// </summary>

View File

@@ -356,5 +356,30 @@ namespace Discord
/// <param name="entitlementId">The id of the entitlement.</param>
/// <param name="options">The options to be used when sending the request.</param>
Task ConsumeEntitlementAsync(ulong entitlementId, RequestOptions options = null);
/// <summary>
/// Gets an emote for the current application.
/// </summary>
public Task<Emote> GetApplicationEmoteAsync(ulong emoteId, RequestOptions options = null);
/// <summary>
/// Gets all emotes for the current application.
/// </summary>
public Task<IReadOnlyCollection<Emote>> GetApplicationEmotesAsync(RequestOptions options = null);
/// <summary>
/// Modifies an emote for the current application.
/// </summary>
public Task<Emote> ModifyApplicationEmoteAsync(ulong emoteId, Action<ApplicationEmoteProperties> args, RequestOptions options = null);
/// <summary>
/// Creates an emote for the current application.
/// </summary>
public Task<Emote> CreateApplicationEmoteAsync(string name, Image image, RequestOptions options = null);
/// <summary>
/// Deletes an emote for the current application.
/// </summary>
public Task DeleteApplicationEmoteAsync(ulong emoteId, RequestOptions options = null);
}
}

View File

@@ -11,16 +11,16 @@ internal class Emoji
public string Name { get; set; }
[JsonProperty("animated")]
public bool? Animated { get; set; }
public Optional<bool> Animated { get; set; }
[JsonProperty("roles")]
public ulong[] Roles { get; set; }
public Optional<ulong[]> Roles { get; set; }
[JsonProperty("require_colons")]
public bool RequireColons { get; set; }
public Optional<bool> RequireColons { get; set; }
[JsonProperty("managed")]
public bool Managed { get; set; }
public Optional<bool> Managed { get; set; }
[JsonProperty("user")]
public Optional<User> User { get; set; }

View File

@@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace Discord.API;
internal class ListApplicationEmojisResponse
{
[JsonProperty("items")]
public Emoji[] Items { get; set; }
}

View File

@@ -0,0 +1,12 @@
using Newtonsoft.Json;
namespace Discord.API.Rest;
internal class CreateApplicationEmoteParams
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("image")]
public Image Image { get; set; }
}

View File

@@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace Discord.API.Rest;
internal class ModifyApplicationEmoteParams
{
[JsonProperty("name")]
public Optional<string> Name { get; set; }
}

View File

@@ -299,6 +299,22 @@ namespace Discord.Rest
/// </summary>
Task IDiscordClient.ConsumeEntitlementAsync(ulong entitlementId, RequestOptions options) => Task.CompletedTask;
/// <inheritdoc />
Task<Emote> IDiscordClient.GetApplicationEmoteAsync(ulong emoteId, RequestOptions options) => Task.FromResult<Emote>(null);
/// <inheritdoc />
Task<IReadOnlyCollection<Emote>> IDiscordClient.GetApplicationEmotesAsync(RequestOptions options) => Task.FromResult<IReadOnlyCollection<Emote>>(ImmutableArray.Create<Emote>());
/// <inheritdoc />
Task<Emote> IDiscordClient.ModifyApplicationEmoteAsync(ulong emoteId, Action<ApplicationEmoteProperties> args, RequestOptions options) => Task.FromResult<Emote>(null);
/// <inheritdoc />
Task<Emote> IDiscordClient.CreateApplicationEmoteAsync(string name, Image image, RequestOptions options) => Task.FromResult<Emote>(null);
/// <inheritdoc />
Task IDiscordClient.DeleteApplicationEmoteAsync(ulong emoteId, RequestOptions options) => Task.CompletedTask;
#endregion
}
}

View File

@@ -450,5 +450,48 @@ namespace Discord.Rest
=> client.ApiClient.ConsumeEntitlementAsync(entitlementId, options);
#endregion
#region Application Emojis
public static async Task<IReadOnlyCollection<Emote>> GetApplicationEmojisAsync(BaseDiscordClient client, RequestOptions options = null)
{
var model = await client.ApiClient.GetApplicationEmotesAsync(options).ConfigureAwait(false);
return model.Items.Select(x => x.ToEmote(client)).ToImmutableArray();
}
public static async Task<Emote> GetApplicationEmojiAsync(BaseDiscordClient client, ulong emojiId, RequestOptions options = null)
{
var model = await client.ApiClient.GetApplicationEmoteAsync(emojiId, options).ConfigureAwait(false);
return model.ToEmote(client);
}
public static async Task<Emote> CreateApplicationEmojiAsync(BaseDiscordClient client, string name, Image image, RequestOptions options = null)
{
var model = await client.ApiClient.CreateApplicationEmoteAsync(new CreateApplicationEmoteParams
{
Name = name,
Image = image.ToModel()
}, options).ConfigureAwait(false);
return model.ToEmote(client);
}
public static async Task<Emote> ModifyApplicationEmojiAsync(BaseDiscordClient client, ulong emojiId, Action<ApplicationEmoteProperties> func, RequestOptions options = null)
{
var args = new ApplicationEmoteProperties();
func(args);
var model = await client.ApiClient.ModifyApplicationEmoteAsync(emojiId, new ModifyApplicationEmoteParams
{
Name = args.Name,
}, options).ConfigureAwait(false);
return model.ToEmote(client);
}
public static Task DeleteApplicationEmojiAsync(BaseDiscordClient client, ulong emojiId, RequestOptions options = null)
=> client.ApiClient.DeleteApplicationEmoteAsync(emojiId, options);
#endregion
}
}

View File

@@ -2093,7 +2093,7 @@ namespace Discord.API
}
#endregion
#region Guild emoji
#region Guild Emoji
public Task<IReadOnlyCollection<Emoji>> GetGuildEmotesAsync(ulong guildId, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));
@@ -2845,5 +2845,56 @@ namespace Discord.API
=> SendAsync<Message>("POST", () => $"channels/{channelId}/polls/{messageId}/expire", new BucketIds(channelId: channelId), options: options);
#endregion
#region App Emojis
public Task<Emoji> CreateApplicationEmoteAsync(CreateApplicationEmoteParams args, RequestOptions options = null)
{
Preconditions.NotNull(args, nameof(args));
Preconditions.NotNullOrWhitespace(args.Name, nameof(args.Name));
Preconditions.NotNull(args.Image.Stream, nameof(args.Image));
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds();
return SendJsonAsync<Emoji>("POST", () => $"applications/{CurrentApplicationId}/emojis", args, ids, options: options);
}
public Task<Emoji> ModifyApplicationEmoteAsync(ulong emoteId, ModifyApplicationEmoteParams args, RequestOptions options = null)
{
Preconditions.NotEqual(emoteId, 0, nameof(emoteId));
Preconditions.NotNull(args, nameof(args));
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds();
return SendJsonAsync<Emoji>("PATCH", () => $"applications/{CurrentApplicationId}/emojis/{emoteId}", args, ids, options: options);
}
public Task DeleteApplicationEmoteAsync(ulong emoteId, RequestOptions options = null)
{
Preconditions.NotEqual(emoteId, 0, nameof(emoteId));
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds();
return SendAsync("DELETE", () => $"applications/{CurrentApplicationId}/emojis/{emoteId}", ids, options: options);
}
public Task<Emoji> GetApplicationEmoteAsync(ulong emoteId, RequestOptions options = null)
{
Preconditions.NotEqual(emoteId, 0, nameof(emoteId));
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds();
return SendAsync<Emoji>("GET", () => $"applications/{CurrentApplicationId}/emojis/{emoteId}", ids, options: options);
}
public Task<ListApplicationEmojisResponse> GetApplicationEmotesAsync(RequestOptions options = null)
{
options = RequestOptions.CreateOrClone(options);
var ids = new BucketIds();
return SendAsync<ListApplicationEmojisResponse>("GET", () => $"applications/{CurrentApplicationId}/emojis", ids, options: options);
}
#endregion
}
}

View File

@@ -300,6 +300,26 @@ namespace Discord.Rest
public Task ConsumeEntitlementAsync(ulong entitlementId, RequestOptions options = null)
=> ClientHelper.ConsumeEntitlementAsync(this, entitlementId, options);
/// <inheritdoc />
public Task<Emote> GetApplicationEmoteAsync(ulong emoteId, RequestOptions options = null)
=> ClientHelper.GetApplicationEmojiAsync(this, emoteId, options);
/// <inheritdoc />
public Task<IReadOnlyCollection<Emote>> GetApplicationEmotesAsync(RequestOptions options = null)
=> ClientHelper.GetApplicationEmojisAsync(this, options);
/// <inheritdoc />
public Task<Emote> ModifyApplicationEmoteAsync(ulong emoteId, Action<ApplicationEmoteProperties> args, RequestOptions options = null)
=> ClientHelper.ModifyApplicationEmojiAsync(this, emoteId, args, options);
/// <inheritdoc />
public Task<Emote> CreateApplicationEmoteAsync(string name, Image image, RequestOptions options = null)
=> ClientHelper.CreateApplicationEmojiAsync(this, name, image, options);
/// <inheritdoc />
public Task DeleteApplicationEmoteAsync(ulong emoteId, RequestOptions options = null)
=> ClientHelper.DeleteApplicationEmojiAsync(this, emoteId, options);
#endregion
#region IDiscordClient

View File

@@ -36,7 +36,7 @@ public class RestGuildOnboardingPromptOption : RestEntity<ulong>, IGuildOnboardi
if (model.Emoji.Id.HasValue)
{
Emoji = new Emote(model.Emoji.Id.Value, model.Emoji.Name, model.Emoji.Animated ?? false);
Emoji = new Emote(model.Emoji.Id.Value, model.Emoji.Name, model.Emoji.Animated.GetValueOrDefault(false));
}
else if (!string.IsNullOrWhiteSpace(model.Emoji.Name))
{

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
@@ -13,13 +14,21 @@ namespace Discord.Rest
return new Emoji(model.Name);
}
public static Emote ToEmote(this API.Emoji model, BaseDiscordClient discord = null)
=> new(model.Id.GetValueOrDefault(),
model.Name,
model.Animated.GetValueOrDefault(false),
model.User.IsSpecified ?
RestUser.Create(discord, model.User.Value)
: null);
public static GuildEmote ToEntity(this API.Emoji model)
=> new GuildEmote(model.Id.Value,
model.Name,
model.Animated.GetValueOrDefault(),
model.Managed,
model.RequireColons,
ImmutableArray.Create(model.Roles),
model.Animated.GetValueOrDefault(false),
model.Managed.GetValueOrDefault(false),
model.RequireColons.GetValueOrDefault(false),
model.Roles.GetValueOrDefault([]).ToImmutableArray(),
model.User.IsSpecified ? model.User.Value.Id : null,
model.IsAvailable.ToNullable());

View File

@@ -451,6 +451,26 @@ namespace Discord.WebSocket
public Task ConsumeEntitlementAsync(ulong entitlementId, RequestOptions options = null)
=> ClientHelper.ConsumeEntitlementAsync(this, entitlementId, options);
/// <inheritdoc />
public Task<Emote> GetApplicationEmoteAsync(ulong emoteId, RequestOptions options = null)
=> ClientHelper.GetApplicationEmojiAsync(this, emoteId, options);
/// <inheritdoc />
public Task<IReadOnlyCollection<Emote>> GetApplicationEmotesAsync(RequestOptions options = null)
=> ClientHelper.GetApplicationEmojisAsync(this, options);
/// <inheritdoc />
public Task<Emote> ModifyApplicationEmoteAsync(ulong emoteId, Action<ApplicationEmoteProperties> args, RequestOptions options = null)
=> ClientHelper.ModifyApplicationEmojiAsync(this, emoteId, args, options);
/// <inheritdoc />
public Task<Emote> CreateApplicationEmoteAsync(string name, Image image, RequestOptions options = null)
=> ClientHelper.CreateApplicationEmojiAsync(this, name, image, options);
/// <inheritdoc />
public Task DeleteApplicationEmoteAsync(ulong emoteId, RequestOptions options = null)
=> ClientHelper.DeleteApplicationEmojiAsync(this, emoteId, options);
/// <summary>
/// Gets entitlements from cache.
/// </summary>

View File

@@ -47,7 +47,7 @@ public class SocketGuildOnboardingPromptOption : SocketEntity<ulong>, IGuildOnbo
if (model.Emoji.Id.HasValue)
{
Emoji = new Emote(model.Emoji.Id.Value, model.Emoji.Name, model.Emoji.Animated ?? false);
Emoji = new Emote(model.Emoji.Id.Value, model.Emoji.Name, model.Emoji.Animated.GetValueOrDefault(false));
}
else if (!string.IsNullOrWhiteSpace(model.Emoji.Name))
{