From 7164296cb19e6a4734eaef85bc84fc3e4cb77597 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Mon, 10 Feb 2020 16:25:24 -0700 Subject: [PATCH 1/2] Fix manual downloading and integrate it into the main app --- Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs | 7 +++++++ Wabbajack.Test/EncryptedDataTests.cs | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs create mode 100644 Wabbajack.Test/EncryptedDataTests.cs diff --git a/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs b/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs new file mode 100644 index 00000000..37faf1ad --- /dev/null +++ b/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs @@ -0,0 +1,7 @@ +namespace Wabbajack.Lib +{ + public class ManuallyDownloadFile + { + + } +} diff --git a/Wabbajack.Test/EncryptedDataTests.cs b/Wabbajack.Test/EncryptedDataTests.cs new file mode 100644 index 00000000..bc34331e --- /dev/null +++ b/Wabbajack.Test/EncryptedDataTests.cs @@ -0,0 +1,7 @@ +namespace Wabbajack.Test +{ + public class EncryptedDataTests + { + + } +} From 608b8c77a721eaebe3dfd627dab119b0c21c82a7 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Mon, 10 Feb 2020 17:30:38 -0700 Subject: [PATCH 2/2] Manual download improvements --- Wabbajack.Common/GameMetaData.cs | 21 ++++++++++ Wabbajack.Lib/Downloaders/ManualDownloader.cs | 31 ++------------ Wabbajack.Lib/MO2Compiler.cs | 8 ---- Wabbajack.Lib/NexusApi/NexusApi.cs | 2 +- .../StatusMessages/ManuallyDownloadFile.cs | 35 +++++++++++++++- Wabbajack.Lib/VortexCompiler.cs | 6 --- .../WebAutomation/CefSharpWrapper.cs | 3 ++ Wabbajack.Lib/WebAutomation/IWebDriver.cs | 1 + Wabbajack.Test/EncryptedDataTests.cs | 32 +++++++++++++- .../View Models/UserInterventionHandlers.cs | 42 ++++++++++++++++++- Wabbajack/Views/WebBrowserView.xaml | 5 ++- 11 files changed, 136 insertions(+), 50 deletions(-) diff --git a/Wabbajack.Common/GameMetaData.cs b/Wabbajack.Common/GameMetaData.cs index f65a6ddd..e98bd6f8 100644 --- a/Wabbajack.Common/GameMetaData.cs +++ b/Wabbajack.Common/GameMetaData.cs @@ -123,6 +123,26 @@ namespace Wabbajack.Common .FirstOrDefault(g => g.SteamIDs != null && g.SteamIDs.Count > 0 && g.SteamIDs.Any(i => i == id)); } + /// + /// Tries to parse game data from an arbitrary string. Tries first via parsing as a game Enum, then by Nexus name, + /// + /// + public static GameMetaData GetByFuzzyName(string someName) + { + + if (Enum.TryParse(typeof(Game), someName, true, out var metadata)) return ((Game)metadata).MetaData(); + + GameMetaData result = null; + + result = GetByNexusName(someName); + if (result != null) return result; + + result = GetByMO2ArchiveName(someName); + if (result != null) return result; + + return int.TryParse(someName, out int id) ? GetBySteamID(id) : null; + } + public static IReadOnlyDictionary Games = new Dictionary { { @@ -438,5 +458,6 @@ namespace Wabbajack.Common } } }; + } } diff --git a/Wabbajack.Lib/Downloaders/ManualDownloader.cs b/Wabbajack.Lib/Downloaders/ManualDownloader.cs index de298fba..fd74e334 100644 --- a/Wabbajack.Lib/Downloaders/ManualDownloader.cs +++ b/Wabbajack.Lib/Downloaders/ManualDownloader.cs @@ -82,34 +82,9 @@ namespace Wabbajack.Lib.Downloaders public override async Task Download(Archive a, string destination) { - var downloader = (ManualDownloader)GetDownloader(); - var absPath = Path.Combine(downloader._downloadfolder.Path, a.Name); - using (await downloader.Lock.Wait()) - { - try - { - Utils.Log($"You must manually visit {Url} and download {a.Name} file by hand"); - Utils.Log($"Waiting for {a.Name}"); - downloader._watcher.EnableRaisingEvents = true; - var watcher = downloader._fileEvents - .Where(f => f.Size == a.Size) - .Where(f => f.FullPath.FileHash(true) == a.Hash) - .Buffer(new TimeSpan(0, 5, 0), 1) - .Select(x => x.FirstOrDefault()) - .FirstOrDefaultAsync(); - Process.Start(Url); - - absPath = (await watcher)?.FullPath; - if (!File.Exists(absPath)) - throw new InvalidDataException($"File not found after manual download operation"); - File.Move(absPath, destination); - } - finally - { - downloader._watcher.EnableRaisingEvents = false; - } - } - return true; + var (uri, client) = await Utils.Log(await ManuallyDownloadFile.Create(this)).Task; + var state = new HTTPDownloader.State {Url = uri.ToString(), Client = client}; + return await state.Download(a, destination); } public override async Task Verify(Archive a) diff --git a/Wabbajack.Lib/MO2Compiler.cs b/Wabbajack.Lib/MO2Compiler.cs index c4bb342e..4fce0949 100644 --- a/Wabbajack.Lib/MO2Compiler.cs +++ b/Wabbajack.Lib/MO2Compiler.cs @@ -252,17 +252,9 @@ namespace Wabbajack.Lib Info("Getting Nexus api_key, please click authorize if a browser window appears"); - if (IndexedArchives.Any(a => a.IniData?.General?.gameName != null)) - { - var nexusClient = await NexusApiClient.Get(); - if (!(await nexusClient.IsPremium())) Error($"User {(await nexusClient.Username())} is not a premium Nexus user, so we cannot access the necessary API calls, cannot continue"); - - } - UpdateTracker.NextStep("Verifying Files"); zEditIntegration.VerifyMerges(this); - UpdateTracker.NextStep("Gathering Archives"); await GatherArchives(); UpdateTracker.NextStep("Including Archive Metadata"); diff --git a/Wabbajack.Lib/NexusApi/NexusApi.cs b/Wabbajack.Lib/NexusApi/NexusApi.cs index 74245fc9..36ea2f08 100644 --- a/Wabbajack.Lib/NexusApi/NexusApi.cs +++ b/Wabbajack.Lib/NexusApi/NexusApi.cs @@ -349,7 +349,7 @@ namespace Wabbajack.Lib.NexusApi public static Uri ManualDownloadUrl(NexusDownloader.State state) { - return new Uri($"https://www.nexusmods.com/{GameRegistry.GetByMO2ArchiveName(state.GameName).NexusName}/mods/{state.ModID}?tab=files"); + return new Uri($"https://www.nexusmods.com/{GameRegistry.GetByFuzzyName(state.GameName).NexusName}/mods/{state.ModID}?tab=files"); } } } diff --git a/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs b/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs index 37faf1ad..0bef7492 100644 --- a/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs +++ b/Wabbajack.Lib/StatusMessages/ManuallyDownloadFile.cs @@ -1,7 +1,38 @@ -namespace Wabbajack.Lib +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Wabbajack.Common; +using Wabbajack.Lib.Downloaders; + +namespace Wabbajack.Lib { - public class ManuallyDownloadFile + public class ManuallyDownloadFile : AUserIntervention { + public ManualDownloader.State State { get; } + public override string ShortDescription { get; } + public override string ExtendedDescription { get; } + private TaskCompletionSource<(Uri, HttpClient)> _tcs = new TaskCompletionSource<(Uri, HttpClient)>(); + public Task<(Uri, HttpClient)> Task => _tcs.Task; + + private ManuallyDownloadFile(ManualDownloader.State state) + { + State = state; + } + + public static async Task Create(ManualDownloader.State state) + { + var result = new ManuallyDownloadFile(state); + return result; + } + public override void Cancel() + { + _tcs.SetCanceled(); + } + + public void Resume(Uri s, HttpClient client) + { + _tcs.SetResult((s, client)); + } } } diff --git a/Wabbajack.Lib/VortexCompiler.cs b/Wabbajack.Lib/VortexCompiler.cs index 6eb5c5fe..92ba4fd0 100644 --- a/Wabbajack.Lib/VortexCompiler.cs +++ b/Wabbajack.Lib/VortexCompiler.cs @@ -219,12 +219,6 @@ namespace Wabbajack.Lib InstallDirectives = results.Where(i => !(i is IgnoredDirectly)).ToList(); Info("Getting Nexus api_key, please click authorize if a browser window appears"); - if (IndexedArchives.Any(a => a.IniData?.General?.gameName != null)) - { - var nexusClient = await NexusApiClient.Get(); - if (!await nexusClient.IsPremium()) Error($"User {await nexusClient.Username()} is not a premium Nexus user, so we cannot access the necessary API calls, cannot continue"); - } - if (cancel.IsCancellationRequested) return false; UpdateTracker.NextStep("Gathering Archives"); diff --git a/Wabbajack.Lib/WebAutomation/CefSharpWrapper.cs b/Wabbajack.Lib/WebAutomation/CefSharpWrapper.cs index c13254d2..0c70b711 100644 --- a/Wabbajack.Lib/WebAutomation/CefSharpWrapper.cs +++ b/Wabbajack.Lib/WebAutomation/CefSharpWrapper.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Net.Http; using System.Text; using System.Threading.Tasks; using CefSharp; @@ -60,6 +61,8 @@ namespace Wabbajack.Lib.WebAutomation while (!_browser.IsBrowserInitialized) await Task.Delay(100); } + + public string Location => _browser.Address; } public class DownloadHandler : IDownloadHandler diff --git a/Wabbajack.Lib/WebAutomation/IWebDriver.cs b/Wabbajack.Lib/WebAutomation/IWebDriver.cs index c0ea960c..0672aef5 100644 --- a/Wabbajack.Lib/WebAutomation/IWebDriver.cs +++ b/Wabbajack.Lib/WebAutomation/IWebDriver.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; using System.Text; using System.Threading.Tasks; using Wabbajack.Lib.LibCefHelpers; diff --git a/Wabbajack.Test/EncryptedDataTests.cs b/Wabbajack.Test/EncryptedDataTests.cs index bc34331e..02c3974e 100644 --- a/Wabbajack.Test/EncryptedDataTests.cs +++ b/Wabbajack.Test/EncryptedDataTests.cs @@ -1,7 +1,37 @@ -namespace Wabbajack.Test +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Windows; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Wabbajack.Common; + +namespace Wabbajack.Test { + [TestClass] public class EncryptedDataTests { + + [TestMethod] + public async Task CanDetectNewEncryptedData() + { + var test_string = Guid.NewGuid().ToString(); + var data = new ConcurrentBag(); + var events = Utils.HaveEncryptedJsonObservable(test_string).Subscribe(e => + { + if (e) + data.Add(test_string); + else + data.Clear(); + }); + + test_string.ToEcryptedJson(test_string); + await Task.Delay(100); + + CollectionAssert.Contains(data, test_string); + + + } } } diff --git a/Wabbajack/View Models/UserInterventionHandlers.cs b/Wabbajack/View Models/UserInterventionHandlers.cs index 05b273b1..aa2061ef 100644 --- a/Wabbajack/View Models/UserInterventionHandlers.cs +++ b/Wabbajack/View Models/UserInterventionHandlers.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -11,6 +12,7 @@ using ReactiveUI; using Wabbajack.Common; using Wabbajack.Lib; using Wabbajack.Lib.Downloaders; +using Wabbajack.Lib.LibCefHelpers; using Wabbajack.Lib.NexusApi; using Wabbajack.Lib.WebAutomation; @@ -27,7 +29,7 @@ namespace Wabbajack private async Task WrapBrowserJob(IUserIntervention intervention, Func toDo) { - CancellationTokenSource cancel = new CancellationTokenSource(); + var cancel = new CancellationTokenSource(); var oldPane = MainWindow.ActivePane; var vm = await WebBrowserVM.GetNew(); MainWindow.NavigateTo(vm); @@ -85,6 +87,9 @@ namespace Wabbajack case ManuallyDownloadNexusFile c: await WrapBrowserJob(msg, (vm, cancel) => HandleManualNexusDownload(vm, cancel, c)); break; + case ManuallyDownloadFile c: + await WrapBrowserJob(msg, (vm, cancel) => HandleManualDownload(vm, cancel, c)); + break; case RequestBethesdaNetLogin c: await WrapBethesdaNetLogin(c); break; @@ -108,10 +113,42 @@ namespace Wabbajack } } + private async Task HandleManualDownload(WebBrowserVM vm, CancellationTokenSource cancel, ManuallyDownloadFile manuallyDownloadFile) + { + var browser = new CefSharpWrapper(vm.Browser); + vm.Instructions = $"Please locate and download {manuallyDownloadFile.State.Url}"; + + var result = new TaskCompletionSource(); + + browser.DownloadHandler = uri => + { + //var client = Helpers.GetClient(browser.GetCookies("").Result, browser.Location); + result.SetResult(uri); + }; + + await vm.Driver.WaitForInitialized(); + + await browser.NavigateTo(new Uri(manuallyDownloadFile.State.Url)); + + while (!cancel.IsCancellationRequested) + { + if (result.Task.IsCompleted) + { + var cookies = await Helpers.GetCookies(); + var referer = browser.Location; + var client = Helpers.GetClient(cookies, referer); + manuallyDownloadFile.Resume(result.Task.Result, client); + break; + } + await Task.Delay(100); + } + + } + private async Task HandleManualNexusDownload(WebBrowserVM vm, CancellationTokenSource cancel, ManuallyDownloadNexusFile manuallyDownloadNexusFile) { var state = manuallyDownloadNexusFile.State; - var game = GameRegistry.GetByMO2ArchiveName(state.GameName); + var game = GameRegistry.GetByFuzzyName(state.GameName); var hrefs = new[] { $"/Core/Libs/Common/Widgets/DownloadPopUp?id={state.FileID}&game_id={game.NexusGameId}", @@ -124,6 +161,7 @@ namespace Wabbajack browser.DownloadHandler = uri => { manuallyDownloadNexusFile.Resume(uri); + browser.DownloadHandler = null; }; await browser.NavigateTo(NexusApiClient.ManualDownloadUrl(manuallyDownloadNexusFile.State)); diff --git a/Wabbajack/Views/WebBrowserView.xaml b/Wabbajack/Views/WebBrowserView.xaml index bdb63ebe..56f45066 100644 --- a/Wabbajack/Views/WebBrowserView.xaml +++ b/Wabbajack/Views/WebBrowserView.xaml @@ -41,15 +41,16 @@ - +