diff --git a/docs/medusa/creating-a-medusa.md b/docs/medusa/creating-a-medusa.md
index 666e17907..fef07f02f 100644
--- a/docs/medusa/creating-a-medusa.md
+++ b/docs/medusa/creating-a-medusa.md
@@ -147,6 +147,7 @@ This section will guide you through how to create a simple custom medusa. You ca
preview
true
+ true
true
diff --git a/src/NadekoBot/Modules/Utility/Utility.cs b/src/NadekoBot/Modules/Utility/Utility.cs
index fa58edf57..0d2282c36 100644
--- a/src/NadekoBot/Modules/Utility/Utility.cs
+++ b/src/NadekoBot/Modules/Utility/Utility.cs
@@ -402,6 +402,99 @@ public partial class Utility : NadekoModule
await ctx.OkAsync();
}
+
+ [Cmd]
+ [RequireContext(ContextType.Guild)]
+ [BotPerm(GuildPerm.ManageEmojisAndStickers)]
+ [UserPerm(GuildPerm.ManageEmojisAndStickers)]
+ public async Task StickerAdd(string name = null, string description = null, params string[] tags)
+ {
+ string format;
+ Stream stream;
+
+ if (ctx.Message.Stickers.Count is 1 && ctx.Message.Stickers.First() is SocketSticker ss)
+ {
+ name ??= ss.Name;
+ description = ss.Description;
+ format = FormatToExtension(ss.Format);
+
+ using var http = _httpFactory.CreateClient();
+ stream = await http.GetStreamAsync(ss.GetStickerUrl());
+ }
+ // else if (ctx.Message.Attachments.FirstOrDefault() is { } attachment)
+ // {
+ // var url = attachment?.Url;
+ //
+ // if (url is null)
+ // return;
+ //
+ // if (name is null)
+ // {
+ // await ReplyErrorLocalizedAsync(strs.sticker_missing_name);
+ // return;
+ // }
+ //
+ // format = Path.GetExtension(attachment.Filename);
+ //
+ // if (attachment is not { Width: 300, Height: 300 })
+ // {
+ // await ReplyErrorLocalizedAsync(strs.sticker_invalid_size);
+ // return;
+ // }
+ //
+ // using var http = _httpFactory.CreateClient();
+ //
+ // using var res = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
+ // if (res.GetContentLength() > 512.Kilobytes().Bytes)
+ // {
+ // await ReplyErrorLocalizedAsync(strs.invalid_emoji_link);
+ // return;
+ // }
+ //
+ // stream = await res.Content.ReadAsStreamAsync();
+ // }
+ else
+ {
+ await ReplyErrorLocalizedAsync(strs.sticker_error);
+ return;
+ }
+
+ try
+ {
+ await ctx.Guild.CreateStickerAsync(name,
+ string.IsNullOrWhiteSpace(description) ? "Missing description" : description,
+ tags,
+ stream,
+ $"{name}.{format}");
+
+ await ctx.OkAsync();
+ }
+ catch (Exception ex)
+ {
+ Log.Warning(ex, "Error occurred while adding a sticker: {Message}", ex.Message);
+ await ReplyErrorLocalizedAsync(strs.error_occured);
+ }
+ finally
+ {
+ await stream.DisposeAsync();
+ }
+ }
+
+ private static string FormatToExtension(StickerFormatType format)
+ {
+ switch (format)
+ {
+ case StickerFormatType.None:
+ case StickerFormatType.Png:
+ case StickerFormatType.Apng:
+ return "png";
+ case StickerFormatType.Lottie:
+ return "lottie";
+ default:
+ throw new ArgumentException(nameof (format));
+ }
+ }
+
[Cmd]
[OwnerOnly]
public async Task ListServers(int page = 1)
diff --git a/src/NadekoBot/data/aliases.yml b/src/NadekoBot/data/aliases.yml
index 1333478bc..3be9458ef 100644
--- a/src/NadekoBot/data/aliases.yml
+++ b/src/NadekoBot/data/aliases.yml
@@ -728,6 +728,9 @@ showemojis:
emojiadd:
- emojiadd
- ea
+stickeradd:
+ - stickeradd
+ - sa
emojiremove:
- emojiremove
- emojirm
diff --git a/src/NadekoBot/data/strings/commands/commands.en-US.yml b/src/NadekoBot/data/strings/commands/commands.en-US.yml
index 3aa57cbf4..f6e0602dd 100644
--- a/src/NadekoBot/data/strings/commands/commands.en-US.yml
+++ b/src/NadekoBot/data/strings/commands/commands.en-US.yml
@@ -1245,6 +1245,10 @@ emojiremove:
desc: "Removes the specified emoji or emojis from this server."
args:
- ":eagleWarrior: :plumedArcher:"
+stickeradd:
+ desc: "Adds the sticker from your message to this server. Send the sticker along with this command (in the same message)."
+ args:
+ - "optionalname \"optional description\" tag1 tag2 tagN"
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 80866ef37..97ed53614 100644
--- a/src/NadekoBot/data/strings/responses/responses.en-US.json
+++ b/src/NadekoBot/data/strings/responses/responses.en-US.json
@@ -977,14 +977,14 @@
"created_by": "Created by {0}",
"module_footer": "{0}cmds {1}",
"module_page_empty": "No module on this page.",
- "module_description_help": "Get command help, descriptions and usage examples",
- "module_description_gambling": "Bet on dice rolls, blackjack, slots, coinflips and others",
- "module_description_games": "Play trivia, nunchi, hangman, connect4 and other games",
- "module_description_nsfw": "NSFW commands.",
- "module_description_music": "Play music from youtube, local files soundcloud and radio streams",
- "module_description_utility": "Manage custom quotes, repeating messages and check facts about the server",
+ "module_description_help": "Get command help, descriptions and usage examples",
+ "module_description_gambling": "Bet on dice rolls, blackjack, slots, coinflips and others",
+ "module_description_games": "Play trivia, nunchi, hangman, connect4 and other games",
+ "module_description_nsfw": "NSFW commands.",
+ "module_description_music": "Play music from youtube, local files soundcloud and radio streams",
+ "module_description_utility": "Manage custom quotes, repeating messages and check facts about the server",
"module_description_administration": "Moderation, punish users, setup self assignable roles and greet messages",
- "module_description_expressions": "Setup custom bot responses to certain words or phrases",
+ "module_description_expressions": "Setup custom bot responses to certain words or phrases",
"module_description_permissions": "Setup perms for commands, filter words and set up command cooldowns",
"module_description_searches": "Search for jokes, images of animals, anime and manga",
"module_description_xp": "Gain xp based on chat activity, check users' xp cards",
@@ -1005,7 +1005,7 @@
"linkonly_disable": "This channel is no longer link-only.",
"deleted_x_servers": "Deleted {0} servers.",
"curtr_gift": "Gift from {0} [{1}]",
- "curtr_award": "Awarded by bot owner {0} [{1}]",
+ "curtr_award": "Awarded by bot owner {0} [{1}]",
"curtr_take": "Taken by bot owner {0} [{1}]",
"list_of_medusae": "List of Medusae",
"list_of_unloaded": "List of Available Medusae",
@@ -1052,6 +1052,9 @@
"xpshop_already_owned": "You already own this item.",
"xpshop_item_not_found": "An item with that key doesn't exist.",
"xpshop_website": "You can see the list of all Xp Shop items here: ",
+ "sticker_invalid_size": "Stickers must be exactly 300x300 pixels.",
+ "sticker_error": "You must either send a sticker along with this command, or upload a 300x300 .png or .apng image.",
+ "sticker_missing_name": "Please specify a name for the sticker.",
"thread_deleted": "Thread Deleted",
"thread_created": "Thread Created"
}