mirror of
https://github.com/RPCS3/discord-bot.git
synced 2026-01-31 01:25:22 +01:00
fix resharper warnings
This commit is contained in:
@@ -277,7 +277,7 @@ namespace CompatBot.Commands
|
||||
[Description("Provides advanced clairvoyance services to predict the time frame for specified event with maximum accuracy")]
|
||||
public async Task When(CommandContext ctx, [RemainingText, Description("Something to happen")] string whatever = "")
|
||||
{
|
||||
var question = whatever?.Trim().TrimEnd('?').ToLowerInvariant() ?? "";
|
||||
var question = whatever.Trim().TrimEnd('?').ToLowerInvariant();
|
||||
var prefix = DateTime.UtcNow.ToString("yyyyMMddHH");
|
||||
var crng = new Random((prefix + question).GetHashCode());
|
||||
var number = crng.Next(100) + 1;
|
||||
@@ -436,7 +436,7 @@ namespace CompatBot.Commands
|
||||
result.Append(suffix).Append(' ');
|
||||
}
|
||||
whatever = result.ToString();
|
||||
var cutIdx = whatever.LastIndexOf("never mind");
|
||||
var cutIdx = whatever.LastIndexOf("never mind", StringComparison.Ordinal);
|
||||
if (cutIdx > -1)
|
||||
whatever = whatever[cutIdx..];
|
||||
whatever = whatever.Replace("'s's", "'s").TrimStart(EveryTimable).Trim();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using CompatBot.Database.Providers;
|
||||
using CompatBot.Utils;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace CompatBot.Commands
|
||||
{
|
||||
try
|
||||
{
|
||||
var isMod = ctx.User.IsWhitelisted(ctx.Client, ctx.Guild);
|
||||
if (number < 1)
|
||||
number = 10;
|
||||
var table = new AsciiTable(
|
||||
@@ -90,21 +89,19 @@ namespace CompatBot.Commands
|
||||
new AsciiColumn("Reason"),
|
||||
new AsciiColumn("Context", disabled: !ctx.Channel.IsPrivate)
|
||||
);
|
||||
using (var db = new BotDb())
|
||||
await using var db = new BotDb();
|
||||
var query = from warn in db.Warning
|
||||
where warn.IssuerId == moderatorId && !warn.Retracted
|
||||
orderby warn.Id descending
|
||||
select warn;
|
||||
foreach (var row in query.Take(number))
|
||||
{
|
||||
var query = from warn in db.Warning
|
||||
where warn.IssuerId == moderatorId && !warn.Retracted
|
||||
orderby warn.Id descending
|
||||
select warn;
|
||||
foreach (var row in query.Take(number))
|
||||
{
|
||||
var username = await ctx.GetUserNameAsync(row.DiscordId).ConfigureAwait(false);
|
||||
var timestamp = row.Timestamp.HasValue ? new DateTime(row.Timestamp.Value, DateTimeKind.Utc).ToString("u") : "";
|
||||
table.Add(row.Id.ToString(), username, row.DiscordId.ToString(), timestamp, row.Reason, row.FullReason);
|
||||
}
|
||||
var username = await ctx.GetUserNameAsync(row.DiscordId).ConfigureAwait(false);
|
||||
var timestamp = row.Timestamp.HasValue ? new DateTime(row.Timestamp.Value, DateTimeKind.Utc).ToString("u") : "";
|
||||
table.Add(row.Id.ToString(), username, row.DiscordId.ToString(), timestamp, row.Reason, row.FullReason);
|
||||
}
|
||||
var modname = await ctx.GetUserNameAsync(moderatorId, defaultName: "Unknown mod").ConfigureAwait(false);
|
||||
await ctx.SendAutosplitMessageAsync(new StringBuilder($"Recent warnings issued by {modname}:").Append(table)).ConfigureAwait(false);
|
||||
var modName = await ctx.GetUserNameAsync(moderatorId, defaultName: "Unknown mod").ConfigureAwait(false);
|
||||
await ctx.SendAutosplitMessageAsync(new StringBuilder($"Recent warnings issued by {modName}:").Append(table)).ConfigureAwait(false);
|
||||
|
||||
}
|
||||
|
||||
@@ -158,17 +155,17 @@ namespace CompatBot.Commands
|
||||
foreach (var row in query.Take(number))
|
||||
{
|
||||
var username = await ctx.GetUserNameAsync(row.DiscordId).ConfigureAwait(false);
|
||||
var modname = await ctx.GetUserNameAsync(row.IssuerId, defaultName: "Unknown mod").ConfigureAwait(false);
|
||||
var modName = await ctx.GetUserNameAsync(row.IssuerId, defaultName: "Unknown mod").ConfigureAwait(false);
|
||||
var timestamp = row.Timestamp.HasValue ? new DateTime(row.Timestamp.Value, DateTimeKind.Utc).ToString("u") : "";
|
||||
if (row.Retracted)
|
||||
{
|
||||
var modnameRetracted = row.RetractedBy.HasValue ? await ctx.GetUserNameAsync(row.RetractedBy.Value, defaultName: "Unknown mod").ConfigureAwait(false) : "";
|
||||
var modNameRetracted = row.RetractedBy.HasValue ? await ctx.GetUserNameAsync(row.RetractedBy.Value, defaultName: "Unknown mod").ConfigureAwait(false) : "";
|
||||
var timestampRetracted = row.RetractionTimestamp.HasValue ? new DateTime(row.RetractionTimestamp.Value, DateTimeKind.Utc).ToString("u") : "";
|
||||
table.Add(row.Id.ToString(), "-", username, row.DiscordId.ToString(), modnameRetracted, timestampRetracted, row.RetractionReason ?? "", "");
|
||||
table.Add(row.Id.ToString(), "+", username.StrikeThrough(), row.DiscordId.ToString().StrikeThrough(), modname.StrikeThrough(), timestamp.StrikeThrough(), row.Reason.StrikeThrough(), row.FullReason.StrikeThrough());
|
||||
table.Add(row.Id.ToString(), "-", username, row.DiscordId.ToString(), modNameRetracted, timestampRetracted, row.RetractionReason ?? "", "");
|
||||
table.Add(row.Id.ToString(), "+", username.StrikeThrough(), row.DiscordId.ToString().StrikeThrough(), modName.StrikeThrough(), timestamp.StrikeThrough(), row.Reason.StrikeThrough(), row.FullReason.StrikeThrough());
|
||||
}
|
||||
else
|
||||
table.Add(row.Id.ToString(), "+", username, row.DiscordId.ToString(), modname, timestamp, row.Reason, row.FullReason);
|
||||
table.Add(row.Id.ToString(), "+", username, row.DiscordId.ToString(), modName, timestamp, row.Reason, row.FullReason);
|
||||
}
|
||||
await ctx.SendAutosplitMessageAsync(new StringBuilder("Recent warnings:").Append(table)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
|
||||
namespace CompatBot.Database
|
||||
{
|
||||
|
||||
@@ -8,46 +8,46 @@ namespace CompatBot.Database.Providers
|
||||
{
|
||||
internal static class ModProvider
|
||||
{
|
||||
private static readonly Dictionary<ulong, Moderator> mods;
|
||||
private static readonly BotDb db = new();
|
||||
public static ReadOnlyDictionary<ulong, Moderator> Mods => new(mods);
|
||||
private static readonly Dictionary<ulong, Moderator> Moderators;
|
||||
private static readonly BotDb Db = new();
|
||||
public static ReadOnlyDictionary<ulong, Moderator> Mods => new(Moderators);
|
||||
|
||||
static ModProvider()
|
||||
{
|
||||
mods = db.Moderator.ToDictionary(m => m.DiscordId, m => m);
|
||||
Moderators = Db.Moderator.ToDictionary(m => m.DiscordId, m => m);
|
||||
}
|
||||
|
||||
public static bool IsMod(ulong userId) => mods.ContainsKey(userId);
|
||||
public static bool IsMod(ulong userId) => Moderators.ContainsKey(userId);
|
||||
|
||||
public static bool IsSudoer(ulong userId) => mods.TryGetValue(userId, out var mod) && mod.Sudoer;
|
||||
public static bool IsSudoer(ulong userId) => Moderators.TryGetValue(userId, out var mod) && mod.Sudoer;
|
||||
|
||||
public static async Task<bool> AddAsync(ulong userId)
|
||||
{
|
||||
if (IsMod(userId))
|
||||
return false;
|
||||
|
||||
var result = await db.Moderator.AddAsync(new Moderator {DiscordId = userId}).ConfigureAwait(false);
|
||||
await db.SaveChangesAsync().ConfigureAwait(false);
|
||||
lock (mods)
|
||||
var result = await Db.Moderator.AddAsync(new Moderator {DiscordId = userId}).ConfigureAwait(false);
|
||||
await Db.SaveChangesAsync().ConfigureAwait(false);
|
||||
lock (Moderators)
|
||||
{
|
||||
if (IsMod(userId))
|
||||
return false;
|
||||
mods[userId] = result.Entity;
|
||||
Moderators[userId] = result.Entity;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async Task<bool> RemoveAsync(ulong userId)
|
||||
{
|
||||
if (!mods.TryGetValue(userId, out var mod))
|
||||
if (!Moderators.TryGetValue(userId, out var mod))
|
||||
return false;
|
||||
|
||||
db.Moderator.Remove(mod);
|
||||
await db.SaveChangesAsync().ConfigureAwait(false);
|
||||
lock (mods)
|
||||
Db.Moderator.Remove(mod);
|
||||
await Db.SaveChangesAsync().ConfigureAwait(false);
|
||||
lock (Moderators)
|
||||
{
|
||||
if (IsMod(userId))
|
||||
mods.Remove(userId);
|
||||
Moderators.Remove(userId);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -56,21 +56,21 @@ namespace CompatBot.Database.Providers
|
||||
|
||||
public static async Task<bool> MakeSudoerAsync(ulong userId)
|
||||
{
|
||||
if (!mods.TryGetValue(userId, out var mod) || mod.Sudoer)
|
||||
if (!Moderators.TryGetValue(userId, out var mod) || mod.Sudoer)
|
||||
return false;
|
||||
|
||||
mod.Sudoer = true;
|
||||
await db.SaveChangesAsync().ConfigureAwait(false);
|
||||
await Db.SaveChangesAsync().ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async Task<bool> UnmakeSudoerAsync(ulong userId)
|
||||
{
|
||||
if (!mods.TryGetValue(userId, out var mod) || !mod.Sudoer)
|
||||
if (!Moderators.TryGetValue(userId, out var mod) || !mod.Sudoer)
|
||||
return false;
|
||||
|
||||
mod.Sudoer = false;
|
||||
await db.SaveChangesAsync().ConfigureAwait(false);
|
||||
await Db.SaveChangesAsync().ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -9,9 +8,7 @@ using CompatBot.Utils;
|
||||
using DSharpPlus;
|
||||
using DSharpPlus.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using PsnClient.POCOs;
|
||||
|
||||
namespace CompatBot.Database.Providers
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
@@ -10,6 +9,9 @@ using DSharpPlus;
|
||||
using DSharpPlus.Entities;
|
||||
using DSharpPlus.EventArgs;
|
||||
using NReco.Text;
|
||||
#if DEBUG
|
||||
using System.Collections.Generic;
|
||||
#endif
|
||||
|
||||
namespace CompatBot.EventHandlers
|
||||
{
|
||||
@@ -70,11 +72,11 @@ namespace CompatBot.EventHandlers
|
||||
@"\b((?<kot>kot(to)?)|(?<doggo>doggo|jarves))\b",
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.ExplicitCapture
|
||||
);
|
||||
private static readonly Random rng = new();
|
||||
private static readonly object theDoor = new();
|
||||
private static readonly Random Rng = new();
|
||||
private static readonly object TheDoor = new();
|
||||
|
||||
public static DiscordEmoji RandomNegativeReaction { get { lock (theDoor) return SadReactions[rng.Next(SadReactions.Length)]; } }
|
||||
public static DiscordEmoji RandomPositiveReaction { get { lock (theDoor) return ThankYouReactions[rng.Next(ThankYouReactions.Length)]; } }
|
||||
public static DiscordEmoji RandomNegativeReaction { get { lock (TheDoor) return SadReactions[Rng.Next(SadReactions.Length)]; } }
|
||||
public static DiscordEmoji RandomPositiveReaction { get { lock (TheDoor) return ThankYouReactions[Rng.Next(ThankYouReactions.Length)]; } }
|
||||
|
||||
public static async Task OnMessageCreated(DiscordClient c, MessageCreateEventArgs args)
|
||||
{
|
||||
@@ -160,12 +162,12 @@ namespace CompatBot.EventHandlers
|
||||
{
|
||||
DiscordEmoji emoji;
|
||||
string? thankYouMessage;
|
||||
lock (theDoor)
|
||||
lock (TheDoor)
|
||||
{
|
||||
emoji = ThankYouReactions[rng.Next(ThankYouReactions.Length)];
|
||||
emoji = ThankYouReactions[Rng.Next(ThankYouReactions.Length)];
|
||||
thankYouMessage = LimitedToSpamChannel.IsSpamChannel(args.Channel)
|
||||
|| LimitedToOfftopicChannel.IsOfftopicChannel(args.Channel)
|
||||
? ThankYouMessages[rng.Next(ThankYouMessages.Length)]
|
||||
? ThankYouMessages[Rng.Next(ThankYouMessages.Length)]
|
||||
: null;
|
||||
}
|
||||
await args.Message.ReactWithAsync(emoji, thankYouMessage).ConfigureAwait(false);
|
||||
@@ -174,10 +176,10 @@ namespace CompatBot.EventHandlers
|
||||
{
|
||||
DiscordEmoji emoji;
|
||||
string sadMessage;
|
||||
lock (theDoor)
|
||||
lock (TheDoor)
|
||||
{
|
||||
emoji = SadReactions[rng.Next(SadReactions.Length)];
|
||||
sadMessage = SadMessages[rng.Next(SadMessages.Length)];
|
||||
emoji = SadReactions[Rng.Next(SadReactions.Length)];
|
||||
sadMessage = SadMessages[Rng.Next(SadMessages.Length)];
|
||||
}
|
||||
await args.Message.ReactWithAsync(emoji, sadMessage).ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace CompatBot.EventHandlers
|
||||
{
|
||||
public static readonly MemoryCache RemovedByBotCache = new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(10) });
|
||||
public static readonly TimeSpan CacheRetainTime = TimeSpan.FromMinutes(1);
|
||||
private static readonly SemaphoreSlim postLock = new(1);
|
||||
private static readonly SemaphoreSlim PostLock = new(1);
|
||||
|
||||
public static async Task OnMessageDeleted(DiscordClient c, MessageDeleteEventArgs e)
|
||||
{
|
||||
@@ -56,7 +56,7 @@ namespace CompatBot.EventHandlers
|
||||
var color = await ThumbnailProvider.GetImageColorAsync(msg.Author.AvatarUrl).ConfigureAwait(false);
|
||||
if (color.HasValue)
|
||||
embed.WithColor(color.Value);
|
||||
await postLock.WaitAsync().ConfigureAwait(false);
|
||||
await PostLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
await logChannel.SendMessageAsync(embed: embed, mentions: Config.AllowedMentions.Nothing).ConfigureAwait(false);
|
||||
@@ -67,7 +67,7 @@ namespace CompatBot.EventHandlers
|
||||
}
|
||||
finally
|
||||
{
|
||||
postLock.Release();
|
||||
PostLock.Release();
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace CompatBot.EventHandlers
|
||||
return (false, false, new List<DiscordInvite>(0));
|
||||
|
||||
var inviteCodes = new HashSet<string>(InviteLink.Matches(message).Select(m => m.Groups["invite_id"].Value).Where(s => !string.IsNullOrEmpty(s)));
|
||||
var discordMeLinks = InviteLink.Matches(message).Select(m => m.Groups["me_id"]?.Value).Distinct().Where(s => !string.IsNullOrEmpty(s)).ToList();
|
||||
var discordMeLinks = InviteLink.Matches(message).Select(m => m.Groups["me_id"].Value).Distinct().Where(s => !string.IsNullOrEmpty(s)).ToList();
|
||||
var attemptedWorkaround = false;
|
||||
if (author != null && InviteCodeCache.TryGetValue(author.Id, out HashSet<string> recentInvites))
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace CompatBot.EventHandlers
|
||||
MessageQueue[args.Channel.Id] = queue = new ConcurrentQueue<DiscordMessage>();
|
||||
queue.Enqueue(args.Message);
|
||||
while (queue.Count > 10)
|
||||
queue.TryDequeue(out var _i);
|
||||
queue.TryDequeue(out var _);
|
||||
var content = args.Message.Content;
|
||||
if (string.IsNullOrEmpty(content))
|
||||
return;
|
||||
@@ -74,7 +74,7 @@ namespace CompatBot.EventHandlers
|
||||
if (channel.IsPrivate)
|
||||
return;
|
||||
|
||||
if (message?.Author == null)
|
||||
if (message.Author == null)
|
||||
return;
|
||||
|
||||
if (message.Author.IsCurrent)
|
||||
|
||||
@@ -29,11 +29,11 @@ namespace CompatBot.EventHandlers
|
||||
if (!MessageQueue.TryGetValue(args.Channel.Id, out queue))
|
||||
MessageQueue[args.Channel.Id] = queue = new FixedLengthBuffer<ulong, DiscordMessage>(KeyGen);
|
||||
}
|
||||
lock(queue.syncObj)
|
||||
lock(queue.SyncObj)
|
||||
queue.Add(args.Message);
|
||||
|
||||
while (queue.Count > Config.ChannelMessageHistorySize)
|
||||
lock(queue.syncObj)
|
||||
lock(queue.SyncObj)
|
||||
queue.TrimExcess();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -46,7 +46,7 @@ namespace CompatBot.EventHandlers
|
||||
if (!MessageQueue.TryGetValue(args.Channel.Id, out var queue))
|
||||
return Task.CompletedTask;
|
||||
|
||||
lock (queue.syncObj)
|
||||
lock (queue.SyncObj)
|
||||
queue.Evict(args.Message.Id);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ namespace CompatBot.EventHandlers
|
||||
if (!MessageQueue.TryGetValue(args.Channel.Id, out var queue))
|
||||
return Task.CompletedTask;
|
||||
|
||||
lock (queue.syncObj)
|
||||
lock (queue.SyncObj)
|
||||
foreach (var m in args.Messages)
|
||||
queue.Evict(m.Id);
|
||||
return Task.CompletedTask;
|
||||
@@ -73,7 +73,7 @@ namespace CompatBot.EventHandlers
|
||||
if (!MessageQueue.TryGetValue(args.Channel.Id, out var queue))
|
||||
return Task.CompletedTask;
|
||||
|
||||
lock(queue.syncObj)
|
||||
lock(queue.SyncObj)
|
||||
queue.AddOrReplace(args.Message);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ namespace CompatBot.EventHandlers
|
||||
if (!MessageQueue.TryGetValue(ch.Id, out queue))
|
||||
MessageQueue[ch.Id] = queue = new FixedLengthBuffer<ulong, DiscordMessage>(KeyGen);
|
||||
List<DiscordMessage> result;
|
||||
lock(queue.syncObj)
|
||||
lock(queue.SyncObj)
|
||||
result = queue.Reverse().Take(count).ToList();
|
||||
var cacheCount = result.Count;
|
||||
var fetchCount = Math.Max(count - cacheCount, 0);
|
||||
@@ -98,7 +98,7 @@ namespace CompatBot.EventHandlers
|
||||
fetchedList = ch.GetMessagesAsync(fetchCount).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
result.AddRange(fetchedList);
|
||||
if (queue.Count < Config.ChannelMessageHistorySize)
|
||||
lock (queue.syncObj)
|
||||
lock (queue.SyncObj)
|
||||
{
|
||||
// items in queue might've changed since the previous check at the beginning of this method
|
||||
var freshCopy = queue.Reverse().ToList();
|
||||
@@ -116,7 +116,7 @@ namespace CompatBot.EventHandlers
|
||||
if (!MessageQueue.TryGetValue(ch.Id, out queue))
|
||||
MessageQueue[ch.Id] = queue = new FixedLengthBuffer<ulong, DiscordMessage>(KeyGen);
|
||||
List<DiscordMessage> result;
|
||||
lock(queue.syncObj)
|
||||
lock(queue.SyncObj)
|
||||
result = queue.Reverse().SkipWhile(m => m.Id >= msgId).Take(count).ToList();
|
||||
var cacheCount = result.Count;
|
||||
var fetchCount = Math.Max(count - cacheCount, 0);
|
||||
@@ -127,7 +127,7 @@ namespace CompatBot.EventHandlers
|
||||
{
|
||||
fetchedList = ch.GetMessagesBeforeAsync(result[0].Id, fetchCount).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (queue.Count < Config.ChannelMessageHistorySize)
|
||||
lock (queue.syncObj)
|
||||
lock (queue.SyncObj)
|
||||
{
|
||||
// items in queue might've changed since the previous check at the beginning of this method
|
||||
var freshCopy = queue.Reverse().ToList();
|
||||
|
||||
@@ -120,16 +120,15 @@ namespace CompatBot.EventHandlers
|
||||
if (listWithStatus.Count > 0)
|
||||
bestMatch = listWithStatus.First();
|
||||
var (code, info, score) = bestMatch;
|
||||
Config.Log.Debug($"Looked up \"{gameTitle}\", got \"{info?.Title}\" with score {score}");
|
||||
Config.Log.Debug($"Looked up \"{gameTitle}\", got \"{info.Title}\" with score {score}");
|
||||
if (score < Config.GameTitleMatchThreshold)
|
||||
return (null, null);
|
||||
|
||||
if (!string.IsNullOrEmpty(info?.Title))
|
||||
if (!string.IsNullOrEmpty(info.Title))
|
||||
{
|
||||
StatsStorage.GameStatCache.TryGetValue(info.Title, out int stat);
|
||||
StatsStorage.GameStatCache.Set(info.Title, ++stat, StatsStorage.CacheTime);
|
||||
}
|
||||
|
||||
return (code, info);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -283,8 +283,8 @@ namespace CompatBot.EventHandlers.LogParsing
|
||||
}
|
||||
else
|
||||
{
|
||||
var utf8line = line.ToUtf8();
|
||||
state.FilterTriggers[m.Id] = (m, utf8line);
|
||||
var utf8Line = line.ToUtf8();
|
||||
state.FilterTriggers[m.Id] = (m, utf8Line);
|
||||
if (m.Actions.HasFlag(FilterAction.IssueWarning))
|
||||
state.Error = LogParseState.ErrorCode.PiracyDetected;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace CompatBot.EventHandlers.LogParsing
|
||||
EndTrigger = sectionDescription.EndTrigger.Select(s => s.ToLatin8BitEncoding()).ToArray(),
|
||||
};
|
||||
// the idea here is to construct Aho-Corasick parser that will look for any data marker and run the associated regex to extract the data into state
|
||||
if (sectionDescription.Extractors?.Count > 0)
|
||||
if (sectionDescription.Extractors.Count > 0)
|
||||
{
|
||||
var act = new AhoCorasickDoubleArrayTrie<Action<string, LogParseState>>(sectionDescription.Extractors.Select(extractorPair =>
|
||||
new SectionAction(
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
{
|
||||
protected const RegexOptions DefaultOptions = RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;
|
||||
protected const int SnoopBufferSize = 4096;
|
||||
internal static readonly ArrayPool<byte> bufferPool = ArrayPool<byte>.Create(SnoopBufferSize, 64);
|
||||
internal static readonly ArrayPool<byte> BufferPool = ArrayPool<byte>.Create(SnoopBufferSize, 64);
|
||||
|
||||
public abstract Task<(ISource? source, string? failReason)> FindHandlerAsync(DiscordMessage message, ICollection<IArchiveHandler> handlers);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
try
|
||||
{
|
||||
await using var stream = await client.GetStreamAsync(attachment.Url).ConfigureAwait(false);
|
||||
var buf = bufferPool.Rent(SnoopBufferSize);
|
||||
var buf = BufferPool.Rent(SnoopBufferSize);
|
||||
try
|
||||
{
|
||||
var read = await stream.ReadBytesAsync(buf).ConfigureAwait(false);
|
||||
@@ -35,7 +35,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferPool.Return(buf);
|
||||
BufferPool.Return(buf);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -9,7 +9,6 @@ using CompatBot.Utils;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using CompatApiClient;
|
||||
using CompatApiClient.Utils;
|
||||
|
||||
namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
@@ -52,7 +51,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
}
|
||||
|
||||
await using var stream = await client.GetStreamAsync(uri).ConfigureAwait(false);
|
||||
var buf = bufferPool.Rent(SnoopBufferSize);
|
||||
var buf = BufferPool.Rent(SnoopBufferSize);
|
||||
try
|
||||
{
|
||||
var read = await stream.ReadBytesAsync(buf).ConfigureAwait(false);
|
||||
@@ -67,7 +66,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferPool.Return(buf);
|
||||
BufferPool.Return(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,14 +31,14 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
|
||||
public async Task FillPipeAsync(PipeWriter writer, CancellationToken cancellationToken)
|
||||
{
|
||||
using var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
await using var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
await handler.FillPipeAsync(stream, writer, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static async Task<ISource> DetectArchiveHandlerAsync(string path, ICollection<IArchiveHandler> handlers)
|
||||
{
|
||||
var buf = new byte[4096];
|
||||
using var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
await using var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
var read = await stream.ReadBytesAsync(buf).ConfigureAwait(false);
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
}
|
||||
|
||||
await using var stream = await client.GetStreamAsync(uri).ConfigureAwait(false);
|
||||
var buf = bufferPool.Rent(SnoopBufferSize);
|
||||
var buf = BufferPool.Rent(SnoopBufferSize);
|
||||
try
|
||||
{
|
||||
var read = await stream.ReadBytesAsync(buf).ConfigureAwait(false);
|
||||
@@ -65,7 +65,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferPool.Return(buf);
|
||||
BufferPool.Return(buf);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
var fileMeta = await fileInfoRequest.ExecuteAsync(Config.Cts.Token).ConfigureAwait(false);
|
||||
if (fileMeta.Kind == "drive#file" && fileMeta.Size > 0)
|
||||
{
|
||||
var buf = bufferPool.Rent(SnoopBufferSize);
|
||||
var buf = BufferPool.Rent(SnoopBufferSize);
|
||||
try
|
||||
{
|
||||
int read;
|
||||
@@ -71,7 +71,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferPool.Return(buf);
|
||||
BufferPool.Return(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
// mega.nz/#!8IJHBYyB!jw21m-GCs85uzj9E5XRysqyJCsNfZS0Zx4Eu9_zvuUM
|
||||
// mega.nz/file/8IJHBYyB#jw21m-GCs85uzj9E5XRysqyJCsNfZS0Zx4Eu9_zvuUM
|
||||
private static readonly Regex ExternalLink = new(@"(?<mega_link>(https?://)?mega(\.co)?\.nz/(#(?<mega_id>[^/>\s]+)|file/(?<new_mega_id>[^/>\s]+)))", DefaultOptions);
|
||||
private static readonly IProgress<double> doodad = new Progress<double>(_ => { });
|
||||
private static readonly IProgress<double> Doodad = new Progress<double>(_ => { });
|
||||
|
||||
public override async Task<(ISource? source, string? failReason)> FindHandlerAsync(DiscordMessage message, ICollection<IArchiveHandler> handlers)
|
||||
{
|
||||
@@ -40,11 +40,11 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
var node = await client.GetNodeFromLinkAsync(uri).ConfigureAwait(false);
|
||||
if (node.Type == NodeType.File)
|
||||
{
|
||||
var buf = bufferPool.Rent(SnoopBufferSize);
|
||||
var buf = BufferPool.Rent(SnoopBufferSize);
|
||||
try
|
||||
{
|
||||
int read;
|
||||
await using (var stream = await client.DownloadAsync(uri, doodad, Config.Cts.Token).ConfigureAwait(false))
|
||||
await using (var stream = await client.DownloadAsync(uri, Doodad, Config.Cts.Token).ConfigureAwait(false))
|
||||
read = await stream.ReadBytesAsync(buf).ConfigureAwait(false);
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
@@ -57,7 +57,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferPool.Return(buf);
|
||||
BufferPool.Return(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
|
||||
public async Task FillPipeAsync(PipeWriter writer, CancellationToken cancellationToken)
|
||||
{
|
||||
await using var stream = await client.DownloadAsync(uri, doodad, cancellationToken).ConfigureAwait(false);
|
||||
await using var stream = await client.DownloadAsync(uri, Doodad, cancellationToken).ConfigureAwait(false);
|
||||
await handler.FillPipeAsync(stream, writer, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CG.Web.MegaApiClient;
|
||||
using CompatBot.EventHandlers.LogParsing.ArchiveHandlers;
|
||||
using CompatBot.Utils;
|
||||
using DSharpPlus.Entities;
|
||||
@@ -19,9 +16,9 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
internal sealed class OneDriveSourceHandler : BaseSourceHandler
|
||||
{
|
||||
private static readonly Regex ExternalLink = new(@"(?<onedrive_link>(https?://)?(1drv\.ms|onedrive\.live\.com)/[^>\s]+)", DefaultOptions);
|
||||
private static readonly Client client = new();
|
||||
private static readonly Client Client = new();
|
||||
|
||||
public async override Task<(ISource? source, string? failReason)> FindHandlerAsync(DiscordMessage message, ICollection<IArchiveHandler> handlers)
|
||||
public override async Task<(ISource? source, string? failReason)> FindHandlerAsync(DiscordMessage message, ICollection<IArchiveHandler> handlers)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message.Content))
|
||||
return (null, null);
|
||||
@@ -38,7 +35,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
if (m.Groups["onedrive_link"].Value is string lnk
|
||||
&& !string.IsNullOrEmpty(lnk)
|
||||
&& Uri.TryCreate(lnk, UriKind.Absolute, out var uri)
|
||||
&& await client.ResolveContentLinkAsync(uri, Config.Cts.Token).ConfigureAwait(false) is DriveItemMeta itemMeta
|
||||
&& await Client.ResolveContentLinkAsync(uri, Config.Cts.Token).ConfigureAwait(false) is DriveItemMeta itemMeta
|
||||
&& itemMeta.ContentDownloadUrl is string downloadUrl)
|
||||
{
|
||||
try
|
||||
@@ -48,7 +45,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
uri = new Uri(downloadUrl);
|
||||
|
||||
await using var stream = await httpClient.GetStreamAsync(uri).ConfigureAwait(false);
|
||||
var buf = bufferPool.Rent(SnoopBufferSize);
|
||||
var buf = BufferPool.Rent(SnoopBufferSize);
|
||||
try
|
||||
{
|
||||
var read = await stream.ReadBytesAsync(buf).ConfigureAwait(false);
|
||||
@@ -63,7 +60,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferPool.Return(buf);
|
||||
BufferPool.Return(buf);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
{
|
||||
var uri = new Uri("https://pastebin.com/raw/" + pid);
|
||||
await using var stream = await client.GetStreamAsync(uri).ConfigureAwait(false);
|
||||
var buf = bufferPool.Rent(SnoopBufferSize);
|
||||
var buf = BufferPool.Rent(SnoopBufferSize);
|
||||
try
|
||||
{
|
||||
var read = await stream.ReadBytesAsync(buf).ConfigureAwait(false);
|
||||
@@ -51,7 +51,7 @@ namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferPool.Return(buf);
|
||||
BufferPool.Return(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ namespace CompatBot.EventHandlers
|
||||
{
|
||||
public static class LogParsingHandler
|
||||
{
|
||||
private static readonly char[] linkSeparator = { ' ', '>', '\r', '\n' };
|
||||
private static readonly ISourceHandler[] sourceHandlers =
|
||||
private static readonly char[] LinkSeparator = { ' ', '>', '\r', '\n' };
|
||||
private static readonly ISourceHandler[] SourceHandlers =
|
||||
{
|
||||
new DiscordAttachmentHandler(),
|
||||
new GoogleDriveHandler(),
|
||||
@@ -38,7 +38,7 @@ namespace CompatBot.EventHandlers
|
||||
new GenericLinkHandler(),
|
||||
new PastebinHandler(),
|
||||
};
|
||||
private static readonly IArchiveHandler[] archiveHandlers =
|
||||
private static readonly IArchiveHandler[] ArchiveHandlers =
|
||||
{
|
||||
new GzipHandler(),
|
||||
new ZipHandler(),
|
||||
@@ -49,9 +49,7 @@ namespace CompatBot.EventHandlers
|
||||
|
||||
private static readonly SemaphoreSlim QueueLimiter = new(Math.Max(1, Environment.ProcessorCount / 2), Math.Max(1, Environment.ProcessorCount / 2));
|
||||
private delegate void OnLog(DiscordClient client, DiscordChannel channel, DiscordMessage message, DiscordMember? requester = null, bool checkExternalLinks = false, bool force = false);
|
||||
private static event OnLog OnNewLog;
|
||||
|
||||
static LogParsingHandler() => OnNewLog += EnqueueLogProcessing;
|
||||
private static event OnLog OnNewLog = EnqueueLogProcessing;
|
||||
|
||||
public static Task OnMessageCreated(DiscordClient c, MessageCreateEventArgs args)
|
||||
{
|
||||
@@ -89,7 +87,7 @@ namespace CompatBot.EventHandlers
|
||||
DiscordMessage? botMsg = null;
|
||||
try
|
||||
{
|
||||
var possibleHandlers = sourceHandlers.Select(h => h.FindHandlerAsync(message, archiveHandlers).ConfigureAwait(false).GetAwaiter().GetResult()).ToList();
|
||||
var possibleHandlers = SourceHandlers.Select(h => h.FindHandlerAsync(message, ArchiveHandlers).ConfigureAwait(false).GetAwaiter().GetResult()).ToList();
|
||||
var source = possibleHandlers.FirstOrDefault(h => h.source != null).source;
|
||||
var fail = possibleHandlers.FirstOrDefault(h => !string.IsNullOrEmpty(h.failReason)).failReason;
|
||||
|
||||
@@ -280,7 +278,7 @@ namespace CompatBot.EventHandlers
|
||||
var linkStart = message.Content.IndexOf("http", StringComparison.Ordinal);
|
||||
if (linkStart > -1)
|
||||
{
|
||||
var link = message.Content[linkStart..].Split(linkSeparator, 2)[0];
|
||||
var link = message.Content[linkStart..].Split(LinkSeparator, 2)[0];
|
||||
if (link.Contains(".log", StringComparison.InvariantCultureIgnoreCase) || link.Contains("rpcs3.zip", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
await channel.SendMessageAsync("If you intended to upload a log file please re-upload it directly to discord").ConfigureAwait(false);
|
||||
|
||||
@@ -13,7 +13,6 @@ using CompatBot.Utils;
|
||||
using CompatBot.Utils.Extensions;
|
||||
using DSharpPlus;
|
||||
using DSharpPlus.EventArgs;
|
||||
using DSharpPlus.Interactivity;
|
||||
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision;
|
||||
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
|
||||
|
||||
@@ -25,7 +24,7 @@ namespace CompatBot.EventHandlers
|
||||
private readonly ComputerVisionClient cvClient = new(new ApiKeyServiceClientCredentials(Config.AzureComputerVisionKey)) {Endpoint = Config.AzureComputerVisionEndpoint};
|
||||
private readonly SemaphoreSlim workSemaphore = new(0);
|
||||
private readonly ConcurrentQueue<(MessageCreateEventArgs evt, Guid readOperationId)> workQueue = new ConcurrentQueue<(MessageCreateEventArgs args, Guid readOperationId)>();
|
||||
public static int MaxQueueLength { get; private set; } = 0;
|
||||
public static int MaxQueueLength { get; private set; }
|
||||
|
||||
internal MediaScreenshotMonitor(DiscordClient client)
|
||||
{
|
||||
|
||||
@@ -191,7 +191,7 @@ namespace CompatBot.EventHandlers
|
||||
|
||||
private static async Task BadUpdateAsync(DiscordClient client, DiscordUser user, DiscordMessage message, DiscordEmoji emoji)
|
||||
{
|
||||
if (message?.Channel.Id != Config.BotChannelId)
|
||||
if (message.Channel.Id != Config.BotChannelId)
|
||||
return;
|
||||
|
||||
if (!user.IsSmartlisted(client, message.Channel.Guild))
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Threading.Tasks;
|
||||
using CompatApiClient.Utils;
|
||||
using CompatBot.Utils;
|
||||
using DSharpPlus;
|
||||
using DSharpPlus.Entities;
|
||||
using DSharpPlus.EventArgs;
|
||||
|
||||
namespace CompatBot.EventHandlers
|
||||
@@ -38,9 +37,9 @@ namespace CompatBot.EventHandlers
|
||||
content.Contains("┻━┻")))
|
||||
return;
|
||||
|
||||
var tableIdx = content.IndexOf("┻━┻");
|
||||
var tableIdx = content.IndexOf("┻━┻", StringComparison.Ordinal);
|
||||
if (tableIdx < 0)
|
||||
tableIdx = content.IndexOf("┻━┻");
|
||||
tableIdx = content.IndexOf("┻━┻", StringComparison.Ordinal);
|
||||
var faceIdx = content[..tableIdx].LastIndexOfAny(OpenParen);
|
||||
var face = content[faceIdx..tableIdx];
|
||||
if (face.Length > 30)
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CompatApiClient.Utils;
|
||||
using CompatBot.Utils;
|
||||
using CompatBot.Utils.Extensions;
|
||||
using DSharpPlus;
|
||||
using DSharpPlus.Entities;
|
||||
using DSharpPlus.EventArgs;
|
||||
@@ -34,7 +33,7 @@ namespace CompatBot.EventHandlers
|
||||
if (!potentialTargets.Any())
|
||||
return;
|
||||
|
||||
if (await IsFlashmobAsync(c, potentialTargets).ConfigureAwait(false))
|
||||
if (await IsFlashMobAsync(c, potentialTargets).ConfigureAwait(false))
|
||||
return;
|
||||
|
||||
await c.ReportAsync("🕵️ Potential user impersonation",
|
||||
@@ -54,7 +53,7 @@ namespace CompatBot.EventHandlers
|
||||
if (!potentialTargets.Any())
|
||||
return;
|
||||
|
||||
if (await IsFlashmobAsync(c, potentialTargets).ConfigureAwait(false))
|
||||
if (await IsFlashMobAsync(c, potentialTargets).ConfigureAwait(false))
|
||||
return;
|
||||
|
||||
await c.ReportAsync("🕵️ Potential user impersonation",
|
||||
@@ -71,7 +70,7 @@ namespace CompatBot.EventHandlers
|
||||
if (!potentialTargets.Any())
|
||||
return;
|
||||
|
||||
if (await IsFlashmobAsync(c, potentialTargets).ConfigureAwait(false))
|
||||
if (await IsFlashMobAsync(c, potentialTargets).ConfigureAwait(false))
|
||||
return;
|
||||
|
||||
await c.ReportAsync("🕵️ Potential user impersonation",
|
||||
@@ -99,30 +98,32 @@ namespace CompatBot.EventHandlers
|
||||
return potentialTargets;
|
||||
}
|
||||
|
||||
private static async Task<bool> IsFlashmobAsync(DiscordClient client, List<DiscordMember> potentialVictims)
|
||||
private static async Task<bool> IsFlashMobAsync(DiscordClient client, List<DiscordMember> potentialVictims)
|
||||
{
|
||||
if (potentialVictims?.Count > 0)
|
||||
try
|
||||
if (potentialVictims.Count == 0)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
var displayName = GetCanonical(potentialVictims[0].DisplayName);
|
||||
if (SpoofingReportThrottlingCache.TryGetValue(displayName, out string s) && !string.IsNullOrEmpty(s))
|
||||
{
|
||||
var displayName = GetCanonical(potentialVictims[0].DisplayName);
|
||||
if (SpoofingReportThrottlingCache.TryGetValue(displayName, out string s) && !string.IsNullOrEmpty(s))
|
||||
{
|
||||
SpoofingReportThrottlingCache.Set(displayName, s, SnoozeDuration);
|
||||
return true;
|
||||
}
|
||||
SpoofingReportThrottlingCache.Set(displayName, s, SnoozeDuration);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (potentialVictims.Count > 3)
|
||||
{
|
||||
SpoofingReportThrottlingCache.Set(displayName, "y", SnoozeDuration);
|
||||
var channel = await client.GetChannelAsync(Config.BotLogId).ConfigureAwait(false);
|
||||
await channel.SendMessageAsync($"`{displayName.Sanitize()}` is a popular member! Snoozing notifications for an hour").ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
if (potentialVictims.Count > 3)
|
||||
{
|
||||
Config.Log.Debug(e);
|
||||
SpoofingReportThrottlingCache.Set(displayName, "y", SnoozeDuration);
|
||||
var channel = await client.GetChannelAsync(Config.BotLogId).ConfigureAwait(false);
|
||||
await channel.SendMessageAsync($"`{displayName.Sanitize()}` is a popular member! Snoozing notifications for an hour").ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Config.Log.Debug(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace CompatBot
|
||||
private static readonly SemaphoreSlim InstanceCheck = new(0, 1);
|
||||
private static readonly SemaphoreSlim ShutdownCheck = new(0, 1);
|
||||
// pre-load the assembly so it won't fail after framework update while the process is still running
|
||||
private static readonly Assembly diagnosticsAssembly = Assembly.Load(typeof(Process).Assembly.GetName());
|
||||
private static readonly Assembly DiagnosticsAssembly = Assembly.Load(typeof(Process).Assembly.GetName());
|
||||
internal const ulong InvalidChannelId = 13;
|
||||
|
||||
internal static async Task Main(string[] args)
|
||||
@@ -239,7 +239,7 @@ namespace CompatBot
|
||||
client.MessageReactionAdded += Starbucks.Handler;
|
||||
client.MessageReactionAdded += ContentFilterMonitor.OnReaction;
|
||||
|
||||
client.MessageCreated += (_, __) => { Watchdog.TimeSinceLastIncomingMessage.Restart(); return Task.CompletedTask;};
|
||||
client.MessageCreated += (_, _) => { Watchdog.TimeSinceLastIncomingMessage.Restart(); return Task.CompletedTask;};
|
||||
client.MessageCreated += ContentFilterMonitor.OnMessageCreated; // should be first
|
||||
client.MessageCreated += GlobalMessageCache.OnMessageCreated;
|
||||
var mediaScreenshotMonitor = new MediaScreenshotMonitor(client);
|
||||
@@ -355,7 +355,7 @@ namespace CompatBot
|
||||
{
|
||||
if (client.Ping > 1000)
|
||||
Config.Log.Warn($"High ping detected: {client.Ping}");
|
||||
await Task.Delay(TimeSpan.FromMinutes(1), Config.Cts.Token).ContinueWith(dt => {/* in case it was cancelled */}, TaskScheduler.Default).ConfigureAwait(false);
|
||||
await Task.Delay(TimeSpan.FromMinutes(1), Config.Cts.Token).ContinueWith(_ => {/* in case it was cancelled */}, TaskScheduler.Default).ConfigureAwait(false);
|
||||
}
|
||||
await backgroundTasks.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace CompatBot.ThumbScrapper
|
||||
private static readonly PsnClient.Client Client = new();
|
||||
public static readonly Regex ContentIdMatcher = new(@"(?<content_id>(?<service_id>(?<service_letters>\w\w)(?<service_number>\d{4}))-(?<product_id>(?<product_letters>\w{4})(?<product_number>\d{5}))_(?<part>\d\d)-(?<label>\w{16}))", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.ExplicitCapture);
|
||||
private static readonly SemaphoreSlim LockObj = new(1, 1);
|
||||
private static List<string> PsnStores = new();
|
||||
private static DateTime StoreRefreshTimestamp = DateTime.MinValue;
|
||||
private static List<string> psnStores = new();
|
||||
private static DateTime storeRefreshTimestamp = DateTime.MinValue;
|
||||
private static readonly SemaphoreSlim QueueLimiter = new(32, 32);
|
||||
|
||||
public static async Task RunAsync(CancellationToken cancellationToken)
|
||||
@@ -63,7 +63,7 @@ namespace CompatBot.ThumbScrapper
|
||||
await LockObj.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
storesToScrape = new List<string>(PsnStores);
|
||||
storesToScrape = new List<string>(psnStores);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -96,18 +96,18 @@ namespace CompatBot.ThumbScrapper
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ScrapeStateProvider.IsFresh(StoreRefreshTimestamp))
|
||||
if (ScrapeStateProvider.IsFresh(storeRefreshTimestamp))
|
||||
return;
|
||||
|
||||
var result = GetLocalesInPreferredOrder(PsnClient.Client.GetLocales());
|
||||
await LockObj.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (ScrapeStateProvider.IsFresh(StoreRefreshTimestamp))
|
||||
if (ScrapeStateProvider.IsFresh(storeRefreshTimestamp))
|
||||
return;
|
||||
|
||||
PsnStores = result;
|
||||
StoreRefreshTimestamp = DateTime.UtcNow;
|
||||
psnStores = result;
|
||||
storeRefreshTimestamp = DateTime.UtcNow;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -126,7 +126,7 @@ namespace CompatBot.ThumbScrapper
|
||||
await LockObj.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
storesToScrape = new List<string>(PsnStores);
|
||||
storesToScrape = new List<string>(psnStores);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace CompatBot.Utils.Extensions
|
||||
{
|
||||
internal static class Converters
|
||||
{
|
||||
private static readonly ColorSpaceConverter colorSpaceConverter = new();
|
||||
private static readonly ColorSpaceConverter ColorSpaceConverter = new();
|
||||
|
||||
public static Color ToStandardColor(this ColorThiefDotNet.Color c)
|
||||
=> new Rgba32(c.R, c.G, c.B, c.A);
|
||||
@@ -33,10 +33,10 @@ namespace CompatBot.Utils.Extensions
|
||||
}
|
||||
if (!preserveOpacity)
|
||||
a = Math.Max(a, (byte)127); //We don't want contrast color to be more than 50% transparent ever.
|
||||
var hsb = colorSpaceConverter.ToHsv(new Rgb24(c.R, c.G, c.B));
|
||||
var hsb = ColorSpaceConverter.ToHsv(new Rgb24(c.R, c.G, c.B));
|
||||
var h = hsb.H;
|
||||
h = h < 180 ? h + 180 : h - 180;
|
||||
var r = colorSpaceConverter.ToRgb(new Hsv(h, hsb.S, hsb.V));
|
||||
var r = ColorSpaceConverter.ToRgb(new Hsv(h, hsb.S, hsb.V));
|
||||
return new Rgba32(r.R, r.G, r.B, a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ namespace CompatBot.Utils
|
||||
|
||||
private static (long, int) GetFuzzyCacheKey(string strA, string strB)
|
||||
{
|
||||
var hashPair = (((long) (strA.GetHashCode())) << (sizeof(int) * 8)) | (((long) strB.GetHashCode()) & ((long) uint.MaxValue));
|
||||
var hashPair = (((long)strA.GetHashCode()) << (sizeof(int) * 8)) | (strB.GetHashCode() & uint.MaxValue);
|
||||
var lengthPair = (strA.Length << (sizeof(short) * 8)) | (strB.Length & ushort.MaxValue);
|
||||
return (hashPair, lengthPair);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace CompatBot.Utils
|
||||
@@ -9,7 +8,7 @@ namespace CompatBot.Utils
|
||||
internal class FixedLengthBuffer<TKey, TValue>: IList<TValue>
|
||||
where TKey: notnull
|
||||
{
|
||||
internal readonly object syncObj = new();
|
||||
internal readonly object SyncObj = new();
|
||||
|
||||
public FixedLengthBuffer(Func<TValue, TKey> keyGenerator)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
internal static class FwInfoFormatter
|
||||
{
|
||||
//2019_0828_c975768e5d70e105a72656f498cc9be9/PS3UPDAT.PUP
|
||||
private static readonly Regex fwLinkInfo = new(@"(?<year>\d{4})_(?<month>\d\d)(?<day>\d\d)_(?<md5>[0-9a-f]+)",
|
||||
private static readonly Regex FwLinkInfo = new(@"(?<year>\d{4})_(?<month>\d\d)(?<day>\d\d)_(?<md5>[0-9a-f]+)",
|
||||
RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.Singleline | RegexOptions.IgnoreCase);
|
||||
private static readonly Dictionary<string, string> RegionToFlagMap = new(StringComparer.InvariantCultureIgnoreCase)
|
||||
{
|
||||
@@ -36,32 +36,28 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
.WithTitle("PS3 Firmware Information")
|
||||
.WithColor(Config.Colors.DownloadLinks);
|
||||
|
||||
if (fwInfoList?.Count > 0)
|
||||
if (fwInfoList.Count > 0
|
||||
&& fwInfoList.Select(fwi => FwLinkInfo.Match(fwi.DownloadUrl)).FirstOrDefault(m => m.Success) is Match info)
|
||||
{
|
||||
var info = fwInfoList.Select(fwi => fwLinkInfo.Match(fwi.DownloadUrl)).FirstOrDefault(m => m.Success);
|
||||
if (info != null)
|
||||
result.Description = $"Latest version is **{fwInfoList[0].Version}** released on {info.Groups["year"].Value}-{info.Groups["month"].Value}-{info.Groups["day"].Value}\n" +
|
||||
$"It is available in {fwInfoList.Count} region{(fwInfoList.Count == 1 ? "" : "s")} out of {RegionToFlagMap.Count}";
|
||||
result.AddField("Checksums", $"MD5: `{info.Groups["md5"].Value}`\n" +
|
||||
"You can use [HashCheck](https://github.com/gurnec/HashCheck/releases/latest) to verify your download");
|
||||
var links = new StringBuilder();
|
||||
foreach (var fwi in fwInfoList)
|
||||
{
|
||||
result.Description = $"Latest version is **{fwInfoList[0].Version}** released on {info.Groups["year"].Value}-{info.Groups["month"].Value}-{info.Groups["day"].Value}\n" +
|
||||
$"It is available in {fwInfoList.Count} region{(fwInfoList.Count == 1 ? "" : "s")} out of {RegionToFlagMap.Count}";
|
||||
result.AddField("Checksums", $"MD5: `{info.Groups["md5"].Value}`\n" +
|
||||
"You can use [HashCheck](https://github.com/gurnec/HashCheck/releases/latest) to verify your download");
|
||||
var links = new StringBuilder();
|
||||
foreach (var fwi in fwInfoList)
|
||||
{
|
||||
var newLink = $"[{RegionToFlagMap[fwi.Locale]}]({fwi.DownloadUrl}) ";
|
||||
if (links.Length + newLink.Length > EmbedPager.MaxFieldLength)
|
||||
break;
|
||||
var newLink = $"[{RegionToFlagMap[fwi.Locale]}]({fwi.DownloadUrl}) ";
|
||||
if (links.Length + newLink.Length > EmbedPager.MaxFieldLength)
|
||||
break;
|
||||
|
||||
links.Append(newLink);
|
||||
}
|
||||
result.AddField("System Software License Agreement", "You **must** read and agree with the terms described [here](https://doc.dl.playstation.net/doc/ps3-eula/) before downloading");
|
||||
result.AddField("Download Links", links.ToString().TrimEnd());
|
||||
return result.WithFooter("Every region has identical firmware content");
|
||||
links.Append(newLink);
|
||||
}
|
||||
result.AddField("System Software License Agreement", "You **must** read and agree with the terms described [here](https://doc.dl.playstation.net/doc/ps3-eula/) before downloading");
|
||||
result.AddField("Download Links", links.ToString().TrimEnd());
|
||||
return result.WithFooter("Every region has identical firmware content");
|
||||
}
|
||||
|
||||
return result
|
||||
.WithColor(Config.Colors.CompatStatusUnknown);
|
||||
return result.WithColor(Config.Colors.CompatStatusUnknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
{
|
||||
internal static partial class LogParserResult
|
||||
{
|
||||
private static readonly Version decompilerIssueStartVersion = new(0, 0, 9, 10307);
|
||||
private static readonly Version decompilerIssueEndVersion = new(0, 0, 10, 10346);
|
||||
private static readonly Version DecompilerIssueStartVersion = new(0, 0, 9, 10307);
|
||||
private static readonly Version DecompilerIssueEndVersion = new(0, 0, 10, 10346);
|
||||
|
||||
private static async Task BuildNotesSectionAsync(DiscordEmbedBuilder builder, LogParseState state, DiscordClient discordClient)
|
||||
{
|
||||
@@ -94,8 +94,8 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
{
|
||||
if (items["build_branch"]?.ToLowerInvariant() == "head"
|
||||
&& Version.TryParse(items["build_full_version"], out var v)
|
||||
&& v >= decompilerIssueStartVersion
|
||||
&& v < decompilerIssueEndVersion)
|
||||
&& v >= DecompilerIssueStartVersion
|
||||
&& v < DecompilerIssueEndVersion)
|
||||
{
|
||||
knownFatal = true;
|
||||
notes.Add("❌ This RPCS3 build has a known regression, please update to the latest version");
|
||||
@@ -591,7 +591,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
|
||||
builder.AddField("Missing Licenses", content);
|
||||
|
||||
var gameRegion = serial?.Length > 3 ? new[] {serial[2]} : Enumerable.Empty<char>();
|
||||
var gameRegion = serial.Length > 3 ? new[] {serial[2]} : Enumerable.Empty<char>();
|
||||
var dlcRegions = licenseNames
|
||||
.Where(l => l.Length > 9)
|
||||
.Select(n => n[9])
|
||||
@@ -629,7 +629,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
HashSet<string> knownFiles;
|
||||
try
|
||||
{
|
||||
var irdFiles = await irdClient.DownloadAsync(productCode, Config.IrdCachePath, Config.Cts.Token).ConfigureAwait(false);
|
||||
var irdFiles = await IrdClient.DownloadAsync(productCode, Config.IrdCachePath, Config.Cts.Token).ConfigureAwait(false);
|
||||
knownFiles = new HashSet<string>(
|
||||
from ird in irdFiles
|
||||
from name in ird.GetFilenames()
|
||||
|
||||
@@ -348,9 +348,9 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
CheckDesSettings(serial, items, notes, ppuPatches, ppuHashes, generalNotes);
|
||||
CheckTlouSettings(serial, items, notes, ppuPatches, patchNames);
|
||||
CheckRdrSettings(serial, items, notes);
|
||||
CheckMgs4Settings(serial, items, notes, generalNotes);
|
||||
CheckMgs4Settings(serial, items, generalNotes);
|
||||
CheckProjectDivaSettings(serial, items, notes, ppuPatches, ppuHashes, generalNotes);
|
||||
CheckGt5Settings(serial, items, notes, generalNotes);
|
||||
CheckGt5Settings(serial, items, generalNotes);
|
||||
CheckGt6Settings(serial, items, notes, generalNotes);
|
||||
CheckSly4Settings(serial, items, notes);
|
||||
CheckDragonsCrownSettings(serial, items, notes);
|
||||
@@ -958,7 +958,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
"NPHB00065", "NPHB00067",
|
||||
};
|
||||
|
||||
private static void CheckMgs4Settings(string serial, NameValueCollection items, List<string> _, List<string> generalNotes)
|
||||
private static void CheckMgs4Settings(string serial, NameValueCollection items, List<string> generalNotes)
|
||||
{
|
||||
if (!Mgs4Ids.Contains(serial))
|
||||
return;
|
||||
@@ -1032,7 +1032,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
"BCUS98114", "BCUS98272", "BCUS98394",
|
||||
};
|
||||
|
||||
private static void CheckGt5Settings(string serial, NameValueCollection items, List<string> _, List<string> generalNotes)
|
||||
private static void CheckGt5Settings(string serial, NameValueCollection items, List<string> generalNotes)
|
||||
{
|
||||
if (!Gt5Ids.Contains(serial))
|
||||
return;
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
{
|
||||
internal static partial class LogParserResult
|
||||
{
|
||||
private static readonly Client compatClient = new();
|
||||
private static readonly IrdClient irdClient = new();
|
||||
private static readonly PsnClient.Client psnClient = new();
|
||||
private static readonly Client CompatClient = new();
|
||||
private static readonly IrdClient IrdClient = new();
|
||||
private static readonly PsnClient.Client PsnClient = new();
|
||||
|
||||
private static readonly RegexOptions DefaultSingleLine = RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.Singleline;
|
||||
// RPCS3 v0.0.3-3-3499d08 Alpha | HEAD
|
||||
@@ -246,7 +246,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
collection["serial"] = psnSerial;
|
||||
collection["game_category"] = "HG";
|
||||
}
|
||||
var titleUpdateInfoTask = psnClient.GetTitleUpdatesAsync(collection["serial"], Config.Cts.Token);
|
||||
var titleUpdateInfoTask = PsnClient.GetTitleUpdatesAsync(collection["serial"], Config.Cts.Token);
|
||||
var gameInfo = await client.LookupGameInfoAsync(collection["serial"], collection["game_title"], true, category: collection["game_category"]).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
@@ -476,9 +476,9 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
var currentBuildCommit = items["build_commit"];
|
||||
if (string.IsNullOrEmpty(currentBuildCommit))
|
||||
currentBuildCommit = null;
|
||||
var updateInfo = await compatClient.GetUpdateAsync(Config.Cts.Token, currentBuildCommit).ConfigureAwait(false);
|
||||
var updateInfo = await CompatClient.GetUpdateAsync(Config.Cts.Token, currentBuildCommit).ConfigureAwait(false);
|
||||
if (updateInfo?.ReturnCode != 1 && currentBuildCommit != null)
|
||||
updateInfo = await compatClient.GetUpdateAsync(Config.Cts.Token).ConfigureAwait(false);
|
||||
updateInfo = await CompatClient.GetUpdateAsync(Config.Cts.Token).ConfigureAwait(false);
|
||||
var link = updateInfo?.LatestBuild?.Windows?.Download ?? updateInfo?.LatestBuild?.Linux?.Download;
|
||||
if (string.IsNullOrEmpty(link))
|
||||
return null;
|
||||
@@ -795,14 +795,6 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
return result;
|
||||
}
|
||||
|
||||
private static HashSet<string> GetHashes(string hashList)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hashList))
|
||||
return new HashSet<string>(0, StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
return new HashSet<string>(hashList.Split(Environment.NewLine), StringComparer.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
internal static DiscordEmbedBuilder AddAuthor(this DiscordEmbedBuilder builder, DiscordClient client, DiscordMessage? message, ISource source, LogParseState? state = null)
|
||||
{
|
||||
if (message == null || state?.Error == LogParseState.ErrorCode.PiracyDetected)
|
||||
@@ -815,14 +807,14 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
msg = $"Log from {author.Username.Sanitize()} | {author.Id}\n";
|
||||
else
|
||||
msg = $"Log from {member.DisplayName.Sanitize()} | {member.Id}\n";
|
||||
msg += " | " + (source?.SourceType ?? "Unknown source");
|
||||
if (state?.ReadBytes > 0 && source?.LogFileSize > 0 && source.LogFileSize < 2L*1024*1024*1024 && state.ReadBytes <= source.LogFileSize)
|
||||
msg += " | " + source.SourceType;
|
||||
if (state?.ReadBytes > 0 && source.LogFileSize > 0 && source.LogFileSize < 2L*1024*1024*1024 && state.ReadBytes <= source.LogFileSize)
|
||||
msg += $" | Parsed {state.ReadBytes * 100.0 / source.LogFileSize:0.##}%";
|
||||
else if (source?.SourceFilePosition > 0 && source.SourceFileSize > 0 && source.SourceFilePosition <= source.SourceFileSize)
|
||||
else if (source.SourceFilePosition > 0 && source.SourceFileSize > 0 && source.SourceFilePosition <= source.SourceFileSize)
|
||||
msg += $" | Read {source.SourceFilePosition * 100.0 / source.SourceFileSize:0.##}%";
|
||||
else if (state?.ReadBytes > 0)
|
||||
msg += $" | Parsed {state.ReadBytes} byte{(state.ReadBytes == 1 ? "" : "s")}";
|
||||
else if (source?.LogFileSize > 0)
|
||||
else if (source.LogFileSize > 0)
|
||||
msg += $" | {source.LogFileSize} byte{(source.LogFileSize == 1 ? "" : "s")}";
|
||||
#if DEBUG
|
||||
if (state?.ParsingTime.TotalMilliseconds > 0)
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
{
|
||||
internal static class UpdateInfoFormatter
|
||||
{
|
||||
private static readonly GithubClient.Client githubClient = new();
|
||||
private static readonly GithubClient.Client GithubClient = new();
|
||||
|
||||
public static async Task<DiscordEmbedBuilder> AsEmbedAsync(this UpdateInfo? info, DiscordClient client, bool includePrBody = false, DiscordEmbedBuilder? builder = null, PrInfo? currentPrInfo = null)
|
||||
{
|
||||
@@ -35,7 +35,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
{
|
||||
if (latestPr > 0)
|
||||
{
|
||||
latestPrInfo = await githubClient.GetPrInfoAsync(latestPr.Value, Config.Cts.Token).ConfigureAwait(false);
|
||||
latestPrInfo = await GithubClient.GetPrInfoAsync(latestPr.Value, Config.Cts.Token).ConfigureAwait(false);
|
||||
url = latestPrInfo?.HtmlUrl ?? "https://github.com/RPCS3/rpcs3/pull/" + latestPr;
|
||||
var userName = latestPrInfo?.User?.Login ?? "???";
|
||||
if (GetUserNameEmoji(client, userName) is DiscordEmoji emoji)
|
||||
@@ -46,7 +46,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
prDesc = "PR #???";
|
||||
|
||||
if (currentPr > 0 && currentPr != latestPr)
|
||||
currentPrInfo ??= await githubClient.GetPrInfoAsync(currentPr.Value, Config.Cts.Token).ConfigureAwait(false);
|
||||
currentPrInfo ??= await GithubClient.GetPrInfoAsync(currentPr.Value, Config.Cts.Token).ConfigureAwait(false);
|
||||
}
|
||||
var desc = latestPrInfo?.Title;
|
||||
if (includePrBody
|
||||
@@ -61,7 +61,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
var uniqueLinks = new HashSet<string>(10);
|
||||
foreach (Match m in issueMatches)
|
||||
{
|
||||
if (m.Groups["issue_mention"]?.Value is string str
|
||||
if (m.Groups["issue_mention"].Value is string str
|
||||
&& !string.IsNullOrEmpty(str)
|
||||
&& uniqueLinks.Add(str))
|
||||
{
|
||||
@@ -165,7 +165,7 @@ namespace CompatBot.Utils.ResultFormatters
|
||||
if (string.IsNullOrEmpty(link))
|
||||
return "No link available";
|
||||
|
||||
var text = new Uri(link).Segments?.Last() ?? "";
|
||||
var text = new Uri(link).Segments.Last();
|
||||
if (simpleName && text.StartsWith("rpcs3-"))
|
||||
text = text[6..];
|
||||
if (simpleName && text.Contains('_'))
|
||||
|
||||
@@ -38,9 +38,11 @@ namespace CompatBot.Utils
|
||||
if (uniqueNames.Contains(tzi.StandardName) || uniqueNames.Contains(tzi.DaylightName) || uniqueNames.Contains(tzi.Id))
|
||||
{
|
||||
Config.Log.Trace("[TZI] Looks like it's a match!");
|
||||
var acronyms = from tza in TimeZoneAcronyms
|
||||
var acronyms = (
|
||||
from tza in TimeZoneAcronyms
|
||||
where tza.Value.Contains(tzi.StandardName) || tza.Value.Contains(tzi.DaylightName) || tza.Value.Contains(tzi.Id)
|
||||
select tza.Key;
|
||||
select tza.Key
|
||||
).ToList();
|
||||
Config.Log.Trace("[TZI] Matched acronyms: " + string.Join(", ", acronyms));
|
||||
foreach (var tza in acronyms)
|
||||
result[tza] = tzi;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime;
|
||||
using System.Threading.Tasks;
|
||||
using CompatBot.Commands;
|
||||
using CompatBot.Database.Providers;
|
||||
@@ -19,7 +18,7 @@ namespace CompatBot
|
||||
public static readonly ConcurrentQueue<DateTime> DisconnectTimestamps = new();
|
||||
public static readonly Stopwatch TimeSinceLastIncomingMessage = Stopwatch.StartNew();
|
||||
private static bool IsOk => DisconnectTimestamps.IsEmpty && TimeSinceLastIncomingMessage.Elapsed < Config.IncomingMessageCheckIntervalInMin;
|
||||
private static DiscordClient? discordClient = null;
|
||||
private static DiscordClient? discordClient;
|
||||
|
||||
public static async Task Watch(DiscordClient client)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Tests
|
||||
[TestFixture]
|
||||
public class LogParsingProfiler
|
||||
{
|
||||
private static readonly IArchiveHandler[] archiveHandlers =
|
||||
private static readonly IArchiveHandler[] ArchiveHandlers =
|
||||
{
|
||||
new GzipHandler(),
|
||||
new ZipHandler(),
|
||||
@@ -37,7 +37,7 @@ namespace Tests
|
||||
Config.RebuildConfiguration();
|
||||
var timer = Stopwatch.StartNew();
|
||||
var cts = new CancellationTokenSource();
|
||||
var source = await FileSource.DetectArchiveHandlerAsync(path, archiveHandlers).ConfigureAwait(false);
|
||||
var source = await FileSource.DetectArchiveHandlerAsync(path, ArchiveHandlers).ConfigureAwait(false);
|
||||
var pipe = new Pipe();
|
||||
var fillPipeTask = source.FillPipeAsync(pipe.Writer, cts.Token);
|
||||
var readPipeTask = LogParser.ReadPipeAsync(pipe.Reader, cts.Token);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=6D9CA448_002D60C1_002D4D66_002D91D6_002DEC6C586508E6_002Fd_003ADatabase_002Fd_003AMigrations/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ASMJIT/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=blit/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Confusables/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
Reference in New Issue
Block a user