Support logs compressed with RAR

Fixes #97
This commit is contained in:
13xforever
2018-11-01 21:02:05 +05:00
parent a57c63864d
commit 601e2a7c3e
4 changed files with 94 additions and 5 deletions

6
.gitignore vendored
View File

@@ -260,9 +260,7 @@ paket-files/
__pycache__/
*.pyc
launchSettings.json
bot.db
.vscode/
thumbs.db
*.db
*.db-journal
logs/
logs/

View File

@@ -26,6 +26,7 @@
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.1.2" />
<PackageReference Include="NLog" Version="4.5.10" />
<PackageReference Include="NReco.Text.AhoCorasickDoubleArrayTrie" Version="1.0.1" />
<PackageReference Include="SharpCompress" Version="0.22.0" />
<PackageReference Include="System.IO.Pipelines" Version="4.5.2" />
</ItemGroup>

View File

@@ -0,0 +1,90 @@
using System;
using System.Buffers;
using System.IO;
using System.IO.Pipelines;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using CompatBot.Utils;
using DSharpPlus.Entities;
using SharpCompress.Archives.Rar;
namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
{
public class RarHandler: ISourceHandler
{
private static readonly ArrayPool<byte> bufferPool = ArrayPool<byte>.Create(1024, 16);
public async Task<bool> CanHandleAsync(DiscordAttachment attachment)
{
if (!attachment.FileName.EndsWith(".rar", StringComparison.InvariantCultureIgnoreCase))
return false;
try
{
using (var client = HttpClientFactory.Create())
using (var stream = await client.GetStreamAsync(attachment.Url).ConfigureAwait(false))
{
var buf = bufferPool.Rent(1024);
var read = await stream.ReadBytesAsync(buf).ConfigureAwait(false);
var firstEntry = Encoding.ASCII.GetString(new ReadOnlySpan<byte>(buf, 0, read));
var result = firstEntry.Contains(".log", StringComparison.InvariantCultureIgnoreCase);
bufferPool.Return(buf);
return result;
}
}
catch (Exception e)
{
Config.Log.Error(e, "Error sniffing the rar content");
return false;
}
}
public async Task FillPipeAsync(DiscordAttachment attachment, PipeWriter writer)
{
try
{
using (var fileStream = new FileStream(Path.GetTempFileName(), FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 16384, FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose))
{
using (var client = HttpClientFactory.Create())
using (var downloadStream = await client.GetStreamAsync(attachment.Url).ConfigureAwait(false))
await downloadStream.CopyToAsync(fileStream, 16384, Config.Cts.Token).ConfigureAwait(false);
fileStream.Seek(0, SeekOrigin.Begin);
using (var rarArchive = RarArchive.Open(fileStream))
{
using (var rarReader = rarArchive.ExtractAllEntries())
{
while (rarReader.MoveToNextEntry())
{
if (!rarReader.Entry.IsDirectory && rarReader.Entry.Key.EndsWith(".log", StringComparison.InvariantCultureIgnoreCase))
{
using (var rarStream = rarReader.OpenEntryStream())
{
int read;
FlushResult flushed;
do
{
var memory = writer.GetMemory(Config.MinimumBufferSize);
read = await rarStream.ReadAsync(memory, Config.Cts.Token);
writer.Advance(read);
flushed = await writer.FlushAsync(Config.Cts.Token).ConfigureAwait(false);
} while (read > 0 && !(flushed.IsCompleted || flushed.IsCanceled || Config.Cts.IsCancellationRequested));
}
writer.Complete();
return;
}
}
}
}
Config.Log.Warn("No rar entries that match the log criteria");
}
}
catch (Exception e)
{
Config.Log.Error(e, "Error filling the log pipe");
}
writer.Complete();
}
}
}

View File

@@ -24,6 +24,7 @@ namespace CompatBot.EventHandlers
new GzipHandler(),
new PlainTextHandler(),
new ZipHandler(),
new RarHandler(),
};
private static readonly SemaphoreSlim QueueLimiter = new SemaphoreSlim(Math.Max(1, Environment.ProcessorCount / 2), Math.Max(1, Environment.ProcessorCount / 2));
@@ -134,7 +135,6 @@ namespace CompatBot.EventHandlers
var potentialLogExtension = message.Attachments.Select(a => Path.GetExtension(a.FileName).ToUpperInvariant().TrimStart('.')).FirstOrDefault();
switch (potentialLogExtension)
{
case "RAR":
case "7Z":
{
await args.Channel.SendMessageAsync($"{message.Author.Mention} {potentialLogExtension} archive type is not supported, re-upload log compressed as **ZIP**").ConfigureAwait(false);