diff --git a/CHANGELOG.md b/CHANGELOG.md index d2913c267..305b61f57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,18 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog. ## Unreleased +## [3.0.9] - 21.11.2021 + ### Added - - Patreon Access and Refresh Tokens should now be automatically updated once a month as long as the user has provided the necessary credentials in creds.yml file: - - `Patreon.ClientId` - - `Patreon.RefreshToken` (will also get updated once a month but needs an initial value) - - `Patreon.ClientSecret` - - `Patreon.CampaignId` +- Added `.emojiadd` with 3 overloads + - `.ea :customEmoji:` which copies another server's emoji + - `.ea newName :customEmoji:` which copies emoji under a different name + - `.ea emojiName ` which creates a new emoji from the specified image +- Patreon Access and Refresh Tokens should now be automatically updated once a month as long as the user has provided the necessary credentials in creds.yml file: + - `Patreon.ClientId` + - `Patreon.RefreshToken` (will also get updated once a month but needs an initial value) + - `Patreon.ClientSecret` + - `Patreon.CampaignId` ### Fixed - Fixed an error that would show up in the console when a club image couldn't be drawn in certain circumstances diff --git a/src/NadekoBot/Common/TypeReaders/EmoteTypeReader.cs b/src/NadekoBot/Common/TypeReaders/EmoteTypeReader.cs new file mode 100644 index 000000000..bb45e641a --- /dev/null +++ b/src/NadekoBot/Common/TypeReaders/EmoteTypeReader.cs @@ -0,0 +1,17 @@ +using System.Threading.Tasks; +using Discord; +using Discord.Commands; + +namespace NadekoBot.Common.TypeReaders +{ + public sealed class EmoteTypeReader : NadekoTypeReader + { + public override Task ReadAsync(ICommandContext ctx, string input) + { + if (!Emote.TryParse(input, out var emote)) + return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Input is not a valid emote")); + + return Task.FromResult(TypeReaderResult.FromSuccess(emote)); + } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Utility/Utility.cs b/src/NadekoBot/Modules/Utility/Utility.cs index 859a1cc62..62c3b785d 100644 --- a/src/NadekoBot/Modules/Utility/Utility.cs +++ b/src/NadekoBot/Modules/Utility/Utility.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -25,15 +26,18 @@ namespace NadekoBot.Modules.Utility private readonly IStatsService _stats; private readonly IBotCredentials _creds; private readonly DownloadTracker _tracker; + private readonly IHttpClientFactory _httpFactory; public Utility(DiscordSocketClient client, ICoordinator coord, - IStatsService stats, IBotCredentials creds, DownloadTracker tracker) + IStatsService stats, IBotCredentials creds, DownloadTracker tracker, + IHttpClientFactory httpFactory) { _client = client; _coord = coord; _stats = stats; _creds = creds; _tracker = tracker; + _httpFactory = httpFactory; } [NadekoCommand, Aliases] @@ -278,6 +282,52 @@ namespace NadekoBot.Modules.Utility await ctx.Channel.SendMessageAsync(result.TrimTo(2000)).ConfigureAwait(false); } + [NadekoCommand, Aliases] + [RequireContext(ContextType.Guild)] + [RequireBotPermission(GuildPermission.ManageEmojis)] + [RequireUserPermission(GuildPermission.ManageEmojis)] + [Priority(0)] + public Task EmojiAdd(string name, Emote emote) + => EmojiAdd(name, emote.Url); + + [NadekoCommand, Aliases] + [RequireContext(ContextType.Guild)] + [RequireBotPermission(GuildPermission.ManageEmojis)] + [RequireUserPermission(GuildPermission.ManageEmojis)] + public Task EmojiAdd(Emote emote) + => EmojiAdd(emote.Name, emote.Url); + + [NadekoCommand, Aliases] + [RequireContext(ContextType.Guild)] + [RequireBotPermission(GuildPermission.ManageEmojis)] + [RequireUserPermission(GuildPermission.ManageEmojis)] + public async Task EmojiAdd(string name, string url) + { + name = name.Trim(':'); + using var http = _httpFactory.CreateClient(); + var res = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); + if (!res.IsImage() || res.GetImageSize() is null or > 262_144) + { + await ReplyErrorLocalizedAsync(strs.invalid_emoji_link); + return; + } + + await using var imgStream = await res.Content.ReadAsStreamAsync(); + Emote em; + try + { + em = await ctx.Guild.CreateEmoteAsync(name, new(imgStream)); + } + catch (Exception ex) + { + Log.Warning(ex, "Error adding emoji on server {GuildId}", ctx.Guild.Id); + + await ReplyErrorLocalizedAsync(strs.emoji_add_error); + return; + } + await ConfirmLocalizedAsync(strs.emoji_added(em.ToString())); + } + [NadekoCommand, Aliases] [OwnerOnly] public async Task ListServers(int page = 1) diff --git a/src/NadekoBot/data/aliases.yml b/src/NadekoBot/data/aliases.yml index 21a24a0eb..3360bf057 100644 --- a/src/NadekoBot/data/aliases.yml +++ b/src/NadekoBot/data/aliases.yml @@ -720,6 +720,9 @@ removeperm: showemojis: - showemojis - se +emojiadd: +- emojiadd +- ea deckshuffle: - deckshuffle - dsh diff --git a/src/NadekoBot/data/strings/commands/commands.en-US.yml b/src/NadekoBot/data/strings/commands/commands.en-US.yml index cc61b6b9e..170f1d99b 100644 --- a/src/NadekoBot/data/strings/commands/commands.en-US.yml +++ b/src/NadekoBot/data/strings/commands/commands.en-US.yml @@ -1195,6 +1195,16 @@ showemojis: desc: "Shows a name and a link to every SPECIAL emoji in the message." args: - "A message full of SPECIAL emojis" +emojiadd: + desc: |- + Adds the specified emoji to this server. + You can specify a name before the emoji to add it under a different name. + You can specify a name followed by an image link to add a new emoji from an image. + Image size has to be below 256KB. + args: + - ":someonesCustomEmoji:" + - "MyEmojiName :someonesCustomEmoji:" + - "owoNice https://cdn.discordapp.com/emojis/587930873811173386.png?size=128" deckshuffle: desc: "Reshuffles all cards back into the deck." args: diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json index 9f63e1b88..142d9665d 100644 --- a/src/NadekoBot/data/strings/responses/responses.en-US.json +++ b/src/NadekoBot/data/strings/responses/responses.en-US.json @@ -9,6 +9,9 @@ "crr_reset": "Custom reaction with id {0} will no longer add reactions.", "crr_set": "Custom reaction with id {0} will add following reactions to the response message: {1}", "invalid_emojis": "All emojis you've specified are invalid.", + "invalid_emoji_link": "Specified link is either not an image or exceeds 256KB.", + "emoji_add_error": "Error adding emoji. You either ran out of emoji slots, or image size is inadequate.", + "emoji_added": "Added a new emoji: {0}", "fw_cleared": "Removed all filtered words and filtered words channel settings.", "aliases_cleared": "All {0} aliases on this server have been removed.", "no_results": "No results found.",