summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2017-09-22 00:47:46 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2017-09-22 00:47:46 -0400
commit2c02dfe45a6d1252bfef557db8f39f97e57d3d19 (patch)
tree4fb8b5759d56ba6a62a452e09180ede280228b3b /src
parentedbc3ef3c08909486d6c4b8797f0e3c2934854fa (diff)
downloadSMAPI-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.cs71
-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.cs37
-rw-r--r--src/StardewModdingAPI.Web/Models/ModSearchModel.cs6
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; }
}
}