private static async void SpoofingCheck(CommandContext ctx) { if (!CheckLock.Wait(0)) { await ctx.Channel.SendMessageAsync("Another check is already in progress").ConfigureAwait(false); return; } try { await ctx.ReactWithAsync(Config.Reactions.PleaseWait).ConfigureAwait(false); var members = GetMembers(ctx.Client); if (members.Count < 2) { return; } var result = new StringBuilder("List of potential impersonators → victims:").AppendLine(); var headerLength = result.Length; var checkedMembers = new List <DiscordMember>(members.Count) { members[0] }; for (var i = 1; i < members.Count; i++) { var member = members[i]; var victims = UsernameSpoofMonitor.GetPotentialVictims(ctx.Client, member, true, true, checkedMembers); if (victims.Any()) { result.Append(member.GetMentionWithNickname()).Append(" → ").AppendLine(string.Join(", ", victims.Select(m => m.GetMentionWithNickname()))); } checkedMembers.Add(member); } await using var compressedStream = Config.MemoryStreamManager.GetStream(); await using var uncompressedStream = Config.MemoryStreamManager.GetStream(); await using (var writer = new StreamWriter(uncompressedStream, new UTF8Encoding(false), 4096, true)) { await writer.WriteAsync(result.ToString()).ConfigureAwait(false); await writer.FlushAsync().ConfigureAwait(false); } uncompressedStream.Seek(0, SeekOrigin.Begin); if (result.Length <= headerLength) { await ctx.Channel.SendMessageAsync("No potential name spoofing was detected").ConfigureAwait(false); return; } if (uncompressedStream.Length <= Config.AttachmentSizeLimit) { await ctx.Channel.SendMessageAsync(new DiscordMessageBuilder().WithFile("spoofing_check_results.txt", uncompressedStream)).ConfigureAwait(false); return; } await using (var gzip = new GZipStream(compressedStream, CompressionLevel.Optimal, true)) { await uncompressedStream.CopyToAsync(gzip).ConfigureAwait(false); gzip.Flush(); } compressedStream.Seek(0, SeekOrigin.Begin); if (compressedStream.Length <= Config.AttachmentSizeLimit) { await ctx.Channel.SendMessageAsync(new DiscordMessageBuilder().WithFile("spoofing_check_results.txt.gz", compressedStream)).ConfigureAwait(false); } else { await ctx.Channel.SendMessageAsync($"Dump is too large: {compressedStream.Length} bytes").ConfigureAwait(false); } } catch (Exception e) { Config.Log.Error(e); //should be extra careful, as async void will run on a thread pull, and will terminate the whole application with an uncaught exception try { await ctx.ReactWithAsync(Config.Reactions.Failure, "(X_X)").ConfigureAwait(false); } catch { } } finally { CheckLock.Release(); await ctx.RemoveReactionAsync(Config.Reactions.PleaseWait).ConfigureAwait(false); } }