diff options
author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2017-09-22 00:47:46 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2017-09-22 00:47:46 -0400 |
commit | 2c02dfe45a6d1252bfef557db8f39f97e57d3d19 (patch) | |
tree | 4fb8b5759d56ba6a62a452e09180ede280228b3b /src | |
parent | edbc3ef3c08909486d6c4b8797f0e3c2934854fa (diff) | |
download | SMAPI-2c02dfe45a6d1252bfef557db8f39f97e57d3d19.tar.gz SMAPI-2c02dfe45a6d1252bfef557db8f39f97e57d3d19.tar.bz2 SMAPI-2c02dfe45a6d1252bfef557db8f39f97e57d3d19.zip |
rewrite to make update-check logic vendor-agnostic (#336)
Diffstat (limited to 'src')
-rw-r--r-- | src/StardewModdingAPI.Web/Controllers/CheckController.cs | 71 | ||||
-rw-r--r-- | src/StardewModdingAPI.Web/Framework/ModRepositories/IModRepository.cs (renamed from src/StardewModdingAPI.Web/Framework/IModRepository.cs) | 11 | ||||
-rw-r--r-- | src/StardewModdingAPI.Web/Framework/ModRepositories/NexusRepository.cs (renamed from src/StardewModdingAPI.Web/Framework/NexusModsClient.cs) | 25 | ||||
-rw-r--r-- | src/StardewModdingAPI.Web/Models/ModGenericModel.cs | 37 | ||||
-rw-r--r-- | src/StardewModdingAPI.Web/Models/ModSearchModel.cs | 6 |
5 files changed, 104 insertions, 46 deletions
diff --git a/src/StardewModdingAPI.Web/Controllers/CheckController.cs b/src/StardewModdingAPI.Web/Controllers/CheckController.cs index 9ec068cb..2a346cf3 100644 --- a/src/StardewModdingAPI.Web/Controllers/CheckController.cs +++ b/src/StardewModdingAPI.Web/Controllers/CheckController.cs @@ -1,7 +1,9 @@ +using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using StardewModdingAPI.Web.Framework; +using StardewModdingAPI.Web.Framework.ModRepositories; using StardewModdingAPI.Web.Models; namespace StardewModdingAPI.Web.Controllers @@ -12,27 +14,74 @@ namespace StardewModdingAPI.Web.Controllers public class CheckController : Controller { /********* + ** Properties + *********/ + /// <summary>The mod repositories which provide mod metadata.</summary> + private readonly IDictionary<string, IModRepository> Repositories = + new IModRepository[] + { + new NexusRepository() + } + .ToDictionary(p => p.VendorKey, StringComparer.CurrentCultureIgnoreCase); + + + /********* ** Public methods *********/ /// <summary>Fetch version metadata for the given mods.</summary> - /// <param name="mods">The mods for which to fetch update metadata.</param> + /// <param name="search">The mod update search criteria.</param> [HttpPost] - public async Task<ModGenericModel[]> Post([FromBody] ModSearchModel[] mods) + public async Task<ModGenericModel[]> Post([FromBody] ModSearchModel search) { - using (NexusModsClient client = new NexusModsClient()) + IList<ModGenericModel> result = new List<ModGenericModel>(); + + foreach (string modKey in search.ModKeys) { - List<ModGenericModel> result = new List<ModGenericModel>(); + // parse mod key + if (!this.TryParseModKey(modKey, out string vendorKey, out string modID)) + { + result.Add(new ModGenericModel(modKey, "The mod key isn't in a valid format. It should contain the mod repository key and mod ID like 'Nexus:541'.")); + continue; + } - foreach (ModSearchModel mod in mods) + // get matching repository + if (!this.Repositories.TryGetValue(vendorKey, out IModRepository repository)) { - if (mod.NexusID.HasValue) - result.Add(await client.GetModInfoAsync(mod.NexusID.Value)); - else - result.Add(new ModGenericModel(null, mod.NexusID ?? 0)); + result.Add(new ModGenericModel(modKey, "There's no mod repository matching this namespaced mod ID.")); + continue; } - return result.ToArray(); + // fetch mod info + result.Add(await repository.GetModInfoAsync(modID)); } + + return result.ToArray(); + } + + + /********* + ** Private methods + *********/ + /// <summary>Parse a namespaced mod ID.</summary> + /// <param name="raw">The raw mod ID to parse.</param> + /// <param name="vendorKey">The parsed vendor key.</param> + /// <param name="modID">The parsed mod ID.</param> + /// <returns>Returns whether the value could be parsed.</returns> + private bool TryParseModKey(string raw, out string vendorKey, out string modID) + { + // split parts + string[] parts = raw?.Split(':'); + if (parts == null || parts.Length != 2) + { + vendorKey = null; + modID = null; + return false; + } + + // parse + vendorKey = parts[0]; + modID = parts[1]; + return true; } } } diff --git a/src/StardewModdingAPI.Web/Framework/IModRepository.cs b/src/StardewModdingAPI.Web/Framework/ModRepositories/IModRepository.cs index ebf9850f..43bad4e9 100644 --- a/src/StardewModdingAPI.Web/Framework/IModRepository.cs +++ b/src/StardewModdingAPI.Web/Framework/ModRepositories/IModRepository.cs @@ -2,16 +2,23 @@ using System; using System.Threading.Tasks; using StardewModdingAPI.Web.Models; -namespace StardewModdingAPI.Web.Framework +namespace StardewModdingAPI.Web.Framework.ModRepositories { /// <summary>A repository which provides mod metadata.</summary> internal interface IModRepository : IDisposable { /********* + ** Accessors + *********/ + /// <summary>The unique key for this vendor.</summary> + string VendorKey { get; } + + + /********* ** Public methods *********/ /// <summary>Get metadata about a mod in the repository.</summary> /// <param name="id">The mod ID in this repository.</param> - Task<ModGenericModel> GetModInfoAsync(int id); + Task<ModGenericModel> GetModInfoAsync(string id); } } diff --git a/src/StardewModdingAPI.Web/Framework/NexusModsClient.cs b/src/StardewModdingAPI.Web/Framework/ModRepositories/NexusRepository.cs index 8f010d56..37f309da 100644 --- a/src/StardewModdingAPI.Web/Framework/NexusModsClient.cs +++ b/src/StardewModdingAPI.Web/Framework/ModRepositories/NexusRepository.cs @@ -4,10 +4,10 @@ using Newtonsoft.Json; using Pathoschild.Http.Client; using StardewModdingAPI.Web.Models; -namespace StardewModdingAPI.Web.Framework +namespace StardewModdingAPI.Web.Framework.ModRepositories { /// <summary>An HTTP client for fetching mod metadata from Nexus Mods.</summary> - internal class NexusModsClient : IModRepository + internal class NexusRepository : IModRepository { /********* ** Properties @@ -15,11 +15,19 @@ namespace StardewModdingAPI.Web.Framework /// <summary>The underlying HTTP client.</summary> private readonly IClient Client; + + /********* + ** Accessors + *********/ + /// <summary>The unique key for this vendor.</summary> + public string VendorKey { get; } = "Nexus"; + + /********* ** Public methods *********/ /// <summary>Construct an instance.</summary> - public NexusModsClient() + public NexusRepository() { this.Client = new FluentClient("http://www.nexusmods.com/stardewvalley") .SetUserAgent("Nexus Client v0.63.15"); @@ -27,18 +35,18 @@ namespace StardewModdingAPI.Web.Framework /// <summary>Get metadata about a mod in the repository.</summary> /// <param name="id">The mod ID in this repository.</param> - public async Task<ModGenericModel> GetModInfoAsync(int id) + public async Task<ModGenericModel> GetModInfoAsync(string id) { try { NexusResponseModel response = await this.Client .GetAsync($"mods/{id}") .As<NexusResponseModel>(); - return new ModGenericModel("Nexus", id, response.Name, response.Version, response.Url); + return new ModGenericModel($"{this.VendorKey}:{id}", response.Name, response.Version, response.Url); } - catch (Exception) + catch (Exception ex) { - return new ModGenericModel("Nexus", id); + return new ModGenericModel($"{this.VendorKey}:{id}", ex.ToString()); } } @@ -58,9 +66,6 @@ namespace StardewModdingAPI.Web.Framework /********* ** Accessors *********/ - /// <summary>The unique mod ID.</summary> - public int ID { get; set; } - /// <summary>The mod name.</summary> public string Name { get; set; } diff --git a/src/StardewModdingAPI.Web/Models/ModGenericModel.cs b/src/StardewModdingAPI.Web/Models/ModGenericModel.cs index dc36c7f4..88a6e4bd 100644 --- a/src/StardewModdingAPI.Web/Models/ModGenericModel.cs +++ b/src/StardewModdingAPI.Web/Models/ModGenericModel.cs @@ -1,3 +1,5 @@ +using Newtonsoft.Json; + namespace StardewModdingAPI.Web.Models { /// <summary>Generic metadata about a mod.</summary> @@ -6,53 +8,48 @@ namespace StardewModdingAPI.Web.Models /********* ** Accessors *********/ - /// <summary>The unique mod ID.</summary> - public int ID { get; } + /// <summary>The namespaced mod key.</summary> + public string ModKey { get; } /// <summary>The mod name.</summary> public string Name { get; } - /// <summary>The mod's vendor ID.</summary> - public string Vendor { get; } - /// <summary>The mod's semantic version number.</summary> public string Version { get; } /// <summary>The mod's web URL.</summary> public string Url { get; } - /// <summary>Whether the mod is valid.</summary> - public bool Valid { get; } + /// <summary>The error message indicating why the mod is invalid (if applicable).</summary> + public string Error { get; } /********* ** Public methods *********/ /// <summary>Construct a valid instance.</summary> - /// <param name="vendor">The mod's vendor ID.</param> - /// <param name="id">The unique mod ID.</param> + /// <param name="modKey">The namespaced mod key.</param> /// <param name="name">The mod name.</param> /// <param name="version">The mod's semantic version number.</param> /// <param name="url">The mod's web URL.</param> - /// <param name="valid">Whether the mod is valid.</param> - public ModGenericModel(string vendor, int id, string name, string version, string url, bool valid = true) + /// <param name="error">The error message indicating why the mod is invalid (if applicable).</param> + [JsonConstructor] + public ModGenericModel(string modKey, string name, string version, string url, string error = null) { - this.Vendor = vendor; - this.ID = id; + this.ModKey = modKey; this.Name = name; this.Version = version; this.Url = url; - this.Valid = valid; + this.Error = error; // mainly initialised here for the JSON deserialiser } /// <summary>Construct an valid instance.</summary> - /// <param name="vendor">The mod's vendor ID.</param> - /// <param name="id">The unique mod ID.</param> - public ModGenericModel(string vendor, int id) + /// <param name="modKey">The namespaced mod key.</param> + /// <param name="error">The error message indicating why the mod is invalid.</param> + public ModGenericModel(string modKey, string error) { - this.Vendor = vendor; - this.ID = id; - this.Valid = false; + this.ModKey = modKey; + this.Error = error; } } } diff --git a/src/StardewModdingAPI.Web/Models/ModSearchModel.cs b/src/StardewModdingAPI.Web/Models/ModSearchModel.cs index eb9ac920..852ea439 100644 --- a/src/StardewModdingAPI.Web/Models/ModSearchModel.cs +++ b/src/StardewModdingAPI.Web/Models/ModSearchModel.cs @@ -1,9 +1,9 @@ namespace StardewModdingAPI.Web.Models { - /// <summary>The search criteria for a mod.</summary> + /// <summary>The mod update search criteria.</summary> public class ModSearchModel { - /// <summary>The Nexus Mods ID (if any).</summary> - public int? NexusID { get; set; } + /// <summary>The namespaced mod keys to search.</summary> + public string[] ModKeys { get; set; } } } |