better downgrader support, support manual Mega downloads

This commit is contained in:
Timothy Baldridge 2022-01-31 23:07:23 -07:00
parent 4d8ab94456
commit a84394ad6b
6 changed files with 159 additions and 4 deletions

View File

@ -0,0 +1,41 @@
using System.Linq;
using System.Threading.Tasks;
using F23.StringSimilarity;
using Wabbajack.Common;
using Wabbajack.Lib.Downloaders;
namespace Wabbajack.Lib.CompilationSteps
{
public class PatchStockGameFiles : ACompilationStep
{
private readonly Task<ILookup<Hash, Archive>> _files;
private readonly Levenshtein _distFn;
public PatchStockGameFiles(ACompiler compiler) : base(compiler)
{
_distFn = new Levenshtein();
_files = Task.Run(async () => (await ClientAPI.GetGameFilesFromGithub(Game.SkyrimSpecialEdition, "1.5.97.0"))
.ToLookup(f => f.Hash));
}
public override async ValueTask<Directive?> Run(RawSourceFile source)
{
if (_compiler.CompilingGame.Game != Game.SkyrimSpecialEdition) return null;
var found = (await _files)[source.Hash];
if (!found.Any()) return null;
var srcFile = _compiler.IndexedArchives
.Where(f => f.State is GameFileSourceDownloader.State)
.OrderBy(l => _distFn.Distance(l.File.Name.FileName.ToString(), source.Path.FileName.ToString()))
.FirstOrDefault();
if (srcFile == null) return null;
var resolved = source.EvolveTo<PatchedFromArchive>();
resolved.Choices = new[] {srcFile.File};
resolved.FromHash = srcFile.File.Hash;
return resolved;
}
}
}

View File

@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using System.Linq;
using System.Reactive.Subjects;
using System.Threading;
@ -54,9 +55,17 @@ namespace Wabbajack.Lib.Downloaders
public override async Task<bool> Download(Archive a, AbsolutePath destination)
{
var (uri, client) = await Utils.Log(await ManuallyDownloadFile.Create(this)).Task;
var state = new HTTPDownloader.State(uri.ToString()) { Client = client };
return await state.Download(a, destination);
if ((new Uri(Url)).Host == "mega.nz")
{
await Utils.Log(await ManuallyDownloadMegaFile.Create(this, destination)).Task;
return true;
}
else
{
var (uri, client) = await Utils.Log(await ManuallyDownloadFile.Create(this)).Task;
var state = new HTTPDownloader.State(uri.ToString()) {Client = client};
return await state.Download(a, destination);
}
}
public override async Task<bool> Verify(Archive a, CancellationToken? token)

View File

@ -460,6 +460,7 @@ namespace Wabbajack.Lib
new IncludeRegex(this, "^[^\\\\]*\\.bat$"),
new IncludeModIniData(this),
new DirectMatch(this),
new PatchStockGameFiles(this),
new IncludeTaggedMods(this, Consts.WABBAJACK_INCLUDE),
new IncludeTaggedFolders(this, Consts.WABBAJACK_INCLUDE),
new IgnoreEndsWith(this, ".pyc"),

View File

@ -0,0 +1,43 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Wabbajack.Common;
using Wabbajack.Lib.Downloaders;
namespace Wabbajack.Lib
{
public class ManuallyDownloadMegaFile : AUserIntervention
{
public ManualDownloader.State State { get; }
public override string ShortDescription { get; } = string.Empty;
public override string ExtendedDescription { get; } = string.Empty;
private TaskCompletionSource _tcs = new();
public Task Task => _tcs.Task;
public AbsolutePath Destination { get; }
private ManuallyDownloadMegaFile(ManualDownloader.State state, AbsolutePath destination)
{
State = state;
Destination = destination;
}
public static async Task<ManuallyDownloadMegaFile> Create(ManualDownloader.State state, AbsolutePath destination)
{
var result = new ManuallyDownloadMegaFile(state, destination);
return result;
}
public override void Cancel()
{
_tcs.SetCanceled();
}
public void Resume()
{
_tcs.SetResult();
}
}
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reactive.Disposables;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@ -26,6 +27,16 @@ namespace Wabbajack.Lib.WebAutomation
_browser.LifeSpanHandler = new PopupBlocker(this);
}
public IDisposable SetDownloadHandler(IDownloadHandler handler)
{
var oldVal = _browser.DownloadHandler;
_browser.DownloadHandler = handler;
return Disposable.Create(oldVal, ov =>
{
_browser.DownloadHandler = ov;
});
}
public Task NavigateTo(Uri uri, CancellationToken? token = null)
{
var tcs = new TaskCompletionSource<bool>();

View File

@ -84,6 +84,9 @@ namespace Wabbajack
case ManuallyDownloadFile c:
await WrapBrowserJob(c, (vm, cancel) => HandleManualDownload(vm, cancel, c));
break;
case ManuallyDownloadMegaFile c:
await WrapBrowserJob(c, (vm, cancel) => HandleManualMegaDownload(vm, cancel, c));
break;
case AbstractNeedsLoginDownloader.RequestSiteLogin c:
await WrapBrowserJob(c, async (vm, cancel) =>
{
@ -187,6 +190,53 @@ namespace Wabbajack
}
}
private async Task HandleManualMegaDownload(WebBrowserVM vm, CancellationTokenSource cancel, ManuallyDownloadMegaFile manuallyDownloadFile)
{
var browser = new CefSharpWrapper(vm.Browser);
vm.Instructions = $"Please locate and download {manuallyDownloadFile.State.Url}";
await vm.Driver.WaitForInitialized();
var tcs = new TaskCompletionSource();
using var _ = browser.SetDownloadHandler(new BlobDownloadHandler(manuallyDownloadFile, tcs));
await browser.NavigateTo(new Uri(manuallyDownloadFile.State.Url));
while (!cancel.IsCancellationRequested && !tcs.Task.IsCompleted)
{
await Task.Delay(100);
}
manuallyDownloadFile.Resume();
}
private class BlobDownloadHandler : IDownloadHandler
{
private readonly ManuallyDownloadMegaFile _manualFile;
private readonly TaskCompletionSource _tcs;
public BlobDownloadHandler(ManuallyDownloadMegaFile f, TaskCompletionSource tcs)
{
_manualFile = f;
_tcs = tcs;
}
public void OnBeforeDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem,
IBeforeDownloadCallback callback)
{
callback.Continue(_manualFile.ToString(), false);
}
public void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem,
IDownloadItemCallback callback)
{
if (downloadItem.IsComplete)
{
_tcs.TrySetResult();
}
callback.Resume();
}
}
private async Task HandleManualNexusDownload(WebBrowserVM vm, CancellationTokenSource cancel, ManuallyDownloadNexusFile manuallyDownloadNexusFile)
{