* Implemented emoji endpoints. * Fixed: now using API entities for REST client. * Removed emoji listing endpoint, as per @foxbot's request.tags/2.0.0-beta
| @@ -0,0 +1,10 @@ | |||||
| using System.Collections.Generic; | |||||
| namespace Discord | |||||
| { | |||||
| public class EmoteProperties | |||||
| { | |||||
| public Optional<string> Name { get; set; } | |||||
| public Optional<IEnumerable<IRole>> Roles { get; set; } | |||||
| } | |||||
| } | |||||
| @@ -117,5 +117,14 @@ namespace Discord | |||||
| Task DownloadUsersAsync(); | Task DownloadUsersAsync(); | ||||
| /// <summary> Removes all users from this guild if they have not logged on in a provided number of days or, if simulate is true, returns the number of users that would be removed. </summary> | /// <summary> Removes all users from this guild if they have not logged on in a provided number of days or, if simulate is true, returns the number of users that would be removed. </summary> | ||||
| Task<int> PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null); | Task<int> PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null); | ||||
| /// <summary> Gets a specific emote from this guild. </summary> | |||||
| Task<GuildEmote> GetEmoteAsync(ulong id, RequestOptions options = null); | |||||
| /// <summary> Creates a new emote in this guild. </summary> | |||||
| Task<GuildEmote> CreateEmoteAsync(string name, Image image, Optional<IEnumerable<IRole>> roles = default(Optional<IEnumerable<IRole>>), RequestOptions options = null); | |||||
| /// <summary> Modifies an existing emote in this guild. </summary> | |||||
| Task<GuildEmote> ModifyEmoteAsync(GuildEmote emote, Action<EmoteProperties> func, RequestOptions options = null); | |||||
| /// <summary> Deletes an existing emote from this guild. </summary> | |||||
| Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null); | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,16 @@ | |||||
| #pragma warning disable CS1591 | |||||
| using Newtonsoft.Json; | |||||
| namespace Discord.API.Rest | |||||
| { | |||||
| [JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
| internal class CreateGuildEmoteParams | |||||
| { | |||||
| [JsonProperty("name")] | |||||
| public string Name { get; set; } | |||||
| [JsonProperty("image")] | |||||
| public Image Image { get; set; } | |||||
| [JsonProperty("roles")] | |||||
| public Optional<ulong[]> RoleIds { get; set; } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,14 @@ | |||||
| #pragma warning disable CS1591 | |||||
| using Newtonsoft.Json; | |||||
| namespace Discord.API.Rest | |||||
| { | |||||
| [JsonObject(MemberSerialization = MemberSerialization.OptIn)] | |||||
| internal class ModifyGuildEmoteParams | |||||
| { | |||||
| [JsonProperty("name")] | |||||
| public Optional<string> Name { get; set; } | |||||
| [JsonProperty("roles")] | |||||
| public Optional<ulong[]> RoleIds { get; set; } | |||||
| } | |||||
| } | |||||
| @@ -1066,6 +1066,50 @@ namespace Discord.API | |||||
| return await SendJsonAsync<IReadOnlyCollection<Role>>("PATCH", () => $"guilds/{guildId}/roles", args, ids, options: options).ConfigureAwait(false); | return await SendJsonAsync<IReadOnlyCollection<Role>>("PATCH", () => $"guilds/{guildId}/roles", args, ids, options: options).ConfigureAwait(false); | ||||
| } | } | ||||
| //Guild emoji | |||||
| public async Task<Emoji> GetGuildEmoteAsync(ulong guildId, ulong emoteId, RequestOptions options = null) | |||||
| { | |||||
| Preconditions.NotEqual(guildId, 0, nameof(guildId)); | |||||
| Preconditions.NotEqual(emoteId, 0, nameof(emoteId)); | |||||
| options = RequestOptions.CreateOrClone(options); | |||||
| var ids = new BucketIds(guildId: guildId); | |||||
| return await SendAsync<Emoji>("GET", () => $"guilds/{guildId}/emojis/{emoteId}", ids, options: options); | |||||
| } | |||||
| public async Task<Emoji> CreateGuildEmoteAsync(ulong guildId, Rest.CreateGuildEmoteParams args, RequestOptions options = null) | |||||
| { | |||||
| Preconditions.NotEqual(guildId, 0, nameof(guildId)); | |||||
| 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(guildId: guildId); | |||||
| return await SendJsonAsync<Emoji>("POST", () => $"guilds/{guildId}/emojis", args, ids, options: options); | |||||
| } | |||||
| public async Task<Emoji> ModifyGuildEmoteAsync(ulong guildId, ulong emoteId, ModifyGuildEmoteParams args, RequestOptions options = null) | |||||
| { | |||||
| Preconditions.NotEqual(guildId, 0, nameof(guildId)); | |||||
| Preconditions.NotEqual(emoteId, 0, nameof(emoteId)); | |||||
| Preconditions.NotNull(args, nameof(args)); | |||||
| options = RequestOptions.CreateOrClone(options); | |||||
| var ids = new BucketIds(guildId: guildId); | |||||
| return await SendJsonAsync<Emoji>("PATCH", () => $"guilds/{guildId}/emojis/{emoteId}", args, ids, options: options); | |||||
| } | |||||
| public async Task DeleteGuildEmoteAsync(ulong guildId, ulong emoteId, RequestOptions options = null) | |||||
| { | |||||
| Preconditions.NotEqual(guildId, 0, nameof(guildId)); | |||||
| Preconditions.NotEqual(emoteId, 0, nameof(emoteId)); | |||||
| options = RequestOptions.CreateOrClone(options); | |||||
| var ids = new BucketIds(guildId: guildId); | |||||
| await SendAsync("DELETE", () => $"guilds/{guildId}/emojis/{emoteId}", ids, options: options); | |||||
| } | |||||
| //Users | //Users | ||||
| public async Task<User> GetUserAsync(ulong userId, RequestOptions options = null) | public async Task<User> GetUserAsync(ulong userId, RequestOptions options = null) | ||||
| { | { | ||||
| @@ -253,5 +253,46 @@ namespace Discord.Rest | |||||
| model = await client.ApiClient.BeginGuildPruneAsync(guild.Id, args, options).ConfigureAwait(false); | model = await client.ApiClient.BeginGuildPruneAsync(guild.Id, args, options).ConfigureAwait(false); | ||||
| return model.Pruned; | return model.Pruned; | ||||
| } | } | ||||
| //Emotes | |||||
| public static async Task<GuildEmote> GetEmoteAsync(IGuild guild, BaseDiscordClient client, ulong id, RequestOptions options) | |||||
| { | |||||
| var emote = await client.ApiClient.GetGuildEmoteAsync(guild.Id, id, options); | |||||
| return emote.ToEntity(); | |||||
| } | |||||
| public static async Task<GuildEmote> CreateEmoteAsync(IGuild guild, BaseDiscordClient client, string name, Image image, Optional<IEnumerable<IRole>> roles, | |||||
| RequestOptions options) | |||||
| { | |||||
| var apiargs = new CreateGuildEmoteParams | |||||
| { | |||||
| Name = name, | |||||
| Image = image.ToModel() | |||||
| }; | |||||
| if (roles.IsSpecified) | |||||
| apiargs.RoleIds = roles.Value?.Select(xr => xr.Id)?.ToArray(); | |||||
| var emote = await client.ApiClient.CreateGuildEmoteAsync(guild.Id, apiargs, options); | |||||
| return emote.ToEntity(); | |||||
| } | |||||
| public static async Task<GuildEmote> ModifyEmoteAsync(IGuild guild, BaseDiscordClient client, ulong id, Action<EmoteProperties> func, | |||||
| RequestOptions options) | |||||
| { | |||||
| if (func == null) throw new ArgumentNullException(nameof(func)); | |||||
| var props = new EmoteProperties(); | |||||
| func(props); | |||||
| var apiargs = new ModifyGuildEmoteParams | |||||
| { | |||||
| Name = props.Name | |||||
| }; | |||||
| if (props.Roles.IsSpecified) | |||||
| apiargs.RoleIds = props.Roles.Value?.Select(xr => xr.Id)?.ToArray(); | |||||
| var emote = await client.ApiClient.ModifyGuildEmoteAsync(guild.Id, id, apiargs, options); | |||||
| return emote.ToEntity(); | |||||
| } | |||||
| public static Task DeleteEmoteAsync(IGuild guild, BaseDiscordClient client, ulong id, RequestOptions options) | |||||
| => client.ApiClient.DeleteGuildEmoteAsync(guild.Id, id, options); | |||||
| } | } | ||||
| } | } | ||||
| @@ -260,6 +260,16 @@ namespace Discord.Rest | |||||
| public override string ToString() => Name; | public override string ToString() => Name; | ||||
| private string DebuggerDisplay => $"{Name} ({Id})"; | private string DebuggerDisplay => $"{Name} ({Id})"; | ||||
| //Emotes | |||||
| public Task<GuildEmote> GetEmoteAsync(ulong id, RequestOptions options = null) | |||||
| => GuildHelper.GetEmoteAsync(this, Discord, id, options); | |||||
| public Task<GuildEmote> CreateEmoteAsync(string name, Image image, Optional<IEnumerable<IRole>> roles = default(Optional<IEnumerable<IRole>>), RequestOptions options = null) | |||||
| => GuildHelper.CreateEmoteAsync(this, Discord, name, image, roles, options); | |||||
| public Task<GuildEmote> ModifyEmoteAsync(GuildEmote emote, Action<EmoteProperties> func, RequestOptions options = null) | |||||
| => GuildHelper.ModifyEmoteAsync(this, Discord, emote.Id, func, options); | |||||
| public Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null) | |||||
| => GuildHelper.DeleteEmoteAsync(this, Discord, emote.Id, options); | |||||
| //IGuild | //IGuild | ||||
| bool IGuild.Available => Available; | bool IGuild.Available => Available; | ||||
| IAudioClient IGuild.AudioClient => null; | IAudioClient IGuild.AudioClient => null; | ||||
| @@ -433,6 +433,16 @@ namespace Discord.WebSocket | |||||
| _downloaderPromise.TrySetResultAsync(true); | _downloaderPromise.TrySetResultAsync(true); | ||||
| } | } | ||||
| //Emotes | |||||
| public Task<GuildEmote> GetEmoteAsync(ulong id, RequestOptions options = null) | |||||
| => GuildHelper.GetEmoteAsync(this, Discord, id, options); | |||||
| public Task<GuildEmote> CreateEmoteAsync(string name, Image image, Optional<IEnumerable<IRole>> roles = default(Optional<IEnumerable<IRole>>), RequestOptions options = null) | |||||
| => GuildHelper.CreateEmoteAsync(this, Discord, name, image, roles, options); | |||||
| public Task<GuildEmote> ModifyEmoteAsync(GuildEmote emote, Action<EmoteProperties> func, RequestOptions options = null) | |||||
| => GuildHelper.ModifyEmoteAsync(this, Discord, emote.Id, func, options); | |||||
| public Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null) | |||||
| => GuildHelper.DeleteEmoteAsync(this, Discord, emote.Id, options); | |||||
| //Voice States | //Voice States | ||||
| internal async Task<SocketVoiceState> AddOrUpdateVoiceStateAsync(ClientState state, VoiceStateModel model) | internal async Task<SocketVoiceState> AddOrUpdateVoiceStateAsync(ClientState state, VoiceStateModel model) | ||||
| { | { | ||||