From 05541c11a72735d79d98cf3ae14d592e70bd8f54 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 24 Dec 2017 23:28:07 -0500 Subject: decouple API clients from mods API (#411) --- .../Clients/Chucklefish/ChucklefishClient.cs | 83 ++++++++++++++++++++++ .../Clients/Chucklefish/ChucklefishMod.cs | 18 +++++ .../Clients/Chucklefish/IChucklefishClient.cs | 17 +++++ 3 files changed, 118 insertions(+) create mode 100644 src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs create mode 100644 src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishMod.cs create mode 100644 src/SMAPI.Web/Framework/Clients/Chucklefish/IChucklefishClient.cs (limited to 'src/SMAPI.Web/Framework/Clients/Chucklefish') diff --git a/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs b/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs new file mode 100644 index 00000000..6772672c --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs @@ -0,0 +1,83 @@ +using System; +using System.Net; +using System.Threading.Tasks; +using HtmlAgilityPack; +using Pathoschild.Http.Client; + +namespace StardewModdingAPI.Web.Framework.Clients.Chucklefish +{ + /// An HTTP client for fetching mod metadata from the Chucklefish mod site. + internal class ChucklefishClient : IChucklefishClient + { + /********* + ** Properties + *********/ + /// The base URL for the Chucklefish mod site. + private readonly string BaseUrl; + + /// The URL for a mod page excluding the base URL, where {0} is the mod ID. + private readonly string ModPageUrlFormat; + + /// The underlying HTTP client. + private readonly IClient Client; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The user agent for the API client. + /// The base URL for the Chucklefish mod site. + /// The URL for a mod page excluding the , where {0} is the mod ID. + public ChucklefishClient(string userAgent, string baseUrl, string modPageUrlFormat) + { + this.BaseUrl = baseUrl; + this.ModPageUrlFormat = modPageUrlFormat; + this.Client = new FluentClient(baseUrl).SetUserAgent(userAgent); + } + + /// Get metadata about a mod. + /// The Chucklefish mod ID. + /// Returns the mod info if found, else null. + public async Task GetModAsync(uint id) + { + // fetch HTML + string html; + try + { + html = await this.Client + .GetAsync(string.Format(this.ModPageUrlFormat, id)) + .AsString(); + } + catch (ApiException ex) when (ex.Status == HttpStatusCode.NotFound) + { + return null; + } + + // parse HTML + var doc = new HtmlDocument(); + doc.LoadHtml(html); + + // extract mod info + string url = new UriBuilder(new Uri(this.BaseUrl)) { Path = string.Format(this.ModPageUrlFormat, id) }.Uri.ToString(); + string name = doc.DocumentNode.SelectSingleNode("//meta[@name='twitter:title']").Attributes["content"].Value; + if (name.StartsWith("[SMAPI] ")) + name = name.Substring("[SMAPI] ".Length); + string version = doc.DocumentNode.SelectSingleNode("//h1/span").InnerText; + + // create model + return new ChucklefishMod + { + Name = name, + Version = version, + Url = url + }; + } + + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + public void Dispose() + { + this.Client?.Dispose(); + } + } +} diff --git a/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishMod.cs b/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishMod.cs new file mode 100644 index 00000000..fd0101d4 --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishMod.cs @@ -0,0 +1,18 @@ +namespace StardewModdingAPI.Web.Framework.Clients.Chucklefish +{ + /// Mod metadata from the Chucklefish mod site. + internal class ChucklefishMod + { + /********* + ** Accessors + *********/ + /// The mod name. + public string Name { get; set; } + + /// The mod's semantic version number. + public string Version { get; set; } + + /// The mod's web URL. + public string Url { get; set; } + } +} diff --git a/src/SMAPI.Web/Framework/Clients/Chucklefish/IChucklefishClient.cs b/src/SMAPI.Web/Framework/Clients/Chucklefish/IChucklefishClient.cs new file mode 100644 index 00000000..1d8b256e --- /dev/null +++ b/src/SMAPI.Web/Framework/Clients/Chucklefish/IChucklefishClient.cs @@ -0,0 +1,17 @@ +using System; +using System.Threading.Tasks; + +namespace StardewModdingAPI.Web.Framework.Clients.Chucklefish +{ + /// An HTTP client for fetching mod metadata from the Chucklefish mod site. + internal interface IChucklefishClient : IDisposable + { + /********* + ** Methods + *********/ + /// Get metadata about a mod. + /// The Chucklefish mod ID. + /// Returns the mod info if found, else null. + Task GetModAsync(uint id); + } +} -- cgit