mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Merge branch 'master' into issue-520
This commit is contained in:
commit
109681b2c6
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||||
|
@ -112,6 +112,9 @@ namespace Wabbajack.BuildServer.Controllers
|
|||||||
Utils.Log("No valid INI parser for: \n" + iniString);
|
Utils.Log("No valid INI parser for: \n" + iniString);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data is ManualDownloader.State)
|
||||||
|
continue;
|
||||||
|
|
||||||
var key = data.PrimaryKeyString;
|
var key = data.PrimaryKeyString;
|
||||||
var found = await Db.DownloadStates.AsQueryable().Where(f => f.Key == key).Take(1).ToListAsync();
|
var found = await Db.DownloadStates.AsQueryable().Where(f => f.Key == key).Take(1).ToListAsync();
|
||||||
|
@ -24,6 +24,9 @@ namespace Wabbajack.BuildServer.Models.Jobs
|
|||||||
public override bool UsesNexus { get => Archive.State is NexusDownloader.State; }
|
public override bool UsesNexus { get => Archive.State is NexusDownloader.State; }
|
||||||
public override async Task<JobResult> Execute(DBContext db, SqlService sql, AppSettings settings)
|
public override async Task<JobResult> Execute(DBContext db, SqlService sql, AppSettings settings)
|
||||||
{
|
{
|
||||||
|
if (Archive.State is ManualDownloader.State)
|
||||||
|
return JobResult.Success();
|
||||||
|
|
||||||
var pk = new List<object>();
|
var pk = new List<object>();
|
||||||
pk.Add(AbstractDownloadState.TypeToName[Archive.State.GetType()]);
|
pk.Add(AbstractDownloadState.TypeToName[Archive.State.GetType()]);
|
||||||
pk.AddRange(Archive.State.PrimaryKey);
|
pk.AddRange(Archive.State.PrimaryKey);
|
||||||
|
@ -102,5 +102,6 @@ namespace Wabbajack.Common
|
|||||||
public const string MO2ModFolderName = "mods";
|
public const string MO2ModFolderName = "mods";
|
||||||
|
|
||||||
public static string PatchCacheFolder => Path.Combine(LocalAppDataPath, "patch_cache");
|
public static string PatchCacheFolder => Path.Combine(LocalAppDataPath, "patch_cache");
|
||||||
|
public static int MaxConnectionsPerServer = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
62
Wabbajack.Common/Http/Client.cs
Normal file
62
Wabbajack.Common/Http/Client.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Wabbajack.Common.Http
|
||||||
|
{
|
||||||
|
public class Client
|
||||||
|
{
|
||||||
|
public List<(string, string)> Headers = new List<(string, string)>();
|
||||||
|
public List<Cookie> Cookies = new List<Cookie>();
|
||||||
|
public async Task<HttpResponseMessage> GetAsync(string url, HttpCompletionOption responseHeadersRead = HttpCompletionOption.ResponseContentRead)
|
||||||
|
{
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||||
|
foreach (var (k, v) in Headers)
|
||||||
|
request.Headers.Add(k, v);
|
||||||
|
return await SendAsync(request, responseHeadersRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetStringAsync(string url)
|
||||||
|
{
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||||
|
foreach (var (k, v) in Headers)
|
||||||
|
request.Headers.Add(k, v);
|
||||||
|
if (Cookies.Count > 0)
|
||||||
|
Cookies.ForEach(c => ClientFactory.Cookies.Add(c));
|
||||||
|
|
||||||
|
return await SendStringAsync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> SendStringAsync(HttpRequestMessage request)
|
||||||
|
{
|
||||||
|
var result = await SendAsync(request);
|
||||||
|
return await result.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage msg, HttpCompletionOption responseHeadersRead = HttpCompletionOption.ResponseContentRead)
|
||||||
|
{
|
||||||
|
int retries = 0;
|
||||||
|
TOP:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await ClientFactory.Client.SendAsync(msg, responseHeadersRead);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
if (retries > Consts.MaxHTTPRetries) throw;
|
||||||
|
|
||||||
|
retries++;
|
||||||
|
Utils.Log($"Http Connect error to {msg.RequestUri} retry {retries}");
|
||||||
|
await Task.Delay(100 * retries);
|
||||||
|
goto TOP;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
Wabbajack.Common/Http/ClientFactory.cs
Normal file
25
Wabbajack.Common/Http/ClientFactory.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using SysHttp = System.Net.Http;
|
||||||
|
namespace Wabbajack.Common.Http
|
||||||
|
{
|
||||||
|
public static class ClientFactory
|
||||||
|
{
|
||||||
|
private static SysHttp.SocketsHttpHandler _socketsHandler { get; }
|
||||||
|
internal static SysHttp.HttpClient Client { get; }
|
||||||
|
internal static CookieContainer Cookies { get; }
|
||||||
|
|
||||||
|
static ClientFactory()
|
||||||
|
{
|
||||||
|
Cookies = new CookieContainer();
|
||||||
|
_socketsHandler = new SysHttp.SocketsHttpHandler
|
||||||
|
{
|
||||||
|
CookieContainer = Cookies,
|
||||||
|
MaxConnectionsPerServer = 8,
|
||||||
|
PooledConnectionLifetime = TimeSpan.FromSeconds(2),
|
||||||
|
PooledConnectionIdleTimeout = TimeSpan.FromSeconds(2)
|
||||||
|
};
|
||||||
|
Client = new SysHttp.HttpClient(_socketsHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -32,7 +32,7 @@ namespace Wabbajack.Common
|
|||||||
var tempKey = progIDKey?.OpenSubKey("shell\\open\\command");
|
var tempKey = progIDKey?.OpenSubKey("shell\\open\\command");
|
||||||
if (progIDKey == null || tempKey == null) return true;
|
if (progIDKey == null || tempKey == null) return true;
|
||||||
var value = tempKey.GetValue("");
|
var value = tempKey.GetValue("");
|
||||||
return value == null || value.ToString().Equals($"\"{appPath}\" -i=\"%1\"");
|
return value == null || !value.ToString().Equals($"\"{appPath}\" -i=\"%1\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsAssociated()
|
public static bool IsAssociated()
|
||||||
|
@ -53,15 +53,18 @@ namespace Wabbajack.Common
|
|||||||
if (!Directory.Exists(Consts.LocalAppDataPath))
|
if (!Directory.Exists(Consts.LocalAppDataPath))
|
||||||
Directory.CreateDirectory(Consts.LocalAppDataPath);
|
Directory.CreateDirectory(Consts.LocalAppDataPath);
|
||||||
|
|
||||||
|
if (!Directory.Exists("logs"))
|
||||||
|
Directory.CreateDirectory("logs");
|
||||||
|
|
||||||
var programName = Assembly.GetEntryAssembly()?.Location ?? "Wabbajack";
|
var programName = Assembly.GetEntryAssembly()?.Location ?? "Wabbajack";
|
||||||
LogFile = Path.GetFileNameWithoutExtension(programName) + ".current.log";
|
LogFile = Path.Combine("logs", Path.GetFileNameWithoutExtension(programName) + ".current.log");
|
||||||
_startTime = DateTime.Now;
|
_startTime = DateTime.Now;
|
||||||
|
|
||||||
|
|
||||||
if (LogFile.FileExists())
|
if (LogFile.FileExists())
|
||||||
{
|
{
|
||||||
var new_path = Path.GetFileNameWithoutExtension(programName) + (new FileInfo(LogFile)).LastWriteTime.ToString(" yyyy-MM-dd HH_mm_ss") + ".log";
|
var newPath = Path.Combine("logs", Path.GetFileNameWithoutExtension(programName) + (new FileInfo(LogFile)).LastWriteTime.ToString(" yyyy-MM-dd HH_mm_ss") + ".log");
|
||||||
File.Move(LogFile, new_path, MoveOptions.ReplaceExisting);
|
File.Move(LogFile, newPath, MoveOptions.ReplaceExisting);
|
||||||
}
|
}
|
||||||
|
|
||||||
var watcher = new FileSystemWatcher(Consts.LocalAppDataPath);
|
var watcher = new FileSystemWatcher(Consts.LocalAppDataPath);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||||
|
|
||||||
@ -40,6 +40,7 @@
|
|||||||
<PackageReference Include="ReactiveUI" Version="11.1.23" />
|
<PackageReference Include="ReactiveUI" Version="11.1.23" />
|
||||||
<PackageReference Include="SharpZipLib" Version="1.2.0" />
|
<PackageReference Include="SharpZipLib" Version="1.2.0" />
|
||||||
<PackageReference Include="System.Data.HashFunction.xxHash" Version="2.0.0" />
|
<PackageReference Include="System.Data.HashFunction.xxHash" Version="2.0.0" />
|
||||||
|
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
|
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
|
||||||
<PackageReference Include="System.Security.Principal.Windows" Version="4.7.0" />
|
<PackageReference Include="System.Security.Principal.Windows" Version="4.7.0" />
|
||||||
<PackageReference Include="YamlDotNet" Version="8.1.0" />
|
<PackageReference Include="YamlDotNet" Version="8.1.0" />
|
||||||
|
@ -22,7 +22,7 @@ namespace Wabbajack.Lib
|
|||||||
public bool ReadmeIsWebsite;
|
public bool ReadmeIsWebsite;
|
||||||
public string WabbajackVersion;
|
public string WabbajackVersion;
|
||||||
|
|
||||||
protected static string _vfsCacheName => Path.Combine(Consts.LocalAppDataPath, "vfs_compile_cache.bin");
|
protected string _vfsCacheName => Path.Combine(Consts.LocalAppDataPath, $"vfs_compile_cache_{ModListName?.StringSHA256Hex() ?? "_Unknown_"}.bin");
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A stream of tuples of ("Update Title", 0.25) which represent the name of the current task
|
/// A stream of tuples of ("Update Title", 0.25) which represent the name of the current task
|
||||||
/// and the current progress.
|
/// and the current progress.
|
||||||
|
@ -21,7 +21,7 @@ namespace Wabbajack.Lib.Downloaders
|
|||||||
private readonly string _encryptedKeyName;
|
private readonly string _encryptedKeyName;
|
||||||
private readonly string _cookieDomain;
|
private readonly string _cookieDomain;
|
||||||
private readonly string _cookieName;
|
private readonly string _cookieName;
|
||||||
internal HttpClient AuthedClient;
|
internal Common.Http.Client AuthedClient;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets up all the login facilites needed for a INeedsLogin downloader based on having the user log
|
/// Sets up all the login facilites needed for a INeedsLogin downloader based on having the user log
|
||||||
@ -81,7 +81,7 @@ namespace Wabbajack.Lib.Downloaders
|
|||||||
return cookies;
|
return cookies;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<HttpClient> GetAuthedClient()
|
public async Task<Common.Http.Client> GetAuthedClient()
|
||||||
{
|
{
|
||||||
Helpers.Cookie[] cookies;
|
Helpers.Cookie[] cookies;
|
||||||
try
|
try
|
||||||
|
@ -53,7 +53,7 @@ namespace Wabbajack.Lib.Downloaders
|
|||||||
private async Task<HTTPDownloader.State> ToHttpState()
|
private async Task<HTTPDownloader.State> ToHttpState()
|
||||||
{
|
{
|
||||||
var initialURL = $"https://drive.google.com/uc?id={Id}&export=download";
|
var initialURL = $"https://drive.google.com/uc?id={Id}&export=download";
|
||||||
var client = new HttpClient();
|
var client = new Common.Http.Client();
|
||||||
var response = await client.GetAsync(initialURL);
|
var response = await client.GetAsync(initialURL);
|
||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
throw new HttpException((int)response.StatusCode, response.ReasonPhrase);
|
throw new HttpException((int)response.StatusCode, response.ReasonPhrase);
|
||||||
|
@ -61,7 +61,7 @@ namespace Wabbajack.Lib.Downloaders
|
|||||||
public List<string> Headers { get; set; }
|
public List<string> Headers { get; set; }
|
||||||
|
|
||||||
[Exclude]
|
[Exclude]
|
||||||
public HttpClient Client { get; set; }
|
public Common.Http.Client Client { get; set; }
|
||||||
|
|
||||||
public override object[] PrimaryKey { get => new object[] {Url};}
|
public override object[] PrimaryKey { get => new object[] {Url};}
|
||||||
|
|
||||||
@ -86,8 +86,8 @@ namespace Wabbajack.Lib.Downloaders
|
|||||||
|
|
||||||
using (var fs = download ? File.Open(destination, FileMode.Create) : null)
|
using (var fs = download ? File.Open(destination, FileMode.Create) : null)
|
||||||
{
|
{
|
||||||
var client = Client ?? new HttpClient();
|
var client = Client ?? new Common.Http.Client();
|
||||||
client.DefaultRequestHeaders.Add("User-Agent", Consts.UserAgent);
|
client.Headers.Add(("User-Agent", Consts.UserAgent));
|
||||||
|
|
||||||
if (Headers != null)
|
if (Headers != null)
|
||||||
foreach (var header in Headers)
|
foreach (var header in Headers)
|
||||||
@ -95,7 +95,7 @@ namespace Wabbajack.Lib.Downloaders
|
|||||||
var idx = header.IndexOf(':');
|
var idx = header.IndexOf(':');
|
||||||
var k = header.Substring(0, idx);
|
var k = header.Substring(0, idx);
|
||||||
var v = header.Substring(idx + 1);
|
var v = header.Substring(idx + 1);
|
||||||
client.DefaultRequestHeaders.Add(k, v);
|
client.Headers.Add((k, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
long totalRead = 0;
|
long totalRead = 0;
|
||||||
|
@ -53,7 +53,7 @@ namespace Wabbajack.Lib.Downloaders
|
|||||||
if (newURL == null || !newURL.StartsWith("http")) return null;
|
if (newURL == null || !newURL.StartsWith("http")) return null;
|
||||||
return new HTTPDownloader.State()
|
return new HTTPDownloader.State()
|
||||||
{
|
{
|
||||||
Client = new HttpClient(),
|
Client = new Common.Http.Client(),
|
||||||
Url = newURL
|
Url = newURL
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ namespace Wabbajack.Lib.FileUploader
|
|||||||
|
|
||||||
public static HttpClient GetAuthorizedClient()
|
public static HttpClient GetAuthorizedClient()
|
||||||
{
|
{
|
||||||
var handler = new HttpClientHandler {MaxConnectionsPerServer = MAX_CONNECTIONS};
|
var handler = new HttpClientHandler {MaxConnectionsPerServer = Consts.MaxConnectionsPerServer};
|
||||||
var client = new HttpClient(handler);
|
var client = new HttpClient(handler);
|
||||||
client.DefaultRequestHeaders.Add("X-API-KEY", AuthorAPI.GetAPIKey());
|
client.DefaultRequestHeaders.Add("X-API-KEY", AuthorAPI.GetAPIKey());
|
||||||
return client;
|
return client;
|
||||||
@ -144,7 +144,7 @@ namespace Wabbajack.Lib.FileUploader
|
|||||||
return await RunJob("UpdateModLists");
|
return await RunJob("UpdateModLists");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task UploadPackagedInis(IEnumerable<IndexedArchive> archives)
|
public static async Task UploadPackagedInis(WorkQueue queue, IEnumerable<Archive> archives)
|
||||||
{
|
{
|
||||||
archives = archives.ToArray(); // defensive copy
|
archives = archives.ToArray(); // defensive copy
|
||||||
Utils.Log($"Packaging {archives.Count()} inis");
|
Utils.Log($"Packaging {archives.Count()} inis");
|
||||||
@ -153,12 +153,12 @@ namespace Wabbajack.Lib.FileUploader
|
|||||||
await using var ms = new MemoryStream();
|
await using var ms = new MemoryStream();
|
||||||
using (var z = new ZipArchive(ms, ZipArchiveMode.Create, true))
|
using (var z = new ZipArchive(ms, ZipArchiveMode.Create, true))
|
||||||
{
|
{
|
||||||
foreach (var archive in archives)
|
foreach (var e in archives)
|
||||||
{
|
{
|
||||||
var state = (AbstractDownloadState)(await DownloadDispatcher.ResolveArchive(archive.IniData));
|
if (e.State == null) continue;
|
||||||
var entry = z.CreateEntry(Path.GetFileName(archive.Name));
|
var entry = z.CreateEntry(Path.GetFileName(e.Name));
|
||||||
await using var os = entry.Open();
|
await using var os = entry.Open();
|
||||||
await os.WriteAsync(Encoding.UTF8.GetBytes(string.Join("\n", state.GetMetaIni())));
|
await os.WriteAsync(Encoding.UTF8.GetBytes(string.Join("\n", e.State.GetMetaIni())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +16,11 @@ namespace Wabbajack.Lib.LibCefHelpers
|
|||||||
{
|
{
|
||||||
public static class Helpers
|
public static class Helpers
|
||||||
{
|
{
|
||||||
public static HttpClient GetClient(IEnumerable<Cookie> cookies, string referer)
|
public static Common.Http.Client GetClient(IEnumerable<Cookie> cookies, string referer)
|
||||||
{
|
{
|
||||||
var container = ToCookieContainer(cookies);
|
var client = new Common.Http.Client();
|
||||||
var handler = new HttpClientHandler { CookieContainer = container };
|
client.Headers.Add(("Referrer", referer));
|
||||||
var client = new HttpClient(handler);
|
client.Cookies.AddRange(cookies.Select(cookie => new System.Net.Cookie(cookie.Name, cookie.Value, cookie.Path, cookie.Domain)));
|
||||||
client.DefaultRequestHeaders.Referrer = new Uri(referer);
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +123,13 @@ namespace Wabbajack.Lib
|
|||||||
.Where(p => p.FileExists())
|
.Where(p => p.FileExists())
|
||||||
.Select(p => new RawSourceFile(VFS.Index.ByRootPath[p], Path.Combine(Consts.LOOTFolderFilesDir, p.RelativeTo(lootPath))));
|
.Select(p => new RawSourceFile(VFS.Index.ByRootPath[p], Path.Combine(Consts.LOOTFolderFilesDir, p.RelativeTo(lootPath))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancel.IsCancellationRequested) return false;
|
if (cancel.IsCancellationRequested) return false;
|
||||||
UpdateTracker.NextStep("Cleaning output folder");
|
UpdateTracker.NextStep("Cleaning output folder");
|
||||||
if (Directory.Exists(ModListOutputFolder))
|
if (Directory.Exists(ModListOutputFolder))
|
||||||
Utils.DeleteDirectory(ModListOutputFolder);
|
Utils.DeleteDirectory(ModListOutputFolder);
|
||||||
|
|
||||||
|
/*
|
||||||
if (cancel.IsCancellationRequested) return false;
|
if (cancel.IsCancellationRequested) return false;
|
||||||
UpdateTracker.NextStep("Inferring metas for game file downloads");
|
UpdateTracker.NextStep("Inferring metas for game file downloads");
|
||||||
await InferMetas();
|
await InferMetas();
|
||||||
@ -137,9 +138,11 @@ namespace Wabbajack.Lib
|
|||||||
UpdateTracker.NextStep("Reindexing downloads after meta inferring");
|
UpdateTracker.NextStep("Reindexing downloads after meta inferring");
|
||||||
await VFS.AddRoot(MO2DownloadsFolder);
|
await VFS.AddRoot(MO2DownloadsFolder);
|
||||||
await VFS.WriteToFile(_vfsCacheName);
|
await VFS.WriteToFile(_vfsCacheName);
|
||||||
|
*/
|
||||||
|
|
||||||
if (cancel.IsCancellationRequested) return false;
|
if (cancel.IsCancellationRequested) return false;
|
||||||
UpdateTracker.NextStep("Pre-validating Archives");
|
UpdateTracker.NextStep("Pre-validating Archives");
|
||||||
|
|
||||||
|
|
||||||
IndexedArchives = Directory.EnumerateFiles(MO2DownloadsFolder)
|
IndexedArchives = Directory.EnumerateFiles(MO2DownloadsFolder)
|
||||||
.Where(f => File.Exists(f + Consts.MetaFileExtension))
|
.Where(f => File.Exists(f + Consts.MetaFileExtension))
|
||||||
@ -152,8 +155,7 @@ namespace Wabbajack.Lib
|
|||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Don't await this because we don't care if it fails.
|
|
||||||
var _ = AuthorAPI.UploadPackagedInis(IndexedArchives);
|
|
||||||
|
|
||||||
await CleanInvalidArchives();
|
await CleanInvalidArchives();
|
||||||
|
|
||||||
@ -261,6 +263,11 @@ namespace Wabbajack.Lib
|
|||||||
|
|
||||||
UpdateTracker.NextStep("Gathering Archives");
|
UpdateTracker.NextStep("Gathering Archives");
|
||||||
await GatherArchives();
|
await GatherArchives();
|
||||||
|
|
||||||
|
// Don't await this because we don't care if it fails.
|
||||||
|
Utils.Log("Finding States to package");
|
||||||
|
await AuthorAPI.UploadPackagedInis(Queue, SelectedArchives.ToArray());
|
||||||
|
|
||||||
UpdateTracker.NextStep("Including Archive Metadata");
|
UpdateTracker.NextStep("Including Archive Metadata");
|
||||||
await IncludeArchiveMetadata();
|
await IncludeArchiveMetadata();
|
||||||
UpdateTracker.NextStep("Building Patches");
|
UpdateTracker.NextStep("Building Patches");
|
||||||
@ -348,8 +355,16 @@ namespace Wabbajack.Lib
|
|||||||
var response =
|
var response =
|
||||||
await client.GetAsync(
|
await client.GetAsync(
|
||||||
$"http://build.wabbajack.org/indexed_files/{vf.Hash.FromBase64().ToHex()}/meta.ini");
|
$"http://build.wabbajack.org/indexed_files/{vf.Hash.FromBase64().ToHex()}/meta.ini");
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode) return;
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
File.WriteAllLines(vf.FullPath + Consts.MetaFileExtension, new []
|
||||||
|
{
|
||||||
|
"[General]",
|
||||||
|
"unknownArchive=true"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var ini_data = await response.Content.ReadAsStringAsync();
|
var ini_data = await response.Content.ReadAsStringAsync();
|
||||||
Utils.Log($"Inferred .meta for {Path.GetFileName(vf.FullPath)}, writing to disk");
|
Utils.Log($"Inferred .meta for {Path.GetFileName(vf.FullPath)}, writing to disk");
|
||||||
|
@ -23,10 +23,8 @@ namespace Wabbajack.Lib.NexusApi
|
|||||||
{
|
{
|
||||||
private static readonly string API_KEY_CACHE_FILE = "nexus.key_cache";
|
private static readonly string API_KEY_CACHE_FILE = "nexus.key_cache";
|
||||||
private static string _additionalEntropy = "vtP2HF6ezg";
|
private static string _additionalEntropy = "vtP2HF6ezg";
|
||||||
|
|
||||||
private static object _diskLock = new object();
|
public Common.Http.Client HttpClient { get; } = new Common.Http.Client();
|
||||||
|
|
||||||
public HttpClient HttpClient { get; } = new HttpClient();
|
|
||||||
|
|
||||||
#region Authentication
|
#region Authentication
|
||||||
|
|
||||||
@ -202,14 +200,13 @@ namespace Wabbajack.Lib.NexusApi
|
|||||||
{
|
{
|
||||||
ApiKey = apiKey;
|
ApiKey = apiKey;
|
||||||
|
|
||||||
HttpClient.BaseAddress = new Uri("https://api.nexusmods.com");
|
|
||||||
// set default headers for all requests to the Nexus API
|
// set default headers for all requests to the Nexus API
|
||||||
var headers = HttpClient.DefaultRequestHeaders;
|
var headers = HttpClient.Headers;
|
||||||
headers.Add("User-Agent", Consts.UserAgent);
|
headers.Add(("User-Agent", Consts.UserAgent));
|
||||||
headers.Add("apikey", ApiKey);
|
headers.Add(("apikey", ApiKey));
|
||||||
headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
headers.Add(("Accept", "application/json"));
|
||||||
headers.Add("Application-Name", Consts.AppName);
|
headers.Add(("Application-Name", Consts.AppName));
|
||||||
headers.Add("Application-Version", $"{Assembly.GetEntryAssembly()?.GetName()?.Version ?? new Version(0, 1)}");
|
headers.Add(("Application-Version", $"{Assembly.GetEntryAssembly()?.GetName()?.Version ?? new Version(0, 1)}"));
|
||||||
|
|
||||||
if (!Directory.Exists(Consts.NexusCacheDirectory))
|
if (!Directory.Exists(Consts.NexusCacheDirectory))
|
||||||
Directory.CreateDirectory(Consts.NexusCacheDirectory);
|
Directory.CreateDirectory(Consts.NexusCacheDirectory);
|
||||||
@ -227,16 +224,17 @@ namespace Wabbajack.Lib.NexusApi
|
|||||||
TOP:
|
TOP:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await HttpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
using var response = await HttpClient.GetAsync(url, HttpCompletionOption.ResponseContentRead);
|
||||||
UpdateRemaining(response);
|
UpdateRemaining(response);
|
||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
throw new HttpRequestException($"{response.StatusCode} - {response.ReasonPhrase}");
|
|
||||||
|
|
||||||
|
|
||||||
using (var stream = await response.Content.ReadAsStreamAsync())
|
|
||||||
{
|
{
|
||||||
return stream.FromJSON<T>();
|
Utils.Log($"Nexus call failed: {response.RequestMessage}");
|
||||||
|
throw new HttpRequestException($"{response.StatusCode} - {response.ReasonPhrase}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await using var stream = await response.Content.ReadAsStreamAsync();
|
||||||
|
return stream.FromJSON<T>();
|
||||||
}
|
}
|
||||||
catch (TimeoutException)
|
catch (TimeoutException)
|
||||||
{
|
{
|
||||||
@ -246,13 +244,18 @@ namespace Wabbajack.Lib.NexusApi
|
|||||||
retries++;
|
retries++;
|
||||||
goto TOP;
|
goto TOP;
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Utils.Log(e.ToString());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<T> GetCached<T>(string url)
|
private async Task<T> GetCached<T>(string url)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var builder = new UriBuilder(url) { Host = Consts.WabbajackCacheHostname, Port = Consts.WabbajackCachePort, Scheme = "http" };
|
var builder = new UriBuilder(url) { Host = Consts.WabbajackCacheHostname, Scheme = "https" };
|
||||||
return await Get<T>(builder.ToString());
|
return await Get<T>(builder.ToString());
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@ -273,6 +276,10 @@ namespace Wabbajack.Lib.NexusApi
|
|||||||
}
|
}
|
||||||
catch (HttpRequestException)
|
catch (HttpRequestException)
|
||||||
{
|
{
|
||||||
|
if (await IsPremium())
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -319,19 +326,6 @@ namespace Wabbajack.Lib.NexusApi
|
|||||||
return await GetCached<ModInfo>(url);
|
return await GetCached<ModInfo>(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EndorsementResponse> EndorseMod(NexusDownloader.State mod)
|
|
||||||
{
|
|
||||||
Utils.Status($"Endorsing ${mod.GameName} - ${mod.ModID}");
|
|
||||||
var url = $"https://api.nexusmods.com/v1/games/{ConvertGameName(mod.GameName)}/mods/{mod.ModID}/endorse.json";
|
|
||||||
|
|
||||||
var content = new FormUrlEncodedContent(new Dictionary<string, string> { { "version", mod.Version } });
|
|
||||||
|
|
||||||
using (var stream = await HttpClient.PostStream(url, content))
|
|
||||||
{
|
|
||||||
return stream.FromJSON<EndorsementResponse>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DownloadLink
|
private class DownloadLink
|
||||||
{
|
{
|
||||||
public string URI { get; set; }
|
public string URI { get; set; }
|
||||||
|
@ -12,8 +12,8 @@ namespace Wabbajack.Lib
|
|||||||
public override string ShortDescription { get; }
|
public override string ShortDescription { get; }
|
||||||
public override string ExtendedDescription { get; }
|
public override string ExtendedDescription { get; }
|
||||||
|
|
||||||
private TaskCompletionSource<(Uri, HttpClient)> _tcs = new TaskCompletionSource<(Uri, HttpClient)>();
|
private TaskCompletionSource<(Uri, Common.Http.Client)> _tcs = new TaskCompletionSource<(Uri, Common.Http.Client)>();
|
||||||
public Task<(Uri, HttpClient)> Task => _tcs.Task;
|
public Task<(Uri, Common.Http.Client)> Task => _tcs.Task;
|
||||||
|
|
||||||
private ManuallyDownloadFile(ManualDownloader.State state)
|
private ManuallyDownloadFile(ManualDownloader.State state)
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ namespace Wabbajack.Lib
|
|||||||
_tcs.SetCanceled();
|
_tcs.SetCanceled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Resume(Uri s, HttpClient client)
|
public void Resume(Uri s, Common.Http.Client client)
|
||||||
{
|
{
|
||||||
_tcs.SetResult((s, client));
|
_tcs.SetResult((s, client));
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -24,7 +24,7 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
Utils.Log("Cleaning VFS, this may take a bit of time");
|
Utils.Log("Cleaning VFS, this may take a bit of time");
|
||||||
Utils.DeleteDirectory(_stagingFolder);
|
Utils.DeleteDirectory(_stagingFolder);
|
||||||
}
|
}
|
||||||
public const ulong FileVersion = 0x02;
|
public const ulong FileVersion = 0x03;
|
||||||
public const string Magic = "WABBAJACK VFS FILE";
|
public const string Magic = "WABBAJACK VFS FILE";
|
||||||
|
|
||||||
private static readonly string _stagingFolder = "vfs_staging";
|
private static readonly string _stagingFolder = "vfs_staging";
|
||||||
@ -420,13 +420,16 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
public TemporaryDirectory(string name)
|
public TemporaryDirectory(string name)
|
||||||
{
|
{
|
||||||
FullName = name;
|
FullName = name;
|
||||||
|
if (!Directory.Exists(FullName))
|
||||||
|
Directory.CreateDirectory(FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string FullName { get; }
|
public string FullName { get; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Utils.DeleteDirectory(FullName);
|
if (Directory.Exists(FullName))
|
||||||
|
Utils.DeleteDirectory(FullName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,20 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
return _thisAndAllChildren;
|
return _thisAndAllChildren;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public T ThisAndAllChildrenReduced<T>(T acc, Func<T, VirtualFile, T> fn)
|
||||||
|
{
|
||||||
|
acc = fn(acc, this);
|
||||||
|
return this.Children.Aggregate(acc, (current, itm) => itm.ThisAndAllChildrenReduced<T>(current, fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ThisAndAllChildrenReduced(Action<VirtualFile> fn)
|
||||||
|
{
|
||||||
|
fn(this);
|
||||||
|
foreach (var itm in Children)
|
||||||
|
itm.ThisAndAllChildrenReduced(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -233,6 +247,7 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
private void Write(BinaryWriter bw)
|
private void Write(BinaryWriter bw)
|
||||||
{
|
{
|
||||||
bw.Write(Name);
|
bw.Write(Name);
|
||||||
|
bw.Write(FullPath);
|
||||||
bw.Write(Hash);
|
bw.Write(Hash);
|
||||||
bw.Write(Size);
|
bw.Write(Size);
|
||||||
bw.Write(LastModified);
|
bw.Write(LastModified);
|
||||||
@ -258,6 +273,7 @@ namespace Wabbajack.VirtualFileSystem
|
|||||||
Context = context,
|
Context = context,
|
||||||
Parent = parent,
|
Parent = parent,
|
||||||
Name = br.ReadString(),
|
Name = br.ReadString(),
|
||||||
|
_fullPath = br.ReadString(),
|
||||||
Hash = br.ReadString(),
|
Hash = br.ReadString(),
|
||||||
Size = br.ReadInt64(),
|
Size = br.ReadInt64(),
|
||||||
LastModified = br.ReadInt64(),
|
LastModified = br.ReadInt64(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -76,12 +76,20 @@ Global
|
|||||||
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|Any CPU.ActiveCfg = Release|x64
|
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|x64.ActiveCfg = Release|x64
|
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|x64.ActiveCfg = Release|x64
|
||||||
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|x64.Build.0 = Release|x64
|
{5D6A2EAF-6604-4C51-8AE2-A746B4BC5E3E}.Release|x64.Build.0 = Release|x64
|
||||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|Any CPU.ActiveCfg = Debug|x64
|
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|x64.ActiveCfg = Debug|x64
|
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|x64.Build.0 = Debug|x64
|
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Debug|x64.Build.0 = Debug|x64
|
||||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|Any CPU.ActiveCfg = Release|x64
|
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|x64.ActiveCfg = Release|x64
|
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Release|x64.ActiveCfg = Release|x64
|
||||||
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|x64.Build.0 = Release|x64
|
{37E4D421-8FD3-4D57-8F3A-7A511D6ED5C5}.Release|x64.Build.0 = Release|x64
|
||||||
|
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{DE18D89E-39C5-48FD-8E42-16235E3C4593}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{6ED08CFB-B879-4B55-8741-663A4A3491CE}.Debug|Any CPU.ActiveCfg = Debug|x64
|
{6ED08CFB-B879-4B55-8741-663A4A3491CE}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
{6ED08CFB-B879-4B55-8741-663A4A3491CE}.Debug|x64.ActiveCfg = Debug|x64
|
{6ED08CFB-B879-4B55-8741-663A4A3491CE}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{6ED08CFB-B879-4B55-8741-663A4A3491CE}.Debug|x64.Build.0 = Debug|x64
|
{6ED08CFB-B879-4B55-8741-663A4A3491CE}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
Loading…
Reference in New Issue
Block a user