summaryrefslogtreecommitdiff
path: root/src/SMAPI.Toolkit/Framework/Clients
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2019-11-24 13:49:30 -0500
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2019-11-24 13:49:30 -0500
commita3f21685049cabf2d824c8060dc0b1de47e9449e (patch)
treead9add30e9da2a50e0ea0245f1546b7378f0d282 /src/SMAPI.Toolkit/Framework/Clients
parent6521df7b131924835eb797251c1e956fae0d6e13 (diff)
parent277bf082675b98b95bf6184fe3c7a45b969c7ac2 (diff)
downloadSMAPI-a3f21685049cabf2d824c8060dc0b1de47e9449e.tar.gz
SMAPI-a3f21685049cabf2d824c8060dc0b1de47e9449e.tar.bz2
SMAPI-a3f21685049cabf2d824c8060dc0b1de47e9449e.zip
Merge branch 'develop' into stable
Diffstat (limited to 'src/SMAPI.Toolkit/Framework/Clients')
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs18
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs36
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs36
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSearchEntryModel.cs13
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSearchModel.cs52
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs10
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs42
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs21
8 files changed, 179 insertions, 49 deletions
diff --git a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs
index 8a9c0a25..f1bcfccc 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModEntryModel.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
{
/// <summary>Metadata about a mod.</summary>
@@ -9,23 +11,31 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>The mod's unique ID (if known).</summary>
public string ID { get; set; }
+ /// <summary>The update version recommended by the web API based on its version update and mapping rules.</summary>
+ public ModEntryVersionModel SuggestedUpdate { get; set; }
+
+ /// <summary>Optional extended data which isn't needed for update checks.</summary>
+ public ModExtendedMetadataModel Metadata { get; set; }
+
/// <summary>The main version.</summary>
+ [Obsolete]
public ModEntryVersionModel Main { get; set; }
/// <summary>The latest optional version, if newer than <see cref="Main"/>.</summary>
+ [Obsolete]
public ModEntryVersionModel Optional { get; set; }
/// <summary>The latest unofficial version, if newer than <see cref="Main"/> and <see cref="Optional"/>.</summary>
+ [Obsolete]
public ModEntryVersionModel Unofficial { get; set; }
/// <summary>The latest unofficial version for the current Stardew Valley or SMAPI beta, if any (see <see cref="HasBetaInfo"/>).</summary>
+ [Obsolete]
public ModEntryVersionModel UnofficialForBeta { get; set; }
- /// <summary>Optional extended data which isn't needed for update checks.</summary>
- public ModExtendedMetadataModel Metadata { get; set; }
-
/// <summary>Whether a Stardew Valley or SMAPI beta which affects mod compatibility is in progress. If this is true, <see cref="UnofficialForBeta"/> should be used for beta versions of SMAPI instead of <see cref="Unofficial"/>.</summary>
- public bool HasBetaInfo { get; set; }
+ [Obsolete]
+ public bool? HasBetaInfo { get; set; }
/// <summary>The errors that occurred while fetching update data.</summary>
public string[] Errors { get; set; } = new string[0];
diff --git a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs
index 989c18b0..4a697585 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs
@@ -28,6 +28,12 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>The mod ID in the Chucklefish mod repo.</summary>
public int? ChucklefishID { get; set; }
+ /// <summary>The mod ID in the CurseForge mod repo.</summary>
+ public int? CurseForgeID { get; set; }
+
+ /// <summary>The mod key in the CurseForge mod repo (used in mod page URLs).</summary>
+ public string CurseForgeKey { get; set; }
+
/// <summary>The mod ID in the ModDrop mod repo.</summary>
public int? ModDropID { get; set; }
@@ -40,6 +46,17 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>The custom mod page URL (if applicable).</summary>
public string CustomUrl { 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 latest unofficial version, if newer than <see cref="Main"/> and <see cref="Optional"/>.</summary>
+ public ModEntryVersionModel Unofficial { get; set; }
+
+ /// <summary>The latest unofficial version for the current Stardew Valley or SMAPI beta, if any (see <see cref="HasBetaInfo"/>).</summary>
+ public ModEntryVersionModel UnofficialForBeta { get; set; }
/****
** Stable compatibility
@@ -48,13 +65,12 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
[JsonConverter(typeof(StringEnumConverter))]
public WikiCompatibilityStatus? CompatibilityStatus { get; set; }
- /// <summary>The human-readable summary of the compatibility status or workaround, without HTML formatitng.</summary>
+ /// <summary>The human-readable summary of the compatibility status or workaround, without HTML formatting.</summary>
public string CompatibilitySummary { get; set; }
/// <summary>The game or SMAPI version which broke this mod, if applicable.</summary>
public string BrokeIn { get; set; }
-
/****
** Beta compatibility
****/
@@ -62,7 +78,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
[JsonConverter(typeof(StringEnumConverter))]
public WikiCompatibilityStatus? BetaCompatibilityStatus { get; set; }
- /// <summary>The human-readable summary of the compatibility status or workaround for the Stardew Valley beta (if any), without HTML formatitng.</summary>
+ /// <summary>The human-readable summary of the compatibility status or workaround for the Stardew Valley beta (if any), without HTML formatting.</summary>
public string BetaCompatibilitySummary { get; set; }
/// <summary>The beta game or SMAPI version which broke this mod, if applicable.</summary>
@@ -78,8 +94,18 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>Construct an instance.</summary>
/// <param name="wiki">The mod metadata from the wiki (if available).</param>
/// <param name="db">The mod metadata from SMAPI's internal DB (if available).</param>
- public ModExtendedMetadataModel(WikiModEntry wiki, ModDataRecord db)
+ /// <param name="main">The main version.</param>
+ /// <param name="optional">The latest optional version, if newer than <paramref name="main"/>.</param>
+ /// <param name="unofficial">The latest unofficial version, if newer than <paramref name="main"/> and <paramref name="optional"/>.</param>
+ /// <param name="unofficialForBeta">The latest unofficial version for the current Stardew Valley or SMAPI beta, if any.</param>
+ public ModExtendedMetadataModel(WikiModEntry wiki, ModDataRecord db, ModEntryVersionModel main, ModEntryVersionModel optional, ModEntryVersionModel unofficial, ModEntryVersionModel unofficialForBeta)
{
+ // versions
+ this.Main = main;
+ this.Optional = optional;
+ this.Unofficial = unofficial;
+ this.UnofficialForBeta = unofficialForBeta;
+
// wiki data
if (wiki != null)
{
@@ -87,6 +113,8 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
this.Name = wiki.Name.FirstOrDefault();
this.NexusID = wiki.NexusID;
this.ChucklefishID = wiki.ChucklefishID;
+ this.CurseForgeID = wiki.CurseForgeID;
+ this.CurseForgeKey = wiki.CurseForgeKey;
this.ModDropID = wiki.ModDropID;
this.GitHubRepo = wiki.GitHubRepo;
this.CustomSourceUrl = wiki.CustomSourceUrl;
diff --git a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs
deleted file mode 100644
index e352e1cc..00000000
--- a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Linq;
-
-namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
-{
- /// <summary>Specifies mods whose update-check info to fetch.</summary>
- public class ModSearchModel
- {
- /*********
- ** Accessors
- *********/
- /// <summary>The mods for which to find data.</summary>
- public ModSearchEntryModel[] Mods { get; set; }
-
- /// <summary>Whether to include extended metadata for each mod.</summary>
- public bool IncludeExtendedMetadata { get; set; }
-
-
- /*********
- ** Public methods
- *********/
- /// <summary>Construct an empty instance.</summary>
- public ModSearchModel()
- {
- // needed for JSON deserialising
- }
-
- /// <summary>Construct an instance.</summary>
- /// <param name="mods">The mods to search.</param>
- /// <param name="includeExtendedMetadata">Whether to include extended metadata for each mod.</param>
- public ModSearchModel(ModSearchEntryModel[] mods, bool includeExtendedMetadata)
- {
- this.Mods = mods.ToArray();
- this.IncludeExtendedMetadata = includeExtendedMetadata;
- }
- }
-}
diff --git a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSearchEntryModel.cs b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSearchEntryModel.cs
index bca47647..bf81e102 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSearchEntryModel.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSearchEntryModel.cs
@@ -12,6 +12,12 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>The namespaced mod update keys (if available).</summary>
public string[] UpdateKeys { get; set; }
+ /// <summary>The mod version installed by the local player. This is used for version mapping in some cases.</summary>
+ public ISemanticVersion InstalledVersion { get; set; }
+
+ /// <summary>Whether the installed version is broken or could not be loaded.</summary>
+ public bool IsBroken { get; set; }
+
/*********
** Public methods
@@ -19,15 +25,18 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>Construct an empty instance.</summary>
public ModSearchEntryModel()
{
- // needed for JSON deserialising
+ // needed for JSON deserializing
}
/// <summary>Construct an instance.</summary>
/// <param name="id">The unique mod ID.</param>
+ /// <param name="installedVersion">The version installed by the local player. This is used for version mapping in some cases.</param>
/// <param name="updateKeys">The namespaced mod update keys (if available).</param>
- public ModSearchEntryModel(string id, string[] updateKeys)
+ /// <param name="isBroken">Whether the installed version is broken or could not be loaded.</param>
+ public ModSearchEntryModel(string id, ISemanticVersion installedVersion, string[] updateKeys, bool isBroken = false)
{
this.ID = id;
+ this.InstalledVersion = installedVersion;
this.UpdateKeys = updateKeys ?? new string[0];
}
}
diff --git a/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSearchModel.cs b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSearchModel.cs
new file mode 100644
index 00000000..73698173
--- /dev/null
+++ b/src/SMAPI.Toolkit/Framework/Clients/WebApi/ModSearchModel.cs
@@ -0,0 +1,52 @@
+using System.Linq;
+using StardewModdingAPI.Toolkit.Utilities;
+
+namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
+{
+ /// <summary>Specifies mods whose update-check info to fetch.</summary>
+ public class ModSearchModel
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The mods for which to find data.</summary>
+ public ModSearchEntryModel[] Mods { get; set; }
+
+ /// <summary>Whether to include extended metadata for each mod.</summary>
+ public bool IncludeExtendedMetadata { get; set; }
+
+ /// <summary>The SMAPI version installed by the player. This is used for version mapping in some cases.</summary>
+ public ISemanticVersion ApiVersion { get; set; }
+
+ /// <summary>The Stardew Valley version installed by the player.</summary>
+ public ISemanticVersion GameVersion { get; set; }
+
+ /// <summary>The OS on which the player plays.</summary>
+ public Platform? Platform { get; set; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an empty instance.</summary>
+ public ModSearchModel()
+ {
+ // needed for JSON deserializing
+ }
+
+ /// <summary>Construct an instance.</summary>
+ /// <param name="mods">The mods to search.</param>
+ /// <param name="apiVersion">The SMAPI version installed by the player. If this is null, the API won't provide a recommended update.</param>
+ /// <param name="gameVersion">The Stardew Valley version installed by the player.</param>
+ /// <param name="platform">The OS on which the player plays.</param>
+ /// <param name="includeExtendedMetadata">Whether to include extended metadata for each mod.</param>
+ public ModSearchModel(ModSearchEntryModel[] mods, ISemanticVersion apiVersion, ISemanticVersion gameVersion, Platform platform, bool includeExtendedMetadata)
+ {
+ this.Mods = mods.ToArray();
+ this.ApiVersion = apiVersion;
+ this.GameVersion = gameVersion;
+ this.Platform = platform;
+ this.IncludeExtendedMetadata = includeExtendedMetadata;
+ }
+ }
+}
diff --git a/src/SMAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs b/src/SMAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs
index 7c3df384..f0a7c82a 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs
@@ -3,7 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Net;
using Newtonsoft.Json;
-using StardewModdingAPI.Toolkit.Serialisation;
+using StardewModdingAPI.Toolkit.Serialization;
+using StardewModdingAPI.Toolkit.Utilities;
namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
{
@@ -37,12 +38,15 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
/// <summary>Get metadata about a set of mods from the web API.</summary>
/// <param name="mods">The mod keys for which to fetch the latest version.</param>
+ /// <param name="apiVersion">The SMAPI version installed by the player. If this is null, the API won't provide a recommended update.</param>
+ /// <param name="gameVersion">The Stardew Valley version installed by the player.</param>
+ /// <param name="platform">The OS on which the player plays.</param>
/// <param name="includeExtendedMetadata">Whether to include extended metadata for each mod.</param>
- public IDictionary<string, ModEntryModel> GetModInfo(ModSearchEntryModel[] mods, bool includeExtendedMetadata = false)
+ public IDictionary<string, ModEntryModel> GetModInfo(ModSearchEntryModel[] mods, ISemanticVersion apiVersion, ISemanticVersion gameVersion, Platform platform, bool includeExtendedMetadata = false)
{
return this.Post<ModSearchModel, ModEntryModel[]>(
$"v{this.Version}/mods",
- new ModSearchModel(mods, includeExtendedMetadata)
+ new ModSearchModel(mods, apiVersion, gameVersion, platform, includeExtendedMetadata)
).ToDictionary(p => p.ID);
}
diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
index 3e9b8ea6..384f23fc 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
@@ -93,12 +93,17 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
string[] warnings = this.GetAttributeAsCsv(node, "data-warnings");
int? nexusID = this.GetAttributeAsNullableInt(node, "data-nexus-id");
int? chucklefishID = this.GetAttributeAsNullableInt(node, "data-cf-id");
+ int? curseForgeID = this.GetAttributeAsNullableInt(node, "data-curseforge-id");
+ string curseForgeKey = this.GetAttribute(node, "data-curseforge-key");
int? modDropID = this.GetAttributeAsNullableInt(node, "data-moddrop-id");
string githubRepo = this.GetAttribute(node, "data-github");
string customSourceUrl = this.GetAttribute(node, "data-custom-source");
string customUrl = this.GetAttribute(node, "data-url");
string anchor = this.GetAttribute(node, "id");
string contentPackFor = this.GetAttribute(node, "data-content-pack-for");
+ string devNote = this.GetAttribute(node, "data-dev-note");
+ IDictionary<string, string> mapLocalVersions = this.GetAttributeAsVersionMapping(node, "data-map-local-versions");
+ IDictionary<string, string> mapRemoteVersions = this.GetAttributeAsVersionMapping(node, "data-map-remote-versions");
// parse stable compatibility
WikiCompatibilityInfo compatibility = new WikiCompatibilityInfo
@@ -127,6 +132,15 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
}
}
+ // parse links
+ List<Tuple<Uri, string>> metadataLinks = new List<Tuple<Uri, string>>();
+ foreach (HtmlNode linkElement in node.Descendants("td").Last().Descendants("a").Skip(1)) // skip anchor link
+ {
+ string text = linkElement.InnerText.Trim();
+ Uri url = new Uri(linkElement.GetAttributeValue("href", ""));
+ metadataLinks.Add(Tuple.Create(url, text));
+ }
+
// yield model
yield return new WikiModEntry
{
@@ -135,6 +149,8 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
Author = authors,
NexusID = nexusID,
ChucklefishID = chucklefishID,
+ CurseForgeID = curseForgeID,
+ CurseForgeKey = curseForgeKey,
ModDropID = modDropID,
GitHubRepo = githubRepo,
CustomSourceUrl = customSourceUrl,
@@ -143,6 +159,10 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
Compatibility = compatibility,
BetaCompatibility = betaCompatibility,
Warnings = warnings,
+ MetadataLinks = metadataLinks.ToArray(),
+ DevNote = devNote,
+ MapLocalVersions = mapLocalVersions,
+ MapRemoteVersions = mapRemoteVersions,
Anchor = anchor
};
}
@@ -207,6 +227,28 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
return null;
}
+ /// <summary>Get an attribute value and parse it as a version mapping.</summary>
+ /// <param name="element">The element whose attributes to read.</param>
+ /// <param name="name">The attribute name.</param>
+ private IDictionary<string, string> GetAttributeAsVersionMapping(HtmlNode element, string name)
+ {
+ // get raw value
+ string raw = this.GetAttribute(element, name);
+ if (raw?.Contains("→") != true)
+ return null;
+
+ // parse
+ // Specified on the wiki in the form "remote version → mapped version; another remote version → mapped version"
+ IDictionary<string, string> map = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
+ foreach (string pair in raw.Split(';'))
+ {
+ string[] versions = pair.Split('→');
+ if (versions.Length == 2 && !string.IsNullOrWhiteSpace(versions[0]) && !string.IsNullOrWhiteSpace(versions[1]))
+ map[versions[0].Trim()] = versions[1].Trim();
+ }
+ return map;
+ }
+
/// <summary>Get the text of an element with the given class name.</summary>
/// <param name="container">The metadata container.</param>
/// <param name="className">The field name.</param>
diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
index cf416cc6..931dcd43 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
@@ -1,3 +1,6 @@
+using System;
+using System.Collections.Generic;
+
namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
{
/// <summary>A mod entry in the wiki list.</summary>
@@ -21,6 +24,12 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <summary>The mod ID in the Chucklefish mod repo.</summary>
public int? ChucklefishID { get; set; }
+ /// <summary>The mod ID in the CurseForge mod repo.</summary>
+ public int? CurseForgeID { get; set; }
+
+ /// <summary>The mod key in the CurseForge mod repo (used in mod page URLs).</summary>
+ public string CurseForgeKey { get; set; }
+
/// <summary>The mod ID in the ModDrop mod repo.</summary>
public int? ModDropID { get; set; }
@@ -48,6 +57,18 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <summary>The human-readable warnings for players about this mod.</summary>
public string[] Warnings { get; set; }
+ /// <summary>Extra metadata links (usually for open pull requests).</summary>
+ public Tuple<Uri, string>[] MetadataLinks { get; set; }
+
+ /// <summary>Special notes intended for developers who maintain unofficial updates or submit pull requests. </summary>
+ public string DevNote { get; set; }
+
+ /// <summary>Maps local versions to a semantic version for update checks.</summary>
+ public IDictionary<string, string> MapLocalVersions { get; set; }
+
+ /// <summary>Maps remote versions to a semantic version for update checks.</summary>
+ public IDictionary<string, string> MapRemoteVersions { get; set; }
+
/// <summary>The link anchor for the mod entry in the wiki compatibility list.</summary>
public string Anchor { get; set; }
}