Files
archived-discord-bot/CompatBot/Commands/Sudo.Fix.cs
Ilya 72dbc4074a Some performance and code optimizations (#955)
* upgrade deps, remove wrong ppu hashes

* upgrade compiler packages

will require container pull after build

* replace Regex with compiler-generated versions

* use new collection initialization syntax

* configure global defaults for regex

* bump min amd driver version

fixes #950

* add macos version check

fixes #948

* fix #954 (!sudo log date)
2024-05-18 14:26:34 +01:00

175 lines
7.7 KiB
C#

using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CompatBot.Commands.Converters;
using CompatBot.Database;
using CompatBot.Database.Providers;
using CompatBot.Utils;
using DSharpPlus.CommandsNext;
using DSharpPlus.CommandsNext.Attributes;
namespace CompatBot.Commands;
internal sealed partial class Sudo
{
// '2018-06-09 08:20:44.968000 - '
// '2018-07-19T12:19:06.7888609Z - '
private static readonly Regex Timestamp = new(@"^(?<cutout>(?<date>\d{4}-\d\d-\d\d[ T][0-9:\.]+Z?) - )", RegexOptions.ExplicitCapture | RegexOptions.Singleline);
private static readonly Regex Channel = new(@"(?<id><#\d+>)", RegexOptions.ExplicitCapture | RegexOptions.Singleline);
[Group("fix"), Hidden]
[Description("Commands to fix various stuff")]
public sealed class Fix: BaseCommandModuleCustom
{
[Command("timestamps")]
[Description("Fixes `timestamp` column in the `warning` table")]
public async Task Timestamps(CommandContext ctx)
{
try
{
var @fixed = 0;
await using var db = new BotDb();
foreach (var warning in db.Warning)
if (!string.IsNullOrEmpty(warning.FullReason))
{
var match = Timestamp.Match(warning.FullReason);
if (match.Success && DateTime.TryParse(match.Groups["date"].Value, out var timestamp))
{
warning.Timestamp = timestamp.Ticks;
warning.FullReason = warning.FullReason[(match.Groups["cutout"].Value.Length)..];
@fixed++;
}
}
await db.SaveChangesAsync().ConfigureAwait(false);
await ctx.Channel.SendMessageAsync($"Fixed {@fixed} records").ConfigureAwait(false);
}
catch (Exception e)
{
Config.Log.Warn(e, "Couldn't fix warning timestamps");
await ctx.Channel.SendMessageAsync("Failed to fix warning timestamps").ConfigureAwait(false);
}
}
[Command("channels")]
[Description("Fixes channel mentions in `warning` table")]
public async Task Channels(CommandContext ctx)
{
try
{
var @fixed = 0;
await using var db = new BotDb();
foreach (var warning in db.Warning)
{
var newReason = await FixChannelMentionAsync(ctx, warning.Reason).ConfigureAwait(false);
if (newReason != warning.Reason && newReason != null)
{
warning.Reason = newReason;
@fixed++;
}
}
await db.SaveChangesAsync().ConfigureAwait(false);
await ctx.Channel.SendMessageAsync($"Fixed {@fixed} records").ConfigureAwait(false);
}
catch (Exception e)
{
Config.Log.Warn(e, "Couldn't fix channel mentions");
await ctx.Channel.SendMessageAsync("Failed to fix warning timestamps").ConfigureAwait(false);
}
}
[Command("syscalls")]
[Description("Fixes invalid function names in `syscall-info` table and associated data")]
public async Task Syscalls(CommandContext ctx)
{
try
{
await ctx.Channel.SendMessageAsync("Fixing invalid function names...").ConfigureAwait(false);
var result = await SyscallInfoProvider.FixInvalidFunctionNamesAsync().ConfigureAwait(false);
if (result.funcs > 0)
await ctx.Channel.SendMessageAsync($"Successfully fixed {result.funcs} function name{(result.funcs == 1 ? "" : "s")} and {result.links} game link{(result.links == 1 ? "" : "s")}").ConfigureAwait(false);
else
await ctx.Channel.SendMessageAsync("No invalid syscall functions detected").ConfigureAwait(false);
await ctx.Channel.SendMessageAsync("Fixing duplicates...").ConfigureAwait(false);
result = await SyscallInfoProvider.FixDuplicatesAsync().ConfigureAwait(false);
if (result.funcs > 0)
await ctx.Channel.SendMessageAsync($"Successfully merged {result.funcs} function{(result.funcs == 1 ? "" : "s")} and {result.links} game link{(result.links == 1 ? "" : "s")}").ConfigureAwait(false);
else
await ctx.Channel.SendMessageAsync("No duplicate function entries found").ConfigureAwait(false);
}
catch (Exception e)
{
Config.Log.Warn(e, "Failed to fix syscall info");
await ctx.ReactWithAsync(Config.Reactions.Failure, "Failed to fix syscall information", true).ConfigureAwait(false);
}
}
[Command("title_marks"), Aliases("trademarks", "tms")]
[Description("Strips trade marks and similar cruft from game titles in local database")]
public async Task TitleMarks(CommandContext ctx)
{
var changed = 0;
await using var db = new ThumbnailDb();
foreach (var thumb in db.Thumbnail)
{
if (string.IsNullOrEmpty(thumb.Name))
continue;
var newTitle = thumb.Name.StripMarks();
if (newTitle.EndsWith("full game", StringComparison.OrdinalIgnoreCase))
newTitle = newTitle[..^10];
if (newTitle.EndsWith("full game unlock", StringComparison.OrdinalIgnoreCase))
newTitle = newTitle[..^17];
if (newTitle.EndsWith("downloadable game", StringComparison.OrdinalIgnoreCase))
newTitle = newTitle[..^18];
newTitle = newTitle.TrimEnd();
if (newTitle == thumb.Name)
continue;
changed++;
thumb.Name = newTitle;
}
await db.SaveChangesAsync();
await ctx.Channel.SendMessageAsync($"Fixed {changed} title{(changed == 1 ? "" : "s")}").ConfigureAwait(false);
}
[Command("metacritic_links"), Aliases("mcl")]
[Description("Cleans up Metacritic links")]
public async Task MetacriticLinks(CommandContext ctx, [Description("Remove links for trial and demo versions only")] bool demosOnly = true)
{
var changed = 0;
await using var db = new ThumbnailDb();
foreach (var thumb in db.Thumbnail.Where(t => t.MetacriticId != null))
{
if (demosOnly
&& thumb.Name != null
&& !CompatList.TrialNamePattern().IsMatch(thumb.Name))
continue;
thumb.MetacriticId = null;
changed++;
}
await db.SaveChangesAsync();
await ctx.Channel.SendMessageAsync($"Fixed {changed} title{(changed == 1 ? "" : "s")}").ConfigureAwait(false);
}
public static async Task<string?> FixChannelMentionAsync(CommandContext ctx, string? msg)
{
if (string.IsNullOrEmpty(msg))
return msg;
var entries = Channel.Matches(msg).Select(m => m.Groups["id"].Value).Distinct().ToList();
if (entries.Count == 0)
return msg;
foreach (var channel in entries)
{
var ch = await TextOnlyDiscordChannelConverter.ConvertAsync(channel, ctx).ConfigureAwait(false);
if (ch.HasValue)
msg = msg.Replace(channel, "#" + ch.Value.Name);
}
return msg;
}
}
}