summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2018-06-28 22:01:04 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2018-06-28 22:01:04 -0400
commit3f5a5e54041a641e30fc5cc899046953d9763da4 (patch)
treeca02735544614b85cfc75201823b3dd8d36f2b8a
parent89ad599561a058289d8ea44e0c345f1a30a3a6ac (diff)
downloadSMAPI-3f5a5e54041a641e30fc5cc899046953d9763da4.tar.gz
SMAPI-3f5a5e54041a641e30fc5cc899046953d9763da4.tar.bz2
SMAPI-3f5a5e54041a641e30fc5cc899046953d9763da4.zip
use more structured API response for update checks (#532)
-rw-r--r--src/SMAPI.Web/Controllers/ModsApiController.cs44
-rw-r--r--src/SMAPI.Web/Framework/ModRepositories/IModRepository.cs1
-rw-r--r--src/SMAPI.Web/Framework/ModRepositories/ModInfoModel.cs2
-rw-r--r--src/SMAPI/Program.cs16
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs45
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModEntryVersionModel.cs31
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/ModData/ModDataRecordVersionedFields.cs9
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;
}
}
}