mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Can login to Bethesda.Net and get CC data
This commit is contained in:
parent
45625e3d27
commit
5e1e0ec527
@ -76,6 +76,7 @@ public partial class App
|
|||||||
services.AddTransient<NexusLogin>();
|
services.AddTransient<NexusLogin>();
|
||||||
services.AddTransient<VectorPlexus>();
|
services.AddTransient<VectorPlexus>();
|
||||||
services.AddTransient<LoversLab>();
|
services.AddTransient<LoversLab>();
|
||||||
|
services.AddTransient<BethesdaNetLogin>();
|
||||||
services.AddSingleton<SystemParametersConstructor>();
|
services.AddSingleton<SystemParametersConstructor>();
|
||||||
services.AddSingleton<IStateContainer, StateContainer>();
|
services.AddSingleton<IStateContainer, StateContainer>();
|
||||||
return services;
|
return services;
|
||||||
|
75
Wabbajack.App.Blazor/Browser/ViewModels/BethesdaNetLogin.cs
Normal file
75
Wabbajack.App.Blazor/Browser/ViewModels/BethesdaNetLogin.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Web.WebView2.Core;
|
||||||
|
using Wabbajack.Common;
|
||||||
|
using Wabbajack.Networking.BethesdaNet;
|
||||||
|
using Wabbajack.Services.OSIntegrated;
|
||||||
|
|
||||||
|
namespace Wabbajack.App.Blazor.Browser.ViewModels;
|
||||||
|
|
||||||
|
public class BethesdaNetLogin : BrowserTabViewModel
|
||||||
|
{
|
||||||
|
private readonly EncryptedJsonTokenProvider<Wabbajack.DTOs.Logins.BethesdaNetLoginState> _tokenProvider;
|
||||||
|
private readonly Client _client;
|
||||||
|
|
||||||
|
public BethesdaNetLogin(EncryptedJsonTokenProvider<Wabbajack.DTOs.Logins.BethesdaNetLoginState> tokenProvider, Wabbajack.Networking.BethesdaNet.Client client)
|
||||||
|
{
|
||||||
|
_tokenProvider = tokenProvider;
|
||||||
|
_client = client;
|
||||||
|
HeaderText = "Bethesda Net Login";
|
||||||
|
}
|
||||||
|
protected override async Task Run(CancellationToken token)
|
||||||
|
{
|
||||||
|
await WaitForReady();
|
||||||
|
Instructions = "Please log in to Bethesda.net";
|
||||||
|
|
||||||
|
string requestJson = "";
|
||||||
|
|
||||||
|
Browser.Browser.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All);
|
||||||
|
Browser.Browser.CoreWebView2.WebResourceRequested += (sender, args) =>
|
||||||
|
{
|
||||||
|
if (args.Request.Uri == "https://api.bethesda.net/dwemer/attunement/v1/authenticate" && args.Request.Method == "POST")
|
||||||
|
{
|
||||||
|
requestJson = args.Request.Content.ReadAllText();
|
||||||
|
args.Request.Content = new MemoryStream(Encoding.UTF8.GetBytes(requestJson));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await NavigateTo(new Uri("https://bethesda.net/en/dashboard"));
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var code = await GetCookies("bethesda.net", token);
|
||||||
|
if (code.Any(c => c.Name == "bnet-session")) break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = JsonSerializer.Deserialize<LoginRequest>(requestJson);
|
||||||
|
|
||||||
|
var provider = new Wabbajack.DTOs.Logins.BethesdaNetLoginState()
|
||||||
|
{
|
||||||
|
Username = data.UserName,
|
||||||
|
Password = data.Password
|
||||||
|
};
|
||||||
|
await _tokenProvider.SetToken(provider);
|
||||||
|
await _client.Login(token);
|
||||||
|
|
||||||
|
await Task.Delay(10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LoginRequest
|
||||||
|
{
|
||||||
|
[JsonPropertyName("username")]
|
||||||
|
public string UserName { get; set; }
|
||||||
|
[JsonPropertyName("password")]
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,6 +13,7 @@
|
|||||||
<button onclick="@LoginToNexus">Login To Nexus</button>
|
<button onclick="@LoginToNexus">Login To Nexus</button>
|
||||||
<button onclick="@LoginToVectorPlexus">Login To Vector Plexus</button>
|
<button onclick="@LoginToVectorPlexus">Login To Vector Plexus</button>
|
||||||
<button onclick="@LoginToLoversLab">Login To Lovers Lab</button>
|
<button onclick="@LoginToLoversLab">Login To Lovers Lab</button>
|
||||||
|
<button onclick="@LoginToBethesdaNet">Login To Bethesda Net</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -32,4 +33,8 @@
|
|||||||
{
|
{
|
||||||
MessageBus.Current.SendMessage(new OpenBrowserTab(_serviceProvider.GetRequiredService<VectorPlexus>()));
|
MessageBus.Current.SendMessage(new OpenBrowserTab(_serviceProvider.GetRequiredService<VectorPlexus>()));
|
||||||
}
|
}
|
||||||
|
public void LoginToBethesdaNet()
|
||||||
|
{
|
||||||
|
MessageBus.Current.SendMessage(new OpenBrowserTab(_serviceProvider.GetRequiredService<BethesdaNetLogin>()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,7 @@ internal class Program
|
|||||||
services.AddSingleton<IVerb, SteamAppDumpInfo>();
|
services.AddSingleton<IVerb, SteamAppDumpInfo>();
|
||||||
services.AddSingleton<IVerb, SteamDownloadFile>();
|
services.AddSingleton<IVerb, SteamDownloadFile>();
|
||||||
services.AddSingleton<IVerb, UploadToNexus>();
|
services.AddSingleton<IVerb, UploadToNexus>();
|
||||||
|
services.AddSingleton<IVerb, ListCreationClubContent>();
|
||||||
|
|
||||||
services.AddSingleton<IUserInterventionHandler, UserInterventionHandler>();
|
services.AddSingleton<IUserInterventionHandler, UserInterventionHandler>();
|
||||||
}).Build();
|
}).Build();
|
||||||
|
53
Wabbajack.CLI/Verbs/ListCreationClubContent.cs
Normal file
53
Wabbajack.CLI/Verbs/ListCreationClubContent.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.CommandLine;
|
||||||
|
using System.CommandLine.Invocation;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Wabbajack.Common;
|
||||||
|
using Wabbajack.DTOs;
|
||||||
|
using Wabbajack.Networking.BethesdaNet;
|
||||||
|
using Wabbajack.Paths;
|
||||||
|
|
||||||
|
namespace Wabbajack.CLI.Verbs;
|
||||||
|
|
||||||
|
public class ListCreationClubContent : IVerb
|
||||||
|
{
|
||||||
|
private readonly ILogger<ListCreationClubContent> _logger;
|
||||||
|
private readonly Client _client;
|
||||||
|
|
||||||
|
public ListCreationClubContent(ILogger<ListCreationClubContent> logger, Client wjClient)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_client = wjClient;
|
||||||
|
}
|
||||||
|
public Command MakeCommand()
|
||||||
|
{
|
||||||
|
var command = new Command("list-creation-club-content");
|
||||||
|
command.Description = "Lists all known creation club content";
|
||||||
|
command.Handler = CommandHandler.Create(Run);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> Run(CancellationToken token)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Getting list of content");
|
||||||
|
var skyrimContent = (await _client.ListContent(Game.SkyrimSpecialEdition, token))
|
||||||
|
.Select(f => (Game.SkyrimSpecialEdition, f));
|
||||||
|
var falloutContent = (await _client.ListContent(Game.Fallout4, token))
|
||||||
|
.Select(f => (Game.Fallout4, f));
|
||||||
|
|
||||||
|
foreach (var (game, content) in skyrimContent.Concat(falloutContent).OrderBy(f => f.f.Name))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Game: {game}");
|
||||||
|
Console.WriteLine($"Name: {content.Name}");
|
||||||
|
Console.WriteLine($"Download Size: {content.DepotSize.ToFileSizeString()}");
|
||||||
|
Console.WriteLine($"Uri: bethesda://{game}/{content.ContentId}");
|
||||||
|
Console.WriteLine("-----------------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
12
Wabbajack.DTOs/Logins/BethesdaNet/BeamLogin.cs
Normal file
12
Wabbajack.DTOs/Logins/BethesdaNet/BeamLogin.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Wabbajack.DTOs.Logins.BethesdaNet;
|
||||||
|
|
||||||
|
public class BeamLogin
|
||||||
|
{
|
||||||
|
[JsonPropertyName("password")]
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("language")]
|
||||||
|
public string Language { get; set; } = "en";
|
||||||
|
}
|
33
Wabbajack.DTOs/Logins/BethesdaNet/BeamLoginResponse.cs
Normal file
33
Wabbajack.DTOs/Logins/BethesdaNet/BeamLoginResponse.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Wabbajack.DTOs.Logins.BethesdaNet;
|
||||||
|
|
||||||
|
public class BeamLoginResponse
|
||||||
|
{
|
||||||
|
[JsonPropertyName("access_token")]
|
||||||
|
public string AccessToken { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("account")]
|
||||||
|
public BeamAccount Account { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BeamAccount
|
||||||
|
{
|
||||||
|
[JsonPropertyName("admin")]
|
||||||
|
public bool Admin { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("admin_read_only")]
|
||||||
|
public bool AdminReadOnly { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("mfa_enabled")]
|
||||||
|
public bool MFAEnabled { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("sms_enabled_number")]
|
||||||
|
public object sms_enabled_number { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("username")]
|
||||||
|
public string UserName { get; set; }
|
||||||
|
}
|
9
Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthPost.cs
Normal file
9
Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthPost.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Wabbajack.DTOs.Logins.BethesdaNet;
|
||||||
|
|
||||||
|
public class CDPAuthPost
|
||||||
|
{
|
||||||
|
[JsonPropertyName("access_token")]
|
||||||
|
public string AccessToken { get; set; }
|
||||||
|
}
|
19
Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthResponse.cs
Normal file
19
Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthResponse.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Wabbajack.DTOs.Logins.BethesdaNet;
|
||||||
|
|
||||||
|
public class CDPAuthResponse
|
||||||
|
{
|
||||||
|
[JsonPropertyName("entitlement_ids")]
|
||||||
|
public int[] EntitlementIds { get; set; }
|
||||||
|
[JsonPropertyName("beam_client_api_key")]
|
||||||
|
public string BeamClientApiKey { get; set; }
|
||||||
|
[JsonPropertyName("session_id")]
|
||||||
|
public string SessionId { get; set; }
|
||||||
|
[JsonPropertyName("token")]
|
||||||
|
public string Token { get; set; }
|
||||||
|
[JsonPropertyName("beam_token")]
|
||||||
|
public string[] BeamToken { get; set; }
|
||||||
|
[JsonPropertyName("oauth_token")]
|
||||||
|
public string OAuthToken { get; set; }
|
||||||
|
}
|
10
Wabbajack.DTOs/Logins/BethesdaNetLogin.cs
Normal file
10
Wabbajack.DTOs/Logins/BethesdaNetLogin.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using Wabbajack.DTOs.Logins.BethesdaNet;
|
||||||
|
|
||||||
|
namespace Wabbajack.DTOs.Logins;
|
||||||
|
|
||||||
|
public class BethesdaNetLoginState
|
||||||
|
{
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
public BeamLoginResponse? BeamResponse { get; set; }
|
||||||
|
}
|
136
Wabbajack.Networking.BethesdaNet/Client.cs
Normal file
136
Wabbajack.Networking.BethesdaNet/Client.cs
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Wabbajack.DTOs;
|
||||||
|
using Wabbajack.DTOs.Logins;
|
||||||
|
using Wabbajack.DTOs.Logins.BethesdaNet;
|
||||||
|
using Wabbajack.Networking.BethesdaNet.DTOs;
|
||||||
|
using Wabbajack.Networking.Http;
|
||||||
|
using Wabbajack.Networking.Http.Interfaces;
|
||||||
|
|
||||||
|
namespace Wabbajack.Networking.BethesdaNet;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class Client
|
||||||
|
{
|
||||||
|
private readonly ITokenProvider<BethesdaNetLoginState> _tokenProvider;
|
||||||
|
private readonly ILogger<Client> _logger;
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
private readonly JsonSerializerOptions _jsonOptions;
|
||||||
|
private CDPAuthResponse? _entitlementData = null;
|
||||||
|
public const string AgentPlatform = "WINDOWS";
|
||||||
|
public const string AgentProduct = "FALLOUT4";
|
||||||
|
public const string AgentLanguage = "en";
|
||||||
|
private const string ClientAPIKey = "FeBqmQA8wxd94RtqymKwzmtcQcaA5KHOpDkQBSegx4WePeluZTCIm5scoeKTbmGl";
|
||||||
|
private const string ClientId = "95578d65-45bf-4a03-b7f7-a43d29b9467d";
|
||||||
|
private const string AgentVersion = $"{AgentProduct};;BDK;1.0013.99999.1;{AgentPlatform}";
|
||||||
|
private string FingerprintKey { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Client(ILogger<Client> logger, HttpClient client, ITokenProvider<BethesdaNetLoginState> tokenProvider)
|
||||||
|
{
|
||||||
|
_tokenProvider = tokenProvider;
|
||||||
|
_logger = logger;
|
||||||
|
_httpClient = client;
|
||||||
|
_jsonOptions = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||||
|
};
|
||||||
|
SetFingerprint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Login(CancellationToken token)
|
||||||
|
{
|
||||||
|
var loginData = await _tokenProvider.Get();
|
||||||
|
var msg = MakeMessage(HttpMethod.Post, new Uri($"https://api.bethesda.net/beam/accounts/login/{loginData!.Username}"));
|
||||||
|
msg.Headers.Add("X-Client-API-key", ClientAPIKey);
|
||||||
|
msg.Headers.Add("x-src-fp", FingerprintKey);
|
||||||
|
msg.Headers.Add("X-Platform", AgentPlatform);
|
||||||
|
msg.Content = new StringContent(JsonSerializer.Serialize(new BeamLogin
|
||||||
|
{
|
||||||
|
Password = loginData!.Password,
|
||||||
|
Language = AgentLanguage
|
||||||
|
}, _jsonOptions), Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
var result = await _httpClient.SendAsync(msg, token);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
throw new HttpException(result);
|
||||||
|
|
||||||
|
var response = await result.Content.ReadFromJsonAsync<BeamLoginResponse>(_jsonOptions, token);
|
||||||
|
loginData.BeamResponse = response;
|
||||||
|
|
||||||
|
await _tokenProvider.SetToken(loginData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task CDPAuth(CancellationToken token)
|
||||||
|
{
|
||||||
|
var state = await _tokenProvider.Get();
|
||||||
|
if (string.IsNullOrEmpty(state.BeamResponse?.AccessToken))
|
||||||
|
throw new Exception("Can't get CDPAuth before Bethesda Net login");
|
||||||
|
|
||||||
|
var msg = MakeMessage(HttpMethod.Post, new Uri("https://api.bethesda.net/cdp-user/auth"));
|
||||||
|
msg.Headers.Add("x-src-fp", FingerprintKey);
|
||||||
|
msg.Headers.Add("x-cdp-app", "UGC SDK");
|
||||||
|
msg.Headers.Add("x-cdp-app-ver", "0.9.11314/debug");
|
||||||
|
msg.Headers.Add("x-cdp-lib-ver", "0.9.11314/debug");
|
||||||
|
msg.Headers.Add("x-cdp-platform", "Win/32");
|
||||||
|
msg.Content = new StringContent(JsonSerializer.Serialize(new CDPAuthPost()
|
||||||
|
{AccessToken = state.BeamResponse.AccessToken}), Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
var request = await _httpClient.SendAsync(msg, token);
|
||||||
|
if (!request.IsSuccessStatusCode)
|
||||||
|
throw new HttpException(request);
|
||||||
|
|
||||||
|
_entitlementData = await request.Content.ReadFromJsonAsync<CDPAuthResponse>(_jsonOptions, token);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpRequestMessage MakeMessage(HttpMethod method, Uri uri)
|
||||||
|
{
|
||||||
|
var msg = new HttpRequestMessage(method, uri);
|
||||||
|
msg.Headers.Add("User-Agent", "bnet");
|
||||||
|
msg.Headers.Add("Accept", "application/json");
|
||||||
|
msg.Headers.Add("X-BNET-Agent", AgentVersion);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetFingerprint()
|
||||||
|
{
|
||||||
|
var keyBytes = new byte[20];
|
||||||
|
using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider())
|
||||||
|
rng.GetBytes(keyBytes);
|
||||||
|
|
||||||
|
FingerprintKey = string.Concat(Array.ConvertAll(keyBytes, x => x.ToString("X2")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Content>> ListContent(Game game, CancellationToken token)
|
||||||
|
{
|
||||||
|
var gameKey = game switch
|
||||||
|
{
|
||||||
|
Game.SkyrimSpecialEdition => "SKYRIM",
|
||||||
|
Game.Fallout4 => "FALLOUT4",
|
||||||
|
_ => throw new InvalidOperationException("Only Skyrim and Fallout 4 are supported for Bethesda Net content")
|
||||||
|
};
|
||||||
|
|
||||||
|
await EnsureAuthed(token);
|
||||||
|
var authData = await _tokenProvider.Get();
|
||||||
|
var msg = MakeMessage(HttpMethod.Get,
|
||||||
|
new Uri(
|
||||||
|
$"https://api.bethesda.net/mods/ugc-workshop/list?page=1;sort=alpha;order=asc;number_results=500;platform=WINDOWS;product={gameKey};cc_mod=true"));
|
||||||
|
msg.Headers.Add("X-Access-Token", authData!.BeamResponse!.AccessToken);
|
||||||
|
var request = await _httpClient.SendAsync(msg, token);
|
||||||
|
if (!request.IsSuccessStatusCode)
|
||||||
|
throw new HttpException(request);
|
||||||
|
var response = await request.Content.ReadFromJsonAsync<ListSubscribeResponse>(_jsonOptions, token);
|
||||||
|
return response!.Platform.Response.Content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task EnsureAuthed(CancellationToken token)
|
||||||
|
{
|
||||||
|
if (_entitlementData == null)
|
||||||
|
await CDPAuth(token);
|
||||||
|
}
|
||||||
|
}
|
151
Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs
Normal file
151
Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Wabbajack.Networking.BethesdaNet.DTOs;
|
||||||
|
|
||||||
|
public class Price
|
||||||
|
{
|
||||||
|
[JsonPropertyName("currency_id")]
|
||||||
|
public int CurrencyId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("price_id")]
|
||||||
|
public int PriceId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("sale")]
|
||||||
|
public bool Sale { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("currency_name")]
|
||||||
|
public string CurrencyName { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("currency_type")]
|
||||||
|
public string CurrencyType { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("amount")]
|
||||||
|
public int Amount { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("original_amount")]
|
||||||
|
public int OriginalAmount { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Content
|
||||||
|
{
|
||||||
|
[JsonPropertyName("rating")]
|
||||||
|
public double Rating { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("version")]
|
||||||
|
public int Version { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("depot_size")]
|
||||||
|
public int DepotSize { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("is_subscribed")]
|
||||||
|
public bool IsSubscribed { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("preview_file_size")]
|
||||||
|
public int PreviewFileSize { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("preview_file_url")]
|
||||||
|
public string PreviewFileUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("is_following")]
|
||||||
|
public bool IsFollowing { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("wip")]
|
||||||
|
public bool Wip { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("is_published")]
|
||||||
|
public bool IsPublished { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("user_rating")]
|
||||||
|
public int UserRating { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("platform")]
|
||||||
|
public List<string> Platform { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("state")]
|
||||||
|
public int State { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("rating_count")]
|
||||||
|
public int RatingCount { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("cdp_branch_id")]
|
||||||
|
public int CdpBranchId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("type")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("username")]
|
||||||
|
public string Username { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("product")]
|
||||||
|
public string Product { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("updated")]
|
||||||
|
public string Updated { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("cc_mod")]
|
||||||
|
public bool CcMod { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("bundle")]
|
||||||
|
public bool Bundle { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("prices")]
|
||||||
|
public List<Price> Prices { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("is_public")]
|
||||||
|
public bool IsPublic { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("catalog_item_id")]
|
||||||
|
public int CatalogItemId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("is_auto_moderated")]
|
||||||
|
public bool IsAutoModerated { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("content_id")]
|
||||||
|
public string ContentId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("cdp_product_id")]
|
||||||
|
public int CdpProductId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Response
|
||||||
|
{
|
||||||
|
[JsonPropertyName("product")]
|
||||||
|
public List<string> Product { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("total_results_count")]
|
||||||
|
public int TotalResultsCount { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("content")]
|
||||||
|
public List<Content> Content { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("platform")]
|
||||||
|
public List<string> Platform { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("page_results_count")]
|
||||||
|
public int PageResultsCount { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("page")]
|
||||||
|
public int Page { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Platform
|
||||||
|
{
|
||||||
|
[JsonPropertyName("message")]
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("code")]
|
||||||
|
public int Code { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("response")]
|
||||||
|
public Response Response { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ListSubscribeResponse
|
||||||
|
{
|
||||||
|
[JsonPropertyName("platform")]
|
||||||
|
public Platform Platform { get; set; }
|
||||||
|
}
|
||||||
|
|
11
Wabbajack.Networking.BethesdaNet/ServiceExtensions.cs
Normal file
11
Wabbajack.Networking.BethesdaNet/ServiceExtensions.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Wabbajack.Networking.BethesdaNet;
|
||||||
|
|
||||||
|
public static class ServiceExtensions
|
||||||
|
{
|
||||||
|
public static void AddBethesdaNet(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<BethesdaNet.Client>();
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ using Wabbajack.Downloaders.GameFile;
|
|||||||
using Wabbajack.DTOs;
|
using Wabbajack.DTOs;
|
||||||
using Wabbajack.DTOs.Logins;
|
using Wabbajack.DTOs.Logins;
|
||||||
using Wabbajack.Installer;
|
using Wabbajack.Installer;
|
||||||
|
using Wabbajack.Networking.BethesdaNet;
|
||||||
using Wabbajack.Networking.Discord;
|
using Wabbajack.Networking.Discord;
|
||||||
using Wabbajack.Networking.Http;
|
using Wabbajack.Networking.Http;
|
||||||
using Wabbajack.Networking.Http.Interfaces;
|
using Wabbajack.Networking.Http.Interfaces;
|
||||||
@ -111,9 +112,11 @@ public static class ServiceExtensions
|
|||||||
|
|
||||||
service.AddSingleton<Client>();
|
service.AddSingleton<Client>();
|
||||||
service.AddSingleton<WriteOnlyClient>();
|
service.AddSingleton<WriteOnlyClient>();
|
||||||
|
service.AddBethesdaNet();
|
||||||
|
|
||||||
// Token Providers
|
// Token Providers
|
||||||
service.AddAllSingleton<ITokenProvider<NexusApiState>, EncryptedJsonTokenProvider<NexusApiState>, NexusApiTokenProvider>();
|
service.AddAllSingleton<ITokenProvider<NexusApiState>, EncryptedJsonTokenProvider<NexusApiState>, NexusApiTokenProvider>();
|
||||||
|
service.AddAllSingleton<ITokenProvider<BethesdaNetLoginState>, EncryptedJsonTokenProvider<BethesdaNetLoginState>, BethesdaNetTokenProvider>();
|
||||||
service
|
service
|
||||||
.AddAllSingleton<ITokenProvider<LoversLabLoginState>, EncryptedJsonTokenProvider<LoversLabLoginState>,
|
.AddAllSingleton<ITokenProvider<LoversLabLoginState>, EncryptedJsonTokenProvider<LoversLabLoginState>,
|
||||||
LoversLabTokenProvider>();
|
LoversLabTokenProvider>();
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Wabbajack.DTOs.JsonConverters;
|
||||||
|
using Wabbajack.DTOs.Logins;
|
||||||
|
|
||||||
|
namespace Wabbajack.Services.OSIntegrated.TokenProviders;
|
||||||
|
|
||||||
|
public class BethesdaNetTokenProvider : EncryptedJsonTokenProvider<BethesdaNetLoginState>
|
||||||
|
{
|
||||||
|
public BethesdaNetTokenProvider(ILogger<BethesdaNetLoginState> logger, DTOSerializer dtos) : base(logger, dtos,
|
||||||
|
"bethesda-net")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@
|
|||||||
<ProjectReference Include="..\Wabbajack.Compiler\Wabbajack.Compiler.csproj" />
|
<ProjectReference Include="..\Wabbajack.Compiler\Wabbajack.Compiler.csproj" />
|
||||||
<ProjectReference Include="..\Wabbajack.Downloaders.Dispatcher\Wabbajack.Downloaders.Dispatcher.csproj" />
|
<ProjectReference Include="..\Wabbajack.Downloaders.Dispatcher\Wabbajack.Downloaders.Dispatcher.csproj" />
|
||||||
<ProjectReference Include="..\Wabbajack.Installer\Wabbajack.Installer.csproj" />
|
<ProjectReference Include="..\Wabbajack.Installer\Wabbajack.Installer.csproj" />
|
||||||
|
<ProjectReference Include="..\Wabbajack.Networking.BethesdaNet\Wabbajack.Networking.BethesdaNet.csproj" />
|
||||||
<ProjectReference Include="..\Wabbajack.Networking.Discord\Wabbajack.Networking.Discord.csproj" />
|
<ProjectReference Include="..\Wabbajack.Networking.Discord\Wabbajack.Networking.Discord.csproj" />
|
||||||
<ProjectReference Include="..\Wabbajack.Networking.Steam\Wabbajack.Networking.Steam.csproj" />
|
<ProjectReference Include="..\Wabbajack.Networking.Steam\Wabbajack.Networking.Steam.csproj" />
|
||||||
<ProjectReference Include="..\Wabbajack.VFS\Wabbajack.VFS.csproj" />
|
<ProjectReference Include="..\Wabbajack.VFS\Wabbajack.VFS.csproj" />
|
||||||
|
@ -133,6 +133,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.IO.Async", "Wabba
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Compression.Zip.Test", "Wabbajack.Compression.Zip.Test\Wabbajack.Compression.Zip.Test.csproj", "{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Compression.Zip.Test", "Wabbajack.Compression.Zip.Test\Wabbajack.Compression.Zip.Test.csproj", "{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Networking.BethesdaNet", "Wabbajack.Networking.BethesdaNet\Wabbajack.Networking.BethesdaNet.csproj", "{A3813D73-9A8E-4CE7-861A-C59043DFFC14}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -363,6 +365,10 @@ Global
|
|||||||
{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -408,6 +414,7 @@ Global
|
|||||||
{10165025-D30B-44B7-A764-50E15603AE56} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C}
|
{10165025-D30B-44B7-A764-50E15603AE56} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C}
|
||||||
{64AD7E26-5643-4969-A61C-E0A90FA25FCB} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C}
|
{64AD7E26-5643-4969-A61C-E0A90FA25FCB} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C}
|
||||||
{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C}
|
{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C}
|
||||||
|
{A3813D73-9A8E-4CE7-861A-C59043DFFC14} = {F01F8595-5FD7-4506-8469-F4A5522DACC1}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {0AA30275-0F38-4A7D-B645-F5505178DDE8}
|
SolutionGuid = {0AA30275-0F38-4A7D-B645-F5505178DDE8}
|
||||||
|
Loading…
Reference in New Issue
Block a user