using OakArchive.Models.TcgDex; namespace OakArchive.Services; public interface ITcgDexService { public Task> GetSeries(string language); public Task GetSetsOfSeries(string series, string language); public Task GetSet(string set, string language); public Task GetCard(string set, int id, string language); public Task?> DownloadCardImage(Card card, string language); } public class TcgDexService : ITcgDexService { private readonly HttpClient _httpClient; private readonly IMemoryCacheService _cacheService; private readonly string _baseFolder = Path.Combine(Directory.GetCurrentDirectory(), "Cards"); private readonly SemaphoreSlim _downloadSemaphore = new SemaphoreSlim(3, 3); public TcgDexService(HttpClient httpClient, IMemoryCacheService cacheService) { _httpClient = httpClient; _cacheService = cacheService; } public async Task> GetSeries(string language) { var cacheKey = $"tcgdex_series_{language.ToLower()}"; async Task> FetchFromApi() { var res = await _httpClient.GetFromJsonAsync>($"{language}/series"); return res ?? []; } return await _cacheService.GetOrCreateAsync(cacheKey, FetchFromApi, TimeSpan.FromDays(7)); } public async Task GetSetsOfSeries(string series, string language) { var cacheKey = $"tcgdex_serie_{series.ToLower()}_{language.ToLower()}"; async Task FetchFromApi() { var res = await _httpClient.GetFromJsonAsync($"{language}/series/{series}"); return res; } return await _cacheService.GetOrCreateAsync(cacheKey, FetchFromApi, TimeSpan.FromDays(7)); } public async Task GetSet(string set, string language) { var cacheKey = $"tcgdex_set_{set.ToLower()}_{language.ToLower()}"; async Task FetchFromApi() { var res = await _httpClient.GetFromJsonAsync($"{language}/sets/{set}"); return res; } return await _cacheService.GetOrCreateAsync(cacheKey, FetchFromApi, TimeSpan.FromDays(7)); } public async Task GetCard(string set, int id, string language) { var cacheKey = $"tcgdex_card_{set.ToLower()}_{language.ToLower()}"; async Task FetchFromApi() { var res = await _httpClient.GetFromJsonAsync($"{language}/cards/{set}-{id}"); return res; } return await _cacheService.GetOrCreateAsync(cacheKey, FetchFromApi, TimeSpan.FromDays(7)); } public async Task?> DownloadCardImage(Card card, string language) { var split = card.Id!.Split("-"); var filePath = Path.Combine(_baseFolder, split[0], language,$"{split[1]}.webp"); if (File.Exists(filePath)) { var res = await File.ReadAllBytesAsync(filePath); return Tuple.Create(filePath, res); } await _downloadSemaphore.WaitAsync(); try { var res = await _httpClient.GetByteArrayAsync(card.Image + "/high.webp"); Directory.CreateDirectory(Path.GetDirectoryName(filePath)!); await File.WriteAllBytesAsync(filePath, res); await Task.Delay(200); return Tuple.Create(filePath, res); } finally { _downloadSemaphore.Release(); } } }