Added Resizing back to the Map Chat bot and added an option to send rendered images to Discord via Discord Bridge chat bot.

This commit is contained in:
Milutinke 2022-10-21 20:25:48 +02:00
parent 3945d5631f
commit d8c9e1587b
4 changed files with 138 additions and 16 deletions

View file

@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using DSharpPlus; using DSharpPlus;
@ -11,6 +13,8 @@ namespace MinecraftClient.ChatBots
{ {
public class DiscordBridge : ChatBot public class DiscordBridge : ChatBot
{ {
private static DiscordBridge? instance = null;
private DiscordClient? _client; private DiscordClient? _client;
private DiscordChannel? _channel; private DiscordChannel? _channel;
@ -44,6 +48,11 @@ namespace MinecraftClient.ChatBots
public void OnSettingUpdate() { } public void OnSettingUpdate() { }
} }
public DiscordBridge()
{
instance = this;
}
public override void Initialize() public override void Initialize()
{ {
Task.Run(async () => await MainAsync()); Task.Run(async () => await MainAsync());
@ -74,6 +83,11 @@ namespace MinecraftClient.ChatBots
} }
} }
public static DiscordBridge? GetInstance()
{
return instance;
}
public override void GetText(string text) public override void GetText(string text)
{ {
if (_client == null || _channel == null) if (_client == null || _channel == null)
@ -96,14 +110,6 @@ namespace MinecraftClient.ChatBots
} }
else message = text; else message = text;
SendMessageToDiscord(message, teleportRequest);
}
private void SendMessageToDiscord(string message, bool teleportRequest = false)
{
if (_client == null || _channel == null)
return;
if (teleportRequest) if (teleportRequest)
{ {
var messageBuilder = new DiscordMessageBuilder() var messageBuilder = new DiscordMessageBuilder()
@ -117,13 +123,61 @@ namespace MinecraftClient.ChatBots
new DiscordButtonComponent(ButtonStyle.Danger, "deny_teleport", "Deny") new DiscordButtonComponent(ButtonStyle.Danger, "deny_teleport", "Deny")
}); });
_client.SendMessageAsync(_channel, messageBuilder).Wait(); SendMessage(messageBuilder);
return; return;
} }
else SendMessage(message);
}
public void SendMessage(string message)
{
if (_client == null || _channel == null)
return;
_client.SendMessageAsync(_channel, message).Wait(); _client.SendMessageAsync(_channel, message).Wait();
} }
public void SendMessage(DiscordMessageBuilder builder)
{
if (_client == null || _channel == null)
return;
_client.SendMessageAsync(_channel, builder).Wait();
}
public void SendMessage(DiscordEmbedBuilder embedBuilder)
{
if (_client == null || _channel == null)
return;
_client.SendMessageAsync(_channel, embedBuilder).Wait();
}
public void SendImage(string filePath, string? text = null)
{
if (_client == null || _channel == null)
return;
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
filePath = filePath[(filePath.IndexOf(Path.DirectorySeparatorChar) + 1)..];
var messageBuilder = new DiscordMessageBuilder().WithContent(text);
messageBuilder.WithFiles(new Dictionary<string, Stream>() { { $"attachment://{filePath}", fs } });
_client.SendMessageAsync(_channel, messageBuilder).Wait();
}
}
public void SendFile(FileStream fileStream)
{
if (_client == null || _channel == null)
return;
var messageBuilder = new DiscordMessageBuilder().WithFile(fileStream);
SendMessage(messageBuilder);
}
async Task MainAsync() async Task MainAsync()
{ {
try try

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Text; using System.Text;
using ImageMagick;
using MinecraftClient.Mapping; using MinecraftClient.Mapping;
using Tomlet.Attributes; using Tomlet.Attributes;
@ -35,7 +36,20 @@ namespace MinecraftClient.ChatBots
[TomlInlineComment("$config.ChatBot.Map.Notify_On_First_Update$")] [TomlInlineComment("$config.ChatBot.Map.Notify_On_First_Update$")]
public bool Notify_On_First_Update = true; public bool Notify_On_First_Update = true;
public void OnSettingUpdate() { } [TomlInlineComment("$config.ChatBot.Map.Rasize_Rendered_Image$")]
public bool Rasize_Rendered_Image = false;
[TomlInlineComment("$config.ChatBot.Map.Resize_To$")]
public int Resize_To = 512;
[TomlPrecedingComment("$config.ChatBot.Map.Send_Rendered_To_Discord$")]
public bool Send_Rendered_To_Discord = false;
public void OnSettingUpdate()
{
if (Resize_To <= 0)
Resize_To = 128;
}
} }
private readonly string baseDirectory = @"Rendered_Maps"; private readonly string baseDirectory = @"Rendered_Maps";
@ -47,10 +61,17 @@ namespace MinecraftClient.ChatBots
if (!Directory.Exists(baseDirectory)) if (!Directory.Exists(baseDirectory))
Directory.CreateDirectory(baseDirectory); Directory.CreateDirectory(baseDirectory);
DeleteRenderedMaps();
RegisterChatBotCommand("maps", "bot.map.cmd.desc", "maps list|render <id> or maps l|r <id>", OnMapCommand); RegisterChatBotCommand("maps", "bot.map.cmd.desc", "maps list|render <id> or maps l|r <id>", OnMapCommand);
} }
public override void OnUnload() public override void OnUnload()
{
DeleteRenderedMaps();
}
private void DeleteRenderedMaps()
{ {
if (Config.Delete_All_On_Unload) if (Config.Delete_All_On_Unload)
{ {
@ -199,7 +220,48 @@ namespace MinecraftClient.ChatBots
} }
} }
file.Close(); file.Close();
LogToConsole(Translations.TryGet("bot.map.rendered", map.MapId, fileName)); LogToConsole(Translations.TryGet("bot.map.rendered", map.MapId, fileName));
if (Config.Rasize_Rendered_Image)
{
using (var image = new MagickImage(fileName))
{
var size = new MagickGeometry(Config.Resize_To, Config.Resize_To);
size.IgnoreAspectRatio = true;
image.Resize(size);
image.Write(fileName);
LogToConsole(Translations.TryGet("bot.map.resized_rendered_image", map.MapId, Config.Resize_To));
}
}
if (Config.Send_Rendered_To_Discord)
{
if (DiscordBridge.Config.Enabled)
{
DiscordBridge? discordBridge = DiscordBridge.GetInstance();
if (discordBridge == null)
return;
// We must convert to a PNG in order to send to Discord, BMP does not work
string newFileName = fileName.Replace(".bmp", ".png");
using (var image = new MagickImage(fileName))
{
image.Write(newFileName);
discordBridge.SendImage(newFileName, $"> A render of the map with an id: **{map.MapId}**");
newFileName = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + newFileName;
// Delete the temporary file
if (File.Exists(newFileName))
File.Delete(newFileName);
LogToConsole(Translations.TryGet("bot.map.sent_to_discord", map.MapId));
}
}
}
} }
private void RenderInConsole(McMap map) private void RenderInConsole(McMap map)
@ -389,8 +451,8 @@ namespace MinecraftClient.ChatBots
return new( return new(
r: (byte)((Colors[baseColorId][0] * shadeMultiplier) / 255), r: (byte)((Colors[baseColorId][0] * shadeMultiplier) / 255),
g: (byte)((Colors[baseColorId][1] * shadeMultiplier) / 255), g: (byte)((Colors[baseColorId][1] * shadeMultiplier) / 255),
b: (byte)((Colors[baseColorId][2] * shadeMultiplier) / 255), b: (byte)((Colors[baseColorId][2] * shadeMultiplier) / 255),
a: 255 a: 255
); );
} }

View file

@ -37,6 +37,7 @@
<PackageReference Include="DotNetZip" Version="1.16.0" /> <PackageReference Include="DotNetZip" Version="1.16.0" />
<PackageReference Include="DSharpPlus" Version="4.2.0" /> <PackageReference Include="DSharpPlus" Version="4.2.0" />
<PackageReference Include="DynamicExpresso.Core" Version="2.13.0" /> <PackageReference Include="DynamicExpresso.Core" Version="2.13.0" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="12.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="6.0.0" /> <PackageReference Include="Microsoft.Windows.Compatibility" Version="6.0.0" />

View file

@ -711,6 +711,8 @@ bot.map.rendered=Succesfully rendered a map with id '{0}' to: '{1}'
bot.map.failed_to_render=Failed to render the map with id: '{0}' bot.map.failed_to_render=Failed to render the map with id: '{0}'
bot.map.list_item=- Map id: {0} (Last Updated: {1}) bot.map.list_item=- Map id: {0} (Last Updated: {1})
bot.map.scale=The size of the map is reduced from ({0}x{1}) to ({2}x{3}) due to the size limitation of the current terminal. bot.map.scale=The size of the map is reduced from ({0}x{1}) to ({2}x{3}) due to the size limitation of the current terminal.
bot.map.resized_rendered_image=Resized the rendered image of the map with id: '{0}' to {1}x{1}.
bot.map.sent_to_discord=Sent a rendered image of a map with an id '{0}' to the discord!
# PlayerListLogger # PlayerListLogger
botname.PlayerListLogger=PlayerListLogger botname.PlayerListLogger=PlayerListLogger
@ -947,7 +949,7 @@ config.ChatBot.AutoRespond.Match_Colors=Do not remove colors from text (Note: Yo
config.ChatBot.ChatLog=Logs chat messages in a file on disk. config.ChatBot.ChatLog=Logs chat messages in a file on disk.
# ChatBot.DiscordBridge # ChatBot.DiscordBridge
config.ChatBot.DiscordBridge=This bot allows you to send and recieve messages and commands via a Discord channel.\n# For Setup you can either use the documentation or read here (Documentation has images).\n# Documentation: https://mccteam.github.io/guide/chat-bots.html#discord-bridge\n# Setup:\n# First you need to create a Bot on the Discord Developers Portal, here is a video tutorial: https://www.youtube.com/watch?v=2FgMnZViNPA .\n# IMPORTANT: When creating a bot, you MUST ENABLE "Message Content Intent", "Server Members Intent" and "Presence Intent" in order for bot to work! Also follow along carefully do not miss any steps!\n# When making a bot, copy the generated token and paste it here in "Token" field (tokens are important, keep them safe).\n# Copy the "Application ID" and go to: https://bit.ly/2Spn2Q3 .\n# Paste the id you have copied and check the "Administrator" field in permissions, then click on the link at the bottom.\n# This will open an invitation menu with your servers, choose the server you want to invite the bot on and invite him.\n# Once you've invited the bot, go to your Discord client and go to Settings -> Advanced and Enable "Developer Mode".\n# Exit the settings and right click on a server you have invited the bot to in the server list, then click "Copy ID", and paste the id here in "GuildId".\n# Then right click on a channel where you want to interact with the bot and again right click -> "Copy ID", pase the copied id here in "ChannelId".\n# And for the end, send a message in the channel, right click on your nick and again right click -> "Copy ID", then paste the id here in "OwnersIds".\n# How to use:\n# To execute an MCC command, prefix it with a dot ".", example: ".move 143 64 735" .\n# To send a message, simply type it out and hit enter. config.ChatBot.DiscordBridge=This bot allows you to send and recieve messages and commands via a Discord channel.\n# For Setup you can either use the documentation or read here (Documentation has images).\n# Documentation: https://mccteam.github.io/guide/chat-bots.html#discord-bridge\n# Setup:\n# First you need to create a Bot on the Discord Developers Portal, here is a video tutorial: https://www.youtube.com/watch?v=2FgMnZViNPA .\n# /!\ IMPORTANT /!\: When creating a bot, you MUST ENABLE "Message Content Intent", "Server Members Intent" and "Presence Intent" in order for bot to work! Also follow along carefully do not miss any steps!\n# When making a bot, copy the generated token and paste it here in "Token" field (tokens are important, keep them safe).\n# Copy the "Application ID" and go to: https://bit.ly/2Spn2Q3 .\n# Paste the id you have copied and check the "Administrator" field in permissions, then click on the link at the bottom.\n# This will open an invitation menu with your servers, choose the server you want to invite the bot on and invite him.\n# Once you've invited the bot, go to your Discord client and go to Settings -> Advanced and Enable "Developer Mode".\n# Exit the settings and right click on a server you have invited the bot to in the server list, then click "Copy ID", and paste the id here in "GuildId".\n# Then right click on a channel where you want to interact with the bot and again right click -> "Copy ID", pase the copied id here in "ChannelId".\n# And for the end, send a message in the channel, right click on your nick and again right click -> "Copy ID", then paste the id here in "OwnersIds".\n# How to use:\n# To execute an MCC command, prefix it with a dot ".", example: ".move 143 64 735" .\n# To send a message, simply type it out and hit enter.
config.ChatBot.DiscordBridge.Token=Your Discord Bot token. config.ChatBot.DiscordBridge.Token=Your Discord Bot token.
config.ChatBot.DiscordBridge.GuildId=The ID of a server/guild where you have invited the bot to. config.ChatBot.DiscordBridge.GuildId=The ID of a server/guild where you have invited the bot to.
config.ChatBot.DiscordBridge.ChannelId=The ID of a channel where you want to interact with the MCC using the bot. config.ChatBot.DiscordBridge.ChannelId=The ID of a channel where you want to interact with the MCC using the bot.
@ -970,12 +972,15 @@ config.ChatBot.HangmanGame=A small game to demonstrate chat interactions. Player
config.ChatBot.Mailer=Relay messages between players and servers, like a mail plugin\n# This bot can store messages when the recipients are offline, and send them when they join the server\n# /!\ Server admins can spoof PMs (/tellraw, /nick) so enable this bot only if you trust server admins config.ChatBot.Mailer=Relay messages between players and servers, like a mail plugin\n# This bot can store messages when the recipients are offline, and send them when they join the server\n# /!\ Server admins can spoof PMs (/tellraw, /nick) so enable this bot only if you trust server admins
# ChatBot.Map # ChatBot.Map
config.ChatBot.Map=Allows you to render maps into .jpg images\n# This is useful for solving captchas which use maps\n# The maps are rendered into Rendered_Maps folder.\n# NOTE:\n# This feature is currently only useful for solving captchas which use maps.\n# If some servers have a very short time for solving captchas, enabe Auto_Render_On_Update and prepare to open the file quickly.\n# On linux you can use FTP to access generated files.\n# In the future it might will be possible to display maps directly in the console with a separate command.\n# /!\ Make sure server rules allow bots to be used on the server, or you risk being punished. config.ChatBot.Map=Allows you to render maps in the console and into images (which can be then sent to Discord using Discord Bridge Chat Bot)\n# This is useful for solving captchas which use maps\n# The maps are rendered into Rendered_Maps folder if the Save_To_File is enabled.\n# NOTE:\n# If some servers have a very short time for solving captchas, enabe Auto_Render_On_Update to see them immediatelly in the console.\n# /!\ Make sure server rules allow bots to be used on the server, or you risk being punished.
config.ChatBot.Map.Render_In_Console=Whether to render the map in the console. config.ChatBot.Map.Render_In_Console=Whether to render the map in the console.
config.ChatBot.Map.Save_To_File=Whether to store the rendered map as a file. config.ChatBot.Map.Save_To_File=Whether to store the rendered map as a file (You need this setting if you want to get a map on Discord using Discord Bridge).
config.ChatBot.Map.Auto_Render_On_Update=Automatically render the map once it is received or updated from/by the server config.ChatBot.Map.Auto_Render_On_Update=Automatically render the map once it is received or updated from/by the server
config.ChatBot.Map.Delete_All_On_Unload=Delete all rendered maps on unload/reload (Does not delete the images if you exit the client) config.ChatBot.Map.Delete_All_On_Unload=Delete all rendered maps on unload/reload or when you launch the MCC again.
config.ChatBot.Map.Notify_On_First_Update=Get a notification when you have gotten a map from the server for the first time config.ChatBot.Map.Notify_On_First_Update=Get a notification when you have gotten a map from the server for the first time
config.ChatBot.Map.Resize_To=The size that a rendered image should be resized to, in pixels (eg. 512).
config.ChatBot.Map.Rasize_Rendered_Image=Resize an rendered image, this is useful when images that are rendered are small and when are being sent to Discord.
config.ChatBot.Map.Send_Rendered_To_Discord=Send a rendered map (saved to a file) to a Discord channel via the Discord Bride chat bot (The Discord Bridge chat bot must be enabled and configured!)\n# You need to enable Save_To_File in order for this to work.\n# We also recommend turning on resizing.
# ChatBot.PlayerListLogger # ChatBot.PlayerListLogger
config.ChatBot.PlayerListLogger=Log the list of players periodically into a textual file. config.ChatBot.PlayerListLogger=Log the list of players periodically into a textual file.