summaryrefslogtreecommitdiff
path: root/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs')
-rw-r--r--src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs161
1 files changed, 87 insertions, 74 deletions
diff --git a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
index f85e82e1..7f06d170 100644
--- a/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
+++ b/src/SMAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
@@ -51,8 +51,8 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
doc.LoadHtml(html);
// fetch game versions
- string stableVersion = doc.DocumentNode.SelectSingleNode("//div[@class='game-stable-version']")?.InnerText;
- string betaVersion = doc.DocumentNode.SelectSingleNode("//div[@class='game-beta-version']")?.InnerText;
+ string? stableVersion = doc.DocumentNode.SelectSingleNode("//div[@class='game-stable-version']")?.InnerText;
+ string? betaVersion = doc.DocumentNode.SelectSingleNode("//div[@class='game-beta-version']")?.InnerText;
if (betaVersion == stableVersion)
betaVersion = null;
@@ -63,9 +63,9 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
if (modNodes == null)
throw new InvalidOperationException("Can't parse wiki compatibility list, no mod data overrides section found.");
- foreach (var entry in this.ParseOverrideEntries(modNodes))
+ foreach (WikiDataOverrideEntry entry in this.ParseOverrideEntries(modNodes))
{
- if (entry.Ids?.Any() != true || !entry.HasChanges)
+ if (entry.Ids.Any() != true || !entry.HasChanges)
continue;
foreach (string id in entry.Ids)
@@ -83,18 +83,17 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
}
// build model
- return new WikiModList
- {
- StableVersion = stableVersion,
- BetaVersion = betaVersion,
- Mods = mods
- };
+ return new WikiModList(
+ stableVersion: stableVersion,
+ betaVersion: betaVersion,
+ mods: mods
+ );
}
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
public void Dispose()
{
- this.Client?.Dispose();
+ this.Client.Dispose();
}
@@ -116,71 +115,68 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
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");
+ 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");
- string pullRequestUrl = this.GetAttribute(node, "data-pr");
+ 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");
+ string? pullRequestUrl = this.GetAttribute(node, "data-pr");
// parse stable compatibility
- WikiCompatibilityInfo compatibility = new WikiCompatibilityInfo
- {
- Status = this.GetAttributeAsEnum<WikiCompatibilityStatus>(node, "data-status") ?? WikiCompatibilityStatus.Ok,
- BrokeIn = this.GetAttribute(node, "data-broke-in"),
- UnofficialVersion = this.GetAttributeAsSemanticVersion(node, "data-unofficial-version"),
- UnofficialUrl = this.GetAttribute(node, "data-unofficial-url"),
- Summary = this.GetInnerHtml(node, "mod-summary")?.Trim()
- };
+ WikiCompatibilityInfo compatibility = new(
+ status: this.GetAttributeAsEnum<WikiCompatibilityStatus>(node, "data-status") ?? WikiCompatibilityStatus.Ok,
+ brokeIn: this.GetAttribute(node, "data-broke-in"),
+ unofficialVersion: this.GetAttributeAsSemanticVersion(node, "data-unofficial-version"),
+ unofficialUrl: this.GetAttribute(node, "data-unofficial-url"),
+ summary: this.GetInnerHtml(node, "mod-summary")?.Trim()
+ );
// parse beta compatibility
- WikiCompatibilityInfo betaCompatibility = null;
+ WikiCompatibilityInfo? betaCompatibility = null;
{
WikiCompatibilityStatus? betaStatus = this.GetAttributeAsEnum<WikiCompatibilityStatus>(node, "data-beta-status");
if (betaStatus.HasValue)
{
- betaCompatibility = new WikiCompatibilityInfo
- {
- Status = betaStatus.Value,
- BrokeIn = this.GetAttribute(node, "data-beta-broke-in"),
- UnofficialVersion = this.GetAttributeAsSemanticVersion(node, "data-beta-unofficial-version"),
- UnofficialUrl = this.GetAttribute(node, "data-beta-unofficial-url"),
- Summary = this.GetInnerHtml(node, "mod-beta-summary")
- };
+ betaCompatibility = new WikiCompatibilityInfo(
+ status: betaStatus.Value,
+ brokeIn: this.GetAttribute(node, "data-beta-broke-in"),
+ unofficialVersion: this.GetAttributeAsSemanticVersion(node, "data-beta-unofficial-version"),
+ unofficialUrl: this.GetAttribute(node, "data-beta-unofficial-url"),
+ summary: this.GetInnerHtml(node, "mod-beta-summary")
+ );
}
}
// find data overrides
- WikiDataOverrideEntry overrides = ids
+ WikiDataOverrideEntry? overrides = ids
.Select(id => overridesById.TryGetValue(id, out overrides) ? overrides : null)
.FirstOrDefault(p => p != null);
// yield model
- yield return new WikiModEntry
- {
- ID = ids,
- Name = names,
- Author = authors,
- NexusID = nexusID,
- ChucklefishID = chucklefishID,
- CurseForgeID = curseForgeID,
- CurseForgeKey = curseForgeKey,
- ModDropID = modDropID,
- GitHubRepo = githubRepo,
- CustomSourceUrl = customSourceUrl,
- CustomUrl = customUrl,
- ContentPackFor = contentPackFor,
- Compatibility = compatibility,
- BetaCompatibility = betaCompatibility,
- Warnings = warnings,
- PullRequestUrl = pullRequestUrl,
- DevNote = devNote,
- Overrides = overrides,
- Anchor = anchor
- };
+ yield return new WikiModEntry(
+ id: ids,
+ name: names,
+ author: authors,
+ nexusId: nexusID,
+ chucklefishId: chucklefishID,
+ curseForgeId: curseForgeID,
+ curseForgeKey: curseForgeKey,
+ modDropId: modDropID,
+ githubRepo: githubRepo,
+ customSourceUrl: customSourceUrl,
+ customUrl: customUrl,
+ contentPackFor: contentPackFor,
+ compatibility: compatibility,
+ betaCompatibility: betaCompatibility,
+ warnings: warnings,
+ pullRequestUrl: pullRequestUrl,
+ devNote: devNote,
+ overrides: overrides,
+ anchor: anchor
+ );
}
}
@@ -194,10 +190,10 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
{
Ids = this.GetAttributeAsCsv(node, "data-id"),
ChangeLocalVersions = this.GetAttributeAsChangeDescriptor(node, "data-local-version",
- raw => SemanticVersion.TryParse(raw, out ISemanticVersion version) ? version.ToString() : raw
+ raw => SemanticVersion.TryParse(raw, out ISemanticVersion? version) ? version.ToString() : raw
),
ChangeRemoteVersions = this.GetAttributeAsChangeDescriptor(node, "data-remote-version",
- raw => SemanticVersion.TryParse(raw, out ISemanticVersion version) ? version.ToString() : raw
+ raw => SemanticVersion.TryParse(raw, out ISemanticVersion? version) ? version.ToString() : raw
),
ChangeUpdateKeys = this.GetAttributeAsChangeDescriptor(node, "data-update-keys",
@@ -210,7 +206,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <summary>Get an attribute value.</summary>
/// <param name="element">The element whose attributes to read.</param>
/// <param name="name">The attribute name.</param>
- private string GetAttribute(HtmlNode element, string name)
+ private string? GetAttribute(HtmlNode element, string name)
{
string value = element.GetAttributeValue(name, null);
if (string.IsNullOrWhiteSpace(value))
@@ -223,9 +219,9 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <param name="element">The element whose attributes to read.</param>
/// <param name="name">The attribute name.</param>
/// <param name="formatValue">Format an raw entry value when applying changes.</param>
- private ChangeDescriptor GetAttributeAsChangeDescriptor(HtmlNode element, string name, Func<string, string> formatValue)
+ private ChangeDescriptor? GetAttributeAsChangeDescriptor(HtmlNode element, string name, Func<string, string> formatValue)
{
- string raw = this.GetAttribute(element, name);
+ string? raw = this.GetAttribute(element, name);
return raw != null
? ChangeDescriptor.Parse(raw, out _, formatValue)
: null;
@@ -236,10 +232,10 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <param name="name">The attribute name.</param>
private string[] GetAttributeAsCsv(HtmlNode element, string name)
{
- string raw = this.GetAttribute(element, name);
+ string? raw = this.GetAttribute(element, name);
return !string.IsNullOrWhiteSpace(raw)
? raw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()).ToArray()
- : new string[0];
+ : Array.Empty<string>();
}
/// <summary>Get an attribute value and parse it as an enum value.</summary>
@@ -248,7 +244,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <param name="name">The attribute name.</param>
private TEnum? GetAttributeAsEnum<TEnum>(HtmlNode element, string name) where TEnum : struct
{
- string raw = this.GetAttribute(element, name);
+ string? raw = this.GetAttribute(element, name);
if (raw == null)
return null;
if (!Enum.TryParse(raw, true, out TEnum value) && Enum.IsDefined(typeof(TEnum), value))
@@ -259,10 +255,10 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <summary>Get an attribute value and parse it as a semantic version.</summary>
/// <param name="element">The element whose attributes to read.</param>
/// <param name="name">The attribute name.</param>
- private ISemanticVersion GetAttributeAsSemanticVersion(HtmlNode element, string name)
+ private ISemanticVersion? GetAttributeAsSemanticVersion(HtmlNode element, string name)
{
- string raw = this.GetAttribute(element, name);
- return SemanticVersion.TryParse(raw, out ISemanticVersion version)
+ string? raw = this.GetAttribute(element, name);
+ return SemanticVersion.TryParse(raw, out ISemanticVersion? version)
? version
: null;
}
@@ -272,7 +268,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <param name="name">The attribute name.</param>
private int? GetAttributeAsNullableInt(HtmlNode element, string name)
{
- string raw = this.GetAttribute(element, name);
+ string? raw = this.GetAttribute(element, name);
if (raw != null && int.TryParse(raw, out int value))
return value;
return null;
@@ -281,7 +277,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <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>
- private string GetInnerHtml(HtmlNode container, string className)
+ private string? GetInnerHtml(HtmlNode container, string className)
{
return container.Descendants().FirstOrDefault(p => p.HasClass(className))?.InnerHtml;
}
@@ -291,8 +287,22 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
private class ResponseModel
{
+ /*********
+ ** Accessors
+ *********/
/// <summary>The parse API results.</summary>
- public ResponseParseModel Parse { get; set; }
+ public ResponseParseModel Parse { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="parse">The parse API results.</param>
+ public ResponseModel(ResponseParseModel parse)
+ {
+ this.Parse = parse;
+ }
}
/// <summary>The inner response model for the MediaWiki parse API.</summary>
@@ -301,8 +311,11 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
private class ResponseParseModel
{
+ /*********
+ ** Accessors
+ *********/
/// <summary>The parsed text.</summary>
- public IDictionary<string, string> Text { get; set; }
+ public IDictionary<string, string> Text { get; } = new Dictionary<string, string>();
}
}
}