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. --- src/SMAPI.Web/Framework/Clients/GenericModDownload.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/SMAPI.Web/Framework/Clients') 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 { /// Generic metadata about a file download on a mod page. @@ -29,5 +31,17 @@ namespace StardewModdingAPI.Web.Framework.Clients this.Description = description; this.Version = version; } + + /// + /// Return true if the subkey matches this download. A subkey matches if it appears as + /// a substring in the name or description. + /// + /// the subkey + /// true if matches this download, otherwise false + /// + public bool MatchesSubkey(string subkey) { + return this.Name.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true + || this.Description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true; + } } } -- 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). --- .../Framework/Clients/GenericModDownload.cs | 15 ++++-- src/SMAPI.Web/Framework/Clients/GenericModPage.cs | 16 ++++++ .../UpdateManifest/IUpdateManifestClient.cs | 9 ++++ .../UpdateManifest/TextAsJsonMediaTypeFormatter.cs | 15 ++++++ .../Clients/UpdateManifest/UpdateManifestClient.cs | 55 ++++++++++++++++++++ .../UpdateManifest/UpdateManifestModDownload.cs | 27 ++++++++++ .../UpdateManifest/UpdateManifestModModel.cs | 26 ++++++++++ .../UpdateManifest/UpdateManifestModPage.cs | 58 ++++++++++++++++++++++ .../Clients/UpdateManifest/UpdateManifestModel.cs | 23 +++++++++ .../UpdateManifest/UpdateManifestVersionModel.cs | 26 ++++++++++ 10 files changed, 265 insertions(+), 5 deletions(-) create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/IUpdateManifestClient.cs create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestVersionModel.cs (limited to 'src/SMAPI.Web/Framework/Clients') diff --git a/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs b/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs index b37e5cda..5cc03aba 100644 --- a/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs +++ b/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs @@ -17,6 +17,10 @@ namespace StardewModdingAPI.Web.Framework.Clients /// The download's file version. public string? Version { get; } + /// + /// The URL for this download, if it has one distinct from the mod page's URL. + /// + public string? Url { get; } /********* ** Public methods @@ -25,21 +29,22 @@ namespace StardewModdingAPI.Web.Framework.Clients /// The download's display name. /// The download's description. /// The download's file version. - public GenericModDownload(string name, string? description, string? version) + /// The download's URL (if different from the mod page's URL). + public GenericModDownload(string name, string? description, string? version, string? url = null) { this.Name = name; this.Description = description; this.Version = version; + this.Url = url; } /// - /// Return true if the subkey matches this download. A subkey matches if it appears as + /// Return if the subkey matches this download. A subkey matches if it appears as /// a substring in the name or description. /// /// the subkey - /// true if matches this download, otherwise false - /// - public bool MatchesSubkey(string subkey) { + /// if matches this download, otherwise + public virtual 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/Clients/GenericModPage.cs b/src/SMAPI.Web/Framework/Clients/GenericModPage.cs index 5353c7e1..4c66e1a0 100644 --- a/src/SMAPI.Web/Framework/Clients/GenericModPage.cs +++ b/src/SMAPI.Web/Framework/Clients/GenericModPage.cs @@ -40,6 +40,8 @@ namespace StardewModdingAPI.Web.Framework.Clients [MemberNotNullWhen(true, nameof(IModPage.Name), nameof(IModPage.Url))] public bool IsValid => this.Status == RemoteModStatus.Ok; + /// Whether to use strict subkey matching or not. + public bool IsSubkeyStrict { get; set; } = false; /********* ** Public methods @@ -79,5 +81,19 @@ namespace StardewModdingAPI.Web.Framework.Clients return this; } + + /// Returns the mod page name. + /// ignored + /// The mod page name. + public virtual string? GetName(string? subkey) { + return this.Name; + } + + /// Returns the mod page URL. + /// ignored + /// The mod page URL. + public virtual string? GetUrl(string? subkey) { + return this.Url; + } } } diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/IUpdateManifestClient.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/IUpdateManifestClient.cs new file mode 100644 index 00000000..36d018c7 --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/IUpdateManifestClient.cs @@ -0,0 +1,9 @@ +// Copyright 2022 Jamie Taylor +using System; + +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest +{ + /// An HTTP client for fetching an update manifest from an arbitrary URL. + internal interface IUpdateManifestClient : IModSiteClient, IDisposable { } +} + diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs new file mode 100644 index 00000000..48e3c294 --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs @@ -0,0 +1,15 @@ +// Copyright 2022 Jamie Taylor +using System.Net.Http.Formatting; +using System.Net.Http.Headers; + +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { + /// + /// A that can parse from content of type text/plain. + /// + internal class TextAsJsonMediaTypeFormatter : JsonMediaTypeFormatter { + /// Construct a new + public TextAsJsonMediaTypeFormatter() { + this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain")); + } + } +} diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs new file mode 100644 index 00000000..d7cf4945 --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs @@ -0,0 +1,55 @@ +// Copyright 2022 Jamie Taylor +using System; +using Pathoschild.Http.Client; +using StardewModdingAPI.Toolkit.Framework.UpdateData; +using System.Threading.Tasks; +using System.Net; + +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { + /// An HTTP client for fetching an update manifest from an arbitrary URL. + internal class UpdateManifestClient : IUpdateManifestClient { + /********* + ** Fields + *********/ + /// The underlying HTTP client. + private readonly IClient Client; + + /********* + ** Accessors + *********/ + /// The unique key for the mod site. + public ModSiteKey SiteKey => ModSiteKey.UpdateManifest; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The user agent for the API client. + public UpdateManifestClient(string userAgent) { + this.Client = new FluentClient() + .SetUserAgent(userAgent); + this.Client.Formatters.Add(new TextAsJsonMediaTypeFormatter()); + } + + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + public void Dispose() { + this.Client.Dispose(); + } + + /// + public async Task GetModData(string id) { + UpdateManifestModel? manifest; + try { + manifest = await this.Client.GetAsync(id).As(); + } catch (ApiException ex) when (ex.Status == HttpStatusCode.NotFound) { + return new GenericModPage(this.SiteKey, id).SetError(RemoteModStatus.DoesNotExist, $"No update manifest found at {id}"); + } + if (manifest is null) { + return new GenericModPage(this.SiteKey, id).SetError(RemoteModStatus.DoesNotExist, $"Error parsing manifest at {id}"); + } + + return new UpdateManifestModPage(id, manifest); + } + } +} diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs new file mode 100644 index 00000000..117ae15c --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs @@ -0,0 +1,27 @@ +// Copyright 2022 Jamie Taylor +using System; +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { + /// Metadata about a mod download in an update manifest file. + internal class UpdateManifestModDownload : GenericModDownload { + /// The subkey for this mod download + private readonly string subkey; + /// Construct an instance. + /// The subkey for this download. + /// The mod name for this download. + /// The download's version. + /// The download's URL. + public UpdateManifestModDownload(string subkey, string name, string? version, string? url) : base(name, null, version, url) { + this.subkey = subkey; + } + + /// + /// Returns iff the given subkey is the same as the subkey for this download. + /// + /// The subkey to match + /// if is the same as the subkey for this download, otherwise. + public override bool MatchesSubkey(string subkey) { + return this.subkey == subkey; + } + } +} + diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs new file mode 100644 index 00000000..4ec9c03d --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs @@ -0,0 +1,26 @@ +// Copyright 2022 Jamie Taylor +using System; +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { + /// Data model for a mod in an update manifest. + internal class UpdateManifestModModel { + /// The mod's name. + public string Name { get; } + + /// The mod's URL. + public string? Url { get; } + + /// The versions for this mod. + public UpdateManifestVersionModel[] Versions { get; } + + /// Construct an instance. + /// The mod's name. + /// The mod's URL. + /// The versions for this mod. + public UpdateManifestModModel(string name, string? url, UpdateManifestVersionModel[] versions) { + this.Name = name; + this.Url = url; + this.Versions = versions; + } + } +} + diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs new file mode 100644 index 00000000..109175b5 --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs @@ -0,0 +1,58 @@ +// Copyright 2022 Jamie Taylor +using System; +using System.Collections.Generic; +using System.Linq; +using StardewModdingAPI.Toolkit.Framework.UpdateData; + +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { + /// Metadata about an update manifest "page". + internal class UpdateManifestModPage : GenericModPage { + /// The update manifest model. + private UpdateManifestModel manifest; + + /// Constuct an instance. + /// The "id" (i.e., URL) of this update manifest. + /// The manifest object model. + public UpdateManifestModPage(string id, UpdateManifestModel manifest) : base(ModSiteKey.UpdateManifest, id) { + this.IsSubkeyStrict = true; + this.manifest = manifest; + this.SetInfo(name: id, url: id, version: null, downloads: TranslateDownloads(manifest).ToArray()); + } + + /// Return the mod name for the given subkey, if it exists in this update manifest. + /// The subkey. + /// The mod name for the given subkey, or if this manifest does not contain the given subkey. + public override string? GetName(string? subkey) { + if (subkey is null) + return null; + this.manifest.Subkeys.TryGetValue(subkey, out UpdateManifestModModel? modModel); + return modModel?.Name; + } + + /// Return the mod URL for the given subkey, if it exists in this update manifest. + /// The subkey. + /// The mod URL for the given subkey, or if this manifest does not contain the given subkey. + public override string? GetUrl(string? subkey) { + if (subkey is null) + return null; + this.manifest.Subkeys.TryGetValue(subkey, out UpdateManifestModModel? modModel); + return modModel?.Url; + } + + + /********* + ** Private methods + *********/ + /// Translate the downloads from the manifest's object model into objects. + /// The manifest object model. + /// An for each in the manifest. + private static IEnumerable TranslateDownloads(UpdateManifestModel manifest) { + foreach (var entry in manifest.Subkeys) { + foreach (var version in entry.Value.Versions) { + yield return new UpdateManifestModDownload(entry.Key, entry.Value.Name, version.Version, version.DownloadFileUrl ?? version.DownloadPageUrl); + } + } + } + + } +} \ No newline at end of file diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs new file mode 100644 index 00000000..03f89726 --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs @@ -0,0 +1,23 @@ +// Copyright 2022 Jamie Taylor +using System; +using System.Collections.Generic; + +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { + /// Data model for an update manifest. + internal class UpdateManifestModel { + /// The manifest format version. + public string ManifestVersion { get; } + + /// The subkeys in this update manifest. + public IDictionary Subkeys { get; } + + /// Construct an instance. + /// The manifest format version. + /// The subkeys in this update manifest. + public UpdateManifestModel(string manifestVersion, IDictionary subkeys) { + this.ManifestVersion = manifestVersion; + this.Subkeys = subkeys; + } + } +} + diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestVersionModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestVersionModel.cs new file mode 100644 index 00000000..55b6db61 --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestVersionModel.cs @@ -0,0 +1,26 @@ +// Copyright 2022 Jamie Taylor +using System; +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { + /// Data model for a Version in an update manifest. + internal class UpdateManifestVersionModel { + /// The semantic version string. + public string Version { get; } + + /// The URL for this version's download page (if any). + public string? DownloadPageUrl { get; } + + /// The URL for this version's direct file download (if any). + public string? DownloadFileUrl { get; } + + /// Construct an instance. + /// The semantic version string. + /// This version's download page URL (if any). + /// This version's direct file download URL (if any). + public UpdateManifestVersionModel(string version, string? downloadPageUrl, string? downloadFileUrl) { + this.Version = version; + this.DownloadPageUrl = downloadPageUrl; + this.DownloadFileUrl = downloadFileUrl; + } + } +} + -- 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/Clients/GenericModDownload.cs | 27 ++++---- src/SMAPI.Web/Framework/Clients/GenericModPage.cs | 19 ++--- .../UpdateManifest/IUpdateManifestClient.cs | 3 +- .../UpdateManifest/TextAsJsonMediaTypeFormatter.cs | 18 +++-- .../Clients/UpdateManifest/UpdateManifestClient.cs | 37 ++++++---- .../UpdateManifest/UpdateManifestModDownload.cs | 40 ++++++----- .../UpdateManifest/UpdateManifestModModel.cs | 32 +++++---- .../UpdateManifest/UpdateManifestModPage.cs | 80 +++++++++++++--------- .../Clients/UpdateManifest/UpdateManifestModel.cs | 30 +++++--- .../UpdateManifest/UpdateManifestVersionModel.cs | 28 +++++--- 10 files changed, 185 insertions(+), 129 deletions(-) (limited to 'src/SMAPI.Web/Framework/Clients') diff --git a/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs b/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs index 5cc03aba..6c9c08ef 100644 --- a/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs +++ b/src/SMAPI.Web/Framework/Clients/GenericModDownload.cs @@ -17,10 +17,9 @@ namespace StardewModdingAPI.Web.Framework.Clients /// The download's file version. public string? Version { get; } - /// - /// The URL for this download, if it has one distinct from the mod page's URL. - /// - public string? Url { get; } + /// The mod URL page from which to download this update, if different from the URL of the mod page it was fetched from. + public string? ModPageUrl { get; } + /********* ** Public methods @@ -29,23 +28,21 @@ namespace StardewModdingAPI.Web.Framework.Clients /// The download's display name. /// The download's description. /// The download's file version. - /// The download's URL (if different from the mod page's URL). - public GenericModDownload(string name, string? description, string? version, string? url = null) + /// The mod URL page from which to download this update, if different from the URL of the mod page it was fetched from. + public GenericModDownload(string name, string? description, string? version, string? modPageUrl = null) { this.Name = name; this.Description = description; this.Version = version; - this.Url = url; + this.ModPageUrl = modPageUrl; } - /// - /// Return if the subkey matches this download. A subkey matches if it appears as - /// a substring in the name or description. - /// - /// the subkey - /// if matches this download, otherwise - public virtual bool MatchesSubkey(string subkey) { - return this.Name.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true + /// Get whether the subkey matches this download. + /// The update subkey to check. + public virtual bool MatchesSubkey(string subkey) + { + return + this.Name.Contains(subkey, StringComparison.OrdinalIgnoreCase) || this.Description?.Contains(subkey, StringComparison.OrdinalIgnoreCase) == true; } } diff --git a/src/SMAPI.Web/Framework/Clients/GenericModPage.cs b/src/SMAPI.Web/Framework/Clients/GenericModPage.cs index 4c66e1a0..e939f1d8 100644 --- a/src/SMAPI.Web/Framework/Clients/GenericModPage.cs +++ b/src/SMAPI.Web/Framework/Clients/GenericModPage.cs @@ -40,9 +40,10 @@ namespace StardewModdingAPI.Web.Framework.Clients [MemberNotNullWhen(true, nameof(IModPage.Name), nameof(IModPage.Url))] public bool IsValid => this.Status == RemoteModStatus.Ok; - /// Whether to use strict subkey matching or not. + /// Whether this mod page requires string subkey matching, in which case a subkey that isn't found will return no update instead of falling back to one without. public bool IsSubkeyStrict { get; set; } = false; + /********* ** Public methods *********/ @@ -82,17 +83,17 @@ namespace StardewModdingAPI.Web.Framework.Clients return this; } - /// Returns the mod page name. - /// ignored - /// The mod page name. - public virtual string? GetName(string? subkey) { + /// Get the mod name for an update subkey, if different from the mod page name. + /// The update subkey. + public virtual string? GetName(string? subkey) + { return this.Name; } - /// Returns the mod page URL. - /// ignored - /// The mod page URL. - public virtual string? GetUrl(string? subkey) { + /// Get the mod page URL for an update subkey, if different from the mod page it was fetched from. + /// The update subkey. + public virtual string? GetUrl(string? subkey) + { return this.Url; } } diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/IUpdateManifestClient.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/IUpdateManifestClient.cs index 36d018c7..dd9f5811 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/IUpdateManifestClient.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/IUpdateManifestClient.cs @@ -3,7 +3,6 @@ using System; namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { - /// An HTTP client for fetching an update manifest from an arbitrary URL. + /// An API client for fetching update metadata from an arbitrary JSON URL. internal interface IUpdateManifestClient : IModSiteClient, IDisposable { } } - diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs index 48e3c294..02722cb1 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs @@ -1,14 +1,18 @@ -// Copyright 2022 Jamie Taylor +// Copyright 2022 Jamie Taylor using System.Net.Http.Formatting; using System.Net.Http.Headers; -namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { - /// - /// A that can parse from content of type text/plain. - /// - internal class TextAsJsonMediaTypeFormatter : JsonMediaTypeFormatter { +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest +{ + /// A that can parse from content of type text/plain. + internal class TextAsJsonMediaTypeFormatter : JsonMediaTypeFormatter + { + /********* + ** Public methods + *********/ /// Construct a new - public TextAsJsonMediaTypeFormatter() { + public TextAsJsonMediaTypeFormatter() + { this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain")); } } diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs index d7cf4945..88a5c2f6 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs @@ -1,19 +1,21 @@ // Copyright 2022 Jamie Taylor -using System; +using System.Net; +using System.Threading.Tasks; using Pathoschild.Http.Client; using StardewModdingAPI.Toolkit.Framework.UpdateData; -using System.Threading.Tasks; -using System.Net; -namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { - /// An HTTP client for fetching an update manifest from an arbitrary URL. - internal class UpdateManifestClient : IUpdateManifestClient { +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest +{ + /// An API client for fetching update metadata from an arbitrary JSON URL. + internal class UpdateManifestClient : IUpdateManifestClient + { /********* ** Fields *********/ /// The underlying HTTP client. private readonly IClient Client; + /********* ** Accessors *********/ @@ -26,30 +28,35 @@ namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { *********/ /// Construct an instance. /// The user agent for the API client. - public UpdateManifestClient(string userAgent) { + public UpdateManifestClient(string userAgent) + { this.Client = new FluentClient() .SetUserAgent(userAgent); this.Client.Formatters.Add(new TextAsJsonMediaTypeFormatter()); } /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - public void Dispose() { + public void Dispose() + { this.Client.Dispose(); } /// - public async Task GetModData(string id) { + public async Task GetModData(string id) + { UpdateManifestModel? manifest; - try { + try + { manifest = await this.Client.GetAsync(id).As(); - } catch (ApiException ex) when (ex.Status == HttpStatusCode.NotFound) { - return new GenericModPage(this.SiteKey, id).SetError(RemoteModStatus.DoesNotExist, $"No update manifest found at {id}"); } - if (manifest is null) { - return new GenericModPage(this.SiteKey, id).SetError(RemoteModStatus.DoesNotExist, $"Error parsing manifest at {id}"); + catch (ApiException ex) when (ex.Status == HttpStatusCode.NotFound) + { + return new GenericModPage(this.SiteKey, id).SetError(RemoteModStatus.DoesNotExist, $"No update manifest found at {id}"); } - return new UpdateManifestModPage(id, manifest); + return manifest is not null + ? new UpdateManifestModPage(id, manifest) + : new GenericModPage(this.SiteKey, id).SetError(RemoteModStatus.DoesNotExist, $"The update manifest at {id} has an invalid format"); } } } diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs index 117ae15c..0a6d4736 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs @@ -1,27 +1,35 @@ // Copyright 2022 Jamie Taylor -using System; -namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest +{ /// Metadata about a mod download in an update manifest file. - internal class UpdateManifestModDownload : GenericModDownload { - /// The subkey for this mod download - private readonly string subkey; + internal class UpdateManifestModDownload : GenericModDownload + { + /********* + ** Fields + *********/ + /// The update subkey for this mod download. + private readonly string Subkey; + + + /********* + ** Public methods + *********/ /// Construct an instance. - /// The subkey for this download. + /// The field name for this mod download in the manifest. /// The mod name for this download. /// The download's version. /// The download's URL. - public UpdateManifestModDownload(string subkey, string name, string? version, string? url) : base(name, null, version, url) { - this.subkey = subkey; + public UpdateManifestModDownload(string fieldName, string name, string? version, string? url) + : base(name, null, version, url) + { + this.Subkey = fieldName; } - /// - /// Returns iff the given subkey is the same as the subkey for this download. - /// - /// The subkey to match - /// if is the same as the subkey for this download, otherwise. - public override bool MatchesSubkey(string subkey) { - return this.subkey == subkey; + /// Get whether the subkey matches this download. + /// The update subkey to check. + public override bool MatchesSubkey(string subkey) + { + return subkey == this.Subkey; } } } - diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs index 4ec9c03d..92642321 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs @@ -1,26 +1,34 @@ // Copyright 2022 Jamie Taylor -using System; -namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { - /// Data model for a mod in an update manifest. - internal class UpdateManifestModModel { +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest +{ + /// The data model for a mod in an update manifest file. + internal class UpdateManifestModModel + { + /********* + ** Accessors + *********/ /// The mod's name. - public string Name { get; } + public string? Name { get; } - /// The mod's URL. + /// The mod page URL from which to download updates. public string? Url { get; } - /// The versions for this mod. - public UpdateManifestVersionModel[] Versions { get; } + /// The available versions for this mod. + public UpdateManifestVersionModel[]? Versions { get; } + + /********* + ** Public methods + *********/ /// Construct an instance. /// The mod's name. - /// The mod's URL. - /// The versions for this mod. - public UpdateManifestModModel(string name, string? url, UpdateManifestVersionModel[] versions) { + /// The mod page URL from which to download updates. + /// The available versions for this mod. + public UpdateManifestModModel(string? name, string? url, UpdateManifestVersionModel[]? versions) + { this.Name = name; this.Url = url; this.Versions = versions; } } } - diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs index 109175b5..bbc7b5da 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs @@ -1,58 +1,74 @@ -// Copyright 2022 Jamie Taylor -using System; +// Copyright 2022 Jamie Taylor using System.Collections.Generic; using System.Linq; using StardewModdingAPI.Toolkit.Framework.UpdateData; -namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest +{ /// Metadata about an update manifest "page". - internal class UpdateManifestModPage : GenericModPage { - /// The update manifest model. - private UpdateManifestModel manifest; - - /// Constuct an instance. - /// The "id" (i.e., URL) of this update manifest. - /// The manifest object model. - public UpdateManifestModPage(string id, UpdateManifestModel manifest) : base(ModSiteKey.UpdateManifest, id) { + internal class UpdateManifestModPage : GenericModPage + { + /********* + ** Fields + *********/ + /// The mods from the update manifest. + private readonly IDictionary Mods; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The URL of the update manifest file. + /// The parsed update manifest. + public UpdateManifestModPage(string url, UpdateManifestModel manifest) + : base(ModSiteKey.UpdateManifest, url) + { this.IsSubkeyStrict = true; - this.manifest = manifest; - this.SetInfo(name: id, url: id, version: null, downloads: TranslateDownloads(manifest).ToArray()); + this.Mods = manifest.Mods ?? new Dictionary(); + this.SetInfo(name: url, url: url, version: null, downloads: this.ParseDownloads(manifest.Mods).ToArray()); } /// Return the mod name for the given subkey, if it exists in this update manifest. /// The subkey. /// The mod name for the given subkey, or if this manifest does not contain the given subkey. - public override string? GetName(string? subkey) { - if (subkey is null) - return null; - this.manifest.Subkeys.TryGetValue(subkey, out UpdateManifestModModel? modModel); - return modModel?.Name; + public override string? GetName(string? subkey) + { + return subkey is not null && this.Mods.TryGetValue(subkey, out UpdateManifestModModel? modModel) + ? modModel.Name + : null; } /// Return the mod URL for the given subkey, if it exists in this update manifest. /// The subkey. /// The mod URL for the given subkey, or if this manifest does not contain the given subkey. - public override string? GetUrl(string? subkey) { - if (subkey is null) - return null; - this.manifest.Subkeys.TryGetValue(subkey, out UpdateManifestModModel? modModel); - return modModel?.Url; + public override string? GetUrl(string? subkey) + { + return subkey is not null && this.Mods.TryGetValue(subkey, out UpdateManifestModModel? modModel) + ? modModel.Url + : null; } /********* ** Private methods *********/ - /// Translate the downloads from the manifest's object model into objects. - /// The manifest object model. - /// An for each in the manifest. - private static IEnumerable TranslateDownloads(UpdateManifestModel manifest) { - foreach (var entry in manifest.Subkeys) { - foreach (var version in entry.Value.Versions) { - yield return new UpdateManifestModDownload(entry.Key, entry.Value.Name, version.Version, version.DownloadFileUrl ?? version.DownloadPageUrl); - } + /// Convert the raw download info from an update manifest to . + /// The mods from the update manifest. + private IEnumerable ParseDownloads(IDictionary? mods) + { + if (mods is null) + yield break; + + foreach ((string modKey, UpdateManifestModModel mod) in mods) + { + if (mod.Versions is null) + continue; + + foreach (UpdateManifestVersionModel version in mod.Versions) + yield return new UpdateManifestModDownload(modKey, mod.Name ?? modKey, version.Version, version.DownloadFileUrl ?? version.DownloadPageUrl); } } } -} \ No newline at end of file +} diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs index 03f89726..ad618022 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs @@ -1,23 +1,31 @@ // Copyright 2022 Jamie Taylor -using System; using System.Collections.Generic; -namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { - /// Data model for an update manifest. - internal class UpdateManifestModel { +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest +{ + /// The data model for an update manifest file. + internal class UpdateManifestModel + { + /********* + ** Accessors + *********/ /// The manifest format version. - public string ManifestVersion { get; } + public string? ManifestVersion { get; } - /// The subkeys in this update manifest. - public IDictionary Subkeys { get; } + /// The mod info in this update manifest. + public IDictionary? Mods { get; } + + /********* + ** Public methods + *********/ /// Construct an instance. /// The manifest format version. - /// The subkeys in this update manifest. - public UpdateManifestModel(string manifestVersion, IDictionary subkeys) { + /// The mod info in this update manifest. + public UpdateManifestModel(string manifestVersion, IDictionary mods) + { this.ManifestVersion = manifestVersion; - this.Subkeys = subkeys; + this.Mods = mods; } } } - diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestVersionModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestVersionModel.cs index 55b6db61..90e054d8 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestVersionModel.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestVersionModel.cs @@ -1,10 +1,14 @@ // Copyright 2022 Jamie Taylor -using System; -namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest +{ /// Data model for a Version in an update manifest. - internal class UpdateManifestVersionModel { - /// The semantic version string. - public string Version { get; } + internal class UpdateManifestVersionModel + { + /********* + ** Accessors + *********/ + /// The mod's semantic version. + public string? Version { get; } /// The URL for this version's download page (if any). public string? DownloadPageUrl { get; } @@ -12,15 +16,19 @@ namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { /// The URL for this version's direct file download (if any). public string? DownloadFileUrl { get; } + + /********* + ** Public methods + *********/ /// Construct an instance. - /// The semantic version string. - /// This version's download page URL (if any). - /// This version's direct file download URL (if any). - public UpdateManifestVersionModel(string version, string? downloadPageUrl, string? downloadFileUrl) { + /// The mod's semantic version. + /// This version's download page URL, if any. + /// This version's direct file download URL, if any. + public UpdateManifestVersionModel(string version, string? downloadPageUrl, string? downloadFileUrl) + { this.Version = version; this.DownloadPageUrl = downloadPageUrl; this.DownloadFileUrl = downloadFileUrl; } } } - -- cgit From 25c2081d43bd4026552cda687fb56216dd3a9f8e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 29 Jan 2023 16:37:22 -0500 Subject: encapsulate update manifest implementation details when possible --- .../Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs | 2 +- .../Framework/Clients/UpdateManifest/UpdateManifestModPage.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/SMAPI.Web/Framework/Clients') diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs index 0a6d4736..0128fa17 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModDownload.cs @@ -22,7 +22,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest public UpdateManifestModDownload(string fieldName, string name, string? version, string? url) : base(name, null, version, url) { - this.Subkey = fieldName; + this.Subkey = '@' + fieldName; } /// Get whether the subkey matches this download. diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs index bbc7b5da..befad268 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs @@ -34,7 +34,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest /// The mod name for the given subkey, or if this manifest does not contain the given subkey. public override string? GetName(string? subkey) { - return subkey is not null && this.Mods.TryGetValue(subkey, out UpdateManifestModModel? modModel) + return subkey is not null && this.Mods.TryGetValue(subkey.TrimStart('@'), out UpdateManifestModModel? modModel) ? modModel.Name : null; } @@ -44,7 +44,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest /// The mod URL for the given subkey, or if this manifest does not contain the given subkey. public override string? GetUrl(string? subkey) { - return subkey is not null && this.Mods.TryGetValue(subkey, out UpdateManifestModModel? modModel) + return subkey is not null && this.Mods.TryGetValue(subkey.TrimStart('@'), out UpdateManifestModModel? modModel) ? modModel.Url : null; } -- cgit From e5576d9c925210c83ba9f123c2ced86377ece560 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 29 Jan 2023 16:37:22 -0500 Subject: require subkey for update manifest checks --- src/SMAPI.Web/Framework/Clients/GenericModPage.cs | 4 ++-- .../Framework/Clients/UpdateManifest/UpdateManifestModPage.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/SMAPI.Web/Framework/Clients') diff --git a/src/SMAPI.Web/Framework/Clients/GenericModPage.cs b/src/SMAPI.Web/Framework/Clients/GenericModPage.cs index e939f1d8..63ca5a95 100644 --- a/src/SMAPI.Web/Framework/Clients/GenericModPage.cs +++ b/src/SMAPI.Web/Framework/Clients/GenericModPage.cs @@ -40,8 +40,8 @@ namespace StardewModdingAPI.Web.Framework.Clients [MemberNotNullWhen(true, nameof(IModPage.Name), nameof(IModPage.Url))] public bool IsValid => this.Status == RemoteModStatus.Ok; - /// Whether this mod page requires string subkey matching, in which case a subkey that isn't found will return no update instead of falling back to one without. - public bool IsSubkeyStrict { get; set; } = false; + /// Whether this mod page requires update subkeys and does not allow matching downloads without them. + public bool RequireSubkey { get; set; } = false; /********* diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs index befad268..7537eb24 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs @@ -24,7 +24,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest public UpdateManifestModPage(string url, UpdateManifestModel manifest) : base(ModSiteKey.UpdateManifest, url) { - this.IsSubkeyStrict = true; + this.RequireSubkey = true; this.Mods = manifest.Mods ?? new Dictionary(); this.SetInfo(name: url, url: url, version: null, downloads: this.ParseDownloads(manifest.Mods).ToArray()); } -- cgit From 5c22406c13ef4933a5e17e9036d9fd3ca9b9a9a7 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 29 Jan 2023 16:37:22 -0500 Subject: adjust JSON formatter instead of adding a new one --- .../UpdateManifest/TextAsJsonMediaTypeFormatter.cs | 19 ------------------- .../Clients/UpdateManifest/UpdateManifestClient.cs | 4 +++- 2 files changed, 3 insertions(+), 20 deletions(-) delete mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs (limited to 'src/SMAPI.Web/Framework/Clients') diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs deleted file mode 100644 index 02722cb1..00000000 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/TextAsJsonMediaTypeFormatter.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2022 Jamie Taylor -using System.Net.Http.Formatting; -using System.Net.Http.Headers; - -namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest -{ - /// A that can parse from content of type text/plain. - internal class TextAsJsonMediaTypeFormatter : JsonMediaTypeFormatter - { - /********* - ** Public methods - *********/ - /// Construct a new - public TextAsJsonMediaTypeFormatter() - { - this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain")); - } - } -} diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs index 88a5c2f6..0199027f 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs @@ -1,5 +1,6 @@ // Copyright 2022 Jamie Taylor using System.Net; +using System.Net.Http.Headers; using System.Threading.Tasks; using Pathoschild.Http.Client; using StardewModdingAPI.Toolkit.Framework.UpdateData; @@ -32,7 +33,8 @@ namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { this.Client = new FluentClient() .SetUserAgent(userAgent); - this.Client.Formatters.Add(new TextAsJsonMediaTypeFormatter()); + + this.Client.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain")); } /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. -- cgit From d76964c5f381a5b8faba123646d851e7ae2c06f0 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 29 Jan 2023 16:37:23 -0500 Subject: group response models --- .../ResponseModels/UpdateManifestModModel.cs | 34 ++++++++++++++++++++++ .../ResponseModels/UpdateManifestModel.cs | 31 ++++++++++++++++++++ .../ResponseModels/UpdateManifestVersionModel.cs | 34 ++++++++++++++++++++++ .../Clients/UpdateManifest/UpdateManifestClient.cs | 1 + .../UpdateManifest/UpdateManifestModModel.cs | 34 ---------------------- .../UpdateManifest/UpdateManifestModPage.cs | 1 + .../Clients/UpdateManifest/UpdateManifestModel.cs | 31 -------------------- .../UpdateManifest/UpdateManifestVersionModel.cs | 34 ---------------------- 8 files changed, 101 insertions(+), 99 deletions(-) create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestModModel.cs create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestModel.cs create mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestVersionModel.cs delete mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs delete mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs delete mode 100644 src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestVersionModel.cs (limited to 'src/SMAPI.Web/Framework/Clients') diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestModModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestModModel.cs new file mode 100644 index 00000000..ee1fbeb6 --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestModModel.cs @@ -0,0 +1,34 @@ +// Copyright 2022 Jamie Taylor +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest.ResponseModels +{ + /// The data model for a mod in an update manifest file. + internal class UpdateManifestModModel + { + /********* + ** Accessors + *********/ + /// The mod's name. + public string? Name { get; } + + /// The mod page URL from which to download updates. + public string? Url { get; } + + /// The available versions for this mod. + public UpdateManifestVersionModel[]? Versions { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The mod's name. + /// The mod page URL from which to download updates. + /// The available versions for this mod. + public UpdateManifestModModel(string? name, string? url, UpdateManifestVersionModel[]? versions) + { + this.Name = name; + this.Url = url; + this.Versions = versions; + } + } +} diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestModel.cs new file mode 100644 index 00000000..e213fbab --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestModel.cs @@ -0,0 +1,31 @@ +// Copyright 2022 Jamie Taylor +using System.Collections.Generic; + +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest.ResponseModels +{ + /// The data model for an update manifest file. + internal class UpdateManifestModel + { + /********* + ** Accessors + *********/ + /// The manifest format version. + public string? ManifestVersion { get; } + + /// The mod info in this update manifest. + public IDictionary? Mods { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The manifest format version. + /// The mod info in this update manifest. + public UpdateManifestModel(string manifestVersion, IDictionary mods) + { + this.ManifestVersion = manifestVersion; + this.Mods = mods; + } + } +} diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestVersionModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestVersionModel.cs new file mode 100644 index 00000000..1e84501f --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/ResponseModels/UpdateManifestVersionModel.cs @@ -0,0 +1,34 @@ +// Copyright 2022 Jamie Taylor +namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest.ResponseModels +{ + /// Data model for a Version in an update manifest. + internal class UpdateManifestVersionModel + { + /********* + ** Accessors + *********/ + /// The mod's semantic version. + public string? Version { get; } + + /// The URL for this version's download page (if any). + public string? DownloadPageUrl { get; } + + /// The URL for this version's direct file download (if any). + public string? DownloadFileUrl { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The mod's semantic version. + /// This version's download page URL, if any. + /// This version's direct file download URL, if any. + public UpdateManifestVersionModel(string version, string? downloadPageUrl, string? downloadFileUrl) + { + this.Version = version; + this.DownloadPageUrl = downloadPageUrl; + this.DownloadFileUrl = downloadFileUrl; + } + } +} diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs index 0199027f..0d19900e 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestClient.cs @@ -4,6 +4,7 @@ using System.Net.Http.Headers; using System.Threading.Tasks; using Pathoschild.Http.Client; using StardewModdingAPI.Toolkit.Framework.UpdateData; +using StardewModdingAPI.Web.Framework.Clients.UpdateManifest.ResponseModels; namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs deleted file mode 100644 index 92642321..00000000 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModModel.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2022 Jamie Taylor -namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest -{ - /// The data model for a mod in an update manifest file. - internal class UpdateManifestModModel - { - /********* - ** Accessors - *********/ - /// The mod's name. - public string? Name { get; } - - /// The mod page URL from which to download updates. - public string? Url { get; } - - /// The available versions for this mod. - public UpdateManifestVersionModel[]? Versions { get; } - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// The mod's name. - /// The mod page URL from which to download updates. - /// The available versions for this mod. - public UpdateManifestModModel(string? name, string? url, UpdateManifestVersionModel[]? versions) - { - this.Name = name; - this.Url = url; - this.Versions = versions; - } - } -} diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs index 7537eb24..251ed9ec 100644 --- a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs +++ b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModPage.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using StardewModdingAPI.Toolkit.Framework.UpdateData; +using StardewModdingAPI.Web.Framework.Clients.UpdateManifest.ResponseModels; namespace StardewModdingAPI.Web.Framework.Clients.UpdateManifest { diff --git a/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs b/src/SMAPI.Web/Framework/Clients/UpdateManifest/UpdateManifestModel.cs deleted file mode 100644 index