diff --git a/src/StardewModdingAPI.Web/Controllers/CheckController.cs b/src/StardewModdingAPI.Web/Controllers/CheckController.cs index a7582edd..9ec068cb 100644 --- a/src/StardewModdingAPI.Web/Controllers/CheckController.cs +++ b/src/StardewModdingAPI.Web/Controllers/CheckController.cs @@ -1,9 +1,7 @@ -using System; using System.Collections.Generic; -using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using Newtonsoft.Json; +using StardewModdingAPI.Web.Framework; using StardewModdingAPI.Web.Models; namespace StardewModdingAPI.Web.Controllers @@ -21,45 +19,19 @@ namespace StardewModdingAPI.Web.Controllers [HttpPost] public async Task Post([FromBody] ModSearchModel[] mods) { - using (var client = new HttpClient()) + using (NexusModsClient client = new NexusModsClient()) { - // the return array of mods - var modList = new List(); + List result = new List(); - foreach (var mod in mods) + foreach (ModSearchModel mod in mods) { - if (!mod.NexusID.HasValue) - continue; - - try - { - // create request with HttpRequestMessage - var request = new HttpRequestMessage(HttpMethod.Get, new Uri($"http://www.nexusmods.com/stardewvalley/mods/{mod.NexusID}")); - - // add the Nexus Client useragent to get JSON response from the site - request.Headers.UserAgent.ParseAdd("Nexus Client v0.63.15"); - - // send the request out - var response = await client.SendAsync(request); - // ensure the response is valid (throws exception) - response.EnsureSuccessStatusCode(); - - // get the JSON string of the response - string stringResponse = await response.Content.ReadAsStringAsync(); - - // create the mod data from the JSON string - var modData = JsonConvert.DeserializeObject(stringResponse); - - // add to the list of mods - modList.Add(modData.ModInfo()); - } - catch (Exception) - { - modList.Add(new ModGenericModel { ID = mod.NexusID.Value, Vendor = "Nexus", Valid = false }); - } + if (mod.NexusID.HasValue) + result.Add(await client.GetModInfoAsync(mod.NexusID.Value)); + else + result.Add(new ModGenericModel(null, mod.NexusID ?? 0)); } - return modList.ToArray(); + return result.ToArray(); } } } diff --git a/src/StardewModdingAPI.Web/Framework/IModRepository.cs b/src/StardewModdingAPI.Web/Framework/IModRepository.cs new file mode 100644 index 00000000..ebf9850f --- /dev/null +++ b/src/StardewModdingAPI.Web/Framework/IModRepository.cs @@ -0,0 +1,17 @@ +using System; +using System.Threading.Tasks; +using StardewModdingAPI.Web.Models; + +namespace StardewModdingAPI.Web.Framework +{ + /// A repository which provides mod metadata. + internal interface IModRepository : IDisposable + { + /********* + ** Public methods + *********/ + /// Get metadata about a mod in the repository. + /// The mod ID in this repository. + Task GetModInfoAsync(int id); + } +} diff --git a/src/StardewModdingAPI.Web/Framework/NexusModsClient.cs b/src/StardewModdingAPI.Web/Framework/NexusModsClient.cs new file mode 100644 index 00000000..8f010d56 --- /dev/null +++ b/src/StardewModdingAPI.Web/Framework/NexusModsClient.cs @@ -0,0 +1,75 @@ +using System; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Pathoschild.Http.Client; +using StardewModdingAPI.Web.Models; + +namespace StardewModdingAPI.Web.Framework +{ + /// An HTTP client for fetching mod metadata from Nexus Mods. + internal class NexusModsClient : IModRepository + { + /********* + ** Properties + *********/ + /// The underlying HTTP client. + private readonly IClient Client; + + /********* + ** Public methods + *********/ + /// Construct an instance. + public NexusModsClient() + { + this.Client = new FluentClient("http://www.nexusmods.com/stardewvalley") + .SetUserAgent("Nexus Client v0.63.15"); + } + + /// Get metadata about a mod in the repository. + /// The mod ID in this repository. + public async Task GetModInfoAsync(int id) + { + try + { + NexusResponseModel response = await this.Client + .GetAsync($"mods/{id}") + .As(); + return new ModGenericModel("Nexus", id, response.Name, response.Version, response.Url); + } + catch (Exception) + { + return new ModGenericModel("Nexus", id); + } + } + + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + public void Dispose() + { + this.Client.Dispose(); + } + + + /********* + ** Private models + *********/ + /// A mod metadata response from Nexus Mods. + private class NexusResponseModel + { + /********* + ** Accessors + *********/ + /// The unique mod ID. + public int ID { get; set; } + + /// The mod name. + public string Name { get; set; } + + /// The mod's semantic version number. + public string Version { get; set; } + + /// The mod's web URL. + [JsonProperty("mod_page_uri")] + public string Url { get; set; } + } + } +} diff --git a/src/StardewModdingAPI.Web/Models/IModModel.cs b/src/StardewModdingAPI.Web/Models/IModModel.cs deleted file mode 100644 index 2eadcaec..00000000 --- a/src/StardewModdingAPI.Web/Models/IModModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace StardewModdingAPI.Web.Models -{ - /// A mod metadata response which provides a method to extract generic info. - internal interface IModModel - { - /********* - ** Public methods - *********/ - /// Get basic mod metadata. - ModGenericModel ModInfo(); - } -} diff --git a/src/StardewModdingAPI.Web/Models/ModGenericModel.cs b/src/StardewModdingAPI.Web/Models/ModGenericModel.cs index 208af416..dc36c7f4 100644 --- a/src/StardewModdingAPI.Web/Models/ModGenericModel.cs +++ b/src/StardewModdingAPI.Web/Models/ModGenericModel.cs @@ -7,21 +7,52 @@ namespace StardewModdingAPI.Web.Models ** Accessors *********/ /// The unique mod ID. - public int ID { get; set; } + public int ID { get; } /// The mod name. - public string Name { get; set; } + public string Name { get; } /// The mod's vendor ID. - public string Vendor { get; set; } + public string Vendor { get; } /// The mod's semantic version number. - public string Version { get; set; } + public string Version { get; } /// The mod's web URL. - public string Url { get; set; } + public string Url { get; } /// Whether the mod is valid. - public bool Valid { get; set; } = true; + public bool Valid { get; } + + + /********* + ** Public methods + *********/ + /// Construct a valid instance. + /// The mod's vendor ID. + /// The unique mod ID. + /// The mod name. + /// The mod's semantic version number. + /// The mod's web URL. + /// Whether the mod is valid. + public ModGenericModel(string vendor, int id, string name, string version, string url, bool valid = true) + { + this.Vendor = vendor; + this.ID = id; + this.Name = name; + this.Version = version; + this.Url = url; + this.Valid = valid; + } + + /// Construct an valid instance. + /// The mod's vendor ID. + /// The unique mod ID. + public ModGenericModel(string vendor, int id) + { + this.Vendor = vendor; + this.ID = id; + this.Valid = false; + } } } diff --git a/src/StardewModdingAPI.Web/Models/NexusResponseModel.cs b/src/StardewModdingAPI.Web/Models/NexusResponseModel.cs deleted file mode 100644 index ae5c691c..00000000 --- a/src/StardewModdingAPI.Web/Models/NexusResponseModel.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Newtonsoft.Json; - -namespace StardewModdingAPI.Web.Models -{ - /// A mod metadata response from Nexus Mods. - public class NexusResponseModel : IModModel - { - /********* - ** Accessors - *********/ - /// The unique mod ID. - public int ID { get; set; } - - /// The mod name. - public string Name { get; set; } - - /// The mod's semantic version number. - public string Version { get; set; } - - /// The mod's web URL. - [JsonProperty("mod_page_uri")] - public string Url { get; set; } - - - /********* - ** Public methods - *********/ - /// Get basic mod metadata. - public ModGenericModel ModInfo() - { - return new ModGenericModel - { - ID = this.ID, - Version = this.Version, - Name = this.Name, - Url = this.Url, - Vendor = "Nexus" - }; - } - } -} diff --git a/src/StardewModdingAPI.Web/StardewModdingAPI.Web.csproj b/src/StardewModdingAPI.Web/StardewModdingAPI.Web.csproj index fa1d88eb..eee0f3f3 100644 --- a/src/StardewModdingAPI.Web/StardewModdingAPI.Web.csproj +++ b/src/StardewModdingAPI.Web/StardewModdingAPI.Web.csproj @@ -19,6 +19,7 @@ +