mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Port ModListVM
This commit is contained in:
parent
33161f9817
commit
475e44c895
@ -4,7 +4,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:Wabbajack"
|
xmlns:local="clr-namespace:Wabbajack"
|
||||||
ShutdownMode="OnExplicitShutdown"
|
ShutdownMode="OnExplicitShutdown"
|
||||||
StartupUri="Views\MainWindow.xaml">
|
Startup="OnStartup">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
@ -1,26 +1,33 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
|
using Wabbajack.Services.OSIntegrated;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for App.xaml
|
/// Interaction logic for App.xaml
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class App : Application
|
public partial class App
|
||||||
{
|
{
|
||||||
|
private readonly ServiceProvider _serviceProvider;
|
||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
Consts.LogsFolder = LauncherUpdater.CommonFolder.Value.Combine("logs");
|
var services = new ServiceCollection();
|
||||||
Consts.LogsFolder.CreateDirectory();
|
ConfigureServices(services);
|
||||||
|
_serviceProvider = services.BuildServiceProvider();
|
||||||
LoggingSettings.LogToFile = true;
|
}
|
||||||
Utils.InitializeLogging().Wait();
|
private void ConfigureServices(ServiceCollection services)
|
||||||
|
{
|
||||||
CLIOld.ParseOptions(Environment.GetCommandLineArgs());
|
services.AddOSIntegrated();
|
||||||
if (CLIArguments.Help)
|
services.AddSingleton<MainWindow>();
|
||||||
CLIOld.DisplayHelpText();
|
}
|
||||||
|
private void OnStartup(object sender, StartupEventArgs e)
|
||||||
|
{
|
||||||
|
var mainWindow = _serviceProvider.GetService<MainWindow>();
|
||||||
|
mainWindow!.Show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
using Wabbajack.Compiler;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reactive;
|
||||||
|
using System.Reactive.Subjects;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Wabbajack.Compiler;
|
||||||
using Wabbajack.DTOs.JsonConverters;
|
using Wabbajack.DTOs.JsonConverters;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
using Wabbajack.Paths;
|
using Wabbajack.Paths;
|
||||||
|
@ -3,6 +3,7 @@ using DynamicData.Binding;
|
|||||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
@ -13,6 +14,8 @@ using System.Threading.Tasks;
|
|||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
|
using Wabbajack.Lib.Extensions;
|
||||||
|
using Wabbajack.Paths;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
{
|
{
|
||||||
@ -50,6 +53,24 @@ namespace Wabbajack
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void OpenWebsite(Uri url)
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo("cmd.exe", $"/c start {url}")
|
||||||
|
{
|
||||||
|
CreateNoWindow = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenFolder(AbsolutePath path)
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo(AbsolutePath.WindowsFolder.Combine("explorer.exe").ToString(), path.ToString())
|
||||||
|
{
|
||||||
|
CreateNoWindow = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static AbsolutePath OpenFileDialog(string filter, string initialDirectory = null)
|
public static AbsolutePath OpenFileDialog(string filter, string initialDirectory = null)
|
||||||
{
|
{
|
||||||
OpenFileDialog ofd = new OpenFileDialog();
|
OpenFileDialog ofd = new OpenFileDialog();
|
||||||
|
@ -27,6 +27,7 @@ using Wabbajack.Lib.Extensions;
|
|||||||
using Wabbajack.Lib.Interventions;
|
using Wabbajack.Lib.Interventions;
|
||||||
using Wabbajack.Paths;
|
using Wabbajack.Paths;
|
||||||
using Wabbajack.RateLimiter;
|
using Wabbajack.RateLimiter;
|
||||||
|
using Wabbajack.View_Models;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
{
|
{
|
||||||
|
@ -4,25 +4,36 @@ using System.IO;
|
|||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
|
using Wabbajack.DTOs;
|
||||||
|
using Wabbajack.DTOs.JsonConverters;
|
||||||
|
using Wabbajack.Installer;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
using Wabbajack.Lib.ModListRegistry;
|
using Wabbajack.Paths;
|
||||||
|
using Wabbajack.Paths.IO;
|
||||||
|
using Consts = Wabbajack.Lib.Consts;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
{
|
{
|
||||||
public class ModListVM : ViewModel
|
public class ModListVM : ViewModel
|
||||||
{
|
{
|
||||||
|
private readonly DTOSerializer _dtos;
|
||||||
|
private readonly ILogger<ModListVM> _logger;
|
||||||
public ModList SourceModList { get; private set; }
|
public ModList SourceModList { get; private set; }
|
||||||
public ModlistMetadata SourceModListMetadata { get; private set; }
|
public ModlistMetadata SourceModListMetadata { get; private set; }
|
||||||
public Exception Error { get; }
|
|
||||||
|
[Reactive]
|
||||||
|
public Exception Error { get; set; }
|
||||||
public AbsolutePath ModListPath { get; }
|
public AbsolutePath ModListPath { get; }
|
||||||
public string Name => SourceModList?.Name;
|
public string Name => SourceModList?.Name;
|
||||||
public string Readme => SourceModList?.Readme;
|
public string Readme => SourceModList?.Readme;
|
||||||
public string Author => SourceModList?.Author;
|
public string Author => SourceModList?.Author;
|
||||||
public string Description => SourceModList?.Description;
|
public string Description => SourceModList?.Description;
|
||||||
public Uri Website => SourceModList?.Website;
|
public Uri Website => SourceModList?.Website;
|
||||||
public ModManager ModManager => SourceModList?.ModManager ?? ModManager.MO2;
|
|
||||||
public Version Version => SourceModList?.Version;
|
public Version Version => SourceModList?.Version;
|
||||||
public Version WabbajackVersion => SourceModList?.WabbajackVersion;
|
public Version WabbajackVersion => SourceModList?.WabbajackVersion;
|
||||||
public bool IsNSFW => SourceModList?.IsNSFW ?? false;
|
public bool IsNSFW => SourceModList?.IsNSFW ?? false;
|
||||||
@ -32,18 +43,24 @@ namespace Wabbajack
|
|||||||
// and the cached image will automatically be released when the last interested party is gone.
|
// and the cached image will automatically be released when the last interested party is gone.
|
||||||
public IObservable<BitmapImage> ImageObservable { get; }
|
public IObservable<BitmapImage> ImageObservable { get; }
|
||||||
|
|
||||||
public ModListVM(AbsolutePath modListPath)
|
public ModListVM(ILogger<ModListVM> logger, AbsolutePath modListPath, DTOSerializer dtos)
|
||||||
{
|
{
|
||||||
|
_dtos = dtos;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
ModListPath = modListPath;
|
ModListPath = modListPath;
|
||||||
try
|
|
||||||
{
|
Task.Run(async () =>
|
||||||
SourceModList = AInstaller.LoadFromFile(modListPath);
|
|
||||||
var metadataPath = modListPath.WithExtension(Consts.ModlistMetadataExtension);
|
|
||||||
if (metadataPath.Exists)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SourceModListMetadata = metadataPath.FromJson<ModlistMetadata>();
|
SourceModList = await StandardInstaller.LoadFromFile(_dtos, modListPath);
|
||||||
|
var metadataPath = modListPath.WithExtension(Ext.ModlistMetadataExtension);
|
||||||
|
if (metadataPath.FileExists())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SourceModListMetadata = await metadataPath.FromJson<ModlistMetadata>();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@ -54,8 +71,9 @@ namespace Wabbajack
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Error = ex;
|
Error = ex;
|
||||||
Utils.Error(ex, "Exception while loading the modlist!");
|
_logger.LogError(ex, "Exception while loading the modlist!");
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ImageObservable = Observable.Return(Unit.Default)
|
ImageObservable = Observable.Return(Unit.Default)
|
||||||
// Download and retrieve bytes on background thread
|
// Download and retrieve bytes on background thread
|
||||||
@ -64,7 +82,7 @@ namespace Wabbajack
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await using var fs = await ModListPath.OpenShared();
|
await using var fs = ModListPath.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
using var ar = new ZipArchive(fs, ZipArchiveMode.Read);
|
using var ar = new ZipArchive(fs, ZipArchiveMode.Read);
|
||||||
var ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
var entry = ar.GetEntry("modlist-image.png");
|
var entry = ar.GetEntry("modlist-image.png");
|
||||||
@ -75,7 +93,7 @@ namespace Wabbajack
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Utils.Error(ex, $"Exception while caching Mod List image {Name}");
|
_logger.LogError(ex, "Exception while caching Mod List image {Name}", Name);
|
||||||
return default(MemoryStream);
|
return default(MemoryStream);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -90,7 +108,7 @@ namespace Wabbajack
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Utils.Error(ex, $"Exception while caching Mod List image {Name}");
|
_logger.LogError(ex, "Exception while caching Mod List image {Name}", Name);
|
||||||
return default(BitmapImage);
|
return default(BitmapImage);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -103,7 +121,7 @@ namespace Wabbajack
|
|||||||
public void OpenReadme()
|
public void OpenReadme()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(Readme)) return;
|
if (string.IsNullOrEmpty(Readme)) return;
|
||||||
Utils.OpenWebsite(new Uri(Readme));
|
UIUtils.OpenWebsite(new Uri(Readme));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
|
@ -1,21 +1,15 @@
|
|||||||
using DynamicData;
|
using System;
|
||||||
|
using System.Reactive;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using DynamicData;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reactive;
|
|
||||||
using System.Reactive.Disposables;
|
|
||||||
using System.Reactive.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using Wabbajack.Common;
|
|
||||||
using Wabbajack.DTOs.DownloadStates;
|
using Wabbajack.DTOs.DownloadStates;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
using Wabbajack.Lib.Downloaders;
|
|
||||||
using Wabbajack.Lib.Extensions;
|
using Wabbajack.Lib.Extensions;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack.View_Models
|
||||||
{
|
{
|
||||||
public class SlideShow : ViewModel
|
public class SlideShow : ViewModel
|
||||||
{
|
{
|
||||||
@ -86,7 +80,7 @@ namespace Wabbajack
|
|||||||
if (modList?.SourceModList?.Archives == null)
|
if (modList?.SourceModList?.Archives == null)
|
||||||
{
|
{
|
||||||
return Observable.Empty<IMetaState>()
|
return Observable.Empty<IMetaState>()
|
||||||
.ToObservableChangeSet(x => x.URL);
|
.ToObservableChangeSet(x => x.LinkUrl);
|
||||||
}
|
}
|
||||||
return modList.SourceModList.Archives
|
return modList.SourceModList.Archives
|
||||||
.Select(m => m.State)
|
.Select(m => m.State)
|
||||||
@ -128,7 +122,7 @@ namespace Wabbajack
|
|||||||
VisitURLCommand = ReactiveCommand.Create(
|
VisitURLCommand = ReactiveCommand.Create(
|
||||||
execute: () =>
|
execute: () =>
|
||||||
{
|
{
|
||||||
Utils.OpenWebsite(TargetMod.State.URL);
|
UIUtils.OpenWebsite(TargetMod.State.URL);
|
||||||
return Unit.Default;
|
return Unit.Default;
|
||||||
},
|
},
|
||||||
canExecute: this.WhenAny(x => x.TargetMod.State.URL)
|
canExecute: this.WhenAny(x => x.TargetMod.State.URL)
|
||||||
|
@ -1,23 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Threading;
|
using Microsoft.Extensions.Logging;
|
||||||
using CefSharp;
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
using Wabbajack.Lib.Downloaders;
|
|
||||||
using Wabbajack.Lib.Interventions;
|
using Wabbajack.Lib.Interventions;
|
||||||
using Wabbajack.Lib.LibCefHelpers;
|
|
||||||
using Wabbajack.Lib.NexusApi;
|
|
||||||
using Wabbajack.Lib.WebAutomation;
|
|
||||||
using WebSocketSharp;
|
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
{
|
{
|
||||||
@ -25,9 +14,11 @@ namespace Wabbajack
|
|||||||
{
|
{
|
||||||
public MainWindowVM MainWindow { get; }
|
public MainWindowVM MainWindow { get; }
|
||||||
private AsyncLock _browserLock = new();
|
private AsyncLock _browserLock = new();
|
||||||
|
private readonly ILogger<UserInterventionHandlers> _logger;
|
||||||
|
|
||||||
public UserInterventionHandlers(MainWindowVM mvm)
|
public UserInterventionHandlers(ILogger<UserInterventionHandlers> logger, MainWindowVM mvm)
|
||||||
{
|
{
|
||||||
|
_logger = logger;
|
||||||
MainWindow = mvm;
|
MainWindow = mvm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +27,7 @@ namespace Wabbajack
|
|||||||
var wait = await _browserLock.WaitAsync();
|
var wait = await _browserLock.WaitAsync();
|
||||||
var cancel = new CancellationTokenSource();
|
var cancel = new CancellationTokenSource();
|
||||||
var oldPane = MainWindow.ActivePane;
|
var oldPane = MainWindow.ActivePane;
|
||||||
using var vm = await WebBrowserVM.GetNew();
|
using var vm = await WebBrowserVM.GetNew(_logger);
|
||||||
MainWindow.NavigateTo(vm);
|
MainWindow.NavigateTo(vm);
|
||||||
vm.BackCommand = ReactiveCommand.Create(() =>
|
vm.BackCommand = ReactiveCommand.Create(() =>
|
||||||
{
|
{
|
||||||
@ -55,7 +46,7 @@ namespace Wabbajack
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Utils.Error(ex);
|
_logger.LogError(ex, "During Web browser job");
|
||||||
intervention.Cancel();
|
intervention.Cancel();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -70,6 +61,7 @@ namespace Wabbajack
|
|||||||
{
|
{
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
case RequestNexusAuthorization c:
|
case RequestNexusAuthorization c:
|
||||||
await WrapBrowserJob(c, async (vm, cancel) =>
|
await WrapBrowserJob(c, async (vm, cancel) =>
|
||||||
{
|
{
|
||||||
@ -100,6 +92,7 @@ namespace Wabbajack
|
|||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
*/
|
||||||
case CriticalFailureIntervention c:
|
case CriticalFailureIntervention c:
|
||||||
MessageBox.Show(c.ExtendedDescription, c.ShortDescription, MessageBoxButton.OK,
|
MessageBox.Show(c.ExtendedDescription, c.ShortDescription, MessageBoxButton.OK,
|
||||||
MessageBoxImage.Error);
|
MessageBoxImage.Error);
|
||||||
@ -113,99 +106,5 @@ namespace Wabbajack
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OAuthLogin(RequestOAuthLogin oa, WebBrowserVM vm, CancellationTokenSource cancel)
|
|
||||||
{
|
|
||||||
await vm.Driver.WaitForInitialized();
|
|
||||||
vm.Instructions = $"Please log in and allow Wabbajack to access your {oa.SiteName} account";
|
|
||||||
|
|
||||||
var wrapper = new CefSharpWrapper(vm.Browser);
|
|
||||||
var scopes = string.Join(" ", oa.Scopes);
|
|
||||||
var state = Guid.NewGuid().ToString();
|
|
||||||
|
|
||||||
|
|
||||||
var oldHandler = Helpers.SchemeHandler;
|
|
||||||
Helpers.SchemeHandler = (browser, frame, _, request) =>
|
|
||||||
{
|
|
||||||
var req = new Uri(request.Url);
|
|
||||||
Utils.LogStraightToFile($"Got Scheme callback {req}");
|
|
||||||
var parsed = HttpUtility.ParseQueryString(req.Query);
|
|
||||||
if (parsed.Contains("state"))
|
|
||||||
{
|
|
||||||
if (parsed.Get("state") != state)
|
|
||||||
{
|
|
||||||
Utils.Log("Bad OAuth state, state, this shouldn't happen");
|
|
||||||
oa.Cancel();
|
|
||||||
return new ResourceHandler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (parsed.Contains("code"))
|
|
||||||
{
|
|
||||||
Helpers.SchemeHandler = oldHandler;
|
|
||||||
oa.Resume(parsed.Get("code"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oa.Cancel();
|
|
||||||
}
|
|
||||||
return new ResourceHandler();
|
|
||||||
};
|
|
||||||
|
|
||||||
await wrapper.NavigateTo(new Uri(oa.AuthorizationEndpoint + $"?response_type=code&client_id={oa.ClientID}&state={state}&scope={scopes}"));
|
|
||||||
|
|
||||||
while (!oa.Task.IsCanceled && !oa.Task.IsCompleted && !cancel.IsCancellationRequested)
|
|
||||||
await Task.Delay(250);
|
|
||||||
}
|
|
||||||
|
|
||||||
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<Uri>();
|
|
||||||
|
|
||||||
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 = state.Game.MetaData();
|
|
||||||
await vm.Driver.WaitForInitialized();
|
|
||||||
IWebDriver browser = new CefSharpWrapper(vm.Browser);
|
|
||||||
vm.Instructions = $"Click the download button to continue (get a NexusMods.com Premium account to automate this)";
|
|
||||||
browser.DownloadHandler = uri =>
|
|
||||||
{
|
|
||||||
manuallyDownloadNexusFile.Resume(uri);
|
|
||||||
browser.DownloadHandler = null;
|
|
||||||
};
|
|
||||||
var url = new Uri(@$"https://www.nexusmods.com/{game.NexusName}/mods/{state.ModID}?tab=files&file_id={state.FileID}");
|
|
||||||
await browser.NavigateTo(url);
|
|
||||||
|
|
||||||
while (!cancel.IsCancellationRequested && !manuallyDownloadNexusFile.Task.IsCompleted) {
|
|
||||||
await Task.Delay(250);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Wabbajack.DTOs.JsonConverters;
|
||||||
using Wabbajack.Hashing.xxHash64;
|
using Wabbajack.Hashing.xxHash64;
|
||||||
using Wabbajack.Paths;
|
using Wabbajack.Paths;
|
||||||
using Wabbajack.Paths.IO;
|
using Wabbajack.Paths.IO;
|
||||||
@ -14,4 +15,10 @@ public static class AbsolutePathExtensions
|
|||||||
await using var fs = path.Open(FileMode.Open);
|
await using var fs = path.Open(FileMode.Open);
|
||||||
return await fs.HashingCopy(Stream.Null, token ?? CancellationToken.None);
|
return await fs.HashingCopy(Stream.Null, token ?? CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<T> FromJson<T>(this AbsolutePath path, DTOSerializer? dtos = null)
|
||||||
|
{
|
||||||
|
await using var fs = path.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
return await fs.FromJson<T>(dtos);
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,4 +23,5 @@ public static class Ext
|
|||||||
public static Extension CompilerSettings = new(".compiler_settings");
|
public static Extension CompilerSettings = new(".compiler_settings");
|
||||||
public static Extension MO2CompilerSettings = new(".mo2_compiler_settings");
|
public static Extension MO2CompilerSettings = new(".mo2_compiler_settings");
|
||||||
public static Extension Temp = new(".temp");
|
public static Extension Temp = new(".temp");
|
||||||
|
public static Extension ModlistMetadataExtension = new(".modlist_metadata");
|
||||||
}
|
}
|
@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Wabbajack.DTOs.JsonConverters;
|
||||||
|
|
||||||
namespace Wabbajack.Common;
|
namespace Wabbajack.Common;
|
||||||
|
|
||||||
@ -57,6 +59,11 @@ public static class StreamExtensions
|
|||||||
return sr.ReadToEnd();
|
return sr.ReadToEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<T> FromJson<T>(this Stream stream, DTOSerializer? dtos = null)
|
||||||
|
{
|
||||||
|
return (await JsonSerializer.DeserializeAsync<T>(stream, dtos?.Options))!;
|
||||||
|
}
|
||||||
|
|
||||||
public static async IAsyncEnumerable<string> ReadLinesAsync(this Stream stream)
|
public static async IAsyncEnumerable<string> ReadLinesAsync(this Stream stream)
|
||||||
{
|
{
|
||||||
using var sr = new StreamReader(stream);
|
using var sr = new StreamReader(stream);
|
||||||
|
@ -10,4 +10,6 @@ public interface IMetaState
|
|||||||
Uri? ImageURL { get; set; }
|
Uri? ImageURL { get; set; }
|
||||||
bool IsNSFW { get; set; }
|
bool IsNSFW { get; set; }
|
||||||
string? Description { get; set; }
|
string? Description { get; set; }
|
||||||
|
|
||||||
|
Uri? LinkUrl { get; }
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user