From cc1ee0dbce64e16020a8c6c2fb903a2433dde08b Mon Sep 17 00:00:00 2001 From: Berkay Date: Mon, 25 Nov 2019 13:30:48 +0300 Subject: Add Turkish translation --- src/SMAPI/i18n/tr.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/SMAPI/i18n/tr.json (limited to 'src') diff --git a/src/SMAPI/i18n/tr.json b/src/SMAPI/i18n/tr.json new file mode 100644 index 00000000..34229f2b --- /dev/null +++ b/src/SMAPI/i18n/tr.json @@ -0,0 +1,3 @@ +{ + "warn.invalid-content-removed": "Yanlış paketlenmiş bir içerik, oyunun çökmemesi için yüklenmedi (SMAPI konsol penceresinde detaylı bilgi mevcut)." +} -- cgit From 0223382ca8e267d730629ee69cdf1cff673c8573 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 27 Nov 2019 19:50:42 -0500 Subject: remove unused package --- src/SMAPI.Web/SMAPI.Web.csproj | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/SMAPI.Web/SMAPI.Web.csproj b/src/SMAPI.Web/SMAPI.Web.csproj index 8a7ca741..30209146 100644 --- a/src/SMAPI.Web/SMAPI.Web.csproj +++ b/src/SMAPI.Web/SMAPI.Web.csproj @@ -21,7 +21,6 @@ - -- cgit From b1400bcb684c43790dd38628b6c131e9e7c4d400 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 27 Nov 2019 21:49:36 -0500 Subject: fallback to Amazon S3 if saving a log to Pastebin fails --- src/SMAPI.Web/Controllers/LogParserController.cs | 177 ++++++++++++++++++--- .../Framework/Clients/Pastebin/PasteInfo.cs | 10 +- .../Framework/Clients/Pastebin/PastebinClient.cs | 2 +- .../Framework/ConfigModels/ApiClientsConfig.cs | 16 ++ src/SMAPI.Web/SMAPI.Web.csproj | 1 + src/SMAPI.Web/Startup.cs | 1 + src/SMAPI.Web/ViewModels/LogParserModel.cs | 9 +- src/SMAPI.Web/Views/LogParser/Index.cshtml | 21 ++- src/SMAPI.Web/appsettings.Development.json | 3 + src/SMAPI.Web/appsettings.json | 35 ++-- src/SMAPI.Web/wwwroot/Content/css/log-parser.css | 6 + 11 files changed, 240 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/SMAPI.Web/Controllers/LogParserController.cs b/src/SMAPI.Web/Controllers/LogParserController.cs index f7f19cd8..32c45038 100644 --- a/src/SMAPI.Web/Controllers/LogParserController.cs +++ b/src/SMAPI.Web/Controllers/LogParserController.cs @@ -1,6 +1,13 @@ using System; +using System.IO; using System.Linq; +using System.Text; using System.Threading.Tasks; +using Amazon; +using Amazon.Runtime; +using Amazon.S3; +using Amazon.S3.Model; +using Amazon.S3.Transfer; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using StardewModdingAPI.Toolkit.Utilities; @@ -21,7 +28,10 @@ namespace StardewModdingAPI.Web.Controllers ** Fields *********/ /// The site config settings. - private readonly SiteConfig Config; + private readonly SiteConfig SiteConfig; + + /// The API client settings. + private readonly ApiClientsConfig ClientsConfig; /// The underlying Pastebin client. private readonly IPastebinClient Pastebin; @@ -38,11 +48,13 @@ namespace StardewModdingAPI.Web.Controllers ***/ /// Construct an instance. /// The context config settings. + /// The API client settings. /// The Pastebin API client. /// The underlying text compression helper. - public LogParserController(IOptions siteConfig, IPastebinClient pastebin, IGzipHelper gzipHelper) + public LogParserController(IOptions siteConfig, IOptions clientsConfig, IPastebinClient pastebin, IGzipHelper gzipHelper) { - this.Config = siteConfig.Value; + this.SiteConfig = siteConfig.Value; + this.ClientsConfig = clientsConfig.Value; this.Pastebin = pastebin; this.GzipHelper = gzipHelper; } @@ -66,8 +78,9 @@ namespace StardewModdingAPI.Web.Controllers PasteInfo paste = await this.GetAsync(id); ParsedLog log = paste.Success ? new LogParser().Parse(paste.Content) - : new ParsedLog { IsValid = false, Error = "Pastebin error: " + paste.Error }; - return this.View("Index", this.GetModel(id).SetResult(log, raw)); + : new ParsedLog { IsValid = false, Error = paste.Error }; + + return this.View("Index", this.GetModel(id, uploadWarning: paste.Warning, expiry: paste.Expiry).SetResult(log, raw)); } /*** @@ -85,15 +98,13 @@ namespace StardewModdingAPI.Web.Controllers // upload log input = this.GzipHelper.CompressString(input); - SavePasteResult result = await this.Pastebin.PostAsync($"SMAPI log {DateTime.UtcNow:s}", input); - - // handle errors - if (!result.Success) - return this.View("Index", this.GetModel(result.ID, uploadError: $"Pastebin error: {result.Error ?? "unknown error"}")); + var uploadResult = await this.TrySaveLog(input); + if (!uploadResult.Succeeded) + return this.View("Index", this.GetModel(null, uploadError: uploadResult.UploadError)); // redirect to view - UriBuilder uri = new UriBuilder(new Uri(this.Config.LogParserUrl)); - uri.Path = uri.Path.TrimEnd('/') + '/' + result.ID; + UriBuilder uri = new UriBuilder(new Uri(this.SiteConfig.LogParserUrl)); + uri.Path = $"{uri.Path.TrimEnd('/')}/{uploadResult.ID}"; return this.Redirect(uri.Uri.ToString()); } @@ -105,19 +116,116 @@ namespace StardewModdingAPI.Web.Controllers /// The Pastebin paste ID. private async Task GetAsync(string id) { - PasteInfo response = await this.Pastebin.GetAsync(id); - response.Content = this.GzipHelper.DecompressString(response.Content); - return response; + // get from Amazon S3 + if (Guid.TryParseExact(id, "N", out Guid _)) + { + var credentials = new BasicAWSCredentials(accessKey: this.ClientsConfig.AmazonAccessKey, secretKey: this.ClientsConfig.AmazonSecretKey); + + using (IAmazonS3 s3 = new AmazonS3Client(credentials, RegionEndpoint.GetBySystemName(this.ClientsConfig.AmazonRegion))) + { + try + { + using (GetObjectResponse response = await s3.GetObjectAsync(this.ClientsConfig.AmazonLogBucket, $"logs/{id}")) + using (Stream responseStream = response.ResponseStream) + using (StreamReader reader = new StreamReader(responseStream)) + { + DateTime expiry = response.Expiration.ExpiryDateUtc; + string pastebinError = response.Metadata["x-amz-meta-pastebin-error"]; + string content = this.GzipHelper.DecompressString(reader.ReadToEnd()); + + return new PasteInfo + { + Success = true, + Content = content, + Expiry = expiry, + Warning = pastebinError + }; + } + } + catch (AmazonServiceException ex) + { + return ex.ErrorCode == "NoSuchKey" + ? new PasteInfo { Error = "There's no log with that ID." } + : new PasteInfo { Error = $"Could not fetch that log from AWS S3 ({ex.ErrorCode}: {ex.Message})." }; + } + } + } + + // get from PasteBin + else + { + PasteInfo response = await this.Pastebin.GetAsync(id); + response.Content = this.GzipHelper.DecompressString(response.Content); + return response; + } + } + + /// Save a log to Pastebin or Amazon S3, if available. + /// The content to upload. + /// Returns metadata about the save attempt. + private async Task TrySaveLog(string content) + { + // save to PasteBin + string uploadError; + { + SavePasteResult result = await this.Pastebin.PostAsync($"SMAPI log {DateTime.UtcNow:s}", content); + if (result.Success) + return new UploadResult(true, result.ID, null); + + uploadError = $"Pastebin error: {result.Error ?? "unknown error"}"; + } + + // fallback to S3 + try + { + var credentials = new BasicAWSCredentials(accessKey: this.ClientsConfig.AmazonAccessKey, secretKey: this.ClientsConfig.AmazonSecretKey); + + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(content))) + using (IAmazonS3 s3 = new AmazonS3Client(credentials, RegionEndpoint.GetBySystemName(this.ClientsConfig.AmazonRegion))) + using (TransferUtility uploader = new TransferUtility(s3)) + { + string id = Guid.NewGuid().ToString("N"); + + var uploadRequest = new TransferUtilityUploadRequest + { + BucketName = this.ClientsConfig.AmazonLogBucket, + Key = $"logs/{id}", + InputStream = stream, + Metadata = + { + // note: AWS will lowercase keys and prefix 'x-amz-meta-' + ["smapi-uploaded"] = DateTime.UtcNow.ToString("O"), + ["pastebin-error"] = uploadError + } + }; + + await uploader.UploadAsync(uploadRequest); + + return new UploadResult(true, id, uploadError); + } + } + catch (Exception ex) + { + return new UploadResult(false, null, $"{uploadError}\n{ex.Message}"); + } } /// Build a log parser model. /// The paste ID. - /// An error which occurred while uploading the log to Pastebin. - private LogParserModel GetModel(string pasteID, string uploadError = null) + /// When the uploaded file will no longer be available. + /// A non-blocking warning while uploading the log. + /// An error which occurred while uploading the log. + private LogParserModel GetModel(string pasteID, DateTime? expiry = null, string uploadWarning = null, string uploadError = null) { - string sectionUrl = this.Config.LogParserUrl; + string sectionUrl = this.SiteConfig.LogParserUrl; Platform? platform = this.DetectClientPlatform(); - return new LogParserModel(sectionUrl, pasteID, platform) { UploadError = uploadError }; + + return new LogParserModel(sectionUrl, pasteID, platform) + { + UploadWarning = uploadWarning, + UploadError = uploadError, + Expiry = expiry + }; } /// Detect the viewer's OS. @@ -143,5 +251,36 @@ namespace StardewModdingAPI.Web.Controllers return null; } } + + /// The result of an attempt to upload a file. + private class UploadResult + { + /********* + ** Accessors + *********/ + /// Whether the file upload succeeded. + public bool Succeeded { get; } + + /// The file ID, if applicable. + public string ID { get; } + + /// The upload error, if any. + public string UploadError { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// Whether the file upload succeeded. + /// The file ID, if applicable. + /// The upload error, if any. + public UploadResult(bool succeeded, string id, string uploadError) + { + this.Succeeded = succeeded; + this.ID = id; + this.UploadError = uploadError; + } + } } } diff --git a/src/SMAPI.Web/Framework/Clients/Pastebin/PasteInfo.cs b/src/SMAPI.Web/Framework/Clients/Pastebin/PasteInfo.cs index 955156eb..bb2de356 100644 --- a/src/SMAPI.Web/Framework/Clients/Pastebin/PasteInfo.cs +++ b/src/SMAPI.Web/Framework/Clients/Pastebin/PasteInfo.cs @@ -1,3 +1,5 @@ +using System; + namespace StardewModdingAPI.Web.Framework.Clients.Pastebin { /// The response for a get-paste request. @@ -9,7 +11,13 @@ namespace StardewModdingAPI.Web.Framework.Clients.Pastebin /// The fetched paste content (if is true). public string Content { get; set; } - /// The error message (if saving failed). + /// When the file will no longer be available. + public DateTime? Expiry { get; set; } + + /// The error message if saving succeeded, but a non-blocking issue was encountered. + public string Warning { get; set; } + + /// The error message if saving failed. public string Error { get; set; } } } diff --git a/src/SMAPI.Web/Framework/Clients/Pastebin/PastebinClient.cs b/src/SMAPI.Web/Framework/Clients/Pastebin/PastebinClient.cs index 2e8a8c68..d695aab6 100644 --- a/src/SMAPI.Web/Framework/Clients/Pastebin/PastebinClient.cs +++ b/src/SMAPI.Web/Framework/Clients/Pastebin/PastebinClient.cs @@ -62,7 +62,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.Pastebin } catch (Exception ex) { - return new PasteInfo { Error = ex.ToString() }; + return new PasteInfo { Error = $"Pastebin error: {ex}" }; } } diff --git a/src/SMAPI.Web/Framework/ConfigModels/ApiClientsConfig.cs b/src/SMAPI.Web/Framework/ConfigModels/ApiClientsConfig.cs index 121690c5..7119ef03 100644 --- a/src/SMAPI.Web/Framework/ConfigModels/ApiClientsConfig.cs +++ b/src/SMAPI.Web/Framework/ConfigModels/ApiClientsConfig.cs @@ -13,6 +13,22 @@ namespace StardewModdingAPI.Web.Framework.ConfigModels public string UserAgent { get; set; } + /**** + ** Amazon Web Services + ****/ + /// The access key for AWS authentication. + public string AmazonAccessKey { get; set; } + + /// The secret key for AWS authentication. + public string AmazonSecretKey { get; set; } + + /// The AWS region endpoint (like 'us-east-1'). + public string AmazonRegion { get; set; } + + /// The AWS bucket in which to store temporary uploaded logs. + public string AmazonLogBucket { get; set; } + + /**** ** Chucklefish ****/ diff --git a/src/SMAPI.Web/SMAPI.Web.csproj b/src/SMAPI.Web/SMAPI.Web.csproj index 30209146..863c586e 100644 --- a/src/SMAPI.Web/SMAPI.Web.csproj +++ b/src/SMAPI.Web/SMAPI.Web.csproj @@ -12,6 +12,7 @@ + diff --git a/src/SMAPI.Web/Startup.cs b/src/SMAPI.Web/Startup.cs index 8110b696..fc6161b5 100644 --- a/src/SMAPI.Web/Startup.cs +++ b/src/SMAPI.Web/Startup.cs @@ -58,6 +58,7 @@ namespace StardewModdingAPI.Web { // init basic services services + .Configure(this.Configuration.GetSection("ApiClients")) .Configure(this.Configuration.GetSection("BackgroundServices")) .Configure(this.Configuration.GetSection("ModCompatibilityList")) .Configure(this.Configuration.GetSection("ModUpdateCheck")) diff --git a/src/SMAPI.Web/ViewModels/LogParserModel.cs b/src/SMAPI.Web/ViewModels/LogParserModel.cs index f4c5214b..b06b5b2d 100644 --- a/src/SMAPI.Web/ViewModels/LogParserModel.cs +++ b/src/SMAPI.Web/ViewModels/LogParserModel.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; @@ -34,12 +35,18 @@ namespace StardewModdingAPI.Web.ViewModels /// Whether to show the raw unparsed log. public bool ShowRaw { get; set; } - /// An error which occurred while uploading the log to Pastebin. + /// A non-blocking warning while uploading the log. + public string UploadWarning { get; set; } + + /// An error which occurred while uploading the log. public string UploadError { get; set; } /// An error which occurred while parsing the log file. public string ParseError => this.ParsedLog?.Error; + /// When the uploaded file will no longer be available. + public DateTime? Expiry { get; set; } + /********* ** Public methods diff --git a/src/SMAPI.Web/Views/LogParser/Index.cshtml b/src/SMAPI.Web/Views/LogParser/Index.cshtml index f98ffdf9..df2ac115 100644 --- a/src/SMAPI.Web/Views/LogParser/Index.cshtml +++ b/src/SMAPI.Web/Views/LogParser/Index.cshtml @@ -1,3 +1,4 @@ +@using Humanizer @using Newtonsoft.Json @using StardewModdingAPI.Toolkit.Utilities @using StardewModdingAPI.Web.Framework.LogParsing.Models @@ -18,7 +19,7 @@ { } - + @@ -62,6 +63,18 @@ else if (Model.ParsedLog?.IsValid == true) } +@* save warnings *@ +@if (Model.UploadWarning != null || Model.Expiry != null) +{ + +} + @* upload new log *@ @if (Model.ParsedLog == null) { @@ -71,7 +84,7 @@ else if (Model.ParsedLog?.IsValid == true) @foreach (Platform platform in new[] { Platform.Android, Platform.Linux, Platform.Mac, Platform.Windows }) {
  • - +
  • } @@ -151,7 +164,7 @@ else if (Model.ParsedLog?.IsValid == true)
    @foreach (LogModInfo contentPack in contentPackList.Where(pack => pack.HasUpdate)) { - + @contentPack.Name
    + + @contentPack.Name
    }
    } @@ -173,7 +186,7 @@ else if (Model.ParsedLog?.IsValid == true)
    @foreach (LogModInfo contentPack in contentPackList.Where(pack => pack.HasUpdate)) { - @contentPack.Version → @contentPack.UpdateVersion
    + @contentPack.Version → @contentPack.UpdateVersion
    }
    } diff --git a/src/SMAPI.Web/appsettings.Development.json b/src/SMAPI.Web/appsettings.Development.json index baf7efb7..8e863591 100644 --- a/src/SMAPI.Web/appsettings.Development.json +++ b/src/SMAPI.Web/appsettings.Development.json @@ -18,6 +18,9 @@ }, "ApiClients": { + "AmazonAccessKey": null, + "AmazonSecretKey": null, + "GitHubUsername": null, "GitHubPassword": null, diff --git a/src/SMAPI.Web/appsettings.json b/src/SMAPI.Web/appsettings.json index 674bb672..3b6f8fbd 100644 --- a/src/SMAPI.Web/appsettings.json +++ b/src/SMAPI.Web/appsettings.json @@ -16,17 +16,22 @@ }, "Site": { - "RootUrl": null, // see top note - "ModListUrl": null, // see top note - "LogParserUrl": null, // see top note - "JsonValidatorUrl": null, // see top note - "BetaEnabled": null, // see top note - "BetaBlurb": null // see top note + "RootUrl": null, + "ModListUrl": null, + "LogParserUrl": null, + "JsonValidatorUrl": null, + "BetaEnabled": null, + "BetaBlurb": null }, "ApiClients": { "UserAgent": "SMAPI/{0} (+https://smapi.io)", + "AmazonAccessKey": null, + "AmazonSecretKey": null, + "AmazonRegion": "us-east-1", + "AmazonLogBucket": "smapi-log-parser", + "ChucklefishBaseUrl": "https://community.playstarbound.com", "ChucklefishModPageUrlFormat": "resources/{0}", @@ -34,27 +39,27 @@ "GitHubBaseUrl": "https://api.github.com", "GitHubAcceptHeader": "application/vnd.github.v3+json", - "GitHubUsername": null, // see top note - "GitHubPassword": null, // see top note + "GitHubUsername": null, + "GitHubPassword": null, "ModDropApiUrl": "https://www.moddrop.com/api/mods/data", "ModDropModPageUrl": "https://www.moddrop.com/sdv/mod/{0}", - "NexusApiKey": null, // see top note + "NexusApiKey": null, "NexusBaseUrl": "https://www.nexusmods.com/stardewvalley/", "NexusModUrlFormat": "mods/{0}", "NexusModScrapeUrlFormat": "mods/{0}?tab=files", "PastebinBaseUrl": "https://pastebin.com/", - "PastebinUserKey": null, // see top note - "PastebinDevKey": null // see top note + "PastebinUserKey": null, + "PastebinDevKey": null }, "MongoDB": { - "Host": null, // see top note - "Username": null, // see top note - "Password": null, // see top note - "Database": null // see top note + "Host": null, + "Username": null, + "Password": null, + "Database": null }, "ModCompatibilityList": { diff --git a/src/SMAPI.Web/wwwroot/Content/css/log-parser.css b/src/SMAPI.Web/wwwroot/Content/css/log-parser.css index d5013207..4d4ab326 100644 --- a/src/SMAPI.Web/wwwroot/Content/css/log-parser.css +++ b/src/SMAPI.Web/wwwroot/Content/css/log-parser.css @@ -47,6 +47,12 @@ table caption { background: #FCC; } +.save-metadata { + margin-top: 1em; + font-size: 0.8em; + opacity: 0.3; +} + /********* ** Log metadata & filters *********/ -- cgit From 286f0f8c1e81e7052312f19d73fc0dfe36313859 Mon Sep 17 00:00:00 2001 From: archification Date: Fri, 29 Nov 2019 23:49:59 -0600 Subject: add alacritty support to unix-launcher --- src/SMAPI.Installer/unix-launcher.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/SMAPI.Installer/unix-launcher.sh b/src/SMAPI.Installer/unix-launcher.sh index f81828f0..bebba9fe 100644 --- a/src/SMAPI.Installer/unix-launcher.sh +++ b/src/SMAPI.Installer/unix-launcher.sh @@ -62,7 +62,7 @@ else fi # select terminal (prefer $TERMINAL for overrides and testing, then xterm for best compatibility, then known supported terminals) - for terminal in "$TERMINAL" xterm gnome-terminal kitty terminator xfce4-terminal konsole terminal termite x-terminal-emulator; do + for terminal in "$TERMINAL" xterm gnome-terminal kitty terminator xfce4-terminal konsole terminal termite alacritty x-terminal-emulator; do if $COMMAND "$terminal" 2>/dev/null; then # Find the true shell behind x-terminal-emulator if [ "$(basename "$(readlink -f $(which "$terminal"))")" != "x-terminal-emulator" ]; then @@ -100,6 +100,14 @@ else # Kitty overrides the TERM varible unless you set it explicitly kitty -o term=xterm $LAUNCHER ;; + alacritty) + # Alacritty doesn't like the double quotes or the variable + if [ "$ARCH" == "x86_64" ]; then + alacritty -e sh -c 'TERM=xterm ./StardewModdingAPI.bin.x86_64 $*' + else + alacritty -e sh -c 'TERM=xterm ./StardewModdingAPI.bin.x86 $*' + fi + ;; xterm|xfce4-terminal|gnome-terminal|terminal|termite) $LAUNCHTERM -e "sh -c 'TERM=xterm $LAUNCHER'" ;; -- cgit From 10a18290773f3152f018ef9ecc3f7ae4544d7367 Mon Sep 17 00:00:00 2001 From: Daniel Heath Date: Sat, 30 Nov 2019 20:25:16 +1100 Subject: Prevent linux install failing with cryptic error This avoids the error described at https://stackoverflow.com/questions/49242075/mono-bug-magic-number-is-wrong-542 System.TypeInitializationException: The type initializer for 'System.Console' threw an exception. ---> System.TypeInitializationException: The type initializer for 'System.ConsoleDriver' threw an exception. ---> System.Exception: Magic number is wrong: 542 --- src/SMAPI.Installer/unix-install.sh | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/SMAPI.Installer/unix-install.sh b/src/SMAPI.Installer/unix-install.sh index e3a5d8cc..6d0c86ce 100644 --- a/src/SMAPI.Installer/unix-install.sh +++ b/src/SMAPI.Installer/unix-install.sh @@ -12,6 +12,9 @@ elif type type >/dev/null 2>&1; then COMMAND="type" fi +# if $TERM is not set to xterm, mono will bail out when attempting to write to the console. +export TERM=xterm + # validate Mono & run installer if $COMMAND mono >/dev/null 2>&1; then mono internal/unix-install.exe -- cgit From 9fadc3a6ad5066cabdac9e853f32b3eb69259bab Mon Sep 17 00:00:00 2001 From: FeatherShine Date: Sun, 1 Dec 2019 00:42:27 +0800 Subject: add Chinese translation --- src/SMAPI/i18n/zh.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/SMAPI/i18n/zh.json (limited to 'src') diff --git a/src/SMAPI/i18n/zh.json b/src/SMAPI/i18n/zh.json new file mode 100644 index 00000000..8dec396a --- /dev/null +++ b/src/SMAPI/i18n/zh.json @@ -0,0 +1,3 @@ +{ + "warn.invalid-content-removed": "非法内容已移除以防游戏闪退(查看SMAPI控制台获得更多信息)" +} \ No newline at end of file -- cgit From d7948fbe1cfb111fab009cd0977778dfff358d58 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 30 Nov 2019 16:44:34 -0500 Subject: update translation docs (#664, #671) --- src/SMAPI/i18n/zh.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/SMAPI/i18n/zh.json b/src/SMAPI/i18n/zh.json index 8dec396a..bbd6a574 100644 --- a/src/SMAPI/i18n/zh.json +++ b/src/SMAPI/i18n/zh.json @@ -1,3 +1,3 @@ { "warn.invalid-content-removed": "非法内容已移除以防游戏闪退(查看SMAPI控制台获得更多信息)" -} \ No newline at end of file +} -- cgit From 854ee8c1542ba709d70df3d53082945f1fd196f1 Mon Sep 17 00:00:00 2001 From: Georgii Smirnov Date: Sun, 1 Dec 2019 17:43:50 +0300 Subject: Create ru.json Add Russian Translation --- src/SMAPI/i18n/ru.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/SMAPI/i18n/ru.json (limited to 'src') diff --git a/src/SMAPI/i18n/ru.json b/src/SMAPI/i18n/ru.json new file mode 100644 index 00000000..a6a242fa --- /dev/null +++ b/src/SMAPI/i18n/ru.json @@ -0,0 +1,3 @@ +{ + "warn.invalid-content-removed": "Недопустимое содержимое было удалено, чтобы предотвратить сбой (см. информацию в консоли SMAPI)" +} -- cgit From 5f532c259d5d3050bd6a053659067617db136d57 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 1 Dec 2019 21:55:20 -0500 Subject: migrate from AWS to Azure This commit migrates from subdomains to paths (due to the cost of a wildcard HTTPS certificate on Azure), adds a web project to redirect the old subdomains from AWS to Azure, and removes AWS-specific hacks. --- .../Controllers/ModsApiController.cs | 33 ++++++++ .../Framework/LambdaRewriteRule.cs | 37 +++++++++ src/SMAPI.Web.LegacyRedirects/Program.cs | 23 ++++++ .../Properties/launchSettings.json | 29 +++++++ .../SMAPI.Web.LegacyRedirects.csproj | 21 +++++ src/SMAPI.Web.LegacyRedirects/Startup.cs | 94 ++++++++++++++++++++++ .../Controllers/JsonValidatorController.cs | 24 ++---- src/SMAPI.Web/Controllers/LogParserController.cs | 14 +--- src/SMAPI.Web/Controllers/ModsApiController.cs | 8 +- .../Framework/BeanstalkEnvPropsConfigProvider.cs | 54 ------------- .../Framework/ConfigModels/ModUpdateCheckConfig.cs | 3 - src/SMAPI.Web/Framework/ConfigModels/SiteConfig.cs | 12 --- .../ConditionalRewriteSubdomainRule.cs | 48 ----------- src/SMAPI.Web/Startup.cs | 17 +--- .../ViewModels/JsonValidator/JsonValidatorModel.cs | 7 +- src/SMAPI.Web/ViewModels/LogParserModel.cs | 7 +- src/SMAPI.Web/Views/Index/Index.cshtml | 10 +-- src/SMAPI.Web/Views/Index/Privacy.cshtml | 4 +- src/SMAPI.Web/Views/JsonValidator/Index.cshtml | 10 +-- src/SMAPI.Web/Views/LogParser/Index.cshtml | 16 ++-- src/SMAPI.Web/Views/Shared/_Layout.cshtml | 8 +- src/SMAPI.Web/appsettings.Development.json | 4 - src/SMAPI.Web/appsettings.json | 7 +- src/SMAPI.sln | 6 ++ src/SMAPI/Framework/ModLoading/ModResolver.cs | 2 +- src/SMAPI/Framework/Models/SConfig.cs | 2 +- src/SMAPI/Framework/SCore.cs | 4 +- src/SMAPI/SMAPI.config.json | 2 +- 28 files changed, 289 insertions(+), 217 deletions(-) create mode 100644 src/SMAPI.Web.LegacyRedirects/Controllers/ModsApiController.cs create mode 100644 src/SMAPI.Web.LegacyRedirects/Framework/LambdaRewriteRule.cs create mode 100644 src/SMAPI.Web.LegacyRedirects/Program.cs create mode 100644 src/SMAPI.Web.LegacyRedirects/Properties/launchSettings.json create mode 100644 src/SMAPI.Web.LegacyRedirects/SMAPI.Web.LegacyRedirects.csproj create mode 100644 src/SMAPI.Web.LegacyRedirects/Startup.cs delete mode 100644 src/SMAPI.Web/Framework/BeanstalkEnvPropsConfigProvider.cs delete mode 100644 src/SMAPI.Web/Framework/RewriteRules/ConditionalRewriteSubdomainRule.cs (limited to 'src') diff --git a/src/SMAPI.Web.LegacyRedirects/Controllers/ModsApiController.cs b/src/SMAPI.Web.LegacyRedirects/Controllers/ModsApiController.cs new file mode 100644 index 00000000..44ed0b6b --- /dev/null +++ b/src/SMAPI.Web.LegacyRedirects/Controllers/ModsApiController.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Pathoschild.Http.Client; +using StardewModdingAPI.Toolkit.Framework.Clients.WebApi; + +namespace SMAPI.Web.LegacyRedirects.Controllers +{ + /// Provides an API to perform mod update checks. + [ApiController] + [Produces("application/json")] + [Route("api/v{version}/mods")] + public class ModsApiController : Controller + { + /********* + ** Public methods + *********/ + /// Fetch version metadata for the given mods. + /// The mod search criteria. + [HttpPost] + public async Task> PostAsync([FromBody] ModSearchModel model) + { + using IClient client = new FluentClient("https://smapi.io/api"); + + Startup.ConfigureJsonNet(client.Formatters.JsonFormatter.SerializerSettings); + + return await client + .PostAsync(this.Request.Path) + .WithBody(model) + .AsArray(); + } + } +} diff --git a/src/SMAPI.Web.LegacyRedirects/Framework/LambdaRewriteRule.cs b/src/SMAPI.Web.LegacyRedirects/Framework/LambdaRewriteRule.cs new file mode 100644 index 00000000..e5138e5c --- /dev/null +++ b/src/SMAPI.Web.LegacyRedirects/Framework/LambdaRewriteRule.cs @@ -0,0 +1,37 @@ +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Rewrite; + +namespace SMAPI.Web.LegacyRedirects.Framework +{ + /// Rewrite requests to prepend the subdomain portion (if any) to the path. + /// Derived from . + internal class LambdaRewriteRule : IRule + { + /********* + ** Accessors + *********/ + /// Rewrite an HTTP request if needed. + private readonly Action Rewrite; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// Rewrite an HTTP request if needed. + public LambdaRewriteRule(Action rewrite) + { + this.Rewrite = rewrite ?? throw new ArgumentNullException(nameof(rewrite)); + } + + /// Applies the rule. Implementations of ApplyRule should set the value for (defaults to RuleResult.ContinueRules). + /// The rewrite context. + public void ApplyRule(RewriteContext context) + { + HttpRequest request = context.HttpContext.Request; + HttpResponse response = context.HttpContext.Response; + this.Rewrite(context, request, response); + } + } +} diff --git a/src/SMAPI.Web.LegacyRedirects/Program.cs b/src/SMAPI.Web.LegacyRedirects/Program.cs new file mode 100644 index 00000000..6adee877 --- /dev/null +++ b/src/SMAPI.Web.LegacyRedirects/Program.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + +namespace SMAPI.Web.LegacyRedirects +{ + /// The main app entry point. + public class Program + { + /********* + ** Public methods + *********/ + /// The main app entry point. + /// The command-line arguments. + public static void Main(string[] args) + { + Host + .CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(builder => builder.UseStartup()) + .Build() + .Run(); + } + } +} diff --git a/src/SMAPI.Web.LegacyRedirects/Properties/launchSettings.json b/src/SMAPI.Web.LegacyRedirects/Properties/launchSettings.json new file mode 100644 index 00000000..e9a1b210 --- /dev/null +++ b/src/SMAPI.Web.LegacyRedirects/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:52756", + "sslPort": 0 + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "SMAPI.Web.LegacyRedirects": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "/", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/src/SMAPI.Web.LegacyRedirects/SMAPI.Web.LegacyRedirects.csproj b/src/SMAPI.Web.LegacyRedirects/SMAPI.Web.LegacyRedirects.csproj new file mode 100644 index 00000000..a3d5c2b6 --- /dev/null +++ b/src/SMAPI.Web.LegacyRedirects/SMAPI.Web.LegacyRedirects.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp3.0 + + + + + + + + + + + + + + + + + diff --git a/src/SMAPI.Web.LegacyRedirects/Startup.cs b/src/SMAPI.Web.LegacyRedirects/Startup.cs new file mode 100644 index 00000000..4af51575 --- /dev/null +++ b/src/SMAPI.Web.LegacyRedirects/Startup.cs @@ -0,0 +1,94 @@ +using System.Net; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Rewrite; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Newtonsoft.Json; +using SMAPI.Web.LegacyRedirects.Framework; +using StardewModdingAPI.Toolkit.Serialization; + +namespace SMAPI.Web.LegacyRedirects +{ + /// The web app startup configuration. + public class Startup + { + /********* + ** Public methods + *********/ + /// The method called by the runtime to add services to the container. + /// The service injection container. + public void ConfigureServices(IServiceCollection services) + { + services + .AddControllers() + .AddNewtonsoftJson(options => Startup.ConfigureJsonNet(options.SerializerSettings)); + } + + /// The method called by the runtime to configure the HTTP request pipeline. + /// The application builder. + /// The hosting environment. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + app.UseDeveloperExceptionPage(); + + app + .UseRewriter(this.GetRedirectRules()) + .UseRouting() + .UseAuthorization() + .UseEndpoints(endpoints => endpoints.MapControllers()); + } + + /// Configure a Json.NET serializer. + /// The serializer settings to edit. + internal static void ConfigureJsonNet(JsonSerializerSettings settings) + { + foreach (JsonConverter converter in new JsonHelper().JsonSettings.Converters) + settings.Converters.Add(converter); + + settings.Formatting = Formatting.Indented; + settings.NullValueHandling = NullValueHandling.Ignore; + } + + + /********* + ** Private methods + *********/ + /// Get the redirect rules to apply. + private RewriteOptions GetRedirectRules() + { + var redirects = new RewriteOptions(); + + redirects.Add( + new LambdaRewriteRule((context, request, response) => + { + string host = request.Host.Host; + + // map API requests to proxy + // This is needed because the low-level HTTP client SMAPI uses for Linux/Mac compatibility doesn't support redirects. + if (host == "api.smapi.io") + { + request.Path = $"/api{request.Path}"; + return; + } + + // redirect other requests to Azure + string newRoot = host switch + { + "api.smapi.io" => "smapi.io/api", + "json.smapi.io" => "smapi.io/json", + "log.smapi.io" => "smapi.io/log", + "mods.smapi.io" => "smapi.io/mods", + _ => "smapi.io" + }; + response.StatusCode = (int)HttpStatusCode.PermanentRedirect; + response.Headers["Location"] = $"{(request.IsHttps ? "https" : "http")}://{newRoot}{request.PathBase}{request.Path}{request.QueryString}"; + context.Result = RuleResult.EndResponse; + }) + ); + + return redirects; + } + } +} diff --git a/src/SMAPI.Web/Controllers/JsonValidatorController.cs b/src/SMAPI.Web/Controllers/JsonValidatorController.cs index b2eb9a87..c32fb084 100644 --- a/src/SMAPI.Web/Controllers/JsonValidatorController.cs +++ b/src/SMAPI.Web/Controllers/JsonValidatorController.cs @@ -5,14 +5,12 @@ using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Schema; using StardewModdingAPI.Web.Framework; using StardewModdingAPI.Web.Framework.Clients.Pastebin; using StardewModdingAPI.Web.Framework.Compression; -using StardewModdingAPI.Web.Framework.ConfigModels; using StardewModdingAPI.Web.ViewModels.JsonValidator; namespace StardewModdingAPI.Web.Controllers @@ -23,18 +21,12 @@ namespace StardewModdingAPI.Web.Controllers /********* ** Fields *********/ - /// The site config settings. - private readonly SiteConfig Config; - /// The underlying Pastebin client. private readonly IPastebinClient Pastebin; /// The underlying text compression helper. private readonly IGzipHelper GzipHelper; - /// The section URL for the schema validator. - private string SectionUrl => this.Config.JsonValidatorUrl; - /// The supported JSON schemas (names indexed by ID). private readonly IDictionary SchemaFormats = new Dictionary { @@ -57,12 +49,10 @@ namespace StardewModdingAPI.Web.Controllers ** Constructor ***/ /// Construct an instance. - /// The context config settings. /// The Pastebin API client. /// The underlying text compression helper. - public JsonValidatorController(IOptions siteConfig, IPastebinClient pastebin, IGzipHelper gzipHelper) + public JsonValidatorController(IPastebinClient pastebin, IGzipHelper gzipHelper) { - this.Config = siteConfig.Value; this.Pastebin = pastebin; this.GzipHelper = gzipHelper; } @@ -81,7 +71,7 @@ namespace StardewModdingAPI.Web.Controllers { schemaName = this.NormalizeSchemaName(schemaName); - var result = new JsonValidatorModel(this.SectionUrl, id, schemaName, this.SchemaFormats); + var result = new JsonValidatorModel(id, schemaName, this.SchemaFormats); if (string.IsNullOrWhiteSpace(id)) return this.View("Index", result); @@ -142,7 +132,7 @@ namespace StardewModdingAPI.Web.Controllers public async Task PostAsync(JsonValidatorRequestModel request) { if (request == null) - return this.View("Index", new JsonValidatorModel(this.SectionUrl, null, null, this.SchemaFormats).SetUploadError("The request seems to be invalid.")); + return this.View("Index", new JsonValidatorModel(null, null, this.SchemaFormats).SetUploadError("The request seems to be invalid.")); // normalize schema name string schemaName = this.NormalizeSchemaName(request.SchemaName); @@ -150,7 +140,7 @@ namespace StardewModdingAPI.Web.Controllers // get raw log text string input = request.Content; if (string.IsNullOrWhiteSpace(input)) - return this.View("Index", new JsonValidatorModel(this.SectionUrl, null, schemaName, this.SchemaFormats).SetUploadError("The JSON file seems to be empty.")); + return this.View("Index", new JsonValidatorModel(null, schemaName, this.SchemaFormats).SetUploadError("The JSON file seems to be empty.")); // upload log input = this.GzipHelper.CompressString(input); @@ -158,12 +148,10 @@ namespace StardewModdingAPI.Web.Controllers // handle errors if (!result.Success) - return this.View("Index", new JsonValidatorModel(this.SectionUrl, result.ID, schemaName, this.SchemaFormats).SetUploadError($"Pastebin error: {result.Error ?? "unknown error"}")); + return this.View("Index", new JsonValidatorModel(result.ID, schemaName, this.SchemaFormats).SetUploadError($"Pastebin error: {result.Error ?? "unknown error"}")); // redirect to view - UriBuilder uri = new UriBuilder(new Uri(this.SectionUrl)); - uri.Path = $"{uri.Path.TrimEnd('/')}/{schemaName}/{result.ID}"; - return this.Redirect(uri.Uri.ToString()); + return this.Redirect(this.Url.Action("Index", "LogParser", new { schemaName = schemaName, id = result.ID })); } diff --git a/src/SMAPI.Web/Controllers/LogParserController.cs b/src/SMAPI.Web/Controllers/LogParserController.cs index 32c45038..2ced5a05 100644 --- a/src/SMAPI.Web/Controllers/LogParserController.cs +++ b/src/SMAPI.Web/Controllers/LogParserController.cs @@ -27,9 +27,6 @@ namespace StardewModdingAPI.Web.Controllers /********* ** Fields *********/ - /// The site config settings. - private readonly SiteConfig SiteConfig; - /// The API client settings. private readonly ApiClientsConfig ClientsConfig; @@ -47,13 +44,11 @@ namespace StardewModdingAPI.Web.Controllers ** Constructor ***/ /// Construct an instance. - /// The context config settings. /// The API client settings. /// The Pastebin API client. /// The underlying text compression helper. - public LogParserController(IOptions siteConfig, IOptions clientsConfig, IPastebinClient pastebin, IGzipHelper gzipHelper) + public LogParserController(IOptions clientsConfig, IPastebinClient pastebin, IGzipHelper gzipHelper) { - this.SiteConfig = siteConfig.Value; this.ClientsConfig = clientsConfig.Value; this.Pastebin = pastebin; this.GzipHelper = gzipHelper; @@ -103,9 +98,7 @@ namespace StardewModdingAPI.Web.Controllers return this.View("Index", this.GetModel(null, uploadError: uploadResult.UploadError)); // redirect to view - UriBuilder uri = new UriBuilder(new Uri(this.SiteConfig.LogParserUrl)); - uri.Path = $"{uri.Path.TrimEnd('/')}/{uploadResult.ID}"; - return this.Redirect(uri.Uri.ToString()); + return this.Redirect(this.Url.Action("Index", "LogParser", new { id = uploadResult.ID })); } @@ -217,10 +210,9 @@ namespace StardewModdingAPI.Web.Controllers /// An error which occurred while uploading the log. private LogParserModel GetModel(string pasteID, DateTime? expiry = null, string uploadWarning = null, string uploadError = null) { - string sectionUrl = this.SiteConfig.LogParserUrl; Platform? platform = this.DetectClientPlatform(); - return new LogParserModel(sectionUrl, pasteID, platform) + return new LogParserModel(pasteID, platform) { UploadWarning = uploadWarning, UploadError = uploadError, diff --git a/src/SMAPI.Web/Controllers/ModsApiController.cs b/src/SMAPI.Web/Controllers/ModsApiController.cs index fe220eb5..f10e0067 100644 --- a/src/SMAPI.Web/Controllers/ModsApiController.cs +++ b/src/SMAPI.Web/Controllers/ModsApiController.cs @@ -49,9 +49,6 @@ namespace StardewModdingAPI.Web.Controllers /// The internal mod metadata list. private readonly ModDatabase ModDatabase; - /// The web URL for the compatibility list. - private readonly string CompatibilityPageUrl; - /********* ** Public methods @@ -70,7 +67,6 @@ namespace StardewModdingAPI.Web.Controllers { this.ModDatabase = new ModToolkit().GetModDatabase(Path.Combine(environment.WebRootPath, "SMAPI.metadata.json")); ModUpdateCheckConfig config = configProvider.Value; - this.CompatibilityPageUrl = config.CompatibilityPageUrl; this.WikiCache = wikiCache; this.ModCache = modCache; @@ -205,7 +201,7 @@ namespace StardewModdingAPI.Web.Controllers // get unofficial version if (wikiEntry?.Compatibility.UnofficialVersion != null && this.IsNewer(wikiEntry.Compatibility.UnofficialVersion, main?.Version) && this.IsNewer(wikiEntry.Compatibility.UnofficialVersion, optional?.Version)) - unofficial = new ModEntryVersionModel(wikiEntry.Compatibility.UnofficialVersion, $"{this.CompatibilityPageUrl}/#{wikiEntry.Anchor}"); + unofficial = new ModEntryVersionModel(wikiEntry.Compatibility.UnofficialVersion, $"{this.Url.Action("Index", "Mods")}#{wikiEntry.Anchor}"); // get unofficial version for beta if (wikiEntry?.HasBetaInfo == true) @@ -215,7 +211,7 @@ namespace StardewModdingAPI.Web.Controllers if (wikiEntry.BetaCompatibility.UnofficialVersion != null) { unofficialForBeta = (wikiEntry.BetaCompatibility.UnofficialVersion != null && this.IsNewer(wikiEntry.BetaCompatibility.UnofficialVersion, main?.Version) && this.IsNewer(wikiEntry.BetaCompatibility.UnofficialVersion, optional?.Version)) - ? new ModEntryVersionModel(wikiEntry.BetaCompatibility.UnofficialVersion, $"{this.CompatibilityPageUrl}/#{wikiEntry.Anchor}") + ? new ModEntryVersionModel(wikiEntry.BetaCompatibility.UnofficialVersion, $"{this.Url.Action("Index", "Mods")}#{wikiEntry.Anchor}") : null; } else diff --git a/src/SMAPI.Web/Framework/BeanstalkEnvPropsConfigProvider.cs b/src/SMAPI.Web/Framework/BeanstalkEnvPropsConfigProvider.cs deleted file mode 100644 index fe27fe2f..00000000 --- a/src/SMAPI.Web/Framework/BeanstalkEnvPropsConfigProvider.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Microsoft.Extensions.Configuration; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace StardewModdingAPI.Web.Framework -{ - /// Reads configuration values from the AWS Beanstalk environment properties file (if present). - /// This is a workaround for AWS Beanstalk injection not working with .NET Core apps. - internal class BeanstalkEnvPropsConfigProvider : ConfigurationProvider, IConfigurationSource - { - /********* - ** Fields - *********/ - /// The absolute path to the container configuration file on an Amazon EC2 instance. - private const string ContainerConfigPath = @"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration"; - - - /********* - ** Public methods - *********/ - /// Build the configuration provider for this source. - /// The configuration builder. - public IConfigurationProvider Build(IConfigurationBuilder builder) - { - return new BeanstalkEnvPropsConfigProvider(); - } - - /// Load the environment properties. - public override void Load() - { - this.Data = new Dictionary(StringComparer.OrdinalIgnoreCase); - - // get Beanstalk config file - FileInfo file = new FileInfo(BeanstalkEnvPropsConfigProvider.ContainerConfigPath); - if (!file.Exists) - return; - - // parse JSON - JObject jsonRoot = (JObject)JsonConvert.DeserializeObject(File.ReadAllText(file.FullName)); - if (jsonRoot["iis"]?["env"] is JArray jsonProps) - { - foreach (string prop in jsonProps.Values()) - { - string[] parts = prop.Split('=', 2); // key=value - if (parts.Length == 2) - this.Data[parts[0]] = parts[1]; - } - } - } - } -} diff --git a/src/SMAPI.Web/Framework/ConfigModels/ModUpdateCheckConfig.cs b/src/SMAPI.Web/Framework/ConfigModels/ModUpdateCheckConfig.cs index ab935bb3..46073eb8 100644 --- a/src/SMAPI.Web/Framework/ConfigModels/ModUpdateCheckConfig.cs +++ b/src/SMAPI.Web/Framework/ConfigModels/ModUpdateCheckConfig.cs @@ -11,8 +11,5 @@ namespace StardewModdingAPI.Web.Framework.ConfigModels /// The number of minutes failed update checks should be cached before refetching them. public int ErrorCacheMinutes { get; set; } - - /// The web URL for the wiki compatibility list. - public string CompatibilityPageUrl { get; set; } } } diff --git a/src/SMAPI.Web/Framework/ConfigModels/SiteConfig.cs b/src/SMAPI.Web/Framework/ConfigModels/SiteConfig.cs index bc6e868a..d379c423 100644 --- a/src/SMAPI.Web/Framework/ConfigModels/SiteConfig.cs +++ b/src/SMAPI.Web/Framework/ConfigModels/SiteConfig.cs @@ -6,18 +6,6 @@ namespace StardewModdingAPI.Web.Framework.ConfigModels /********* ** Accessors *********/ - /// The root URL for the app. - public string RootUrl { get; set; } - - /// The root URL for the log parser. - public string LogParserUrl { get; set; } - - /// The root URL for the JSON validator. - public string JsonValidatorUrl { get; set; } - - /// The root URL for the mod list. - public string ModListUrl { get; set; } - /// Whether to show SMAPI beta versions on the main page, if any. public bool BetaEnabled { get; set; } diff --git a/src/SMAPI.Web/Framework/RewriteRules/ConditionalRewriteSubdomainRule.cs b/src/SMAPI.Web/Framework/RewriteRules/ConditionalRewriteSubdomainRule.cs deleted file mode 100644 index 920632ab..00000000 --- a/src/SMAPI.Web/Framework/RewriteRules/ConditionalRewriteSubdomainRule.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Rewrite; - -namespace StardewModdingAPI.Web.Framework.RewriteRules -{ - /// Rewrite requests to prepend the subdomain portion (if any) to the path. - /// Derived from . - internal class ConditionalRewriteSubdomainRule : IRule - { - /********* - ** Accessors - *********/ - /// A predicate which indicates when the rule should be applied. - private readonly Func ShouldRewrite; - - - /********* - ** Public methods - *********/ - /// Construct an instance. - /// A predicate which indicates when the rule should be applied. - public ConditionalRewriteSubdomainRule(Func shouldRewrite = null) - { - this.ShouldRewrite = shouldRewrite ?? (req => true); - } - - /// Applies the rule. Implementations of ApplyRule should set the value for (defaults to RuleResult.ContinueRules). - /// The rewrite context. - public void ApplyRule(RewriteContext context) - { - HttpRequest request = context.HttpContext.Request; - - // check condition - if (!this.ShouldRewrite(request)) - return; - - // get host parts - string host = request.Host.Host; - string[] parts = host.Split('.'); - if (parts.Length < 2) - return; - - // prepend to path - request.Path = $"/{parts[0]}{request.Path}"; - } - } -} diff --git a/src/SMAPI.Web/Startup.cs b/src/SMAPI.Web/Startup.cs index fc6161b5..53823771 100644 --- a/src/SMAPI.Web/Startup.cs +++ b/src/SMAPI.Web/Startup.cs @@ -48,7 +48,7 @@ namespace StardewModdingAPI.Web .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) - .Add(new BeanstalkEnvPropsConfigProvider()) + .AddEnvironmentVariables() .Build(); } @@ -173,8 +173,7 @@ namespace StardewModdingAPI.Web .UseCors(policy => policy .AllowAnyHeader() .AllowAnyMethod() - .WithOrigins("https://smapi.io", "https://*.smapi.io", "https://*.edge.smapi.io") - .SetIsOriginAllowedToAllowWildcardSubdomains() + .WithOrigins("https://smapi.io") ) .UseRewriter(this.GetRedirectRules()) .UseStaticFiles() // wwwroot folder @@ -202,23 +201,13 @@ namespace StardewModdingAPI.Web shouldRewrite: req => req.Host.Host != "localhost" && !req.Path.StartsWithSegments("/api") - && !req.Host.Host.StartsWith("api.") - )); - - // convert subdomain.smapi.io => smapi.io/subdomain for routing - redirects.Add(new ConditionalRewriteSubdomainRule( - shouldRewrite: req => - req.Host.Host != "localhost" - && (req.Host.Host.StartsWith("api.") || req.Host.Host.StartsWith("json.") || req.Host.Host.StartsWith("log.") || req.Host.Host.StartsWith("mods.")) - && !req.Path.StartsWithSegments("/content") - && !req.Path.StartsWithSegments("/favicon.ico") )); // shortcut redirects redirects.Add(new RedirectToUrlRule(@"^/3\.0\.?$", "https://stardewvalleywiki.com/Modding:Migrate_to_SMAPI_3.0")); redirects.Add(new RedirectToUrlRule(@"^/(?:buildmsg|package)(?:/?(.*))$", "https://github.com/Pathoschild/SMAPI/blob/develop/docs/technical/mod-package.md#$1")); // buildmsg deprecated, remove when SDV 1.4 is released redirects.Add(new RedirectToUrlRule(@"^/community\.?$", "https://stardewvalleywiki.com/Modding:Community")); - redirects.Add(new RedirectToUrlRule(@"^/compat\.?$", "https://mods.smapi.io")); + redirects.Add(new RedirectToUrlRule(@"^/compat\.?$", "https://smapi.io/mods")); redirects.Add(new RedirectToUrlRule(@"^/docs\.?$", "https://stardewvalleywiki.com/Modding:Index")); redirects.Add(new RedirectToUrlRule(@"^/install\.?$", "https://stardewvalleywiki.com/Modding:Player_Guide/Getting_Started#Install_SMAPI")); redirects.Add(new RedirectToUrlRule(@"^/troubleshoot(.*)$", "https://stardewvalleywiki.com/Modding:Player_Guide/Troubleshooting$1")); diff --git a/src/SMAPI.Web/ViewModels/JsonValidator/JsonValidatorModel.cs b/src/SMAPI.Web/ViewModels/JsonValidator/JsonValidatorModel.cs index 2d13bf23..5b18331f 100644 --- a/src/SMAPI.Web/ViewModels/JsonValidator/JsonValidatorModel.cs +++ b/src/SMAPI.Web/ViewModels/JsonValidator/JsonValidatorModel.cs @@ -9,9 +9,6 @@ namespace StardewModdingAPI.Web.ViewModels.JsonValidator /********* ** Accessors *********/ - /// The root URL for the log parser controller. - public string SectionUrl { get; set; } - /// The paste ID. public string PasteID { get; set; } @@ -44,13 +41,11 @@ namespace StardewModdingAPI.Web.ViewModels.JsonValidator public JsonValidatorModel() { } /// Construct an instance. - /// The root URL for the log parser controller. /// The paste ID. /// The schema name with which the JSON was validated. /// The supported JSON schemas (names indexed by ID). - public JsonValidatorModel(string sectionUrl, string pasteID, string schemaName, IDictionary schemaFormats) + public JsonValidatorModel(string pasteID, string schemaName, IDictionary schemaFormats) { - this.SectionUrl = sectionUrl; this.PasteID = pasteID; this.SchemaName = schemaName; this.SchemaFormats = schemaFormats; diff --git a/src/SMAPI.Web/ViewModels/LogParserModel.cs b/src/SMAPI.Web/ViewModels/LogParserModel.cs index b06b5b2d..bea79eae 100644 --- a/src/SMAPI.Web/ViewModels/LogParserModel.cs +++ b/src/SMAPI.Web/ViewModel