/// <summary>Get the mod info for an update key.</summary> /// <param name="updateKey">The namespaced update key.</param> private async Task <ModInfoModel> GetInfoForUpdateKeyAsync(string updateKey) { // parse update key 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(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}:{parsed.ID}".ToLower(), async entry => { ModInfoModel result = await repository.GetModInfoAsync(parsed.ID); if (result.Error == null) { if (result.Version == null) { result.Error = $"The update key '{updateKey}' matches a mod with no version number."; } else if (!Regex.IsMatch(result.Version, this.VersionRegex, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) { result.Error = $"The update key '{updateKey}' matches a mod with invalid semantic version '{result.Version}'."; } } entry.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(result.Error == null ? this.SuccessCacheMinutes : this.ErrorCacheMinutes); return result; })); }
/// <summary>Get update keys based on the available mod metadata, while maintaining the precedence order.</summary> /// <param name="specifiedKeys">The specified update keys.</param> /// <param name="record">The mod's entry in SMAPI's internal database.</param> /// <param name="entry">The mod's entry in the wiki list.</param> private IEnumerable <UpdateKey> GetUpdateKeys(string[] specifiedKeys, ModDataRecord record, WikiModEntry entry) { IEnumerable <string> GetRaw() { // specified update keys if (specifiedKeys != null) { foreach (string key in specifiedKeys) { yield return(key?.Trim()); } } // default update key string defaultKey = record?.GetDefaultUpdateKey(); if (defaultKey != null) { yield return(defaultKey); } // wiki metadata if (entry != null) { if (entry.NexusID.HasValue) { yield return($"{ModRepositoryKey.Nexus}:{entry.NexusID}"); } if (entry.ModDropID.HasValue) { yield return($"{ModRepositoryKey.ModDrop}:{entry.ModDropID}"); } if (entry.CurseForgeID.HasValue) { yield return($"{ModRepositoryKey.CurseForge}:{entry.CurseForgeID}"); } if (entry.ChucklefishID.HasValue) { yield return($"{ModRepositoryKey.Chucklefish}:{entry.ChucklefishID}"); } } } HashSet <UpdateKey> seen = new HashSet <UpdateKey>(); foreach (string rawKey in GetRaw()) { if (string.IsNullOrWhiteSpace(rawKey)) { continue; } UpdateKey key = UpdateKey.Parse(rawKey); if (seen.Add(key)) { yield return(key); } } }
/// <inheritdoc /> public IEnumerable <UpdateKey> GetUpdateKeys(bool validOnly = false) { foreach (string rawKey in this.Manifest?.UpdateKeys ?? new string[0]) { UpdateKey updateKey = UpdateKey.Parse(rawKey); if (updateKey.LooksValid || !validOnly) { yield return(updateKey); } } }
/// <inheritdoc /> public IEnumerable <UpdateKey> GetUpdateKeys(bool validOnly = false) { if (!this.HasManifest()) { yield break; } foreach (string rawKey in this.Manifest.UpdateKeys) { UpdateKey updateKey = UpdateKey.Parse(rawKey); if (updateKey.LooksValid || !validOnly) { yield return(updateKey); } } }
/// <summary>Get an update URL for an update key (if valid).</summary> /// <param name="updateKey">The update key.</param> public string GetUpdateUrl(string updateKey) { UpdateKey parsed = UpdateKey.Parse(updateKey); if (!parsed.LooksValid) { return(null); } if (this.VendorModUrls.TryGetValue(parsed.Site, out string urlTemplate)) { return(string.Format(urlTemplate, parsed.ID)); } return(null); }
/// <summary>Get update keys based on the available mod metadata, while maintaining the precedence order.</summary> /// <param name="specifiedKeys">The specified update keys.</param> /// <param name="record">The mod's entry in SMAPI's internal database.</param> /// <param name="entry">The mod's entry in the wiki list.</param> private IEnumerable <UpdateKey> GetUpdateKeys(string[] specifiedKeys, ModDataRecord record, WikiModEntry entry) { // get unique update keys List <UpdateKey> updateKeys = this.GetUnfilteredUpdateKeys(specifiedKeys, record, entry) .Select(UpdateKey.Parse) .Distinct() .ToList(); // apply remove overrides from wiki { var removeKeys = new HashSet <UpdateKey>( from key in entry?.ChangeUpdateKeys ?? new string[0] where key.StartsWith('-') select UpdateKey.Parse(key.Substring(1)) ); if (removeKeys.Any()) { updateKeys.RemoveAll(removeKeys.Contains); } } // if the list has both an update key (like "Nexus:2400") and subkey (like "Nexus:2400@subkey") for the same page, the subkey takes priority { var removeKeys = new HashSet <UpdateKey>(); foreach (var key in updateKeys) { if (key.Subkey != null) { removeKeys.Add(new UpdateKey(key.Site, key.ID, null)); } } if (removeKeys.Any()) { updateKeys.RemoveAll(removeKeys.Contains); } } return(updateKeys); }