From 6d4eed56b1d80d02db773b0cd2f372baec6b2d1b Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Thu, 22 Sep 2022 23:03:26 -0400 Subject: refactor UpdateKey parsing, move responsibility for subkey matching UpdateKey parsing now allows multiple : and @ inside the update key, splitting on the first occurence of each Subkey matching is moved into IModDownload / GenericModDownload, in preparation for some Mod Sites using something less error-prone than substring matching. --- .../Framework/UpdateData/UpdateKey.cs | 45 +++++++++++++--------- 1 file changed, 27 insertions(+), 18 deletions(-) (limited to 'src/SMAPI.Toolkit/Framework') 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) { } + /// + /// 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. + /// + /// The string to split. + /// The character on which to split. + /// + /// If true then the second string returned will include the delimiter character + /// (provided that the string is not null) + /// + /// + /// A pair containing the string consisting of all characters in before the first + /// occurrence of , and a string consisting of all characters in + /// after the first occurrence of or null if the delimiter does not + /// exist in s. Both strings are trimmed of whitespace. + /// + 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()); + } + /// Parse a raw update key. /// The raw update key to parse. 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)) -- cgit From 83aec980b3ee739fb4bc251217556b3ae44f741b Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Sat, 1 Oct 2022 21:09:39 -0400 Subject: Add UpdateManifest site type. Adds the UpdateManifest site key and associated client. This required some additional features in the existing update machinery. Each "version" can now (optionally) have its own download URL. Mod Page objects can now specify that subkey matching (for that page) should be "strict". A strict subkey match does not fall back to matching with no subkey if a subkey was provided but produced no versions. It also strips the leading '@' from the subkey. IModDownload objects are now responsible for deciding whether a subkey matches or not. The default behavior is unchanged, but this allows different mod sites to have different rules for subkey matching (which the UpdateManifest mod site uses to force exact matches). --- src/SMAPI.Toolkit/Framework/UpdateData/ModSiteKey.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/SMAPI.Toolkit/Framework') diff --git a/src/SMAPI.Toolkit/Framework/UpdateData/ModSiteKey.cs b/src/SMAPI.Toolkit/Framework/UpdateData/ModSiteKey.cs index 47cd3f7e..d1dd9049 100644 --- a/src/SMAPI.Toolkit/Framework/UpdateData/ModSiteKey.cs +++ b/src/SMAPI.Toolkit/Framework/UpdateData/ModSiteKey.cs @@ -19,6 +19,9 @@ namespace StardewModdingAPI.Toolkit.Framework.UpdateData ModDrop, /// The Nexus Mods mod repository. - Nexus + Nexus, + + /// An arbitrary URL for an update manifest file. + UpdateManifest } } -- cgit From 55fd4839da43e7ca205eaa85480786e3dfe8af6f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 29 Jan 2023 16:37:22 -0500 Subject: minor formatting, copyediting, and error-handling --- .../Framework/UpdateData/ModSiteKey.cs | 2 +- .../Framework/UpdateData/UpdateKey.cs | 47 ++++++++++------------ 2 files changed, 22 insertions(+), 27 deletions(-) (limited to 'src/SMAPI.Toolkit/Framework') diff --git a/src/SMAPI.Toolkit/Framework/UpdateData/ModSiteKey.cs b/src/SMAPI.Toolkit/Framework/UpdateData/ModSiteKey.cs index d1dd9049..195b0367 100644 --- a/src/SMAPI.Toolkit/Framework/UpdateData/ModSiteKey.cs +++ b/src/SMAPI.Toolkit/Framework/UpdateData/ModSiteKey.cs @@ -21,7 +21,7 @@ namespace StardewModdingAPI.Toolkit.Framework.UpdateData /// The Nexus Mods mod repository. Nexus, - /// An arbitrary URL for an update manifest file. + /// An arbitrary URL to a JSON file containing update data. UpdateManifest } } diff --git a/src/SMAPI.Toolkit/Framework/UpdateData/UpdateKey.cs b/src/SMAPI.Toolkit/Framework/UpdateData/UpdateKey.cs index 7c2cc73c..3e8064fd 100644 --- a/src/SMAPI.Toolkit/Framework/UpdateData/UpdateKey.cs +++ b/src/SMAPI.Toolkit/Framework/UpdateData/UpdateKey.cs @@ -54,29 +54,6 @@ namespace StardewModdingAPI.Toolkit.Framework.UpdateData public UpdateKey(ModSiteKey site, string? id, string? subkey) : this(UpdateKey.GetString(site, id, subkey), site, id, subkey) { } - /// - /// 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. - /// - /// The string to split. - /// The character on which to split. - /// - /// If true then the second string returned will include the delimiter character - /// (provided that the string is not null) - /// - /// - /// A pair containing the string consisting of all characters in before the first - /// occurrence of , and a string consisting of all characters in - /// after the first occurrence of or null if the delimiter does not - /// exist in s. Both strings are trimmed of whitespace. - /// - 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()); - } - /// Parse a raw update key. /// The raw update key to parse. public static UpdateKey Parse(string? raw) @@ -84,14 +61,14 @@ namespace StardewModdingAPI.Toolkit.Framework.UpdateData if (raw is null) return new UpdateKey(raw, ModSiteKey.Unknown, null, null); // extract site + ID - (string rawSite, string? id) = Bifurcate(raw, ':'); - if (string.IsNullOrWhiteSpace(id)) + (string rawSite, string? id) = UpdateKey.SplitTwoParts(raw, ':'); + if (string.IsNullOrEmpty(id)) id = null; // extract subkey string? subkey = null; if (id != null) - (id, subkey) = Bifurcate(id, '@', true); + (id, subkey) = UpdateKey.SplitTwoParts(id, '@', true); // parse if (!Enum.TryParse(rawSite, true, out ModSiteKey site)) @@ -160,5 +137,23 @@ namespace StardewModdingAPI.Toolkit.Framework.UpdateData { return $"{site}:{id}{subkey}".Trim(); } + + + /********* + ** Private methods + *********/ + /// Split a string into two parts at a delimiter and trim whitespace. + /// The string to split. + /// The character on which to split. + /// Whether to include the delimiter in the second string. + /// Returns a tuple containing the two strings, with the second value null if the delimiter wasn't found. + private static (string, string?) SplitTwoParts(string str, char delimiter, bool keepDelimiter = false) + { + int splitIndex = str.IndexOf(delimiter); + + return splitIndex >= 0 + ? (str.Substring(0, splitIndex).Trim(), str.Substring(splitIndex + (keepDelimiter ? 0 : 1)).Trim()) + : (str.Trim(), null); + } } } -- cgit