From e178ed14be24e3971d50addaebb3d13c19c18304 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 23 Sep 2017 18:04:56 -0400 Subject: migrate SMAPI update check to new web API (#336) --- src/StardewModdingAPI.sln | 1 + .../Framework/Models/GitRelease.cs | 19 ------ src/StardewModdingAPI/Framework/Models/SConfig.cs | 14 +++-- src/StardewModdingAPI/Framework/UpdateHelper.cs | 67 ++++++++++++++++------ src/StardewModdingAPI/Program.cs | 12 ++-- .../StardewModdingAPI.config.json | 13 ++++- src/StardewModdingAPI/StardewModdingAPI.csproj | 2 +- 7 files changed, 82 insertions(+), 46 deletions(-) delete mode 100644 src/StardewModdingAPI/Framework/Models/GitRelease.cs (limited to 'src') diff --git a/src/StardewModdingAPI.sln b/src/StardewModdingAPI.sln index bc2bb8b2..9d7baa51 100644 --- a/src/StardewModdingAPI.sln +++ b/src/StardewModdingAPI.sln @@ -38,6 +38,7 @@ EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution StardewModdingAPI.Models\StardewModdingAPI.Models.projitems*{2aa02fb6-ff03-41cf-a215-2ee60ab4f5dc}*SharedItemsImports = 13 + StardewModdingAPI.Models\StardewModdingAPI.Models.projitems*{f1a573b0-f436-472c-ae29-0b91ea6b9f8f}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/src/StardewModdingAPI/Framework/Models/GitRelease.cs b/src/StardewModdingAPI/Framework/Models/GitRelease.cs deleted file mode 100644 index bc53468f..00000000 --- a/src/StardewModdingAPI/Framework/Models/GitRelease.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Newtonsoft.Json; - -namespace StardewModdingAPI.Framework.Models -{ - /// Metadata about a GitHub release tag. - internal class GitRelease - { - /********* - ** Accessors - *********/ - /// The display name. - [JsonProperty("name")] - public string Name { get; set; } - - /// The semantic version string. - [JsonProperty("tag_name")] - public string Tag { get; set; } - } -} \ No newline at end of file diff --git a/src/StardewModdingAPI/Framework/Models/SConfig.cs b/src/StardewModdingAPI/Framework/Models/SConfig.cs index b2ca4113..36799400 100644 --- a/src/StardewModdingAPI/Framework/Models/SConfig.cs +++ b/src/StardewModdingAPI/Framework/Models/SConfig.cs @@ -1,4 +1,4 @@ -namespace StardewModdingAPI.Framework.Models +namespace StardewModdingAPI.Framework.Models { /// The SMAPI configuration settings. internal class SConfig @@ -9,11 +9,17 @@ /// Whether to enable development features. public bool DeveloperMode { get; set; } - /// Whether to check if a newer version of SMAPI is available on startup. - public bool CheckForUpdates { get; set; } = true; + /// Whether to check for newer versions of SMAPI and mods on startup. + public bool CheckForUpdates { get; set; } + + /// SMAPI's GitHub project name, used to perform update checks. + public string GitHubProjectName { get; set; } + + /// The base URL for SMAPI's web API, used to perform update checks. + public string WebApiBaseUrl { get; set; } /// Whether SMAPI should log more information about the game context. - public bool VerboseLogging { get; set; } = false; + public bool VerboseLogging { get; set; } /// A list of mod versions which should be considered compatible or incompatible regardless of whether SMAPI detects incompatible code. public ModCompatibility[] ModCompatibility { get; set; } diff --git a/src/StardewModdingAPI/Framework/UpdateHelper.cs b/src/StardewModdingAPI/Framework/UpdateHelper.cs index e01e55c8..0ee57648 100644 --- a/src/StardewModdingAPI/Framework/UpdateHelper.cs +++ b/src/StardewModdingAPI/Framework/UpdateHelper.cs @@ -1,36 +1,69 @@ -using System.IO; +using System; +using System.Collections.Generic; +using System.IO; using System.Net; -using System.Reflection; using System.Threading.Tasks; using Newtonsoft.Json; -using StardewModdingAPI.Framework.Models; +using StardewModdingAPI.Models; namespace StardewModdingAPI.Framework { - /// Provides utility methods for mod updates. - internal class UpdateHelper + /// 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 *********/ - /// Get the latest release from a GitHub repository. - /// The name of the repository from which to fetch releases (like "cjsu/SMAPI"). - public static async Task GetLatestVersionAsync(string repository) + /// 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 async Task> GetModInfoAsync(params string[] modKeys) { - // build request - // (avoid HttpClient for Mac compatibility) - HttpWebRequest request = WebRequest.CreateHttp($"https://api.github.com/repos/{repository}/releases/latest"); - AssemblyName assembly = typeof(UpdateHelper).Assembly.GetName(); - request.UserAgent = $"{assembly.Name}/{assembly.Version}"; - request.Accept = "application/vnd.github.v3+json"; - - // fetch data + string url = $"v{this.Version}/mods?modKeys={Uri.EscapeDataString(string.Join(",", modKeys))}"; + return await this.GetAsync>(url); + } + + + /********* + ** Private methods + *********/ + /// Fetch the response from the backend API. + /// The expected response type. + /// The request URL, optionally excluding the base URL. + private async Task GetAsync(string url) + { + // build request (avoid HttpClient for Mac compatibility) + HttpWebRequest request = WebRequest.CreateHttp(new Uri(this.BaseUrl, url).ToString()); + request.UserAgent = $"SMAPI/{this.Version}"; + + // fetch data using (WebResponse response = await request.GetResponseAsync()) using (Stream responseStream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(responseStream)) { string responseText = reader.ReadToEnd(); - return JsonConvert.DeserializeObject(responseText); + return JsonConvert.DeserializeObject(responseText); } } } diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index 84af2777..df94b02a 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -21,6 +21,7 @@ using StardewModdingAPI.Framework.ModHelpers; using StardewModdingAPI.Framework.ModLoading; using StardewModdingAPI.Framework.Reflection; using StardewModdingAPI.Framework.Serialisation; +using StardewModdingAPI.Models; using StardewValley; using Monitor = StardewModdingAPI.Framework.Monitor; using SObject = StardewValley.Object; @@ -572,10 +573,13 @@ namespace StardewModdingAPI { try { - GitRelease release = UpdateHelper.GetLatestVersionAsync(Constants.GitHubRepository).Result; - ISemanticVersion latestVersion = new SemanticVersion(release.Tag); - if (latestVersion.IsNewerThan(Constants.ApiVersion)) - this.Monitor.Log($"You can update SMAPI from version {Constants.ApiVersion} to {latestVersion}", LogLevel.Alert); + var client = new WebApiClient(this.Settings.WebApiBaseUrl, Constants.ApiVersion); + string key = $"GitHub:{this.Settings.GitHubProjectName}"; + ModInfoModel info = client.GetModInfoAsync(key).Result[key]; + if (info.Error != null) + this.Monitor.Log($"Couldn't check for a new version of SMAPI. This won't affect your game, but you may not be notified of new versions if this keeps happening.\n{info.Error}"); + else if (new SemanticVersion(info.Version).IsNewerThan(Constants.ApiVersion)) + this.Monitor.Log($"You can update SMAPI from version {Constants.ApiVersion} to {info.Version}.", LogLevel.Alert); } catch (Exception ex) { diff --git a/src/StardewModdingAPI/StardewModdingAPI.config.json b/src/StardewModdingAPI/StardewModdingAPI.config.json index d393f5a9..67d8f270 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.config.json +++ b/src/StardewModdingAPI/StardewModdingAPI.config.json @@ -1,4 +1,4 @@ -/* +/* @@ -21,6 +21,17 @@ This file contains advanced configuration for SMAPI. You generally shouldn't cha */ "CheckForUpdates": true, + /** + * SMAPI's GitHub project name, used to perform update checks. + */ + "GitHubProjectName": "Pathoschild/SMAPI", + + /** + * The base URL for SMAPI's web API, used to perform update checks. + * Note: the protocol will be changed to http:// on Linux/Mac due to OpenSSL issues with the game's bundled Mono. + */ + "WebApiBaseUrl": "https://api.smapi.io", + /** * Whether SMAPI should log more information about the game context. */ diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index 8da93bf4..d5fffd3f 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -219,7 +219,6 @@ - @@ -274,6 +273,7 @@ false + \ No newline at end of file -- cgit