This repository has been archived on 2024-12-22. You can view files and clone it, but cannot push or open issues or pull requests.
elliebot/src/EllieBot/Services/Impl/LocalDataCache.cs
2024-06-18 23:46:10 +12:00

108 lines
No EOL
3.8 KiB
C#

using EllieBot.Common.Pokemon;
using EllieBot.Modules.Games.Common.Trivia;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace EllieBot.Services;
public sealed class LocalDataCache : ILocalDataCache, IEService
{
private const string POKEMON_ABILITIES_FILE = "data/pokemon/pokemon_abilities.json";
private const string POKEMON_LIST_FILE = "data/pokemon/pokemon_list.json";
private const string POKEMON_MAP_PATH = "data/pokemon/name-id_map.json";
private const string QUESTIONS_FILE = "data/trivia_questions.json";
private readonly IBotCache _cache;
private readonly JsonSerializerOptions _opts = new JsonSerializerOptions()
{
AllowTrailingCommas = true,
NumberHandling = JsonNumberHandling.AllowReadingFromString,
PropertyNameCaseInsensitive = true
};
public LocalDataCache(IBotCache cache)
=> _cache = cache;
private async Task<T?> GetOrCreateCachedDataAsync<T>(
TypedKey<T> key,
string fileName)
=> await _cache.GetOrAddAsync(key,
async () =>
{
if (!File.Exists(fileName))
{
Log.Warning($"{fileName} is missing. Relevant data can't be loaded");
return default;
}
try
{
await using var stream = File.OpenRead(fileName);
return await JsonSerializer.DeserializeAsync<T>(stream, _opts);
}
catch (Exception ex)
{
Log.Error(ex,
"Error reading {FileName} file: {ErrorMessage}",
fileName,
ex.Message);
return default;
}
});
private static TypedKey<IReadOnlyDictionary<string, SearchPokemon>> _pokemonListKey
= new("pokemon:list");
public async Task<IReadOnlyDictionary<string, SearchPokemon>?> GetPokemonsAsync()
=> await GetOrCreateCachedDataAsync(_pokemonListKey, POKEMON_LIST_FILE);
private static TypedKey<IReadOnlyDictionary<string, SearchPokemonAbility>> _pokemonAbilitiesKey
= new("pokemon:abilities");
public async Task<IReadOnlyDictionary<string, SearchPokemonAbility>?> GetPokemonAbilitiesAsync()
=> await GetOrCreateCachedDataAsync(_pokemonAbilitiesKey, POKEMON_ABILITIES_FILE);
private static TypedKey<IReadOnlyDictionary<int, string>> _pokeMapKey
= new("pokemon:ab_map2"); // 2 because ab_map was storing arrays
public async Task<IReadOnlyDictionary<int, string>?> GetPokemonMapAsync()
=> await _cache.GetOrAddAsync(_pokeMapKey,
async () =>
{
var fileName = POKEMON_MAP_PATH;
if (!File.Exists(fileName))
{
Log.Warning($"{fileName} is missing. Relevant data can't be loaded");
return default;
}
try
{
await using var stream = File.OpenRead(fileName);
var arr = await JsonSerializer.DeserializeAsync<PokemonNameId[]>(stream, _opts);
return (IReadOnlyDictionary<int, string>?)arr?.ToDictionary(x => x.Id, x => x.Name);
}
catch (Exception ex)
{
Log.Error(ex,
"Error reading {FileName} file: {ErrorMessage}",
fileName,
ex.Message);
return default;
}
});
private static TypedKey<TriviaQuestionModel[]> _triviaKey
= new("trivia:questions");
public async Task<TriviaQuestionModel[]?> GetTriviaQuestionsAsync()
=> await GetOrCreateCachedDataAsync(_triviaKey, QUESTIONS_FILE);
}