using System; using System.Linq; using System.Text.RegularExpressions; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using StardewModdingAPI.Web.Framework.Caching; using StardewModdingAPI.Web.Framework.Caching.Wiki; using StardewModdingAPI.Web.Framework.ConfigModels; using StardewModdingAPI.Web.ViewModels; namespace StardewModdingAPI.Web.Controllers { /// Provides user-friendly info about SMAPI mods. internal class ModsController : Controller { /********* ** Fields *********/ /// The cache in which to store mod metadata. private readonly IWikiCacheRepository Cache; /// The number of minutes before which wiki data should be considered old. private readonly int StaleMinutes; /********* ** Public methods *********/ /// Construct an instance. /// The cache in which to store mod metadata. /// The config settings for mod update checks. public ModsController(IWikiCacheRepository cache, IOptions configProvider) { ModCompatibilityListConfig config = configProvider.Value; this.Cache = cache; this.StaleMinutes = config.StaleMinutes; } /// Display information for all mods. [HttpGet] [Route("mods")] public ViewResult Index() { return this.View("Index", this.FetchData()); } /********* ** Private methods *********/ /// Asynchronously fetch mod metadata from the wiki. public ModListModel FetchData() { // fetch cached data if (!this.Cache.TryGetWikiMetadata(out Cached? metadata)) return new ModListModel(null, null, Array.Empty(), lastUpdated: DateTimeOffset.UtcNow, isStale: true); // build model return new ModListModel( stableVersion: metadata.Data.StableVersion, betaVersion: metadata.Data.BetaVersion, mods: this.Cache .GetWikiMods() .Select(mod => new ModModel(mod.Data)) .OrderBy(p => Regex.Replace((p.Name ?? "").ToLower(), "[^a-z0-9]", "")), // ignore case, spaces, and special characters when sorting lastUpdated: metadata.LastUpdated, isStale: this.Cache.IsStale(metadata.LastUpdated, this.StaleMinutes) ); } } }