diff --git a/Totoro.Core/Contracts/IAnimeIdService.cs b/Totoro.Core/Contracts/IAnimeIdService.cs index 489bd8f9..1a90293d 100644 --- a/Totoro.Core/Contracts/IAnimeIdService.cs +++ b/Totoro.Core/Contracts/IAnimeIdService.cs @@ -6,4 +6,5 @@ public interface IAnimeIdService { Task GetId(ListServiceType serviceType, long id); Task GetId(long id); + Task UpdateOfflineMappings(); } diff --git a/Totoro.Core/Services/AnimeIdService.cs b/Totoro.Core/Services/AnimeIdService.cs index 244c1bf2..3d6aedf5 100644 --- a/Totoro.Core/Services/AnimeIdService.cs +++ b/Totoro.Core/Services/AnimeIdService.cs @@ -1,4 +1,6 @@ -using Totoro.Core.Services.Simkl; +using System.Text.Json.Nodes; +using Flurl.Http; +using Totoro.Core.Services.Simkl; namespace Totoro.Core.Services; @@ -6,21 +8,100 @@ public class AnimeIdService : IAnimeIdService { private readonly ISettings _settings; private readonly ISimklService _simklService; + private readonly IKnownFolders _knownFolders; + private readonly IFileService _fileService; + private readonly string _dbUrl = @"https://raw.githubusercontent.com/Fribb/anime-lists/master/anime-offline-database-reduced.json"; + private readonly string _fileName = @"ids.json"; + private readonly List _ids; + private bool _isUpdating; public AnimeIdService(ISettings settings, - ISimklService simklService) + ISimklService simklService, + IKnownFolders knownFolders, + IFileService fileService) { _settings = settings; _simklService = simklService; + _knownFolders = knownFolders; + _fileService = fileService; + + _ids = fileService.Read>(knownFolders.ApplicationData, _fileName) ?? new(); + } + + public async Task GetId(ListServiceType serviceType, long id) + { + if(_isUpdating || _ids.FirstOrDefault(GetSelector(serviceType, id)) is not { } idExtended) + { + return await _simklService.GetId(serviceType, id); + } + + return idExtended; } - public Task GetId(ListServiceType serviceType, long id) + private static Func GetSelector(ListServiceType type, long serviceId) { - return _simklService.GetId(serviceType, id); + return type switch + { + ListServiceType.AniList => (AnimeIdExtended id) => id.AniList == serviceId, + ListServiceType.MyAnimeList => (AnimeIdExtended id) => id.MyAnimeList == serviceId, + ListServiceType.Kitsu => (AnimeIdExtended id) => id.Kitsu == serviceId, + ListServiceType.AniDb => (AnimeIdExtended id) => id.AniDb == serviceId, + _ => (AnimeIdExtended id) => false, + }; } - public Task GetId(long id) + public Task GetId(long id) => GetId(_settings.DefaultListService, id); + + public async Task UpdateOfflineMappings() { - return _simklService.GetId(_settings.DefaultListService, id); + var stream = await _dbUrl.GetStreamAsync(); + var array = JsonNode.Parse(stream).AsArray(); + var keys = new[] + { + "livechart_id", + "anidb_id", + "kitsu_id", + "mal_id", + "anilist_id" + }; + + _isUpdating = true; + _ids.Clear(); + + foreach (var item in array) + { + var id = new AnimeIdExtended(); + var obj = item.AsObject(); + + foreach (var key in keys) + { + if(obj.ContainsKey(key)) + { + var value = obj[key].GetValue(); + switch (key) + { + case "livechart_id": + id.LiveChart = value; + break; + case "anidb_id": + id.AniDb = value; + break; + case "kitsu_id": + id.Kitsu = value; + break; + case "mal_id": + id.MyAnimeList = value; + break; + case "anilist_id": + id.AniList = value; + break; + } + } + } + + _ids.Add(id); + } + _isUpdating = false; + _fileService.Save(_knownFolders.ApplicationData, _fileName, _ids); } } diff --git a/Totoro.Core/Services/FileService.cs b/Totoro.Core/Services/FileService.cs index 20c023d4..4b05691b 100644 --- a/Totoro.Core/Services/FileService.cs +++ b/Totoro.Core/Services/FileService.cs @@ -5,6 +5,11 @@ namespace Totoro.Core.Services; public class FileService : IFileService { + private readonly JsonSerializerSettings _settings = new() + { + DefaultValueHandling = DefaultValueHandling.Ignore + }; + public T Read(string folderPath, string fileName) { var path = Path.Combine(folderPath, fileName); @@ -24,7 +29,7 @@ public void Save(string folderPath, string fileName, T content) Directory.CreateDirectory(folderPath); } - var fileContent = JsonConvert.SerializeObject(content); + var fileContent = JsonConvert.SerializeObject(content, Formatting.Indented, _settings); File.WriteAllText(Path.Combine(folderPath, fileName), fileContent, Encoding.UTF8); } diff --git a/Totoro.WinUI/Views/SettingsSections/AnimePluginsSection.xaml b/Totoro.WinUI/Views/SettingsSections/AnimePluginsSection.xaml index 259ea79a..df49dfa5 100644 --- a/Totoro.WinUI/Views/SettingsSections/AnimePluginsSection.xaml +++ b/Totoro.WinUI/Views/SettingsSections/AnimePluginsSection.xaml @@ -73,6 +73,16 @@ OnContent="On" /> + + + + +