diff options
10 files changed, 109 insertions, 62 deletions
diff --git a/src/SMAPI.Web/Controllers/ModsApiController.cs b/src/SMAPI.Web/Controllers/ModsApiController.cs index 3d05da16..5ca8c94c 100644 --- a/src/SMAPI.Web/Controllers/ModsApiController.cs +++ b/src/SMAPI.Web/Controllers/ModsApiController.cs @@ -12,6 +12,7 @@ using StardewModdingAPI.Toolkit; using StardewModdingAPI.Toolkit.Framework.Clients.WebApi; using StardewModdingAPI.Toolkit.Framework.Clients.Wiki; using StardewModdingAPI.Toolkit.Framework.ModData; +using StardewModdingAPI.Toolkit.Framework.UpdateData; using StardewModdingAPI.Web.Framework.Clients.Chucklefish; using StardewModdingAPI.Web.Framework.Clients.GitHub; using StardewModdingAPI.Web.Framework.Clients.Nexus; @@ -29,7 +30,7 @@ namespace StardewModdingAPI.Web.Controllers ** Properties *********/ /// <summary>The mod repositories which provide mod metadata.</summary> - private readonly IDictionary<string, IModRepository> Repositories; + private readonly IDictionary<ModRepositoryKey, IModRepository> Repositories; /// <summary>The cache in which to store mod metadata.</summary> private readonly IMemoryCache Cache; @@ -73,11 +74,11 @@ namespace StardewModdingAPI.Web.Controllers this.Repositories = new IModRepository[] { - new ChucklefishRepository(config.ChucklefishKey, chucklefish), - new GitHubRepository(config.GitHubKey, github), - new NexusRepository(config.NexusKey, nexus) + new ChucklefishRepository(chucklefish), + new GitHubRepository(github), + new NexusRepository(nexus) } - .ToDictionary(p => p.VendorKey, StringComparer.CurrentCultureIgnoreCase); + .ToDictionary(p => p.VendorKey); } /// <summary>Fetch version metadata for the given mods.</summary> @@ -189,28 +190,6 @@ namespace StardewModdingAPI.Web.Controllers return result; } - /// <summary>Parse a namespaced mod ID.</summary> - /// <param name="raw">The raw mod ID to parse.</param> - /// <param name="vendorKey">The parsed vendor key.</param> - /// <param name="modID">The parsed mod ID.</param> - /// <returns>Returns whether the value could be parsed.</returns> - private bool TryParseModKey(string raw, out string vendorKey, out string modID) - { - // split parts - string[] parts = raw?.Split(':'); - if (parts == null || parts.Length != 2) - { - vendorKey = null; - modID = null; - return false; - } - - // parse - vendorKey = parts[0].Trim(); - modID = parts[1].Trim(); - return true; - } - /// <summary>Get whether a <paramref name="current"/> version is newer than an <paramref name="other"/> version.</summary> /// <param name="current">The current version.</param> /// <param name="other">The other version.</param> @@ -244,17 +223,18 @@ namespace StardewModdingAPI.Web.Controllers private async Task<ModInfoModel> GetInfoForUpdateKeyAsync(string updateKey) { // parse update key - if (!this.TryParseModKey(updateKey, out string vendorKey, out string modID)) + UpdateKey parsed = UpdateKey.Parse(updateKey); + if (!parsed.LooksValid) return new ModInfoModel($"The update key '{updateKey}' isn't in a valid format. It should contain the site key and mod ID like 'Nexus:541'."); // get matching repository - if (!this.Repositories.TryGetValue(vendorKey, out IModRepository repository)) - return new ModInfoModel($"There's no mod site with key '{vendorKey}'. Expected one of [{string.Join(", ", this.Repositories.Keys)}]."); + if (!this.Repositories.TryGetValue(parsed.Repository, out IModRepository repository)) + return new ModInfoModel($"There's no mod site with key '{parsed.Repository}'. Expected one of [{string.Join(", ", this.Repositories.Keys)}]."); // fetch mod info - return await this.Cache.GetOrCreateAsync($"{repository.VendorKey}:{modID}".ToLower(), async entry => + return await this.Cache.GetOrCreateAsync($"{repository.VendorKey}:{parsed.ID}".ToLower(), async entry => { - ModInfoModel result = await repository.GetModInfoAsync(modID); + ModInfoModel result = await repository.GetModInfoAsync(parsed.ID); if (result.Error != null) { if (result.Version == null) diff --git a/src/SMAPI.Web/Framework/ConfigModels/ModUpdateCheckConfig.cs b/src/SMAPI.Web/Framework/ConfigModels/ModUpdateCheckConfig.cs index ce4f3cb5..5eef7c55 100644 --- a/src/SMAPI.Web/Framework/ConfigModels/ModUpdateCheckConfig.cs +++ b/src/SMAPI.Web/Framework/ConfigModels/ModUpdateCheckConfig.cs @@ -16,15 +16,6 @@ namespace StardewModdingAPI.Web.Framework.ConfigModels /// <remarks>Derived from SMAPI's SemanticVersion implementation.</remarks> public string SemanticVersionRegex { get; set; } - /// <summary>The repository key for the Chucklefish mod site.</summary> - public string ChucklefishKey { get; set; } - - /// <summary>The repository key for Nexus Mods.</summary> - public string GitHubKey { get; set; } - - /// <summary>The repository key for Nexus Mods.</summary> - public string NexusKey { get; set; } - /// <summary>The web URL for the wiki compatibility list.</summary> public string WikiCompatibilityPageUrl { get; set; } } diff --git a/src/SMAPI.Web/Framework/ModRepositories/BaseRepository.cs b/src/SMAPI.Web/Framework/ModRepositories/BaseRepository.cs index 4a4a40cd..94256005 100644 --- a/src/SMAPI.Web/Framework/ModRepositories/BaseRepository.cs +++ b/src/SMAPI.Web/Framework/ModRepositories/BaseRepository.cs @@ -1,6 +1,6 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; -using StardewModdingAPI.Toolkit.Framework.Clients.WebApi; +using StardewModdingAPI.Toolkit.Framework.UpdateData; namespace StardewModdingAPI.Web.Framework.ModRepositories { @@ -10,7 +10,7 @@ namespace StardewModdingAPI.Web.Framework.ModRepositories ** Accessors *********/ /// <summary>The unique key for this vendor.</summary> - public string VendorKey { get; } + public ModRepositoryKey VendorKey { get; } /********* @@ -29,7 +29,7 @@ namespace StardewModdingAPI.Web.Framework.ModRepositories *********/ /// <summary>Construct an instance.</summary> /// <param name="vendorKey">The unique key for this vendor.</param> - protected RepositoryBase(string vendorKey) + protected RepositoryBase(ModRepositoryKey vendorKey) { this.VendorKey = vendorKey; } diff --git a/src/SMAPI.Web/Framework/ModRepositories/ChucklefishRepository.cs b/src/SMAPI.Web/Framework/ModRepositories/ChucklefishRepository.cs index e6074a60..6e2a8814 100644 --- a/src/SMAPI.Web/Framework/ModRepositories/ChucklefishRepository.cs +++ b/src/SMAPI.Web/Framework/ModRepositories/ChucklefishRepository.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using StardewModdingAPI.Toolkit.Framework.Clients.WebApi; +using StardewModdingAPI.Toolkit.Framework.UpdateData; using StardewModdingAPI.Web.Framework.Clients.Chucklefish; namespace StardewModdingAPI.Web.Framework.ModRepositories @@ -19,10 +19,9 @@ namespace StardewModdingAPI.Web.Framework.ModRepositories ** Public methods *********/ /// <summary>Construct an instance.</summary> - /// <param name="vendorKey">The unique key for this vendor.</param> /// <param name="client">The underlying HTTP client.</param> - public ChucklefishRepository(string vendorKey, IChucklefishClient client) - : base(vendorKey) + public ChucklefishRepository(IChucklefishClient client) + : base(ModRepositoryKey.Chucklefish) { this.Client = client; } diff --git a/src/SMAPI.Web/Framework/ModRepositories/GitHubRepository.cs b/src/SMAPI.Web/Framework/ModRepositories/GitHubRepository.cs index 1d7e4fff..7ff22d0e 100644 --- a/src/SMAPI.Web/Framework/ModRepositories/GitHubRepository.cs +++ b/src/SMAPI.Web/Framework/ModRepositories/GitHubRepository.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using StardewModdingAPI.Toolkit.Framework.Clients.WebApi; +using StardewModdingAPI.Toolkit.Framework.UpdateData; using StardewModdingAPI.Web.Framework.Clients.GitHub; namespace StardewModdingAPI.Web.Framework.ModRepositories @@ -19,10 +19,9 @@ namespace StardewModdingAPI.Web.Framework.ModRepositories ** Public methods *********/ /// <summary>Construct an instance.</summary> - /// <param name="vendorKey">The unique key for this vendor.</param> /// <param name="client">The underlying GitHub API client.</param> - public GitHubRepository(string vendorKey, IGitHubClient client) - : base(vendorKey) + public GitHubRepository(IGitHubClient client) + : base(ModRepositoryKey.GitHub) { this.Client = client; } diff --git a/src/SMAPI.Web/Framework/ModRepositories/IModRepository.cs b/src/SMAPI.Web/Framework/ModRepositories/IModRepository.cs index 09c59a86..68f754ae 100644 --- a/src/SMAPI.Web/Framework/ModRepositories/IModRepository.cs +++ b/src/SMAPI.Web/Framework/ModRepositories/IModRepository.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using StardewModdingAPI.Toolkit.Framework.UpdateData; namespace StardewModdingAPI.Web.Framework.ModRepositories { @@ -10,7 +11,7 @@ namespace StardewModdingAPI.Web.Framework.ModRepositories ** Accessors *********/ /// <summary>The unique key for this vendor.</summary> - string VendorKey { get; } + ModRepositoryKey VendorKey { get; } /********* diff --git a/src/SMAPI.Web/Framework/ModRepositories/NexusRepository.cs b/src/SMAPI.Web/Framework/ModRepositories/NexusRepository.cs index 4afcda10..1e242c60 100644 --- a/src/SMAPI.Web/Framework/ModRepositories/NexusRepository.cs +++ b/src/SMAPI.Web/Framework/ModRepositories/NexusRepository.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using StardewModdingAPI.Toolkit.Framework.Clients.WebApi; +using StardewModdingAPI.Toolkit.Framework.UpdateData; using StardewModdingAPI.Web.Framework.Clients.Nexus; namespace StardewModdingAPI.Web.Framework.ModRepositories @@ -19,10 +19,9 @@ namespace StardewModdingAPI.Web.Framework.ModRepositories ** Public methods *********/ /// <summary>Construct an instance.</summary> - /// <param name="vendorKey">The unique key for this vendor.</param> /// <param name="client">The underlying Nexus Mods API client.</param> - public NexusRepository(string vendorKey, INexusClient client) - : base(vendorKey) + public NexusRepository(INexusClient client) + : base(ModRepositoryKey.Nexus) { this.Client = client; } diff --git a/src/SMAPI.Web/appsettings.json b/src/SMAPI.Web/appsettings.json index bd948aa0..2c6aa0cc 100644 --- a/src/SMAPI.Web/appsettings.json +++ b/src/SMAPI.Web/appsettings.json @@ -47,11 +47,6 @@ "SuccessCacheMinutes": 60, "ErrorCacheMinutes": 5, "SemanticVersionRegex": "^(?>(?<major>0|[1-9]\\d*))\\.(?>(?<minor>0|[1-9]\\d*))(?>(?:\\.(?<patch>0|[1-9]\\d*))?)(?:-(?<prerelease>(?>[a-z0-9]+[\\-\\.]?)+))?$", - - "ChucklefishKey": "Chucklefish", - "GitHubKey": "GitHub", - "NexusKey": "Nexus", - "WikiCompatibilityPageUrl": "https://smapi.io/compat" } } diff --git a/src/StardewModdingAPI.Toolkit/Framework/UpdateData/ModRepositoryKey.cs b/src/StardewModdingAPI.Toolkit/Framework/UpdateData/ModRepositoryKey.cs new file mode 100644 index 00000000..7ca32f04 --- /dev/null +++ b/src/StardewModdingAPI.Toolkit/Framework/UpdateData/ModRepositoryKey.cs @@ -0,0 +1,18 @@ +namespace StardewModdingAPI.Toolkit.Framework.UpdateData +{ + /// <summary>A mod repository which SMAPI can check for updates.</summary> + public enum ModRepositoryKey + { + /// <summary>An unknown or invalid mod repository.</summary> + Unknown, + + /// <summary>The Chucklefish mod repository.</summary> + Chucklefish, + + /// <summary>A GitHub project containing releases.</summary> + GitHub, + + /// <summary>The Nexus Mods mod repository.</summary> + Nexus + } +} diff --git a/src/StardewModdingAPI.Toolkit/Framework/UpdateData/UpdateKey.cs b/src/StardewModdingAPI.Toolkit/Framework/UpdateData/UpdateKey.cs new file mode 100644 index 00000000..49b7a272 --- /dev/null +++ b/src/StardewModdingAPI.Toolkit/Framework/UpdateData/UpdateKey.cs @@ -0,0 +1,65 @@ +using System; + +namespace StardewModdingAPI.Toolkit.Framework.UpdateData +{ + /// <summary>A namespaced mod ID which uniquely identifies a mod within a mod repository.</summary> + public class UpdateKey + { + /********* + ** Accessors + *********/ + /// <summary>The raw update key text.</summary> + public string RawText { get; } + + /// <summary>The mod repository containing the mod.</summary> + public ModRepositoryKey Repository { get; } + + /// <summary>The mod ID within the repository.</summary> + public string ID { get; } + + /// <summary>Whether the update key seems to be valid.</summary> + public bool LooksValid { get; } + + + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + /// <param name="rawText">The raw update key text.</param> + /// <param name="repository">The mod repository containing the mod.</param> + /// <param name="id">The mod ID within the repository.</param> + public UpdateKey(string rawText, ModRepositoryKey repository, string id) + { + this.RawText = rawText; + this.Repository = repository; + this.ID = id; + this.LooksValid = + repository != ModRepositoryKey.Unknown + && !string.IsNullOrWhiteSpace(id); + } + + /// <summary>Parse a raw update key.</summary> + /// <param name="raw">The raw update key to parse.</param> + public static UpdateKey Parse(string raw) + { + // split parts + string[] parts = raw?.Split(':'); + if (parts == null || parts.Length != 2) + return new UpdateKey(raw, ModRepositoryKey.Unknown, null); + + // extract parts + string repositoryKey = parts[0].Trim(); + string id = parts[1].Trim(); + if (string.IsNullOrWhiteSpace(id)) + id = null; + + // parse + if (!Enum.TryParse(repositoryKey, true, out ModRepositoryKey repository)) + return new UpdateKey(raw, ModRepositoryKey.Unknown, id); + if (id == null) + return new UpdateKey(raw, repository, null); + + return new UpdateKey(raw, repository, id); + } + } +} |