Skip to content

Commit d8bf48d

Browse files
authored
Null channels within private thread channels. (#335)
#!components: grid-bot #!deployable-components: grid-bot * Update ScriptLogger.cs ~ Take into account that forum channels exist. ~ Allow logging of already existing script hashes (just log the hash instead of the whole content) * Implement channel patches discord-net/Discord.Net#2997 and #335 In the case of interactions, fallback to ChannelId. In the case of messages, fallback to Thread ID. * Update build.yml Add ability to append suffixes to versions * Add fixture * Correct ref mistake * #335: SocketInteractionContext extensions Implement extension methods for the socket interaction context class for the following purposes: ~ Getting the channel as a string, taking into consideration that the channel can be null when interactions are executed within private thread channels. ~ Getting the guild as an object from the interaction context when the interaction is coming from a private thread channel, as the conventional method of checking the type of the interaction's channel against SocketGuildChannel will not work. * LuaUtility.cs ~ Move Regex for format parts to a GeneratedRegex function to improve performance. ~ Only read the LuaVM template once, as it is read from the resources on every subsequent use. ~ Account for the absence of the LuaVM in results. * #335: Private threads hotfix. ExecuteScript.cs: ~ Take reference to current DiscordShardedClient. ~ Move correspondence calls when errors are called to use LuaError instead of regular follow ups. ~ Add detection of scripts containing code blocks within zero content (causes exception) ~ Rewrite error for scripts that contain unicode to reduce ambiguity. ~ Rename GridJob to ClientJob. ~ Clean up call to PollDeletion ~ Integrate use of GetChannelAsString and GetGuild. OnSlashCommand, OnSlashCommandExecuted, LoggerFactory, ScriptLogger: ~ Clean up usings. ~ Rewrite GetGuildId to use extension methods. ~ Change around references to channel to use extension methods.
1 parent 7ce11b0 commit d8bf48d

File tree

9 files changed

+176
-66
lines changed

9 files changed

+176
-66
lines changed

.github/workflows/build.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ on:
3737
default: true
3838
type: boolean
3939

40+
version_suffix:
41+
description: "Version Suffix"
42+
required: false
43+
type: string
44+
4045
permissions:
4146
contents: write
4247
deployments: write
@@ -85,6 +90,8 @@ jobs:
8590

8691
COMPONENT_NAMES: ${{ github.event.inputs.components || needs.get-component-names.outputs.components }}
8792

93+
VERSION_SUFFIX: ${{ github.event.inputs.version_suffix || '' }}
94+
8895
outputs:
8996
components: ${{ steps.build-components.outputs.components }}
9097
version: ${{ steps.version.outputs.version }}
@@ -125,6 +132,11 @@ jobs:
125132
VERSION="$VERSION-dev"
126133
fi
127134
135+
# If we have a version suffix, append it
136+
if [ -n "${{ env.VERSION_SUFFIX }}" ]; then
137+
VERSION="${VERSION}${{ env.VERSION_SUFFIX }}"
138+
fi
139+
128140
echo "version=$VERSION" >> $GITHUB_OUTPUT
129141
130142
- name: Build Components

services/grid-bot/lib/commands/Modules/ExecuteScript.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ namespace Grid.Bot.Interactions.Public;
1313
using System.Text.RegularExpressions;
1414

1515
using Discord;
16+
using Discord.WebSocket;
1617
using Discord.Interactions;
1718

1819
using Loretta.CodeAnalysis;
@@ -25,7 +26,7 @@ namespace Grid.Bot.Interactions.Public;
2526
using Commands;
2627
using Extensions;
2728

28-
using GridJob = Client.Job;
29+
using ClientJob = Client.Job;
2930

3031
/// <summary>
3132
/// Interaction handler for executing Luau code.
@@ -36,6 +37,7 @@ namespace Grid.Bot.Interactions.Public;
3637
/// <param name="logger">The <see cref="ILogger"/>.</param>
3738
/// <param name="gridSettings">The <see cref="GridSettings"/>.</param>
3839
/// <param name="scriptsSettings">The <see cref="ScriptsSettings"/>.</param>
40+
/// <param name="discordClient">The <see cref="DiscordShardedClient"/>.</param>
3941
/// <param name="luaUtility">The <see cref="ILuaUtility"/>.</param>
4042
/// <param name="floodCheckerRegistry">The <see cref="IFloodCheckerRegistry"/>.</param>
4143
/// <param name="backtraceUtility">The <see cref="IBacktraceUtility"/>.</param>
@@ -48,6 +50,7 @@ namespace Grid.Bot.Interactions.Public;
4850
/// - <paramref name="logger"/> cannot be null.
4951
/// - <paramref name="gridSettings"/> cannot be null.
5052
/// - <paramref name="scriptsSettings"/> cannot be null.
53+
/// - <paramref name="discordClient"/> cannot be null.
5154
/// - <paramref name="luaUtility"/> cannot be null.
5255
/// - <paramref name="floodCheckerRegistry"/> cannot be null.
5356
/// - <paramref name="backtraceUtility"/> cannot be null.
@@ -64,6 +67,7 @@ public partial class ExecuteScript(
6467
ILogger logger,
6568
GridSettings gridSettings,
6669
ScriptsSettings scriptsSettings,
70+
DiscordShardedClient discordClient,
6771
ILuaUtility luaUtility,
6872
IFloodCheckerRegistry floodCheckerRegistry,
6973
IBacktraceUtility backtraceUtility,
@@ -83,6 +87,7 @@ IGridServerFileHelper gridServerFileHelper
8387
private readonly GridSettings _gridSettings = gridSettings ?? throw new ArgumentNullException(nameof(gridSettings));
8488
private readonly ScriptsSettings _scriptsSettings = scriptsSettings ?? throw new ArgumentNullException(nameof(scriptsSettings));
8589

90+
private readonly DiscordShardedClient _discordClient = discordClient ?? throw new ArgumentNullException(nameof(discordClient));
8691
private readonly ILuaUtility _luaUtility = luaUtility ?? throw new ArgumentNullException(nameof(luaUtility));
8792
private readonly IFloodCheckerRegistry _floodCheckerRegistry = floodCheckerRegistry ?? throw new ArgumentNullException(nameof(floodCheckerRegistry));
8893
private readonly IBacktraceUtility _backtraceUtility = backtraceUtility ?? throw new ArgumentNullException(nameof(backtraceUtility));
@@ -304,12 +309,20 @@ string script
304309
{
305310
if (string.IsNullOrWhiteSpace(script))
306311
{
307-
await FollowupAsync("The script cannot be empty.");
312+
await LuaErrorAsync("The script cannot be empty!");
308313

309314
return;
310315
}
311316

312317
script = GetCodeBlockContents(script);
318+
319+
if (string.IsNullOrEmpty(script))
320+
{
321+
await LuaErrorAsync("There must be content within a code block!");
322+
323+
return;
324+
}
325+
313326
script = EscapeQuotes(script);
314327

315328
var originalScript = script;
@@ -318,7 +331,7 @@ string script
318331

319332
if (ContainsUnicode(script))
320333
{
321-
await FollowupAsync("The script cannot contain unicode characters as grid-servers cannot support unicode in transit.");
334+
await LuaErrorAsync("Scripts can only contain ASCII characters!");
322335

323336
return;
324337
}
@@ -352,7 +365,7 @@ string script
352365
#endif
353366

354367

355-
var gridJob = new GridJob() { id = scriptId, expirationInSeconds = _gridSettings.ScriptExecutionJobMaxTimeout.TotalSeconds };
368+
var gridJob = new ClientJob() { id = scriptId, expirationInSeconds = _gridSettings.ScriptExecutionJobMaxTimeout.TotalSeconds };
356369
var job = new Job(Guid.NewGuid().ToString());
357370

358371
var sw = Stopwatch.StartNew();
@@ -461,9 +474,8 @@ string script
461474
scriptName
462475
);
463476
scriptName.PollDeletion(
464-
10,
465-
ex => _logger.Warning("Failed to delete '{0}' because: {1}", scriptName, ex.Message),
466-
() => _logger.Debug(
477+
onFailure: ex => _logger.Warning("Failed to delete '{0}' because: {1}", scriptName, ex.Message),
478+
onSuccess: () => _logger.Debug(
467479
"Successfully deleted the script '{0}' at path '{1}'!",
468480
scriptId,
469481
scriptName
@@ -493,8 +505,8 @@ private async Task AlertForSystem(string script, string originalScript, string s
493505
_backtraceUtility.UploadException(ex);
494506

495507
var userInfo = Context.User.ToString();
496-
var guildInfo = Context.Guild?.ToString() ?? "DMs";
497-
var channelInfo = Context.Channel.ToString();
508+
var guildInfo = Context.Interaction.GetGuild(_discordClient)?.ToString() ?? "DMs";
509+
var channelInfo = Context.Interaction.GetChannelAsString();
498510

499511
// Script & original script in attachments
500512
var scriptAttachment = new FileAttachment(new MemoryStream(Encoding.ASCII.GetBytes(script)), "script.lua");

services/grid-bot/lib/events/Events/OnMessage.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ public async Task Invoke(SocketMessage rawMessage)
173173

174174
_totalUsersBypassedMaintenance.WithLabels(
175175
message.Author.Id.ToString(),
176-
message.Channel.Id.ToString(),
176+
message.Channel?.Id.ToString() ?? message.Thread?.Id.ToString(),
177177
GetGuildId(message)
178178
).Inc();
179179
}
@@ -182,7 +182,7 @@ public async Task Invoke(SocketMessage rawMessage)
182182
{
183183
_totalBlacklistedUserAttemptedMessages.WithLabels(
184184
message.Author.Id.ToString(),
185-
message.Channel.Id.ToString(),
185+
message.Channel?.Id.ToString() ?? message.Thread?.Id.ToString(),
186186
GetGuildId(message)
187187
).Inc();
188188

services/grid-bot/lib/events/Events/OnSlashCommand.cs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
using System.Threading.Tasks;
55
using System.Collections.Generic;
66

7+
using Discord;
78
using Discord.WebSocket;
89
using Discord.Interactions;
910

1011
using Prometheus;
1112

1213
using Utility;
13-
using Discord;
14+
using Extensions;
1415

1516
/// <summary>
1617
/// Event handler for interactions.
@@ -87,13 +88,8 @@ ILoggerFactory loggerFactory
8788
}
8889
);
8990

90-
private static string GetGuildId(SocketInteraction interaction)
91-
{
92-
if (interaction.Channel is SocketGuildChannel guildChannel)
93-
return guildChannel.Guild.Id.ToString();
94-
95-
return "DM";
96-
}
91+
private string GetGuildId(SocketInteraction interaction)
92+
=> interaction.GetGuild(_client).ToString() ?? "DM";
9793

9894
/// <summary>
9995
/// Invoke the event handler.
@@ -123,15 +119,6 @@ public async Task Invoke(SocketInteraction interaction)
123119
interaction.Type.ToString()
124120
).Inc();
125121

126-
var guildName = string.Empty;
127-
var guildId = 0UL;
128-
129-
if (interaction.Channel is SocketGuildChannel guildChannel)
130-
{
131-
guildName = guildChannel.Guild.Name;
132-
guildId = guildChannel.Guild.Id;
133-
}
134-
135122
logger.Warning("Maintenance enabled user tried to use the bot.");
136123

137124
var failureMessage = _maintenanceSettings.MaintenanceStatus;
@@ -157,7 +144,7 @@ public async Task Invoke(SocketInteraction interaction)
157144

158145
_totalUsersBypassedMaintenance.WithLabels(
159146
interaction.User.Id.ToString(),
160-
interaction.Channel.Id.ToString(),
147+
interaction.GetChannelAsString(),
161148
GetGuildId(interaction)
162149
).Inc();
163150
}
@@ -166,7 +153,7 @@ public async Task Invoke(SocketInteraction interaction)
166153
{
167154
_totalBlacklistedUserAttemptedInteractions.WithLabels(
168155
interaction.User.Id.ToString(),
169-
interaction.Channel.Id.ToString(),
156+
interaction.GetChannelAsString(),
170157
GetGuildId(interaction)
171158
).Inc();
172159

services/grid-bot/lib/events/Events/OnSlashCommandExecuted.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ namespace Grid.Bot.Events;
66
using System.Threading.Tasks;
77

88
using Discord;
9+
using Discord.WebSocket;
910
using Discord.Interactions;
1011

1112
using Prometheus;
1213

1314
using Logging;
1415

1516
using Utility;
17+
using Extensions;
18+
1619

1720
/// <summary>
1821
/// Invoked when slash commands are executed.
@@ -23,15 +26,18 @@ namespace Grid.Bot.Events;
2326
/// <param name="logger">The <see cref="ILogger"/>.</param>
2427
/// <param name="backtraceUtility">The <see cref="BacktraceUtility"/>.</param>
2528
/// <param name="discordRolesSettings">The <see cref="DiscordRolesSettings"/>.</param>
29+
/// <param name="discordClient">The <see cref="DiscordShardedClient"/>.</param>
2630
/// <exception cref="ArgumentNullException">
2731
/// - <paramref name="logger"/> cannot be null.
2832
/// - <paramref name="backtraceUtility"/> cannot be null.
2933
/// - <paramref name="discordRolesSettings"/> cannot be null.
34+
/// - <paramref name="discordClient"/> cannot be null.
3035
/// </exception>
3136
public class OnInteractionExecuted(
3237
ILogger logger,
3338
IBacktraceUtility backtraceUtility,
34-
DiscordRolesSettings discordRolesSettings
39+
DiscordRolesSettings discordRolesSettings,
40+
DiscordShardedClient discordClient
3541
)
3642
{
3743
private const string UnhandledExceptionOccurredFromCommand = "An error occured with the command:";
@@ -40,6 +46,7 @@ DiscordRolesSettings discordRolesSettings
4046

4147
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
4248
private readonly IBacktraceUtility _backtraceUtility = backtraceUtility ?? throw new ArgumentNullException(nameof(backtraceUtility));
49+
private readonly DiscordShardedClient _discordClient = discordClient ?? throw new ArgumentNullException(nameof(discordClient));
4350

4451
private readonly Counter _totalInteractionsFailed = Metrics.CreateCounter(
4552
"grid_interactions_failed_total",
@@ -51,9 +58,9 @@ DiscordRolesSettings discordRolesSettings
5158
"interaction_guild_id"
5259
);
5360

54-
private string GetGuildId(IInteractionContext context)
61+
private string GetGuildId(SocketInteraction interaction)
5562
{
56-
return context.Guild?.Id.ToString() ?? "DM";
63+
return interaction.GetGuild(_discordClient)?.Id.ToString() ?? "DM";
5764
}
5865

5966
/// <summary>
@@ -64,7 +71,8 @@ private string GetGuildId(IInteractionContext context)
6471
/// <param name="result">The <see cref="IResult"/>.</param>
6572
public async Task Invoke(ICommandInfo command, IInteractionContext context, IResult result)
6673
{
67-
var interaction = context.Interaction;
74+
if (context.Interaction is not SocketInteraction interaction)
75+
return;
6876

6977
if (!result.IsSuccess)
7078
{
@@ -74,8 +82,9 @@ public async Task Invoke(ICommandInfo command, IInteractionContext context, IRes
7482
interaction.Type.ToString(),
7583
interaction.Id.ToString(),
7684
interaction.User.Id.ToString(),
77-
interaction.ChannelId.ToString(),
78-
GetGuildId(context)
85+
/* Temporary until mfdlabs/grid-bot#335 is resolved */
86+
interaction.GetChannelAsString(),
87+
GetGuildId(interaction)
7988
).Inc();
8089

8190
if (result is not ExecuteResult executeResult)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
namespace Grid.Bot.Extensions;
2+
3+
using Discord;
4+
using Discord.WebSocket;
5+
6+
using Threading.Extensions;
7+
8+
/// <summary>
9+
/// Extension methods for <see cref="SocketInteraction" />
10+
/// </summary>
11+
public static class SocketInteractionExtensions
12+
{
13+
/// <summary>
14+
/// Gets the channel from the <see cref="SocketInteraction" />, taking private threads into consideration.
15+
/// </summary>
16+
/// <param name="interaction">The current <see cref="SocketInteraction"/></param>
17+
/// <returns>A string version of either <see cref="ISocketMessageChannel"/> or <see cref="IMessageChannel"/></returns>
18+
public static string GetChannelAsString(this SocketInteraction interaction)
19+
{
20+
if (interaction.Channel is not null) return interaction.Channel.ToString();
21+
22+
return interaction.InteractionChannel.ToString();
23+
}
24+
25+
/// <summary>
26+
/// Gets an <see cref="IGuild"/> for a specific <see cref="SocketInteraction"/>, taking private threads into consideration.
27+
/// </summary>
28+
/// <param name="interaction"></param>
29+
/// <param name="client"></param>
30+
/// <returns></returns>
31+
public static IGuild GetGuild(this SocketInteraction interaction, IDiscordClient client)
32+
{
33+
if (interaction.GuildId == null) return null;
34+
35+
if (interaction.Channel is SocketGuildChannel guildChannel)
36+
return guildChannel.Guild;
37+
38+
return client.GetGuildAsync(interaction.GuildId.Value).SyncOrDefault();
39+
}
40+
}

0 commit comments

Comments
 (0)