diff options
-rw-r--r-- | src/SMAPI.Toolkit/Framework/UpdateData/UpdateKey.cs | 45 | ||||
-rw-r--r-- | src/SMAPI.Web/Framework/Clients/GenericModDownload.cs | 14 | ||||
-rw-r--r-- | src/SMAPI.Web/Framework/IModDownload.cs | 5 | ||||
-rw-r--r-- | src/SMAPI.Web/Framework/ModSiteManager.cs | 12 |
4 files changed, 52 insertions, 24 deletions
diff --git a/src/SMAPI.Toolkit/Framework/UpdateData/UpdateKey.cs b/src/SMAPI.Toolkit/Framework/UpdateData/UpdateKey.cs index 960caf96..7c2cc73c 100644 --- a/src/SMAPI.Toolkit/Framework/UpdateData/UpdateKey.cs +++ b/src/SMAPI.Toolkit/Framework/UpdateData/UpdateKey.cs @@ -54,35 +54,44 @@ namespace StardewModdingAPI.Toolkit.Framework.UpdateData public UpdateKey(ModSiteKey site, string? id, string? subkey) : this(UpdateKey.GetString(site, id, subkey), site, id, subkey) { } + /// <summary> + /// Split a string into two at a delimiter. If the delimiter does not appear in the string then the second + /// value of the returned tuple is null. Both returned strings are trimmed of whitespace. + /// </summary> + /// <param name="s">The string to split.</param> + /// <param name="delimiter">The character on which to split.</param> + /// <param name="keepDelimiter"> + /// If <c>true</c> then the second string returned will include the delimiter character + /// (provided that the string is not <c>null</c>) + /// </param> + /// <returns> + /// A pair containing the string consisting of all characters in <paramref name="s"/> before the first + /// occurrence of <paramref name="delimiter"/>, and a string consisting of all characters in <paramref name="s"/> + /// after the first occurrence of <paramref name="delimiter"/> or <c>null</c> if the delimiter does not + /// exist in s. Both strings are trimmed of whitespace. + /// </returns> + private static (string, string?) Bifurcate(string s, char delimiter, bool keepDelimiter = false) { + int pos = s.IndexOf(delimiter); + if (pos < 0) + return (s.Trim(), null); + return (s.Substring(0, pos).Trim(), s.Substring(pos + (keepDelimiter ? 0 : 1)).Trim()); + } + /// <summary>Parse a raw update key.</summary> /// <param name="raw">The raw update key to parse.</param> public static UpdateKey Parse(string? raw) { + if (raw is null) + return new UpdateKey(raw, ModSiteKey.Unknown, null, null); // extract site + ID - string? rawSite; - string? id; - { - string[]? parts = raw?.Trim().Split(':'); - if (parts?.Length != 2) - return new UpdateKey(raw, ModSiteKey.Unknown, null, null); - - rawSite = parts[0].Trim(); - id = parts[1].Trim(); - } + (string rawSite, string? id) = Bifurcate(raw, ':'); if (string.IsNullOrWhiteSpace(id)) id = null; // extract subkey string? subkey = null; if (id != null) - { - string[] parts = id.Split('@'); - if (parts.Length == 2) - { - id = parts[0].Trim(); - subkey = $"@{parts[1]}".Trim(); - } - } + (id, subkey) = Bifurcate(id, '@', true); // parse if (!Enum.TryParse(rawSite, true, out ModSiteKey site)) diff --git a/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs b/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs index 548f17c3..b37e5cda 100644 --- a/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs +++ b/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs @@ -1,3 +1,5 @@ +using System; + namespace StardewModdingAPI.Web.Framework.Clients { /// <summary>Generic metadata about a file download on a mod page.</summary> @@ -29,5 +31,17 @@ namespace StardewModdingAPI.Web.Framework.Clients this.Description = description; this.Version = version; } + + /// <summary> + /// Return true if the subkey matches this download. A subkey matches if it appears as + /// a substring in the name or description. + /// </summary> + /// <param name="subkey">the subkey</param> + /// <returns><c>true</c> if <paramref name="subkey"/> matches this download, otherwise <c>false</c></returns> + /// <exception cref="System.NotImplementedException"></exception> + public bool MatchesSubkey(string subkey) { + return this.Name.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true + || this.Description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true; + } } } diff --git a/src/SMAPI.Web/Framework/IModDownload.cs b/src/SMAPI.Web/Framework/IModDownload.cs index fe171785..13739f8f 100644 --- a/src/SMAPI.Web/Framework/IModDownload.cs +++ b/src/SMAPI.Web/Framework/IModDownload.cs @@ -14,5 +14,10 @@ namespace StardewModdingAPI.Web.Framework /// <summary>The download's file version.</summary> string? Version { get; } + + /// <summary>Return <c>true</c> iff the subkey matches this download</summary> + /// <param name="subkey">the subkey</param> + /// <returns><c>true</c> if <paramref name="subkey"/> matches this download, otherwise <c>false</c></returns> + bool MatchesSubkey(string subkey); } } diff --git a/src/SMAPI.Web/Framework/ModSiteManager.cs b/src/SMAPI.Web/Framework/ModSiteManager.cs index 674b9ffc..70070d63 100644 --- a/src/SMAPI.Web/Framework/ModSiteManager.cs +++ b/src/SMAPI.Web/Framework/ModSiteManager.cs @@ -119,7 +119,7 @@ namespace StardewModdingAPI.Web.Framework preview = null; // parse all versions from the mod page - IEnumerable<(string? name, string? description, ISemanticVersion? version)> GetAllVersions() + IEnumerable<(IModDownload? download, ISemanticVersion? version)> GetAllVersions() { if (mod != null) { @@ -132,14 +132,14 @@ namespace StardewModdingAPI.Web.Framework // get mod version ISemanticVersion? modVersion = ParseAndMapVersion(mod.Version); if (modVersion != null) - yield return (name: null, description: null, version: ParseAndMapVersion(mod.Version)); + yield return (download: null, version: ParseAndMapVersion(mod.Version)); // get file versions foreach (IModDownload download in mod.Downloads) { ISemanticVersion? cur = ParseAndMapVersion(download.Version); if (cur != null) - yield return (download.Name, download.Description, cur); + yield return (download, cur); } } } @@ -148,13 +148,13 @@ namespace StardewModdingAPI.Web.Framework .ToArray(); // get main + preview versions - void TryGetVersions([NotNullWhen(true)] out ISemanticVersion? mainVersion, out ISemanticVersion? previewVersion, Func<(string? name, string? description, ISemanticVersion? version), bool>? filter = null) + void TryGetVersions([NotNullWhen(true)] out ISemanticVersion? mainVersion, out ISemanticVersion? previewVersion, Func<(IModDownload? download, ISemanticVersion? version), bool>? filter = null) { mainVersion = null; previewVersion = null; // get latest main + preview version - foreach ((string? name, string? description, ISemanticVersion? version) entry in versions) + foreach ((IModDownload? download, ISemanticVersion? version) entry in versions) { if (entry.version is null || filter?.Invoke(entry) == false) continue; @@ -178,7 +178,7 @@ namespace StardewModdingAPI.Web.Framework } if (subkey is not null) - TryGetVersions(out main, out preview, entry => entry.name?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true || entry.description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true); + TryGetVersions(out main, out preview, entry => entry.download?.MatchesSubkey(subkey) == true); if (main is null) TryGetVersions(out main, out preview); |