Remaining NexusAPI made async

This commit is contained in:
Justin Swanson 2019-12-06 21:50:50 -06:00
parent 367978967c
commit 63afc2dc9e
21 changed files with 75 additions and 57 deletions

View File

@ -59,7 +59,7 @@ namespace Compression.BSA.Test
private static async Task<string> DownloadMod((Game, int) info)
{
using (var client = new NexusApiClient())
using (var client = await NexusApiClient.Get())
{
var results = await client.GetModFiles(info.Item1, info.Item2);
var file = results.files.FirstOrDefault(f => f.is_primary) ??

View File

@ -18,20 +18,20 @@ namespace Wabbajack.CacheServer
public NexusCacheModule() : base("/")
{
// ToDo
// Handle what to do with the fact that lots of these are now a tasks
throw new NotImplementedException("Unsure if following functions still work when taking in a Task");
Get("/v1/games/{GameName}/mods/{ModID}/files/{FileID}.json", HandleFileID);
Get("/v1/games/{GameName}/mods/{ModID}/files.json", HandleGetFiles);
Get("/v1/games/{GameName}/mods/{ModID}.json", HandleModInfo);
Get("/nexus_api_cache/{request}.json", HandleCacheCall);
Get("/nexus_api_cache", ListCache);
// ToDo
// Handle what to do with the fact that this is now a task
throw new NotImplementedException("Unsure if following function still works when taking in a Task");
Get("/nexus_api_cache/update", UpdateCache);
}
private async Task<object> UpdateCache(object arg)
{
var api = new NexusApiClient(Request.Headers["apikey"].FirstOrDefault());
var api = await NexusApiClient.Get(Request.Headers["apikey"].FirstOrDefault());
await api.ClearUpdatedModsInCache();
return "Done";
}
@ -50,17 +50,17 @@ namespace Wabbajack.CacheServer
}));
}
private object HandleModInfo(dynamic arg)
private async Task<object> HandleModInfo(dynamic arg)
{
Utils.Log($"{DateTime.Now} - Mod Info - {arg.GameName}/{arg.ModID}/");
var api = new NexusApiClient(Request.Headers["apikey"].FirstOrDefault());
var api = await NexusApiClient.Get(Request.Headers["apikey"].FirstOrDefault());
return api.GetModInfo(GameRegistry.GetByNexusName((string)arg.GameName).Game, (string)arg.ModID).ToJSON();
}
private object HandleFileID(dynamic arg)
private async Task<object> HandleFileID(dynamic arg)
{
Utils.Log($"{DateTime.Now} - File Info - {arg.GameName}/{arg.ModID}/{arg.FileID}");
var api = new NexusApiClient(Request.Headers["apikey"].FirstOrDefault());
var api = await NexusApiClient.Get(Request.Headers["apikey"].FirstOrDefault());
return api.GetFileInfo(new NexusDownloader.State
{
GameName = arg.GameName,
@ -69,10 +69,10 @@ namespace Wabbajack.CacheServer
}).ToJSON();
}
private object HandleGetFiles(dynamic arg)
private async Task<object> HandleGetFiles(dynamic arg)
{
Utils.Log($"{DateTime.Now} - Mod Files - {arg.GameName} {arg.ModID}");
var api = new NexusApiClient(Request.Headers["apikey"].FirstOrDefault());
var api = await NexusApiClient.Get(Request.Headers["apikey"].FirstOrDefault());
return api.GetModFiles(GameRegistry.GetByNexusName((string)arg.GameName).Game, (int)arg.ModID).ToJSON();
}

View File

@ -9,12 +9,13 @@ namespace Wabbajack.Common.StatusFeed
public class GenericInfo : AStatusMessage, IInfo
{
public override string ShortDescription { get; }
public override string ExtendedDescription { get;}
private readonly string _extendedDescription;
public override string ExtendedDescription => _extendedDescription ?? ShortDescription;
public GenericInfo(string short_description, string long_description = "")
public GenericInfo(string short_description, string long_description = null)
{
ShortDescription = short_description;
ExtendedDescription = long_description;
_extendedDescription = long_description;
}
public override string ToString()

View File

@ -214,7 +214,7 @@ namespace Wabbajack.Lib
var result = new Archive
{
State = (AbstractDownloadState) DownloadDispatcher.ResolveArchive(found.IniData)
State = await DownloadDispatcher.ResolveArchive(found.IniData)
};
if (result.State == null)

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Wabbajack.Common;
namespace Wabbajack.Lib.Downloaders
@ -31,9 +32,10 @@ namespace Wabbajack.Lib.Downloaders
return (T)IndexedDownloaders[typeof(T)];
}
public static AbstractDownloadState ResolveArchive(dynamic ini)
public static async Task<AbstractDownloadState> ResolveArchive(dynamic ini)
{
return Downloaders.Select(d => d.GetDownloaderState(ini)).FirstOrDefault(result => result != null);
var states = await Task.WhenAll(Downloaders.Select(d => (Task<AbstractDownloadState>)d.GetDownloaderState(ini)));
return states.FirstOrDefault(result => result != null);
}
/// <summary>

View File

@ -6,7 +6,7 @@ namespace Wabbajack.Lib.Downloaders
{
public class DropboxDownloader : IDownloader, IUrlDownloader
{
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
public async Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI)
{
var urlstring = archiveINI?.General?.directURL;
return GetDownloaderState(urlstring);

View File

@ -8,7 +8,7 @@ namespace Wabbajack.Lib.Downloaders
{
public class GoogleDriveDownloader : IDownloader, IUrlDownloader
{
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
public async Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI)
{
var url = archiveINI?.General?.directURL;
return GetDownloaderState(url);

View File

@ -15,11 +15,10 @@ namespace Wabbajack.Lib.Downloaders
public class HTTPDownloader : IDownloader, IUrlDownloader
{
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
public async Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI)
{
var url = archiveINI?.General?.directURL;
return GetDownloaderState(url, archiveINI);
}
public AbstractDownloadState GetDownloaderState(string uri)

View File

@ -4,7 +4,7 @@ namespace Wabbajack.Lib.Downloaders
{
public interface IDownloader
{
AbstractDownloadState GetDownloaderState(dynamic archiveINI);
Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI);
/// <summary>
/// Called before any downloads are inacted by the installer;

View File

@ -7,8 +7,7 @@ namespace Wabbajack.Lib.Downloaders
{
public class MegaDownloader : IDownloader, IUrlDownloader
{
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
public async Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI)
{
var url = archiveINI?.General?.directURL;
return GetDownloaderState(url);

View File

@ -59,7 +59,7 @@ namespace Wabbajack.Lib.Downloaders
}
}
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
public async Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI)
{
var url = archiveINI?.General?.manualURL;
return url != null ? new State { Url = url} : null;

View File

@ -9,7 +9,7 @@ namespace Wabbajack.Lib.Downloaders
{
public class MediaFireDownloader : IUrlDownloader
{
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
public async Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI)
{
Uri url = DownloaderUtils.GetDirectURL(archiveINI);
if (url == null || url.Host != "www.mediafire.com") return null;

View File

@ -8,7 +8,7 @@ namespace Wabbajack.Lib.Downloaders
{
public class ModDBDownloader : IDownloader, IUrlDownloader
{
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
public async Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI)
{
var url = archiveINI?.General?.directURL;
return GetDownloaderState(url);

View File

@ -10,7 +10,7 @@ namespace Wabbajack.Lib.Downloaders
{
public class NexusDownloader : IDownloader
{
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
public async Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI)
{
var general = archiveINI?.General;
@ -19,7 +19,8 @@ namespace Wabbajack.Lib.Downloaders
var name = (string)general.gameName;
var gameMeta = GameRegistry.GetByMO2ArchiveName(name);
var game = gameMeta != null ? GameRegistry.GetByMO2ArchiveName(name).Game : GameRegistry.GetByNexusName(name).Game;
var info = new NexusApiClient().GetModInfo(game, general.modID);
var client = await NexusApiClient.Get();
var info = await client.GetModInfo(game, general.modID);
return new State
{
GameName = general.gameName,
@ -43,7 +44,7 @@ namespace Wabbajack.Lib.Downloaders
public async Task Prepare()
{
var client = new NexusApiClient();
var client = await NexusApiClient.Get();
var status = await client.GetUserStatus();
if (!client.IsAuthenticated)
{
@ -52,7 +53,7 @@ namespace Wabbajack.Lib.Downloaders
}
if (status.is_premium) return;
Utils.ErrorThrow(new UnconvertedError($"Automated installs with Wabbajack requires a premium nexus account. {client.Username} is not a premium account."));
Utils.ErrorThrow(new UnconvertedError($"Automated installs with Wabbajack requires a premium nexus account. {await client.Username()} is not a premium account."));
}
public class State : AbstractDownloadState
@ -81,7 +82,8 @@ namespace Wabbajack.Lib.Downloaders
string url;
try
{
url = await new NexusApiClient().GetNexusDownloadLink(this, false);
var client = await NexusApiClient.Get();
url = await client.GetNexusDownloadLink(this, false);
}
catch (Exception ex)
{
@ -110,7 +112,8 @@ namespace Wabbajack.Lib.Downloaders
if (!int.TryParse(ModID, out var modID))
return false;
var modFiles = await new NexusApiClient().GetModFiles(game, modID);
var client = await NexusApiClient.Get();
var modFiles = await client.GetModFiles(game, modID);
if (!ulong.TryParse(FileID, out var fileID))
return false;

View File

@ -15,7 +15,7 @@ namespace Wabbajack.Lib.Downloaders
{
private SteamWorkshopItem _item;
public AbstractDownloadState GetDownloaderState(dynamic archiveINI)
public async Task<AbstractDownloadState> GetDownloaderState(dynamic archiveINI)
{
var id = archiveINI?.General?.itemID;
var steamID = archiveINI?.General?.steamID;

View File

@ -234,8 +234,8 @@ namespace Wabbajack.Lib
if (IndexedArchives.Any(a => a.IniData?.General?.gameName != null))
{
var nexusClient = new NexusApiClient();
if (!nexusClient.IsPremium) Error($"User {nexusClient.Username} is not a premium Nexus user, so we cannot access the necessary API calls, cannot continue");
var nexusClient = await NexusApiClient.Get();
if (!(await nexusClient.IsPremium())) Error($"User {(await nexusClient.Username())} is not a premium Nexus user, so we cannot access the necessary API calls, cannot continue");
}

View File

@ -196,7 +196,8 @@ namespace Wabbajack.Lib
await mods.PMap(Queue, async mod =>
{
var er = await new NexusApiClient().EndorseMod(mod);
var client = await NexusApiClient.Get();
var er = await client.EndorseMod(mod);
Utils.Log($"Endorsed {mod.GameName} - {mod.ModID} - Result: {er.message}");
});
Info("Done! You may now exit the application!");

View File

@ -17,6 +17,7 @@ using Wabbajack.Common;
using Wabbajack.Lib.Downloaders;
using WebSocketSharp;
using static Wabbajack.Lib.NexusApi.NexusApiUtils;
using System.Threading;
namespace Wabbajack.Lib.NexusApi
{
@ -38,27 +39,31 @@ namespace Wabbajack.Lib.NexusApi
public bool IsAuthenticated => _apiKey != null;
private UserStatus _userStatus;
private Task<UserStatus> _userStatus;
public UserStatus UserStatus
public Task<UserStatus> UserStatus
{
get
{
if (_userStatus == null)
_userStatus = GetUserStatus().Result;
_userStatus = GetUserStatus();
return _userStatus;
}
}
public bool IsPremium => IsAuthenticated && UserStatus.is_premium;
public string Username => UserStatus?.name;
private static object _getAPIKeyLock = new object();
private static string GetApiKey()
public async Task<bool> IsPremium()
{
lock (_getAPIKeyLock)
return IsAuthenticated && (await UserStatus).is_premium;
}
public async Task<string> Username() => (await UserStatus).name;
private static SemaphoreSlim _getAPIKeyLock = new SemaphoreSlim(1, 1);
private static async Task<string> GetApiKey()
{
await _getAPIKeyLock.WaitAsync();
try
{
// Clean up old location
if (File.Exists(API_KEY_CACHE_FILE))
@ -113,13 +118,15 @@ namespace Wabbajack.Lib.NexusApi
Process.Start($"https://www.nexusmods.com/sso?id={guid}&application=" + Consts.AppName);
// get the api key from the socket and cache it
api_key.Task.Wait();
var result = api_key.Task.Result;
File.WriteAllBytes(cacheFile, ProtectedData.Protect(Encoding.UTF8.GetBytes(result),
var result = await api_key.Task;
File.WriteAllBytes(cacheFile, ProtectedData.Protect(Encoding.UTF8.GetBytes(result),
Encoding.UTF8.GetBytes(_additionalEntropy), DataProtectionScope.CurrentUser));
return result;
}
finally
{
_getAPIKeyLock.Release();
}
}
public async Task<UserStatus> GetUserStatus()
@ -183,9 +190,9 @@ namespace Wabbajack.Lib.NexusApi
#endregion
public NexusApiClient(string apiKey = null)
private NexusApiClient(string apiKey)
{
_apiKey = apiKey ?? GetApiKey();
_apiKey = apiKey;
_httpClient = new HttpClient();
// set default headers for all requests to the Nexus API
@ -200,6 +207,12 @@ namespace Wabbajack.Lib.NexusApi
Directory.CreateDirectory(Consts.NexusCacheDirectory);
}
public static async Task<NexusApiClient> Get(string apiKey = null)
{
apiKey = apiKey ?? await GetApiKey();
return new NexusApiClient(apiKey);
}
private async Task<T> Get<T>(string url)
{
HttpResponseMessage response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);

View File

@ -317,7 +317,7 @@ namespace Wabbajack.Lib
private async Task CreateMetaFiles()
{
Utils.Log("Getting Nexus api_key, please click authorize if a browser window appears");
var nexusClient = new NexusApiClient();
var nexusClient = await NexusApiClient.Get();
await Task.WhenAll(
Directory.EnumerateFiles(DownloadsFolder, "*", SearchOption.TopDirectoryOnly)

View File

@ -19,7 +19,7 @@ namespace Wabbajack.Test.ListValidation
public static async Task SetupNexus(TestContext context)
{
Utils.LogMessages.Subscribe(m => context.WriteLine(m.ToString()));
var api = new NexusApiClient();
var api = await NexusApiClient.Get();
await api.ClearUpdatedModsInCache();
}

View File

@ -105,7 +105,7 @@ namespace Wabbajack.Test
private async Task DownloadAndInstall(Game game, int modid, string mod_name)
{
utils.AddMod(mod_name);
var client = new NexusApiClient();
var client = await NexusApiClient.Get();
var resp = await client.GetModFiles(game, modid);
var file = resp.files.First(f => f.is_primary);
var src = Path.Combine(DOWNLOAD_FOLDER, file.file_name);