Added and applied styles for private readonly fields, private fields to Extensions and Common folders.

- Some renamings and code cleanups
- Chained method calls, binary expressions and binary patterns will now break into newlines
- Type param constraints and base constructor calls will be on the new line
This commit is contained in:
Kwoth
2021-12-27 03:46:30 +01:00
parent 9ae030a5c5
commit 1b0392dfab
85 changed files with 1015 additions and 906 deletions

View File

@@ -7,16 +7,16 @@ namespace NadekoBot.Services;
public sealed class RedisImagesCache : IImageCache, IReadyExecutor
{
private readonly ConnectionMultiplexer _con;
private readonly IBotCredentials _creds;
private readonly HttpClient _http;
private readonly string _imagesPath;
private IDatabase _db => _con.GetDatabase();
private IDatabase Db
=> _con.GetDatabase();
private const string _basePath = "data/";
private const string _cardsPath = $"{_basePath}images/cards";
private const string BASE_PATH = "data/";
private const string CARDS_PATH = $"{BASE_PATH}images/cards";
public ImageUrls ImageUrls { get; private set; }
@@ -35,42 +35,42 @@ public sealed class RedisImagesCache : IImageCache, IReadyExecutor
XpBg
}
public IReadOnlyList<byte[]> Heads
public IReadOnlyList<byte[]> Heads
=> GetByteArrayData(ImageKeys.CoinHeads);
public IReadOnlyList<byte[]> Tails
public IReadOnlyList<byte[]> Tails
=> GetByteArrayData(ImageKeys.CoinTails);
public IReadOnlyList<byte[]> Dice
public IReadOnlyList<byte[]> Dice
=> GetByteArrayData(ImageKeys.Dice);
public IReadOnlyList<byte[]> SlotEmojis
public IReadOnlyList<byte[]> SlotEmojis
=> GetByteArrayData(ImageKeys.SlotEmojis);
public IReadOnlyList<byte[]> Currency
public IReadOnlyList<byte[]> Currency
=> GetByteArrayData(ImageKeys.Currency);
public byte[] SlotBackground
public byte[] SlotBackground
=> GetByteData(ImageKeys.SlotBg);
public byte[] RategirlMatrix
public byte[] RategirlMatrix
=> GetByteData(ImageKeys.RategirlMatrix);
public byte[] RategirlDot
public byte[] RategirlDot
=> GetByteData(ImageKeys.RategirlDot);
public byte[] XpBackground
public byte[] XpBackground
=> GetByteData(ImageKeys.XpBg);
public byte[] Rip
public byte[] Rip
=> GetByteData(ImageKeys.RipBg);
public byte[] RipOverlay
public byte[] RipOverlay
=> GetByteData(ImageKeys.RipOverlay);
public byte[] GetCard(string key)
// since cards are always local for now, don't cache them
=> File.ReadAllBytes(Path.Join(_cardsPath, key + ".jpg"));
=> File.ReadAllBytes(Path.Join(CARDS_PATH, key + ".jpg"));
public async Task OnReadyAsync()
{
@@ -85,7 +85,7 @@ public sealed class RedisImagesCache : IImageCache, IReadyExecutor
_con = con;
_creds = creds;
_http = new();
_imagesPath = Path.Combine(_basePath, "images.yml");
_imagesPath = Path.Combine(BASE_PATH, "images.yml");
Migrate();
@@ -95,58 +95,50 @@ public sealed class RedisImagesCache : IImageCache, IReadyExecutor
private void Migrate()
{
// migrate to yml
if (File.Exists(Path.Combine(_basePath, "images.json")))
if (File.Exists(Path.Combine(BASE_PATH, "images.json")))
{
var oldFilePath = Path.Combine(_basePath, "images.json");
var backupFilePath = Path.Combine(_basePath, "images.json.backup");
var oldData = JsonConvert.DeserializeObject<OldImageUrls>(
File.ReadAllText(oldFilePath));
var oldFilePath = Path.Combine(BASE_PATH, "images.json");
var backupFilePath = Path.Combine(BASE_PATH, "images.json.backup");
var oldData = JsonConvert.DeserializeObject<OldImageUrls>(File.ReadAllText(oldFilePath));
if (oldData is not null)
{
var newData = new ImageUrls()
{
Coins = new()
{
Heads = oldData.Coins.Heads.Length == 1 &&
oldData.Coins.Heads[0].ToString() == "https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/coins/heads.png"
? new[] { new Uri("https://cdn.nadeko.bot/coins/heads3.png") }
: oldData.Coins.Heads,
Tails = oldData.Coins.Tails.Length == 1 &&
oldData.Coins.Tails[0].ToString() == "https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/coins/tails.png"
? new[] { new Uri("https://cdn.nadeko.bot/coins/tails3.png") }
: oldData.Coins.Tails,
},
Coins =
new()
{
Heads = oldData.Coins.Heads.Length == 1 &&
oldData.Coins.Heads[0].ToString() ==
"https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/coins/heads.png"
? new[] { new Uri("https://cdn.nadeko.bot/coins/heads3.png") }
: oldData.Coins.Heads,
Tails = oldData.Coins.Tails.Length == 1 &&
oldData.Coins.Tails[0].ToString() ==
"https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/coins/tails.png"
? new[] { new Uri("https://cdn.nadeko.bot/coins/tails3.png") }
: oldData.Coins.Tails,
},
Dice = oldData.Dice.Map(x => x.ToNewCdn()),
Currency = oldData.Currency.Map(x => x.ToNewCdn()),
Rategirl = new()
{
Dot = oldData.Rategirl.Dot.ToNewCdn(),
Matrix = oldData.Rategirl.Matrix.ToNewCdn()
},
Rip = new()
{
Bg = oldData.Rip.Bg.ToNewCdn(),
Overlay = oldData.Rip.Overlay.ToNewCdn(),
},
Rategirl =
new()
{
Dot = oldData.Rategirl.Dot.ToNewCdn(), Matrix = oldData.Rategirl.Matrix.ToNewCdn()
},
Rip = new() { Bg = oldData.Rip.Bg.ToNewCdn(), Overlay = oldData.Rip.Overlay.ToNewCdn(), },
Slots = new()
{
Bg = new("https://cdn.nadeko.bot/slots/slots_bg.png"),
Emojis = new[]
{
"https://cdn.nadeko.bot/slots/0.png",
"https://cdn.nadeko.bot/slots/1.png",
"https://cdn.nadeko.bot/slots/2.png",
"https://cdn.nadeko.bot/slots/3.png",
"https://cdn.nadeko.bot/slots/4.png",
"https://cdn.nadeko.bot/slots/5.png"
"https://cdn.nadeko.bot/slots/0.png", "https://cdn.nadeko.bot/slots/1.png",
"https://cdn.nadeko.bot/slots/2.png", "https://cdn.nadeko.bot/slots/3.png",
"https://cdn.nadeko.bot/slots/4.png", "https://cdn.nadeko.bot/slots/5.png"
}.Map(x => new Uri(x))
},
Xp = new()
{
Bg = oldData.Xp.Bg.ToNewCdn(),
},
Xp = new() { Bg = oldData.Xp.Bg.ToNewCdn(), },
Version = 2,
};
@@ -216,25 +208,25 @@ public sealed class RedisImagesCache : IImageCache, IReadyExecutor
if (data is null)
return;
await _db.StringSetAsync(GetRedisKey(key), data);
await Db.StringSetAsync(GetRedisKey(key), data);
}
private async Task Load(ImageKeys key, Uri[] uris)
{
await _db.KeyDeleteAsync(GetRedisKey(key));
await Db.KeyDeleteAsync(GetRedisKey(key));
var imageData = await Task.WhenAll(uris.Select(GetImageData));
var vals = imageData
.Where(x => x is not null)
.Select(x => (RedisValue)x)
.ToArray();
var vals = imageData.Where(x => x is not null).Select(x => (RedisValue)x).ToArray();
await Db.ListRightPushAsync(GetRedisKey(key), vals);
await _db.ListRightPushAsync(GetRedisKey(key), vals);
if (uris.Length != vals.Length)
{
Log.Information("{Loaded}/{Max} URIs for the key '{ImageKey}' have been loaded.\n" +
"Some of the supplied URIs are either unavailable or invalid.",
vals.Length, uris.Length, key);
"Some of the supplied URIs are either unavailable or invalid",
vals.Length,
uris.Length,
key
);
}
}
@@ -264,24 +256,23 @@ public sealed class RedisImagesCache : IImageCache, IReadyExecutor
return null;
}
}
private async Task<bool> AllKeysExist()
{
var tasks = await Task.WhenAll(GetAllKeys()
.Select(x => _db.KeyExistsAsync(GetRedisKey(x))));
var tasks = await Task.WhenAll(GetAllKeys().Select(x => Db.KeyExistsAsync(GetRedisKey(x))));
return tasks.All(exist => exist);
}
private IEnumerable<ImageKeys> GetAllKeys() =>
Enum.GetValues<ImageKeys>();
private IEnumerable<ImageKeys> GetAllKeys()
=> Enum.GetValues<ImageKeys>();
private byte[][] GetByteArrayData(ImageKeys key)
=> _db.ListRange(GetRedisKey(key)).Map(x => (byte[])x);
=> Db.ListRange(GetRedisKey(key)).Map(x => (byte[])x);
private byte[] GetByteData(ImageKeys key)
=> _db.StringGet(GetRedisKey(key));
=> Db.StringGet(GetRedisKey(key));
private RedisKey GetRedisKey(ImageKeys key)
private RedisKey GetRedisKey(ImageKeys key)
=> _creds.RedisKey() + "_image_" + key;
}

View File

@@ -10,35 +10,33 @@ public class RedisLocalDataCache : ILocalDataCache
private readonly ConnectionMultiplexer _con;
private readonly IBotCredentials _creds;
private IDatabase _db => _con.GetDatabase();
private const string pokemonAbilitiesFile = "data/pokemon/pokemon_abilities.json";
private const string pokemonListFile = "data/pokemon/pokemon_list.json";
private const string pokemonMapPath = "data/pokemon/name-id_map.json";
private const string questionsFile = "data/trivia_questions.json";
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";
public IReadOnlyDictionary<string, SearchPokemon> Pokemons
{
get => Get<Dictionary<string, SearchPokemon>>("pokemon_list");
private set => Set("pokemon_list", value);
private init => Set("pokemon_list", value);
}
public IReadOnlyDictionary<string, SearchPokemonAbility> PokemonAbilities
{
get => Get<Dictionary<string, SearchPokemonAbility>>("pokemon_abilities");
private set => Set("pokemon_abilities", value);
private init => Set("pokemon_abilities", value);
}
public TriviaQuestion[] TriviaQuestions
{
get => Get<TriviaQuestion[]>("trivia_questions");
private set => Set("trivia_questions", value);
private init => Set("trivia_questions", value);
}
public IReadOnlyDictionary<int, string> PokemonMap
{
get => Get<Dictionary<int, string>>("pokemon_map");
private set => Set("pokemon_map", value);
private init => Set("pokemon_map", value);
}
public RedisLocalDataCache(ConnectionMultiplexer con, IBotCredentials creds, DiscordSocketClient client)
@@ -49,29 +47,33 @@ public class RedisLocalDataCache : ILocalDataCache
if (shardId == 0)
{
if (!File.Exists(pokemonListFile))
if (!File.Exists(POKEMON_LIST_FILE))
{
Log.Warning($"{pokemonListFile} is missing. Pokemon abilities not loaded");
Log.Warning($"{POKEMON_LIST_FILE} is missing. Pokemon abilities not loaded");
}
else
{
Pokemons = JsonConvert.DeserializeObject<Dictionary<string, SearchPokemon>>(File.ReadAllText(pokemonListFile));
Pokemons =
JsonConvert.DeserializeObject<Dictionary<string, SearchPokemon>>(File.ReadAllText(POKEMON_LIST_FILE));
}
if (!File.Exists(pokemonAbilitiesFile))
if (!File.Exists(POKEMON_ABILITIES_FILE))
{
Log.Warning($"{pokemonAbilitiesFile} is missing. Pokemon abilities not loaded.");
Log.Warning($"{POKEMON_ABILITIES_FILE} is missing. Pokemon abilities not loaded.");
}
else
{
PokemonAbilities = JsonConvert.DeserializeObject<Dictionary<string, SearchPokemonAbility>>(File.ReadAllText(pokemonAbilitiesFile));
PokemonAbilities =
JsonConvert.DeserializeObject<Dictionary<string, SearchPokemonAbility>>(
File.ReadAllText(POKEMON_ABILITIES_FILE)
);
}
try
{
TriviaQuestions = JsonConvert.DeserializeObject<TriviaQuestion[]>(File.ReadAllText(questionsFile));
PokemonMap = JsonConvert.DeserializeObject<PokemonNameId[]>(File.ReadAllText(pokemonMapPath))
.ToDictionary(x => x.Id, x => x.Name);
TriviaQuestions = JsonConvert.DeserializeObject<TriviaQuestion[]>(File.ReadAllText(QUESTIONS_FILE));
PokemonMap = JsonConvert.DeserializeObject<PokemonNameId[]>(File.ReadAllText(POKEMON_MAP_PATH))
?.ToDictionary(x => x.Id, x => x.Name) ?? new();
}
catch (Exception ex)
{
@@ -81,9 +83,10 @@ public class RedisLocalDataCache : ILocalDataCache
}
}
private T Get<T>(string key) where T : class
=> JsonConvert.DeserializeObject<T>(_db.StringGet($"{_creds.RedisKey()}_localdata_{key}"));
private T Get<T>(string key)
where T : class
=> JsonConvert.DeserializeObject<T>(_con.GetDatabase().StringGet($"{_creds.RedisKey()}_localdata_{key}"));
private void Set(string key, object obj)
=> _db.StringSet($"{_creds.RedisKey()}_localdata_{key}", JsonConvert.SerializeObject(obj));
=> _con.GetDatabase().StringSet($"{_creds.RedisKey()}_localdata_{key}", JsonConvert.SerializeObject(obj));
}