From de74b038e4c15d393de8828c89814ef7eaefe507 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 2 Jun 2018 18:22:04 -0400 Subject: move web API client into toolkit (#532) --- .../Framework/Clients/WebApi/ModInfoModel.cs | 56 +++++++++++++++++ .../Framework/Clients/WebApi/ModSeachModel.cs | 37 ++++++++++++ .../Framework/Clients/WebApi/WebApiClient.cs | 70 ++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModInfoModel.cs create mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs create mode 100644 src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs (limited to 'src/StardewModdingAPI.Toolkit') diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModInfoModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModInfoModel.cs new file mode 100644 index 00000000..e1a204c6 --- /dev/null +++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModInfoModel.cs @@ -0,0 +1,56 @@ +namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi +{ + /// Generic metadata about a mod. + public class ModInfoModel + { + /********* + ** Accessors + *********/ + /// The mod name. + public string Name { get; set; } + + /// The semantic version for the mod's latest release. + public string Version { get; set; } + + /// The semantic version for the mod's latest preview release, if available and different from . + public string PreviewVersion { get; set; } + + /// The mod's web URL. + public string Url { get; set; } + + /// The error message indicating why the mod is invalid (if applicable). + public string Error { get; set; } + + + /********* + ** Public methods + *********/ + /// Construct an empty instance. + public ModInfoModel() + { + // needed for JSON deserialising + } + + /// Construct an instance. + /// The mod name. + /// The semantic version for the mod's latest release. + /// The semantic version for the mod's latest preview release, if available and different from . + /// The mod's web URL. + /// The error message indicating why the mod is invalid (if applicable). + public ModInfoModel(string name, string version, string url, string previewVersion = null, string error = null) + { + this.Name = name; + this.Version = version; + this.PreviewVersion = previewVersion; + this.Url = url; + this.Error = error; // mainly initialised here for the JSON deserialiser + } + + /// Construct an instance. + /// The error message indicating why the mod is invalid. + public ModInfoModel(string error) + { + this.Error = error; + } + } +} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs new file mode 100644 index 00000000..c0ee34ea --- /dev/null +++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModSeachModel.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using System.Linq; + +namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi +{ + /// Specifies mods whose update-check info to fetch. + public class ModSearchModel + { + /********* + ** Accessors + *********/ + /// The namespaced mod keys to search. + public string[] ModKeys { get; set; } + + /// Whether to allow non-semantic versions, instead of returning an error for those. + public bool AllowInvalidVersions { get; set; } + + + /********* + ** Public methods + *********/ + /// Construct an empty instance. + public ModSearchModel() + { + // needed for JSON deserialising + } + + /// Construct an instance. + /// The namespaced mod keys to search. + /// Whether to allow non-semantic versions, instead of returning an error for those. + public ModSearchModel(IEnumerable modKeys, bool allowInvalidVersions) + { + this.ModKeys = modKeys.ToArray(); + this.AllowInvalidVersions = allowInvalidVersions; + } + } +} diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs new file mode 100644 index 00000000..277fbeeb --- /dev/null +++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/WebApiClient.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Net; +using Newtonsoft.Json; + +namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi +{ + /// Provides methods for interacting with the SMAPI web API. + internal class WebApiClient + { + /********* + ** Properties + *********/ + /// The base URL for the web API. + private readonly Uri BaseUrl; + + /// The API version number. + private readonly ISemanticVersion Version; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The base URL for the web API. + /// The web API version. + public WebApiClient(string baseUrl, ISemanticVersion version) + { +#if !SMAPI_FOR_WINDOWS + baseUrl = baseUrl.Replace("https://", "http://"); // workaround for OpenSSL issues with the game's bundled Mono on Linux/Mac +#endif + this.BaseUrl = new Uri(baseUrl); + this.Version = version; + } + + /// Get the latest SMAPI version. + /// The mod keys for which to fetch the latest version. + public IDictionary GetModInfo(params string[] modKeys) + { + return this.Post>( + $"v{this.Version}/mods", + new ModSearchModel(modKeys, allowInvalidVersions: true) + ); + } + + + /********* + ** Private methods + *********/ + /// Fetch the response from the backend API. + /// The body content type. + /// The expected response type. + /// The request URL, optionally excluding the base URL. + /// The body content to post. + private TResult Post(string url, TBody content) + { + // note: avoid HttpClient for Mac compatibility + using (WebClient client = new WebClient()) + { + Uri fullUrl = new Uri(this.BaseUrl, url); + string data = JsonConvert.SerializeObject(content); + + client.Headers["Content-Type"] = "application/json"; + client.Headers["User-Agent"] = $"SMAPI/{this.Version}"; + string response = client.UploadString(fullUrl, data); + return JsonConvert.DeserializeObject(response); + } + } + } +} -- cgit