add support for unofficial version in update checks (#532)
This commit is contained in:
parent
3f5a5e5404
commit
c9fedebaf3
|
@ -10,6 +10,7 @@
|
|||
* Improved update checks:
|
||||
* added beta update channel;
|
||||
* added support for optional files on Nexus;
|
||||
* added support for unofficial updates from the wiki (only if the installed version is incompatible);
|
||||
* added console warning for mods which don't have update checks configured;
|
||||
* fixed mod update checks failing if a mod only has prerelease versions on GitHub;
|
||||
* fixed Nexus mod update alerts not showing HTTPS links.
|
||||
|
|
|
@ -10,6 +10,7 @@ using Microsoft.Extensions.Caching.Memory;
|
|||
using Microsoft.Extensions.Options;
|
||||
using StardewModdingAPI.Toolkit;
|
||||
using StardewModdingAPI.Toolkit.Framework.Clients.WebApi;
|
||||
using StardewModdingAPI.Toolkit.Framework.Clients.Wiki;
|
||||
using StardewModdingAPI.Toolkit.Framework.ModData;
|
||||
using StardewModdingAPI.Web.Framework.Clients.Chucklefish;
|
||||
using StardewModdingAPI.Web.Framework.Clients.GitHub;
|
||||
|
@ -45,6 +46,9 @@ namespace StardewModdingAPI.Web.Controllers
|
|||
/// <summary>The internal mod metadata list.</summary>
|
||||
private readonly ModDatabase ModDatabase;
|
||||
|
||||
/// <summary>The web URL for the wiki compatibility list.</summary>
|
||||
private readonly string WikiCompatibilityPageUrl;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
|
@ -60,6 +64,7 @@ namespace StardewModdingAPI.Web.Controllers
|
|||
{
|
||||
this.ModDatabase = new ModToolkit().GetModDatabase(Path.Combine(environment.WebRootPath, "StardewModdingAPI.metadata.json"));
|
||||
ModUpdateCheckConfig config = configProvider.Value;
|
||||
this.WikiCompatibilityPageUrl = config.WikiCompatibilityPageUrl;
|
||||
|
||||
this.Cache = cache;
|
||||
this.SuccessCacheMinutes = config.SuccessCacheMinutes;
|
||||
|
@ -84,6 +89,9 @@ namespace StardewModdingAPI.Web.Controllers
|
|||
ISemanticVersion apiVersion = this.GetApiVersion();
|
||||
ModSearchEntryModel[] searchMods = this.GetSearchMods(model, apiVersion).ToArray();
|
||||
|
||||
// fetch wiki data
|
||||
WikiCompatibilityEntry[] wikiData = await this.GetWikiDataAsync();
|
||||
|
||||
// perform checks
|
||||
IDictionary<string, ModEntryModel> mods = new Dictionary<string, ModEntryModel>(StringComparer.CurrentCultureIgnoreCase);
|
||||
foreach (ModSearchEntryModel mod in searchMods)
|
||||
|
@ -123,7 +131,7 @@ namespace StardewModdingAPI.Web.Controllers
|
|||
continue;
|
||||
}
|
||||
|
||||
if (result.Main == null || result.Main.Version.IsOlderThan(version))
|
||||
if (this.IsNewer(version, result.Main?.Version))
|
||||
{
|
||||
result.Name = data.Name;
|
||||
result.Main = new ModEntryVersionModel(version, data.Url);
|
||||
|
@ -139,7 +147,7 @@ namespace StardewModdingAPI.Web.Controllers
|
|||
continue;
|
||||
}
|
||||
|
||||
if (result.Optional == null || result.Optional.Version.IsOlderThan(version))
|
||||
if (this.IsNewer(version, result.Optional?.Version))
|
||||
{
|
||||
result.Name = result.Name ?? data.Name;
|
||||
result.Optional = new ModEntryVersionModel(version, data.Url);
|
||||
|
@ -147,6 +155,13 @@ namespace StardewModdingAPI.Web.Controllers
|
|||
}
|
||||
}
|
||||
|
||||
// get unofficial version
|
||||
{
|
||||
WikiCompatibilityEntry wikiEntry = wikiData.FirstOrDefault(entry => entry.ID.Contains(result.ID.Trim(), StringComparer.InvariantCultureIgnoreCase));
|
||||
if (wikiEntry?.UnofficialVersion != null && this.IsNewer(wikiEntry.UnofficialVersion, result.Main?.Version) && this.IsNewer(wikiEntry.UnofficialVersion, result.Optional?.Version))
|
||||
result.Unofficial = new ModEntryVersionModel(wikiEntry.UnofficialVersion, this.WikiCompatibilityPageUrl);
|
||||
}
|
||||
|
||||
// fallback to preview if latest is invalid
|
||||
if (result.Main == null && result.Optional != null)
|
||||
{
|
||||
|
@ -199,6 +214,14 @@ namespace StardewModdingAPI.Web.Controllers
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Get whether a <paramref name="current"/> version is newer than an <paramref name="other"/> version.</summary>
|
||||
/// <param name="current">The current version.</param>
|
||||
/// <param name="other">The other version.</param>
|
||||
private bool IsNewer(ISemanticVersion current, ISemanticVersion other)
|
||||
{
|
||||
return current != null && (other == null || other.IsOlderThan(current));
|
||||
}
|
||||
|
||||
/// <summary>Get the mods for which the API should return data.</summary>
|
||||
/// <param name="model">The search model.</param>
|
||||
/// <param name="apiVersion">The requested API version.</param>
|
||||
|
@ -222,6 +245,26 @@ namespace StardewModdingAPI.Web.Controllers
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Get mod data from the wiki compatibility list.</summary>
|
||||
private async Task<WikiCompatibilityEntry[]> GetWikiDataAsync()
|
||||
{
|
||||
ModToolkit toolkit = new ModToolkit();
|
||||
return await this.Cache.GetOrCreateAsync($"_wiki", async entry =>
|
||||
{
|
||||
try
|
||||
{
|
||||
WikiCompatibilityEntry[] entries = await toolkit.GetWikiCompatibilityListAsync();
|
||||
entry.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(this.SuccessCacheMinutes);
|
||||
return entries;
|
||||
}
|
||||
catch
|
||||
{
|
||||
entry.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(this.ErrorCacheMinutes);
|
||||
return new WikiCompatibilityEntry[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>Get the mod info for an update key.</summary>
|
||||
/// <param name="updateKey">The namespaced update key.</param>
|
||||
private async Task<ModInfoModel> GetInfoForUpdateKeyAsync(string updateKey)
|
||||
|
|
|
@ -24,5 +24,8 @@ namespace StardewModdingAPI.Web.Framework.ConfigModels
|
|||
|
||||
/// <summary>The repository key for Nexus Mods.</summary>
|
||||
public string NexusKey { get; set; }
|
||||
|
||||
/// <summary>The web URL for the wiki compatibility list.</summary>
|
||||
public string WikiCompatibilityPageUrl { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
|
||||
"ChucklefishKey": "Chucklefish",
|
||||
"GitHubKey": "GitHub",
|
||||
"NexusKey": "Nexus"
|
||||
"NexusKey": "Nexus",
|
||||
|
||||
"WikiCompatibilityPageUrl": "https://smapi.io/compat"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -675,12 +675,15 @@ namespace StardewModdingAPI
|
|||
ISemanticVersion localVersion = mod.DataRecord?.GetLocalVersionForUpdateChecks(mod.Manifest.Version) ?? mod.Manifest.Version;
|
||||
ISemanticVersion latestVersion = mod.DataRecord?.GetRemoteVersionForUpdateChecks(result.Main?.Version) ?? result.Main?.Version;
|
||||
ISemanticVersion optionalVersion = mod.DataRecord?.GetRemoteVersionForUpdateChecks(result.Optional?.Version) ?? result.Optional?.Version;
|
||||
ISemanticVersion unofficialVersion = result.Unofficial?.Version;
|
||||
|
||||
// show update alerts
|
||||
if (this.IsValidUpdate(localVersion, latestVersion, useBetaChannel: true))
|
||||
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.Optional?.Url));
|
||||
else if (this.IsValidUpdate(localVersion, unofficialVersion, useBetaChannel: mod.Status == ModMetadataStatus.Failed))
|
||||
updates.Add(Tuple.Create(mod, unofficialVersion, result.Unofficial?.Url));
|
||||
}
|
||||
|
||||
// show update errors
|
||||
|
|
|
@ -20,6 +20,9 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
|
|||
/// <summary>The latest optional version, if newer than <see cref="Main"/>.</summary>
|
||||
public ModEntryVersionModel Optional { get; set; }
|
||||
|
||||
/// <summary>The latest unofficial version, if newer than <see cref="Main"/> and <see cref="Optional"/>.</summary>
|
||||
public ModEntryVersionModel Unofficial { get; set; }
|
||||
|
||||
/// <summary>The errors that occurred while fetching update data.</summary>
|
||||
public string[] Errors { get; set; } = new string[0];
|
||||
|
||||
|
|
Loading…
Reference in New Issue