mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Can get VP auth tokens
This commit is contained in:
parent
63fd46ffec
commit
30e4fcd40d
97
Wabbajack.Lib/Downloaders/AbstractIPS4OAuthDownloader.cs
Normal file
97
Wabbajack.Lib/Downloaders/AbstractIPS4OAuthDownloader.cs
Normal file
@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Common.StatusFeed;
|
||||
using Wabbajack.Lib.LibCefHelpers;
|
||||
using Wabbajack.Lib.WebAutomation;
|
||||
namespace Wabbajack.Lib.Downloaders
|
||||
{
|
||||
public abstract class AbstractIPS4OAuthDownloader<TDownloader, TState> : INeedsLogin, IDownloader, IWaitForWindowDownloader
|
||||
where TState : AbstractDownloadState, new()
|
||||
where TDownloader : IDownloader
|
||||
{
|
||||
public AbstractIPS4OAuthDownloader(string clientID, Uri authEndpoint, Uri tokenEndpoint, string encryptedKeyName)
|
||||
{
|
||||
ClientID = clientID;
|
||||
AuthorizationEndpoint = authEndpoint;
|
||||
TokenEndpoint = tokenEndpoint;
|
||||
EncryptedKeyName = encryptedKeyName;
|
||||
|
||||
TriggerLogin = ReactiveCommand.CreateFromTask(
|
||||
execute: () => Utils.CatchAndLog(async () => await Utils.Log(new RequestOAuthLogin(ClientID, authEndpoint, tokenEndpoint, SiteName)).Task),
|
||||
canExecute: IsLoggedIn.Select(b => !b).ObserveOnGuiThread());
|
||||
ClearLogin = ReactiveCommand.CreateFromTask(
|
||||
execute: () => Utils.CatchAndLog(async () => await Utils.DeleteEncryptedJson(EncryptedKeyName)),
|
||||
canExecute: IsLoggedIn.ObserveOnGuiThread());
|
||||
|
||||
}
|
||||
|
||||
public string EncryptedKeyName { get; }
|
||||
public Uri TokenEndpoint { get; }
|
||||
public Uri AuthorizationEndpoint { get; }
|
||||
public string ClientID { get; }
|
||||
public ReactiveCommand<Unit, Unit> TriggerLogin { get; }
|
||||
public ReactiveCommand<Unit, Unit> ClearLogin { get; }
|
||||
public IObservable<bool> IsLoggedIn => Utils.HaveEncryptedJsonObservable(EncryptedKeyName);
|
||||
public abstract string SiteName { get; }
|
||||
public IObservable<string>? MetaInfo { get; }
|
||||
public abstract Uri SiteURL { get; }
|
||||
public virtual Uri? IconUri { get; }
|
||||
public Task<AbstractDownloadState?> GetDownloaderState(dynamic archiveINI, bool quickMode = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task Prepare()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task WaitForNextRequestWindow()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class RequestOAuthLogin : AUserIntervention
|
||||
{
|
||||
public string ClientID { get; }
|
||||
public Uri AuthorizationEndpoint { get; }
|
||||
public Uri TokenEndpoint { get; }
|
||||
public string SiteName { get; }
|
||||
|
||||
public RequestOAuthLogin(string clientID, Uri authEndpoint, Uri tokenEndpoint, string siteName)
|
||||
{
|
||||
ClientID = clientID;
|
||||
AuthorizationEndpoint = authEndpoint;
|
||||
TokenEndpoint = tokenEndpoint;
|
||||
SiteName = siteName;
|
||||
}
|
||||
public override string ShortDescription => $"Getting {SiteName} Login";
|
||||
public override string ExtendedDescription { get; } = string.Empty;
|
||||
|
||||
private readonly TaskCompletionSource<string> _source = new ();
|
||||
public Task<string> Task => _source.Task;
|
||||
|
||||
public void Resume(string authToken)
|
||||
{
|
||||
Handled = true;
|
||||
_source.SetResult(authToken);
|
||||
}
|
||||
|
||||
public override void Cancel()
|
||||
{
|
||||
Handled = true;
|
||||
_source.TrySetCanceled();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,16 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using HtmlAgilityPack;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Common.Serialization.Json;
|
||||
using Wabbajack.Lib.Validation;
|
||||
|
||||
namespace Wabbajack.Lib.Downloaders
|
||||
{
|
||||
public class VectorPlexusDownloader : AbstractIPS4Downloader<VectorPlexusDownloader, VectorPlexusDownloader.State>
|
||||
public class VectorPlexusDownloader : AbstractIPS4OAuthDownloader<VectorPlexusDownloader, VectorPlexusDownloader.State>
|
||||
{
|
||||
#region INeedsDownload
|
||||
public override string SiteName => "Vector Plexus";
|
||||
@ -15,13 +18,50 @@ namespace Wabbajack.Lib.Downloaders
|
||||
public override Uri IconUri => new Uri("https://www.vectorplexus.com/favicon.ico");
|
||||
#endregion
|
||||
|
||||
public VectorPlexusDownloader() : base(new Uri("https://vectorplexus.com/login"),
|
||||
"vectorplexus", "vectorplexus.com")
|
||||
public VectorPlexusDownloader() : base("45c6d3c9867903a7daa6ded0a38cedf8",
|
||||
new Uri("https://vectorplexus.com/oauth/authorize/"), new Uri("https://vectorplexus.com/oauth/token/"),
|
||||
"vector-plexus-oauth2")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public class State : AbstractDownloadState
|
||||
{
|
||||
public override object[] PrimaryKey { get; } = Array.Empty<object>();
|
||||
public override bool IsWhitelisted(ServerWhitelist whitelist)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<bool> Download(Archive a, AbsolutePath destination)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<bool> Verify(Archive archive, CancellationToken? token = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override IDownloader GetDownloader()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override string? GetManifestURL(Archive a)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override string[] GetMetaIni()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
[JsonName("VectorPlexusDownloader")]
|
||||
public class State : State<VectorPlexusDownloader>
|
||||
public class State //: State<VectorPlexusDownloader>
|
||||
{
|
||||
public override async Task<bool> LoadMetaData()
|
||||
{
|
||||
@ -68,5 +108,6 @@ namespace Wabbajack.Lib.Downloaders
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -85,6 +85,8 @@ namespace Wabbajack.Lib.LibCefHelpers
|
||||
public string Path { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public static Func<IBrowser, IFrame, string, IRequest, IResourceHandler>? SchemeHandler { get; set; }
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
if (Inited || Cef.IsInitialized) return;
|
||||
@ -92,9 +94,28 @@ namespace Wabbajack.Lib.LibCefHelpers
|
||||
CefSettings settings = new CefSettings();
|
||||
settings.CachePath = Consts.CefCacheLocation.ToString();
|
||||
settings.JavascriptFlags = "--noexpose_wasm";
|
||||
settings.RegisterScheme(new CefCustomScheme()
|
||||
{
|
||||
SchemeName = "wabbajack",
|
||||
SchemeHandlerFactory = new SchemeHandlerFactor()
|
||||
});
|
||||
|
||||
|
||||
Cef.Initialize(settings);
|
||||
}
|
||||
|
||||
private class SchemeHandlerFactor : ISchemeHandlerFactory
|
||||
{
|
||||
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
|
||||
{
|
||||
if (SchemeHandler != null && schemeName == "wabbajack")
|
||||
{
|
||||
return SchemeHandler!(browser, frame, schemeName, request);
|
||||
}
|
||||
return new ResourceHandler();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Inited { get; set; }
|
||||
|
||||
public static void ClearCookies()
|
||||
|
@ -5,6 +5,7 @@ using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using CefSharp;
|
||||
@ -16,6 +17,7 @@ using Wabbajack.Lib.Downloaders;
|
||||
using Wabbajack.Lib.LibCefHelpers;
|
||||
using Wabbajack.Lib.NexusApi;
|
||||
using Wabbajack.Lib.WebAutomation;
|
||||
using WebSocketSharp;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
@ -83,6 +85,14 @@ namespace Wabbajack
|
||||
var data = await c.Downloader.GetAndCacheCookies(new CefSharpWrapper(vm.Browser), m => vm.Instructions = m, cancel.Token);
|
||||
c.Resume(data);
|
||||
});
|
||||
break;
|
||||
case RequestOAuthLogin oa:
|
||||
await WrapBrowserJob(oa, async (vm, cancel) =>
|
||||
{
|
||||
await OAuthLogin(oa, vm, cancel);
|
||||
});
|
||||
|
||||
|
||||
break;
|
||||
case CriticalFailureIntervention c:
|
||||
MessageBox.Show(c.ExtendedDescription, c.ShortDescription, MessageBoxButton.OK,
|
||||
@ -97,6 +107,34 @@ 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 account";
|
||||
|
||||
var wrapper = new CefSharpWrapper(vm.Browser);
|
||||
await wrapper.NavigateTo(new Uri(oa.AuthorizationEndpoint + $"?response_type=code&client_id={oa.ClientID}"));
|
||||
|
||||
Helpers.SchemeHandler = (browser, frame, _, request) =>
|
||||
{
|
||||
var req = new Uri(request.Url);
|
||||
var parsed = HttpUtility.ParseQueryString(req.Query);
|
||||
if (parsed.Contains("code"))
|
||||
{
|
||||
oa.Resume(parsed.Get("code"));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa.Cancel();
|
||||
}
|
||||
|
||||
return new ResourceHandler();
|
||||
};
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user