public async Task <IEnumerable <ModEntryModel> > PostAsync([FromBody] ModSearchModel model) { if (model?.Mods == null) { return(new ModEntryModel[0]); } // fetch wiki data WikiModEntry[] wikiData = this.WikiCache.GetWikiMods().Select(p => p.GetModel()).ToArray(); IDictionary <string, ModEntryModel> mods = new Dictionary <string, ModEntryModel>(StringComparer.CurrentCultureIgnoreCase); foreach (ModSearchEntryModel mod in model.Mods) { if (string.IsNullOrWhiteSpace(mod.ID)) { continue; } ModEntryModel result = await this.GetModData(mod, wikiData, model.IncludeExtendedMetadata); mods[mod.ID] = result; } // return data return(mods.Values); }
public async Task <IEnumerable <ModEntryModel> > PostAsync([FromBody] ModSearchModel model, [FromRoute] string version) { if (model?.Mods == null) { return(new ModEntryModel[0]); } // fetch wiki data WikiModEntry[] wikiData = this.WikiCache.GetWikiMods().Select(p => p.Data).ToArray(); IDictionary <string, ModEntryModel> mods = new Dictionary <string, ModEntryModel>(StringComparer.CurrentCultureIgnoreCase); foreach (ModSearchEntryModel mod in model.Mods) { if (string.IsNullOrWhiteSpace(mod.ID)) { continue; } ModEntryModel result = await this.GetModData(mod, wikiData, model.IncludeExtendedMetadata, model.ApiVersion); if (!model.IncludeExtendedMetadata && (model.ApiVersion == null || mod.InstalledVersion == null)) { var errors = new List <string>(result.Errors); errors.Add($"This API can't suggest an update because {nameof(model.ApiVersion)} or {nameof(mod.InstalledVersion)} are null, and you didn't specify {nameof(model.IncludeExtendedMetadata)} to get other info. See the SMAPI technical docs for usage."); result.Errors = errors.ToArray(); } mods[mod.ID] = result; } // return data return(mods.Values); }
public async Task <object> PostAsync([FromBody] ModSearchModel model) { // parse request data ISemanticVersion apiVersion = this.GetApiVersion(); ModSearchEntryModel[] searchMods = this.GetSearchMods(model, apiVersion).ToArray(); // fetch wiki data WikiCompatibilityEntry[] wikiData = await this.GetWikiDataAsync(); // fetch data IDictionary <string, ModEntryModel> mods = new Dictionary <string, ModEntryModel>(StringComparer.CurrentCultureIgnoreCase); foreach (ModSearchEntryModel mod in searchMods) { if (string.IsNullOrWhiteSpace(mod.ID)) { continue; } ModEntryModel result = await this.GetModData(mod, wikiData, model.IncludeExtendedMetadata); result.SetBackwardsCompatibility(apiVersion); mods[mod.ID] = result; } // return in expected structure return(apiVersion.IsNewerThan("2.6-beta.18") ? mods.Values : (object)mods); }
/// <summary>Get the mods for which the API should return data.</summary> /// <param name="model">The search model.</param> /// <param name="apiVersion">The requested API version.</param> private IEnumerable <ModSearchEntryModel> GetSearchMods(ModSearchModel model, ISemanticVersion apiVersion) { if (model == null) { yield break; } // yield standard entries if (model.Mods != null) { foreach (ModSearchEntryModel mod in model.Mods) { yield return(mod); } } // yield mod update keys if backwards compatible if (model.ModKeys != null && model.ModKeys.Any() && !apiVersion.IsNewerThan("2.6-beta.17")) { foreach (string updateKey in model.ModKeys.Distinct()) { yield return(new ModSearchEntryModel(updateKey, new[] { updateKey })); } } }
public async Task <IDictionary <string, ModInfoModel> > PostAsync([FromBody] ModSearchModel search) { // parse model bool allowInvalidVersions = search?.AllowInvalidVersions ?? false; string[] modKeys = (search?.ModKeys?.ToArray() ?? new string[0]) .Distinct(StringComparer.CurrentCultureIgnoreCase) .OrderBy(p => p, StringComparer.CurrentCultureIgnoreCase) .ToArray(); // fetch mod info IDictionary <string, ModInfoModel> result = new Dictionary <string, ModInfoModel>(StringComparer.CurrentCultureIgnoreCase); foreach (string modKey in modKeys) { // parse mod key if (!this.TryParseModKey(modKey, out string vendorKey, out string modID)) { result[modKey] = new ModInfoModel("The mod key isn't in a valid format. It should contain the site key and mod ID like 'Nexus:541'."); continue; } // get matching repository if (!this.Repositories.TryGetValue(vendorKey, out IModRepository repository)) { result[modKey] = new ModInfoModel($"There's no mod site with key '{vendorKey}'. Expected one of [{string.Join(", ", this.Repositories.Keys)}]."); continue; } // fetch mod info result[modKey] = await this.Cache.GetOrCreateAsync($"{repository.VendorKey}:{modID}".ToLower(), async entry => { // fetch info ModInfoModel info = await repository.GetModInfoAsync(modID); // validate if (info.Error == null) { if (info.Version == null) { info = new ModInfoModel(name: info.Name, version: info.Version, url: info.Url, error: "Mod has no version number."); } if (!allowInvalidVersions && !Regex.IsMatch(info.Version, this.VersionRegex, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) { info = new ModInfoModel(name: info.Name, version: info.Version, url: info.Url, error: $"Mod has invalid semantic version '{info.Version}'."); } } // cache & return entry.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(info.Error == null ? this.SuccessCacheMinutes : this.ErrorCacheMinutes); return(info); }); } return(result); }
public async Task <IEnumerable <ModEntryModel> > 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 <ModEntryModel>()); }
public async Task <IEnumerable <ModEntryModel> > PostAsync([FromBody] ModSearchModel model, [FromRoute] string version) { if (model?.Mods == null) { return(new ModEntryModel[0]); } bool legacyMode = SemanticVersion.TryParse(version, out ISemanticVersion parsedVersion) && parsedVersion.IsOlderThan("3.0.0-beta.20191109"); // fetch wiki data WikiModEntry[] wikiData = this.WikiCache.GetWikiMods().Select(p => p.GetModel()).ToArray(); IDictionary <string, ModEntryModel> mods = new Dictionary <string, ModEntryModel>(StringComparer.CurrentCultureIgnoreCase); foreach (ModSearchEntryModel mod in model.Mods) { if (string.IsNullOrWhiteSpace(mod.ID)) { continue; } ModEntryModel result = await this.GetModData(mod, wikiData, model.IncludeExtendedMetadata || legacyMode, model.ApiVersion); if (legacyMode) { result.Main = result.Metadata.Main; result.Optional = result.Metadata.Optional; result.Unofficial = result.Metadata.Unofficial; result.UnofficialForBeta = result.Metadata.UnofficialForBeta; result.HasBetaInfo = result.Metadata.BetaCompatibilityStatus != null; result.SuggestedUpdate = null; if (!model.IncludeExtendedMetadata) { result.Metadata = null; } } else if (!model.IncludeExtendedMetadata && (model.ApiVersion == null || mod.InstalledVersion == null)) { var errors = new List <string>(result.Errors); errors.Add($"This API can't suggest an update because {nameof(model.ApiVersion)} or {nameof(mod.InstalledVersion)} are null, and you didn't specify {nameof(model.IncludeExtendedMetadata)} to get other info. See the SMAPI technical docs for usage."); result.Errors = errors.ToArray(); } mods[mod.ID] = result; } // return data return(mods.Values); }
public async Task <IEnumerable <ModEntryModel> > PostAsync([FromBody] ModSearchModel model, [FromRoute] string version) { if (model?.Mods == null) { return(Array.Empty <ModEntryModel>()); } ModUpdateCheckConfig config = this.Config.Value; // fetch wiki data WikiModEntry[] wikiData = this.WikiCache.GetWikiMods().Select(p => p.Data).ToArray(); IDictionary <string, ModEntryModel> mods = new Dictionary <string, ModEntryModel>(StringComparer.CurrentCultureIgnoreCase); foreach (ModSearchEntryModel mod in model.Mods) { if (string.IsNullOrWhiteSpace(mod.ID)) { continue; } // special case: if this is an update check for the official SMAPI repo, check the Nexus mod page for beta versions if (mod.ID == config.SmapiInfo.ID && mod.UpdateKeys?.Any(key => key == config.SmapiInfo.DefaultUpdateKey) == true && mod.InstalledVersion?.IsPrerelease() == true) { mod.UpdateKeys = mod.UpdateKeys.Concat(config.SmapiInfo.AddBetaUpdateKeys).ToArray(); } // fetch result ModEntryModel result = await this.GetModData(mod, wikiData, model.IncludeExtendedMetadata, model.ApiVersion); if (!model.IncludeExtendedMetadata && (model.ApiVersion == null || mod.InstalledVersion == null)) { var errors = new List <string>(result.Errors); errors.Add($"This API can't suggest an update because {nameof(model.ApiVersion)} or {nameof(mod.InstalledVersion)} are null, and you didn't specify {nameof(model.IncludeExtendedMetadata)} to get other info. See the SMAPI technical docs for usage."); result.Errors = errors.ToArray(); } mods[mod.ID] = result; } // return data return(mods.Values); }