diff --git a/services/grid-bot/lib/commands/Modules/ExecuteScript.cs b/services/grid-bot/lib/commands/Modules/ExecuteScript.cs index 3c80457b..0587d4cf 100644 --- a/services/grid-bot/lib/commands/Modules/ExecuteScript.cs +++ b/services/grid-bot/lib/commands/Modules/ExecuteScript.cs @@ -13,6 +13,7 @@ namespace Grid.Bot.Interactions.Public; using System.Text.RegularExpressions; using Discord; +using Discord.WebSocket; using Discord.Interactions; using Loretta.CodeAnalysis; @@ -25,7 +26,7 @@ namespace Grid.Bot.Interactions.Public; using Commands; using Extensions; -using GridJob = Client.Job; +using ClientJob = Client.Job; /// /// Interaction handler for executing Luau code. @@ -36,6 +37,7 @@ namespace Grid.Bot.Interactions.Public; /// The . /// The . /// The . +/// The . /// The . /// The . /// The . @@ -48,6 +50,7 @@ namespace Grid.Bot.Interactions.Public; /// - cannot be null. /// - cannot be null. /// - cannot be null. +/// - cannot be null. /// - cannot be null. /// - cannot be null. /// - cannot be null. @@ -64,6 +67,7 @@ public partial class ExecuteScript( ILogger logger, GridSettings gridSettings, ScriptsSettings scriptsSettings, + DiscordShardedClient discordClient, ILuaUtility luaUtility, IFloodCheckerRegistry floodCheckerRegistry, IBacktraceUtility backtraceUtility, @@ -83,6 +87,7 @@ IGridServerFileHelper gridServerFileHelper private readonly GridSettings _gridSettings = gridSettings ?? throw new ArgumentNullException(nameof(gridSettings)); private readonly ScriptsSettings _scriptsSettings = scriptsSettings ?? throw new ArgumentNullException(nameof(scriptsSettings)); + private readonly DiscordShardedClient _discordClient = discordClient ?? throw new ArgumentNullException(nameof(discordClient)); private readonly ILuaUtility _luaUtility = luaUtility ?? throw new ArgumentNullException(nameof(luaUtility)); private readonly IFloodCheckerRegistry _floodCheckerRegistry = floodCheckerRegistry ?? throw new ArgumentNullException(nameof(floodCheckerRegistry)); private readonly IBacktraceUtility _backtraceUtility = backtraceUtility ?? throw new ArgumentNullException(nameof(backtraceUtility)); @@ -304,12 +309,20 @@ string script { if (string.IsNullOrWhiteSpace(script)) { - await FollowupAsync("The script cannot be empty."); + await LuaErrorAsync("The script cannot be empty!"); return; } script = GetCodeBlockContents(script); + + if (string.IsNullOrEmpty(script)) + { + await LuaErrorAsync("There must be content within a code block!"); + + return; + } + script = EscapeQuotes(script); var originalScript = script; @@ -318,7 +331,7 @@ string script if (ContainsUnicode(script)) { - await FollowupAsync("The script cannot contain unicode characters as grid-servers cannot support unicode in transit."); + await LuaErrorAsync("Scripts can only contain ASCII characters!"); return; } @@ -352,7 +365,7 @@ string script #endif - var gridJob = new GridJob() { id = scriptId, expirationInSeconds = _gridSettings.ScriptExecutionJobMaxTimeout.TotalSeconds }; + var gridJob = new ClientJob() { id = scriptId, expirationInSeconds = _gridSettings.ScriptExecutionJobMaxTimeout.TotalSeconds }; var job = new Job(Guid.NewGuid().ToString()); var sw = Stopwatch.StartNew(); @@ -461,9 +474,8 @@ string script scriptName ); scriptName.PollDeletion( - 10, - ex => _logger.Warning("Failed to delete '{0}' because: {1}", scriptName, ex.Message), - () => _logger.Debug( + onFailure: ex => _logger.Warning("Failed to delete '{0}' because: {1}", scriptName, ex.Message), + onSuccess: () => _logger.Debug( "Successfully deleted the script '{0}' at path '{1}'!", scriptId, scriptName @@ -493,10 +505,8 @@ private async Task AlertForSystem(string script, string originalScript, string s _backtraceUtility.UploadException(ex); var userInfo = Context.User.ToString(); - var guildInfo = Context.Guild?.ToString() ?? "DMs"; - - /* Temporary until mfdlabs/grid-bot#335 is resolved */ - var channelInfo = Context.Channel?.ToString() ?? Context.Interaction.ChannelId?.ToString() ?? "Thread"; + var guildInfo = Context.Interaction.GetGuild(_discordClient)?.ToString() ?? "DMs"; + var channelInfo = Context.Interaction.GetChannelAsString(); // Script & original script in attachments var scriptAttachment = new FileAttachment(new MemoryStream(Encoding.ASCII.GetBytes(script)), "script.lua"); diff --git a/services/grid-bot/lib/events/Events/OnSlashCommand.cs b/services/grid-bot/lib/events/Events/OnSlashCommand.cs index d8acffb6..d0437ffc 100644 --- a/services/grid-bot/lib/events/Events/OnSlashCommand.cs +++ b/services/grid-bot/lib/events/Events/OnSlashCommand.cs @@ -4,13 +4,14 @@ using System.Threading.Tasks; using System.Collections.Generic; +using Discord; using Discord.WebSocket; using Discord.Interactions; using Prometheus; using Utility; -using Discord; +using Extensions; /// /// Event handler for interactions. @@ -87,14 +88,8 @@ ILoggerFactory loggerFactory } ); - private static string GetGuildId(SocketInteraction interaction) - { - /* Always false in private thread channels, please look into discord-net/Discord.Net#2997 and mfdlabs/grid-bot#335 */ - if (interaction.Channel is SocketGuildChannel guildChannel) - return guildChannel.Guild.Id.ToString(); - - return "DM"; - } + private string GetGuildId(SocketInteraction interaction) + => interaction.GetGuild(_client).ToString() ?? "DM"; /// /// Invoke the event handler. @@ -149,8 +144,7 @@ public async Task Invoke(SocketInteraction interaction) _totalUsersBypassedMaintenance.WithLabels( interaction.User.Id.ToString(), - /* Temporary until mfdlabs/grid-bot#335 is resolved */ - interaction.Channel?.Id.ToString() ?? interaction.ChannelId?.ToString() ?? "Thread", + interaction.GetChannelAsString(), GetGuildId(interaction) ).Inc(); } @@ -159,8 +153,7 @@ public async Task Invoke(SocketInteraction interaction) { _totalBlacklistedUserAttemptedInteractions.WithLabels( interaction.User.Id.ToString(), - /* Temporary until mfdlabs/grid-bot#335 is resolved */ - interaction.Channel?.Id.ToString() ?? interaction.ChannelId?.ToString() ?? "Thread", + interaction.GetChannelAsString(), GetGuildId(interaction) ).Inc(); diff --git a/services/grid-bot/lib/events/Events/OnSlashCommandExecuted.cs b/services/grid-bot/lib/events/Events/OnSlashCommandExecuted.cs index 45e4a387..d7c2f72a 100644 --- a/services/grid-bot/lib/events/Events/OnSlashCommandExecuted.cs +++ b/services/grid-bot/lib/events/Events/OnSlashCommandExecuted.cs @@ -6,6 +6,7 @@ namespace Grid.Bot.Events; using System.Threading.Tasks; using Discord; +using Discord.WebSocket; using Discord.Interactions; using Prometheus; @@ -13,6 +14,8 @@ namespace Grid.Bot.Events; using Logging; using Utility; +using Extensions; + /// /// Invoked when slash commands are executed. @@ -23,15 +26,18 @@ namespace Grid.Bot.Events; /// The . /// The . /// The . +/// The . /// /// - cannot be null. /// - cannot be null. /// - cannot be null. +/// - cannot be null. /// public class OnInteractionExecuted( ILogger logger, IBacktraceUtility backtraceUtility, - DiscordRolesSettings discordRolesSettings + DiscordRolesSettings discordRolesSettings, + DiscordShardedClient discordClient ) { private const string UnhandledExceptionOccurredFromCommand = "An error occured with the command:"; @@ -40,6 +46,7 @@ DiscordRolesSettings discordRolesSettings private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger)); private readonly IBacktraceUtility _backtraceUtility = backtraceUtility ?? throw new ArgumentNullException(nameof(backtraceUtility)); + private readonly DiscordShardedClient _discordClient = discordClient ?? throw new ArgumentNullException(nameof(discordClient)); private readonly Counter _totalInteractionsFailed = Metrics.CreateCounter( "grid_interactions_failed_total", @@ -51,9 +58,9 @@ DiscordRolesSettings discordRolesSettings "interaction_guild_id" ); - private string GetGuildId(IInteractionContext context) + private string GetGuildId(SocketInteraction interaction) { - return context.Guild?.Id.ToString() ?? "DM"; + return interaction.GetGuild(_discordClient)?.Id.ToString() ?? "DM"; } /// @@ -64,7 +71,8 @@ private string GetGuildId(IInteractionContext context) /// The . public async Task Invoke(ICommandInfo command, IInteractionContext context, IResult result) { - var interaction = context.Interaction; + if (context.Interaction is not SocketInteraction interaction) + return; if (!result.IsSuccess) { @@ -75,8 +83,8 @@ public async Task Invoke(ICommandInfo command, IInteractionContext context, IRes interaction.Id.ToString(), interaction.User.Id.ToString(), /* Temporary until mfdlabs/grid-bot#335 is resolved */ - interaction.ChannelId?.ToString() ?? "Thread", - GetGuildId(context) + interaction.GetChannelAsString(), + GetGuildId(interaction) ).Inc(); if (result is not ExecuteResult executeResult) diff --git a/services/grid-bot/lib/utility/Implementation/LoggerFactory.cs b/services/grid-bot/lib/utility/Implementation/LoggerFactory.cs index 5972fc0d..cc060af2 100644 --- a/services/grid-bot/lib/utility/Implementation/LoggerFactory.cs +++ b/services/grid-bot/lib/utility/Implementation/LoggerFactory.cs @@ -1,16 +1,24 @@ namespace Grid.Bot.Utility; +using System; + using Discord.WebSocket; using Logging; +using Extensions; + /// /// Implementation of . /// +/// The . +/// cannot be null. /// /// -public class LoggerFactory : ILoggerFactory +public class LoggerFactory(DiscordShardedClient discordClient) : ILoggerFactory { + private readonly DiscordShardedClient _discordClient = discordClient ?? throw new ArgumentNullException(nameof(discordClient)); + /// public ILogger CreateLogger(SocketInteraction interaction) { @@ -21,12 +29,14 @@ public ILogger CreateLogger(SocketInteraction interaction) logToFileSystem: false ); - logger.CustomLogPrefixes.Add(() => interaction.ChannelId?.ToString() ?? "Thread"); - logger.CustomLogPrefixes.Add(() => interaction.User.Id.ToString()); + logger.CustomLogPrefixes.Add(() => interaction.GetChannelAsString()); + logger.CustomLogPrefixes.Add(() => interaction.User.ToString()); + + var guild = interaction.GetGuild(_discordClient); // Add guild id if the interaction is from a guild. - if (interaction.Channel is SocketGuildChannel guildChannel) - logger.CustomLogPrefixes.Add(() => guildChannel.Guild.Id.ToString()); + if (guild is not null) + logger.CustomLogPrefixes.Add(() => guild.ToString()); return logger; } @@ -41,13 +51,12 @@ public ILogger CreateLogger(SocketMessage message) logToFileSystem: false ); - logger.CustomLogPrefixes.Add(() => message.Channel.Id.ToString()); - logger.CustomLogPrefixes.Add(() => message.Author.Id.ToString()); + logger.CustomLogPrefixes.Add(() => message.Channel.ToString()); + logger.CustomLogPrefixes.Add(() => message.Author.ToString()); // Add guild id if the message is from a guild. - /* Always false in private thread channels, please look into discord-net/Discord.Net#2997 and mfdlabs/grid-bot#335 */ if (message.Channel is SocketGuildChannel guildChannel) - logger.CustomLogPrefixes.Add(() => guildChannel.Guild.Id.ToString()); + logger.CustomLogPrefixes.Add(() => guildChannel.Guild.ToString()); return logger; } diff --git a/services/grid-bot/lib/utility/Implementation/ScriptLogger.cs b/services/grid-bot/lib/utility/Implementation/ScriptLogger.cs index d907a707..320d3b11 100644 --- a/services/grid-bot/lib/utility/Implementation/ScriptLogger.cs +++ b/services/grid-bot/lib/utility/Implementation/ScriptLogger.cs @@ -9,6 +9,7 @@ namespace Grid.Bot.Utility; using System.Collections.Concurrent; using Discord; +using Discord.WebSocket; using Discord.Interactions; using Newtonsoft.Json; @@ -16,6 +17,9 @@ namespace Grid.Bot.Utility; using Random; using Networking; +using Extensions; + + /// /// Handles sending alerts to a Discord webhook. /// @@ -26,6 +30,7 @@ public class ScriptLogger : IScriptLogger private readonly IPercentageInvoker _percentageInvoker; private readonly IHttpClientFactory _httpClientFactory; private readonly ScriptsSettings _scriptsSettings; + private readonly DiscordShardedClient _discordClient; private readonly ConcurrentBag _scriptHashes = new(); @@ -36,23 +41,27 @@ public class ScriptLogger : IScriptLogger /// The to use. /// The to use. /// The to use. + /// The to use. /// /// - cannot be null. /// - cannot be null. /// - cannot be null. /// - cannot be null. + /// - cannot be null. /// public ScriptLogger( ILocalIpAddressProvider localIpAddressProvider, IPercentageInvoker percentageInvoker, IHttpClientFactory httpClientFactory, - ScriptsSettings scriptsSettings + ScriptsSettings scriptsSettings, + DiscordShardedClient discordClient ) { _localIpAddressProvider = localIpAddressProvider ?? throw new ArgumentNullException(nameof(localIpAddressProvider)); _percentageInvoker = percentageInvoker ?? throw new ArgumentNullException(nameof(percentageInvoker)); _httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory)); _scriptsSettings = scriptsSettings ?? throw new ArgumentNullException(nameof(scriptsSettings)); + _discordClient = discordClient ?? throw new ArgumentNullException(nameof(discordClient)); foreach (var hash in _scriptsSettings.LoggedScriptHashes) _scriptHashes.Add(hash); @@ -83,10 +92,8 @@ public async Task LogScriptAsync(string script, ShardedInteractionContext contex // username based off machine info var username = $"{Environment.MachineName} ({_localIpAddressProvider.AddressV4} / {_localIpAddressProvider.AddressV6})"; var userInfo = context.User.ToString(); - var guildInfo = context.Guild?.ToString() ?? "DMs"; - - /* Temporary until mfdlabs/grid-bot#335 is resolved */ - var channelInfo = context.Channel?.ToString() ?? context.Interaction.ChannelId?.ToString() ?? "Thread"; + var guildInfo = context.Interaction.GetGuild(_discordClient)?.ToString() ?? "DMs"; + var channelInfo = context.Interaction.GetChannelAsString(); // Get a SHA256 hash of the script (hex) var scriptHash = string.Join("", SHA256.HashData(Encoding.UTF8.GetBytes(script)).Select(b => b.ToString("x2")));