diff options
author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2018-06-28 22:01:04 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2018-06-28 22:01:04 -0400 |
commit | 3f5a5e54041a641e30fc5cc899046953d9763da4 (patch) | |
tree | ca02735544614b85cfc75201823b3dd8d36f2b8a | |
parent | 89ad599561a058289d8ea44e0c345f1a30a3a6ac (diff) | |
download | SMAPI-3f5a5e54041a641e30fc5cc899046953d9763da4.tar.gz SMAPI-3f5a5e54041a641e30fc5cc899046953d9763da4.tar.bz2 SMAPI-3f5a5e54041a641e30fc5cc899046953d9763da4.zip |
use more structured API response for update checks (#532)
7 files changed, 106 insertions, 42 deletions
diff --git a/src/SMAPI.Web/Controllers/ModsApiController.cs b/src/SMAPI.Web/Controllers/ModsApiController.cs index 960602f4..c4f1023b 100644 --- a/src/SMAPI.Web/Controllers/ModsApiController.cs +++ b/src/SMAPI.Web/Controllers/ModsApiController.cs @@ -80,7 +80,11 @@ namespace StardewModdingAPI.Web.Controllers [HttpPost] public async Task<IDictionary<string, ModEntryModel>> PostAsync([FromBody] ModSearchModel model) { - ModSearchEntryModel[] searchMods = this.GetSearchMods(model).ToArray(); + // parse request data + ISemanticVersion apiVersion = this.GetApiVersion(); + ModSearchEntryModel[] searchMods = this.GetSearchMods(model, apiVersion).ToArray(); + + // perform checks IDictionary<string, ModEntryModel> mods = new Dictionary<string, ModEntryModel>(StringComparer.CurrentCultureIgnoreCase); foreach (ModSearchEntryModel mod in searchMods) { @@ -119,11 +123,10 @@ namespace StardewModdingAPI.Web.Controllers continue; } - if (result.Version == null || version.IsNewerThan(new SemanticVersion(result.Version))) + if (result.Main == null || result.Main.Version.IsOlderThan(version)) { result.Name = data.Name; - result.Url = data.Url; - result.Version = version.ToString(); + result.Main = new ModEntryVersionModel(version, data.Url); } } @@ -136,35 +139,34 @@ namespace StardewModdingAPI.Web.Controllers continue; } - if (result.PreviewVersion == null || version.IsNewerThan(new SemanticVersion(data.PreviewVersion))) + if (result.Optional == null || result.Optional.Version.IsOlderThan(version)) { result.Name = result.Name ?? data.Name; - result.PreviewUrl = data.Url; - result.PreviewVersion = version.ToString(); + result.Optional = new ModEntryVersionModel(version, data.Url); } } } // fallback to preview if latest is invalid - if (result.Version == null && result.PreviewVersion != null) + if (result.Main == null && result.Optional != null) { - result.Version = result.PreviewVersion; - result.Url = result.PreviewUrl; - result.PreviewVersion = null; - result.PreviewUrl = null; + result.Main = result.Optional; + result.Optional = null; } // special cases if (mod.ID == "Pathoschild.SMAPI") { result.Name = "SMAPI"; - result.Url = "https://smapi.io/"; - if (result.PreviewUrl != null) - result.PreviewUrl = "https://smapi.io/"; + if (result.Main != null) + result.Main.Url = "https://smapi.io/"; + if (result.Optional != null) + result.Optional.Url = "https://smapi.io/"; } // add result result.Errors = errors.ToArray(); + result.SetBackwardsCompatibility(apiVersion); mods[mod.ID] = result; } @@ -199,7 +201,8 @@ namespace StardewModdingAPI.Web.Controllers /// <summary>Get the mods for which the API should return data.</summary> /// <param name="model">The search model.</param> - private IEnumerable<ModSearchEntryModel> GetSearchMods(ModSearchModel model) + /// <param name="apiVersion">The requested API version.</param> + private IEnumerable<ModSearchEntryModel> GetSearchMods(ModSearchModel model, ISemanticVersion apiVersion) { if (model == null) yield break; @@ -212,7 +215,7 @@ namespace StardewModdingAPI.Web.Controllers } // yield mod update keys if backwards compatible - if (model.ModKeys != null && model.ModKeys.Any() && this.ShouldBeBackwardsCompatible("2.6-beta.17")) + if (model.ModKeys != null && model.ModKeys.Any() && !apiVersion.IsNewerThan("2.6-beta.17")) { foreach (string updateKey in model.ModKeys.Distinct()) yield return new ModSearchEntryModel(updateKey, new[] { updateKey }); @@ -247,12 +250,11 @@ namespace StardewModdingAPI.Web.Controllers }); } - /// <summary>Get whether the API should return data in a backwards compatible way.</summary> - /// <param name="maxVersion">The last version for which data should be backwards compatible.</param> - private bool ShouldBeBackwardsCompatible(string maxVersion) + /// <summary>Get the requested API version.</summary> + private ISemanticVersion GetApiVersion() { string actualVersion = (string)this.RouteData.Values["version"]; - return !new SemanticVersion(actualVersion).IsNewerThan(new SemanticVersion(maxVersion)); + return new SemanticVersion(actualVersion); } } } diff --git a/src/SMAPI.Web/Framework/ModRepositories/IModRepository.cs b/src/SMAPI.Web/Framework/ModRepositories/IModRepository.cs index 4c879c8d..09c59a86 100644 --- a/src/SMAPI.Web/Framework/ModRepositories/IModRepository.cs +++ b/src/SMAPI.Web/Framework/ModRepositories/IModRepository.cs @@ -1,6 +1,5 @@ using System; using System.Threading.Tasks; -using StardewModdingAPI.Toolkit.Framework.Clients.WebApi; namespace StardewModdingAPI.Web.Framework.ModRepositories { diff --git a/src/SMAPI.Web/Framework/ModRepositories/ModInfoModel.cs b/src/SMAPI.Web/Framework/ModRepositories/ModInfoModel.cs index ccb0699c..18252298 100644 --- a/src/SMAPI.Web/Framework/ModRepositories/ModInfoModel.cs +++ b/src/SMAPI.Web/Framework/ModRepositories/ModInfoModel.cs @@ -1,7 +1,7 @@ namespace StardewModdingAPI.Web.Framework.ModRepositories { /// <summary>Generic metadata about a mod.</summary> - public class ModInfoModel + internal class ModInfoModel { /********* ** Accessors diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs index 150ed34a..a1180474 100644 --- a/src/SMAPI/Program.cs +++ b/src/SMAPI/Program.cs @@ -596,8 +596,8 @@ namespace StardewModdingAPI try { ModEntryModel response = client.GetModInfo(new ModSearchEntryModel("Pathoschild.SMAPI", new[] { $"GitHub:{this.Settings.GitHubProjectName}" })).Single().Value; - ISemanticVersion latestStable = response.Version != null ? new SemanticVersion(response.Version) : null; - ISemanticVersion latestBeta = response.PreviewVersion != null ? new SemanticVersion(response.PreviewVersion) : null; + ISemanticVersion latestStable = response.Main?.Version; + ISemanticVersion latestBeta = response.Optional?.Version; if (latestStable == null && response.Errors.Any()) { @@ -673,18 +673,14 @@ namespace StardewModdingAPI // parse versions ISemanticVersion localVersion = mod.DataRecord?.GetLocalVersionForUpdateChecks(mod.Manifest.Version) ?? mod.Manifest.Version; - ISemanticVersion latestVersion = result.Version != null - ? mod.DataRecord?.GetRemoteVersionForUpdateChecks(result.Version) ?? new SemanticVersion(result.Version) - : null; - ISemanticVersion optionalVersion = result.PreviewVersion != null - ? (mod.DataRecord?.GetRemoteVersionForUpdateChecks(result.PreviewVersion) ?? new SemanticVersion(result.PreviewVersion)) - : null; + ISemanticVersion latestVersion = mod.DataRecord?.GetRemoteVersionForUpdateChecks(result.Main?.Version) ?? result.Main?.Version; + ISemanticVersion optionalVersion = mod.DataRecord?.GetRemoteVersionForUpdateChecks(result.Optional?.Version) ?? result.Optional?.Version; // show update alerts if (this.IsValidUpdate(localVersion, latestVersion, useBetaChannel: true)) - updates.Add(Tuple.Create(mod, latestVersion, result.Url)); + updates.Add(Tuple.Create(mod, latestVersion, result.Main?.Url)); else if (this.IsValidUpdate(localVersion, optionalVersion, useBetaChannel: localVersion.IsPrerelease())) - updates.Add(Tuple.Create(mod, optionalVersion, result.Url)); + updates.Add(Tuple.Create(mod, optionalVersion, result.Optional?.Url)); } // show update errors diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs index e4ab168e..581a524c 100644 --- a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs +++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs @@ -1,3 +1,5 @@ +using System; + namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi { /// <summary>Metadata about a mod.</summary> @@ -12,19 +14,50 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi /// <summary>The mod name.</summary> public string Name { get; set; } + /// <summary>The main version.</summary> + public ModEntryVersionModel Main { get; set; } + + /// <summary>The latest optional version, if newer than <see cref="Main"/>.</summary> + public ModEntryVersionModel Optional { get; set; } + + /// <summary>The errors that occurred while fetching update data.</summary> + public string[] Errors { get; set; } = new string[0]; + + /**** + ** Backwards-compatible fields + ****/ /// <summary>The mod's latest version number.</summary> - public string Version { get; set; } + [Obsolete("Use " + nameof(ModEntryModel.Main))] + internal string Version { get; private set; } /// <summary>The mod's web URL.</summary> - public string Url { get; set; } + [Obsolete("Use " + nameof(ModEntryModel.Main))] + internal string Url { get; private set; } /// <summary>The mod's latest optional release, if newer than <see cref="Version"/>.</summary> - public string PreviewVersion { get; set; } + [Obsolete("Use " + nameof(ModEntryModel.Optional))] + internal string PreviewVersion { get; private set; } /// <summary>The web URL to the mod's latest optional release, if newer than <see cref="Version"/>.</summary> - public string PreviewUrl { get; set; } + [Obsolete("Use " + nameof(ModEntryModel.Optional))] + internal string PreviewUrl { get; private set; } - /// <summary>The errors that occurred while fetching update data.</summary> - public string[] Errors { get; set; } = new string[0]; + + /********* + ** Public methods + *********/ + /// <summary>Set backwards-compatible fields.</summary> + /// <param name="version">The requested API version.</param> + public void SetBackwardsCompatibility(ISemanticVersion version) + { + if (version.IsOlderThan("2.6-beta.19")) + { + this.Version = this.Main?.Version?.ToString(); + this.Url = this.Main?.Url; + + this.PreviewVersion = this.Optional?.Version?.ToString(); + this.PreviewUrl = this.Optional?.Url; + } + } } } diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryVersionModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryVersionModel.cs new file mode 100644 index 00000000..dadb8c10 --- /dev/null +++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryVersionModel.cs @@ -0,0 +1,31 @@ +namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi +{ + /// <summary>Metadata about a version.</summary> + public class ModEntryVersionModel + { + /********* + ** Accessors + *********/ + /// <summary>The version number.</summary> + public ISemanticVersion Version { get; set; } + + /// <summary>The mod page URL.</summary> + public string Url { get; set; } + + + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + public ModEntryVersionModel() { } + + /// <summary>Construct an instance.</summary> + /// <param name="version">The version number.</param> + /// <param name="url">The mod page URL.</param> + public ModEntryVersionModel(ISemanticVersion version, string url) + { + this.Version = version; + this.Url = url; + } + } +} diff --git a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs index 3601fc53..237f2c66 100644 --- a/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs +++ b/src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs @@ -40,12 +40,15 @@ namespace StardewModdingAPI.Toolkit.Framework.ModData /// <summary>Get a semantic remote version for update checks.</summary> /// <param name="version">The remote version to normalise.</param> - public ISemanticVersion GetRemoteVersionForUpdateChecks(string version) + public ISemanticVersion GetRemoteVersionForUpdateChecks(ISemanticVersion version) { - string rawVersion = this.DataRecord.GetRemoteVersionForUpdateChecks(version); + if (version == null) + return null; + + string rawVersion = this.DataRecord.GetRemoteVersionForUpdateChecks(version.ToString()); return rawVersion != null ? new SemanticVersion(rawVersion) - : null; + : version; } } } |