Skip to content

Commit cb83e42

Browse files
debug eval, debug shell: Fix history for long commands, change key type
1 parent 4f8a9dc commit cb83e42

1 file changed

Lines changed: 65 additions & 28 deletions

File tree

Commands/DebugCommands.cs

Lines changed: 65 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ internal static class DebugCommands
1515
[Description("Evaluate C# code!")]
1616
public static async Task DebugEvalCommandAsync(SlashCommandContext ctx,
1717
[SlashAutoCompleteProvider(typeof(DebugHistoryAutoCompleteProvider))]
18-
[Parameter("code"), Description("The code to evaluate.")] string code)
18+
[Parameter("code"), Description("The code to evaluate.")] string codeOrHistoryEntryId)
1919
{
2020
CancellationToken cancellationToken = default;
2121

@@ -25,23 +25,15 @@ await ctx.RespondAsync(new DiscordInteractionResponseBuilder(builder)
2525
.AsEphemeral(ephemeral: ctx.Interaction.ShouldUseEphemeralResponse(false)));
2626
var msg = await ctx.GetResponseAsync();
2727

28+
string code = await ResolveInputAsync(codeOrHistoryEntryId, EvaluatorInputType.CSharp);
29+
2830
if (Setup.Eval.RestrictedTerms.Any(code.Contains))
2931
{
3032
await ctx.EditResponseAsync(new DiscordMessageBuilder().WithContent("You can't do that."));
3133
return;
3234
}
3335

34-
var currentHistoryEntries = await Setup.Storage.Redis.HashGetAllAsync("evalHistory");
35-
var matchingEntry = currentHistoryEntries.FirstOrDefault(x => x.Value == code);
36-
if (matchingEntry == default)
37-
{
38-
await Setup.Storage.Redis.HashSetAsync("evalHistory", DateTime.UtcNow.ToString(), code);
39-
}
40-
else
41-
{
42-
await Setup.Storage.Redis.HashDeleteAsync("evalHistory", matchingEntry.Name);
43-
await Setup.Storage.Redis.HashSetAsync("evalHistory", DateTime.UtcNow.ToString(), matchingEntry.Value);
44-
}
36+
await StoreHistoryEntryAsync(code, EvaluatorInputType.CSharp);
4537

4638
try
4739
{
@@ -112,7 +104,7 @@ [new DiscordButtonComponent(DiscordButtonStyle.Danger, "button-callback-eval-can
112104
public static async Task DebugShellCommandAsync(SlashCommandContext ctx,
113105
[SlashAutoCompleteProvider(typeof(DebugHistoryAutoCompleteProvider))]
114106
[Parameter("command"), Description("The command to run, including any arguments.")]
115-
string command)
107+
string commandOrHistoryEntryId)
116108
{
117109
await ctx.RespondAsync(new DiscordInteractionResponseBuilder()
118110
.WithContent("Working on it...")
@@ -122,6 +114,8 @@ [new DiscordButtonComponent(DiscordButtonStyle.Danger, "button-callback-eval-can
122114
.AsEphemeral(ephemeral: ctx.Interaction.ShouldUseEphemeralResponse(false))
123115
);
124116

117+
var command = await ResolveInputAsync(commandOrHistoryEntryId, EvaluatorInputType.Shell);
118+
125119
if (Setup.Eval.RestrictedTerms.Any(command.Contains))
126120
if (!Setup.State.Discord.Client.CurrentApplication.Owners.Contains(ctx.User))
127121
{
@@ -138,17 +132,7 @@ [new DiscordButtonComponent(DiscordButtonStyle.Danger, "button-callback-eval-can
138132
return;
139133
}
140134

141-
var currentHistoryEntries = await Setup.Storage.Redis.HashGetAllAsync("shellHistory");
142-
var matchingEntry = currentHistoryEntries.FirstOrDefault(x => x.Value == command);
143-
if (matchingEntry == default)
144-
{
145-
await Setup.Storage.Redis.HashSetAsync("shellHistory", DateTime.UtcNow.ToString(), command);
146-
}
147-
else
148-
{
149-
await Setup.Storage.Redis.HashDeleteAsync("shellHistory", matchingEntry.Name);
150-
await Setup.Storage.Redis.HashSetAsync("shellHistory", DateTime.UtcNow.ToString(), matchingEntry.Value);
151-
}
135+
await StoreHistoryEntryAsync(command, EvaluatorInputType.Shell);
152136

153137
var msg = await ctx.GetResponseAsync();
154138
Setup.State.Caches.CancellationTokens.Add(msg.Id, new CancellationTokenSource());
@@ -751,7 +735,7 @@ await ctx.RespondAsync(new DiscordInteractionResponseBuilder()
751735

752736
#endregion commands
753737

754-
#region '/debug shell' utilities
738+
#region eval and shell utilities
755739

756740
private static async Task<ShellCommandResult> RunShellCommandAsync(string command, CancellationToken cancellationToken)
757741
{
@@ -840,7 +824,60 @@ internal ShellCommandResult(int exitCode, string output)
840824
internal string Error { get; private set; }
841825
}
842826

843-
#endregion '/debug shell' utilities
827+
private static async Task<string> ResolveInputAsync(string input, EvaluatorInputType inputType)
828+
{
829+
if (!Setup.Constants.RegularExpressions.DiscordIdPattern.IsMatch(input))
830+
return input;
831+
832+
string redisHashName;
833+
if (inputType == EvaluatorInputType.CSharp)
834+
redisHashName = "evalHistory";
835+
else if (inputType == EvaluatorInputType.Shell)
836+
redisHashName = "shellHistory";
837+
else
838+
throw new ArgumentException("Invalid input type. Unable to read from history.");
839+
840+
Dictionary<ulong, string> historyEntries = (await Setup.Storage.Redis.HashGetAllAsync(redisHashName))
841+
.ToDictionary(x => Convert.ToUInt64(x.Name), x => x.Value.ToString());
842+
843+
if (historyEntries.TryGetValue(Convert.ToUInt64(input), out string historyEntry))
844+
return historyEntry;
845+
else
846+
return input;
847+
}
848+
849+
private static async Task StoreHistoryEntryAsync(string input, EvaluatorInputType inputType)
850+
{
851+
string redisHashName;
852+
if (inputType == EvaluatorInputType.CSharp)
853+
redisHashName = "evalHistory";
854+
else if (inputType == EvaluatorInputType.Shell)
855+
redisHashName = "shellHistory";
856+
else
857+
throw new ArgumentException("Invalid input type. Unable to store history entry.");
858+
859+
HashEntry[] currentHistoryEntries = await Setup.Storage.Redis.HashGetAllAsync(redisHashName);
860+
var matchingEntry = currentHistoryEntries.FirstOrDefault(x => x.Value == input);
861+
if (matchingEntry == default)
862+
{
863+
await Setup.Storage.Redis.HashSetAsync(redisHashName, DSharpPlus.Utilities.CreateSnowflake(DateTime.UtcNow), input);
864+
}
865+
else
866+
{
867+
await Setup.Storage.Redis.HashDeleteAsync(redisHashName, matchingEntry.Name);
868+
await Setup.Storage.Redis.HashSetAsync(redisHashName, DSharpPlus.Utilities.CreateSnowflake(DateTime.UtcNow), matchingEntry.Value);
869+
}
870+
}
871+
872+
#endregion eval and shell utilities
873+
874+
#region enums
875+
private enum EvaluatorInputType
876+
{
877+
CSharp,
878+
Shell
879+
}
880+
#endregion enums
844881

845882
#region choice/autocomplete providers
846883

@@ -922,8 +959,8 @@ public async ValueTask<IEnumerable<DiscordAutoCompleteChoice>> AutoCompleteAsync
922959
else
923960
return default;
924961
return historyEntries.Where(x => x.Value.ToString().Contains(focusedOption.Value.ToString(), StringComparison.OrdinalIgnoreCase))
925-
.OrderByDescending(x => Convert.ToDateTime(x.Name.ToString()))
926-
.Select(x => new DiscordAutoCompleteChoice(x.Value.ToString(), x.Value.ToString()))
962+
.OrderByDescending(x => x.Name)
963+
.Select(x => new DiscordAutoCompleteChoice(x.Value.ToString().Truncate(100), x.Name.ToString()))
927964
.Take(25).ToList();
928965
}
929966
return default;

0 commit comments

Comments
 (0)