using CVRManager.Models; namespace CVRManager.Services; public record RepoOffer(string Repo, string Asset, List Releases); public class AvailableEntry { public string Key { get; init; } = ""; public HashSet Keys { get; } = new(); public string Name { get; set; } = ""; public CvrmgMod? Cvrmg { get; set; } public List Repos { get; } = new(); } public static class AvailableModsService { public static async Task> BuildAsync( CvrmgService cvrmg, ModImportService importer, IReadOnlyList sources, bool force, Action log, CancellationToken ct) { if (force) importer.Invalidate(); var byKey = new Dictionary(); var entries = new List(); if (sources.Any(s => s.Kind == "cvrmg")) { try { foreach (var m in await cvrmg.GetAllAsync(ct, force)) { var e = new AvailableEntry { Key = CvrmgService.Normalize(m.Name), Name = m.Name, Cvrmg = m }; foreach (var n in new[] { m.Name }.Concat(m.Aliases)) e.Keys.Add(CvrmgService.Normalize(n)); e.Keys.RemoveWhere(k => k.Length == 0); if (e.Keys.Count == 0) continue; entries.Add(e); foreach (var k in e.Keys) byKey.TryAdd(k, e); } } catch (Exception ex) when (ex is not OperationCanceledException) { log($"CVRMG could not be loaded: {ex.Message}"); } } foreach (var src in sources.Where(s => s.Kind == "github" && s.Repo.Length > 0)) { var releases = await importer.ReleasesAsync(src.Repo, log, ct, force); var assets = new Dictionary(); foreach (var r in releases) foreach (var a in r.Assets.Where(a => a.Name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))) assets.TryAdd(CvrmgService.Normalize(Path.GetFileNameWithoutExtension(a.Name)), a.Name); foreach (var (key, asset) in assets) { if (key.Length == 0) continue; if (!byKey.TryGetValue(key, out var entry)) { entry = new AvailableEntry { Key = key, Name = Path.GetFileNameWithoutExtension(asset) }; entry.Keys.Add(key); byKey[key] = entry; entries.Add(entry); } if (entry.Repos.All(o => !o.Repo.Equals(src.Repo, StringComparison.OrdinalIgnoreCase))) entry.Repos.Add(new RepoOffer(src.Repo, asset, ModImportService.FilterReleases(releases, asset))); } } return entries; } }