implement mediafire log source handler

This commit is contained in:
13xforever
2020-11-20 03:03:40 +05:00
parent ed45c505dc
commit bcecd545f1
7 changed files with 251 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading;
using System.Threading.Tasks;
using CompatApiClient;
using CompatApiClient.Compression;
using CompatApiClient.Utils;
using System.Text.Json;
using System.Text.RegularExpressions;
using CompatApiClient.Formatters;
using MediafireClient.POCOs;
namespace MediafireClient
{
public class Client
{
private readonly HttpClient client;
private readonly HttpClient noRedirectsClient;
private readonly JsonSerializerOptions jsonOptions;
//var optSecurityToken = "1605819132.376f3d84695f46daa7b69ee67fbc5edb0a00843a8b2d5ac7d3d1b1ad8a4212b0";
private static readonly Regex SecurityTokenRegex = new(@"(var\s+optSecurityToken|name=""security"" value)\s*=\s*""(?<security_token>.+)""", RegexOptions.ExplicitCapture);
//var optDirectURL = "https://download1499.mediafire.com/12zqzob7gbfg/tmybrjpmtrpcejl/DemonsSouls_CrashLog_Nov.19th.zip";
private static readonly Regex DirectUrlRegex = new(@"(var\s+optDirectURL|href)\s*=\s*""(?<direct_link>https?://download\d+\.mediafire\.com/.+)""");
public Client()
{
client = HttpClientFactory.Create(new CompressionMessageHandler());
noRedirectsClient = HttpClientFactory.Create(new HttpClientHandler {AllowAutoRedirect = false});
jsonOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = SpecialJsonNamingPolicy.SnakeCase,
IgnoreNullValues = true,
IncludeFields = true,
};
}
public async Task<LinksResult?> GetWebLinkAsync(string quickKey, CancellationToken cancellationToken)
{
try
{
var uri = new Uri($"https://www.mediafire.com/api/1.5/file/get_links.php?quick_key={quickKey}&response_format=json");
using var message = new HttpRequestMessage(HttpMethod.Get, uri);
message.Headers.UserAgent.Add(ApiConfig.ProductInfoHeader);
using var response = await client.SendAsync(message, cancellationToken).ConfigureAwait(false);
try
{
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
return await response.Content.ReadFromJsonAsync<LinksResult>(jsonOptions, cancellationToken).ConfigureAwait(false);
}
catch (Exception e)
{
ConsoleLogger.PrintError(e, response);
}
}
catch (Exception e)
{
ApiConfig.Log.Error(e);
}
return null;
}
public async Task<Uri?> GetDirectDownloadLinkAsync(Uri webLink, CancellationToken cancellationToken)
{
try
{
using var message = new HttpRequestMessage(HttpMethod.Get, webLink);
message.Headers.UserAgent.Add(ApiConfig.ProductInfoHeader);
using var response = await client.SendAsync(message, cancellationToken).ConfigureAwait(false);
try
{
await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
var html = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
var m = DirectUrlRegex.Match(html);
if (m.Success)
return new Uri(m.Groups["direct_link"].Value);
}
catch (Exception e)
{
ConsoleLogger.PrintError(e, response);
}
}
catch (Exception e)
{
ApiConfig.Log.Error(e);
}
return null;
}
}
}

View File

@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\CompatApiClient\CompatApiClient.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,26 @@
namespace MediafireClient.POCOs
{
#nullable disable
public sealed class LinksResult
{
public LinksResponse Response;
}
public sealed class LinksResponse
{
public string Action;
public string Result;
public string CurrentApiVersion;
public Link[] Links;
}
public sealed class Link
{
public string Quickkey;
public string NormalDownload;
public string DirectDownload;
}
#nullable restore
}

View File

@@ -72,6 +72,7 @@
<ItemGroup>
<ProjectReference Include="..\Clients\CompatApiClient\CompatApiClient.csproj" />
<ProjectReference Include="..\Clients\GithubClient\GithubClient.csproj" />
<ProjectReference Include="..\Clients\MediafireClient\MediafireClient.csproj" />
<ProjectReference Include="..\Clients\OneDriveClient\OneDriveClient.csproj" />
<ProjectReference Include="..\HomoglyphConverter\HomoglyphConverter.csproj" />
<ProjectReference Include="..\Clients\IrdLibraryClient\IrdLibraryClient.csproj" />

View File

@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CompatBot.EventHandlers.LogParsing.ArchiveHandlers;
using DSharpPlus.Entities;
using CompatBot.Utils;
using System.IO.Pipelines;
using System.Net.Http;
using System.Threading;
using CompatApiClient.Utils;
using MediafireClient;
namespace CompatBot.EventHandlers.LogParsing.SourceHandlers
{
internal sealed class MediafireHandler : BaseSourceHandler
{
//http://www.mediafire.com/file/tmybrjpmtrpcejl/DemonsSouls_CrashLog_Nov.19th.zip/file
private static readonly Regex ExternalLink = new(@"(?<mediafire_link>(https?://)?(www\.)?mediafire\.com/file/(?<quick_key>[^/\s]+)/(?<filename>[^/\?\s]+)(/file)?)", DefaultOptions);
private static readonly Client Client = new();
public override async Task<(ISource? source, string? failReason)> FindHandlerAsync(DiscordMessage message, ICollection<IArchiveHandler> handlers)
{
if (string.IsNullOrEmpty(message.Content))
return (null, null);
var matches = ExternalLink.Matches(message.Content);
if (matches.Count == 0)
return (null, null);
using var client = HttpClientFactory.Create();
foreach (Match m in matches)
{
if (m.Groups["mediafire_link"].Value is string lnk
&& !string.IsNullOrEmpty(lnk)
&& Uri.TryCreate(lnk, UriKind.Absolute, out var webLink))
{
try
{
var filename = m.Groups["filename"].Value;
var filesize = -1;
var directLink = await Client.GetDirectDownloadLinkAsync(webLink, Config.Cts.Token).ConfigureAwait(false);
if (directLink is null)
return (null, null);
using (var request = new HttpRequestMessage(HttpMethod.Head, directLink))
{
using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Config.Cts.Token);
if (response.Content.Headers.ContentLength > 0)
filesize = (int)response.Content.Headers.ContentLength.Value;
if (response.Content.Headers.ContentDisposition?.FileName is string fname && !string.IsNullOrEmpty(fname))
filename = fname;
}
await using var stream = await client.GetStreamAsync(directLink).ConfigureAwait(false);
var buf = BufferPool.Rent(SnoopBufferSize);
try
{
var read = await stream.ReadBytesAsync(buf).ConfigureAwait(false);
foreach (var handler in handlers)
{
var (canHandle, reason) = handler.CanHandle(filename, filesize, buf.AsSpan(0, read));
if (canHandle)
return (new MediafireSource(directLink, handler, filename, filesize), null);
else if (!string.IsNullOrEmpty(reason))
return (null, reason);
}
}
finally
{
BufferPool.Return(buf);
}
}
catch (Exception e)
{
Config.Log.Warn(e, $"Error sniffing {m.Groups["mediafire_link"].Value}");
}
}
}
return (null, null);
}
private sealed class MediafireSource : ISource
{
private readonly Uri? uri;
private readonly IArchiveHandler handler;
public string SourceType => "Mediafire";
public string FileName { get; }
public long SourceFileSize { get; }
public long SourceFilePosition => handler.SourcePosition;
public long LogFileSize => handler.LogSize;
internal MediafireSource(Uri? uri, IArchiveHandler handler, string fileName, int fileSize)
{
this.uri = uri;
this.handler = handler;
FileName = fileName;
SourceFileSize = fileSize;
}
public async Task FillPipeAsync(PipeWriter writer, CancellationToken cancellationToken)
{
using var client = HttpClientFactory.Create();
await using var stream = await client.GetStreamAsync(uri, cancellationToken).ConfigureAwait(false);
await handler.FillPipeAsync(stream, writer, cancellationToken).ConfigureAwait(false);
}
}
}
}

View File

@@ -35,6 +35,7 @@ namespace CompatBot.EventHandlers
new DropboxHandler(),
new MegaHandler(),
new OneDriveSourceHandler(),
new MediafireHandler(),
new GenericLinkHandler(),
new PastebinHandler(),
};

View File

@@ -34,6 +34,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OneDriveClient", "Clients\OneDriveClient\OneDriveClient.csproj", "{5C4BCF33-2EC6-455F-B026-8A0001B7B7AD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediafireClient", "Clients\MediafireClient\MediafireClient.csproj", "{1F743D3D-4A87-47EF-B88D-A0DCEE1C5FB7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -71,6 +73,10 @@ Global
{5C4BCF33-2EC6-455F-B026-8A0001B7B7AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C4BCF33-2EC6-455F-B026-8A0001B7B7AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C4BCF33-2EC6-455F-B026-8A0001B7B7AD}.Release|Any CPU.Build.0 = Release|Any CPU
{1F743D3D-4A87-47EF-B88D-A0DCEE1C5FB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F743D3D-4A87-47EF-B88D-A0DCEE1C5FB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F743D3D-4A87-47EF-B88D-A0DCEE1C5FB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F743D3D-4A87-47EF-B88D-A0DCEE1C5FB7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -81,6 +87,7 @@ Global
{AA2A333B-CD30-41A5-A680-CC9BCB2D726B} = {E7FE0ADD-CBA6-4321-8A1C-0A3B5C3F54C2}
{AF8FDA29-864E-4A1C-9568-99DECB7E4B36} = {E7FE0ADD-CBA6-4321-8A1C-0A3B5C3F54C2}
{5C4BCF33-2EC6-455F-B026-8A0001B7B7AD} = {E7FE0ADD-CBA6-4321-8A1C-0A3B5C3F54C2}
{1F743D3D-4A87-47EF-B88D-A0DCEE1C5FB7} = {E7FE0ADD-CBA6-4321-8A1C-0A3B5C3F54C2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D7696F56-AEAC-4D83-9BD8-BE0C122A5DCE}