FluentNexus is a modern async HTTP client for the Nexus Mods API. It gives you simple strongly-typed methods to access all of the Nexus API endpoints, handling the gritty details like deserialisation, content negotiation, URL encoding, and error-handling.
Designed with discoverability and extensibility as core principles, just autocomplete to see which methods are available at each step.
Install it from NuGet:
Install-Package Pathoschild.FluentNexus
The client works on any modern platform (including Linux, Mac, and Windows):
platform | min version |
---|---|
.NET Core | 1.0 |
.NET Framework | 4.5 |
.NET Standard | 1.3 |
Mono | 4.6 |
Unity | 2018.1 |
Universal Windows Platform | 10.0 |
Xamarin.Android | 7.0 |
Xamarin.iOS | 10.0 |
Xamarin.Mac | 3.0 |
Create the client with your personal API key (or an SSO key), and an arbitrary app name/version which is just stored by Nexus for tracking:
var nexus = new NexusClient("api key here", "My App Name", "1.0.0");
Now just call its methods to interact with the Nexus API!
For example...
-
Start tracking a mod:
await nexus.Users.TrackMod("stardewvalley", 2400);
-
Get a list of files for a mod:
ModFileList files = await nexus.ModFiles.GetModFiles("stardewvalley", 2400);
-
Get download links for a mod file:
ModFileDownloadLink[] downloadLinks = await nexus.ModFiles.GetDownloadLinks("stardewvalley", 2400, 9622);
-
Get a content preview for a mod file if it's an archive (e.g.
.zip
):ModFile file = await nexus.ModFiles.GetModFiles("stardewvalley", 2400, 9622); ContentPreview preview = await nexus.ModFiles.GetContentPreview(file.ContentPreviewLink);
-
Which mods are being tracked by the user?
UserTrackedMod[] mods = await nexus.Users.GetTrackedMods();
See the Nexus API docs for a list of endpoints and fields supported by this client.
The Nexus API returns errors in this format:
{
"code": 403,
"message": "You don't have permission to get download links from the API without visting nexusmods.com - this is for premium users only."
}
The client will throw an ApiException
when that happens, which contains the HTTP status code,
Nexus error message, and response:
try
{
ModFileDownloadLink[] links = await nexus.ModFiles.GetDownloadLinks("stardewvalley", 2400, 9622);
}
catch (ApiException ex)
{
if (ex.Status == HttpStatusCode.Forbidden && ex.Message.Contains("this is for premium users only"))
// user needs a premium account
}
The Nexus API sets some rate limits (see API docs), and will return HTTP 429 if you exceed them.
You can check your rate limit usage anytime. Since this is cached on each response, this will only ping the Nexus API if you haven't sent a request recently. (Even if it does ping the API, this won't be counted against your limits.) To check the rate limit values:
IRateLimitManager limits = await nexus.GetRateLimits();
Console.WriteLine($"Daily usage: {limits.DailyRemaining}/{limits.DailyLimit} requests left, will reset at {limits.DailyReset}.");
Console.WriteLine($"Hourly usage: {limits.HourlyRemaining}/{limits.HourlyLimit} requests left, will reset at {limits.HourlyReset}.");
The client can also help you automate rate limit handling. For example, let's say you want to pause the script when you exceed the rate limits but resume when they renew:
IRateLimitManager rateLimits = await nexus.GetRateLimits();
if (rateLimits.IsBlocked())
{
TimeSpan renewDelay = rateLimits.GetTimeUntilRenewal();
Console.WriteLine($"Exceeded rate limits, will resume at {DateTime.Now + renewDelay} local time.");
Thread.Sleep(renewDelay);
}
If needed, you can use the underlying fluent HTTP client directly (e.g. for an unsupported endpoint):
Mod mod = await nexus.HttpClient
.GetAsync($"v1/games/{domainName}/mods/{modID}.json")
.As<Mod>();
See FluentHttpClient for documentation.
The client is built around the async
and await
keywords, but you can use the client
synchronously. That's not recommended — it complicates error-handling (e.g. errors get wrapped
into AggregateException), and it's very easy to cause thread deadlocks when you do this (see
Parallel Programming with .NET: Await, and UI, and deadlocks! Oh my! and
Don't Block on Async Code).
If you really need to use it synchronously, you can just call the Result
property:
UserTrackedMod[] mods = nexus.Users.GetTrackedMods().Result;
Or if you don't need the response:
nexus.Users.TrackMod("stardewvalley", 2400).Wait();