Abstract away cache. 2 implementations: redis and memory

This commit is contained in:
Kwoth
2022-06-23 13:07:45 +00:00
parent 1716c69132
commit 210da263ad
75 changed files with 11525 additions and 1547 deletions

View File

@@ -1,17 +1,15 @@
#nullable disable
using AngleSharp;
using AngleSharp.Html.Dom;
using NadekoBot.Modules.Searches.Common;
using Newtonsoft.Json;
using System.Net.Http.Json;
namespace NadekoBot.Modules.Searches.Services;
public class AnimeSearchService : INService
{
private readonly IDataCache _cache;
private readonly IBotCache _cache;
private readonly IHttpClientFactory _httpFactory;
public AnimeSearchService(IDataCache cache, IHttpClientFactory httpFactory)
public AnimeSearchService(IBotCache cache, IHttpClientFactory httpFactory)
{
_cache = cache;
_httpFactory = httpFactory;
@@ -21,24 +19,25 @@ public class AnimeSearchService : INService
{
if (string.IsNullOrWhiteSpace(query))
throw new ArgumentNullException(nameof(query));
TypedKey<AnimeResult> GetKey(string link)
=> new TypedKey<AnimeResult>($"anime2:{link}");
try
{
var link = "https://aniapi.nadeko.bot/anime/"
+ Uri.EscapeDataString(query.Replace("/", " ", StringComparison.InvariantCulture));
var suffix = Uri.EscapeDataString(query.Replace("/", " ", StringComparison.InvariantCulture));
var link = $"https://aniapi.nadeko.bot/anime/{suffix}";
link = link.ToLowerInvariant();
var (ok, data) = await _cache.TryGetAnimeDataAsync(link);
if (!ok)
var result = await _cache.GetAsync(GetKey(link));
if (!result.TryPickT0(out var data, out _))
{
using (var http = _httpFactory.CreateClient())
{
data = await http.GetStringAsync(link);
}
using var http = _httpFactory.CreateClient();
data = await http.GetFromJsonAsync<AnimeResult>(link);
await _cache.SetAnimeDataAsync(link, data);
await _cache.AddAsync(GetKey(link), data, expiry: TimeSpan.FromHours(12));
}
return JsonConvert.DeserializeObject<AnimeResult>(data);
return data;
}
catch
{
@@ -46,95 +45,31 @@ public class AnimeSearchService : INService
}
}
public async Task<NovelResult> GetNovelData(string query)
{
if (string.IsNullOrWhiteSpace(query))
throw new ArgumentNullException(nameof(query));
query = query.Replace(" ", "-", StringComparison.InvariantCulture);
try
{
var link = "https://www.novelupdates.com/series/"
+ Uri.EscapeDataString(query.Replace(" ", "-").Replace("/", " "));
link = link.ToLowerInvariant();
var (ok, data) = await _cache.TryGetNovelDataAsync(link);
if (!ok)
{
var config = Configuration.Default.WithDefaultLoader();
using var document = await BrowsingContext.New(config).OpenAsync(link);
var imageElem = document.QuerySelector("div.seriesimg > img");
if (imageElem is null)
return null;
var imageUrl = ((IHtmlImageElement)imageElem).Source;
var descElem = document.QuerySelector("div#editdescription > p");
var desc = descElem.InnerHtml;
var genres = document.QuerySelector("div#seriesgenre")
.Children.Select(x => x as IHtmlAnchorElement)
.Where(x => x is not null)
.Select(x => $"[{x.InnerHtml}]({x.Href})")
.ToArray();
var authors = document.QuerySelector("div#showauthors")
.Children.Select(x => x as IHtmlAnchorElement)
.Where(x => x is not null)
.Select(x => $"[{x.InnerHtml}]({x.Href})")
.ToArray();
var score = ((IHtmlSpanElement)document.QuerySelector("h5.seriesother > span.uvotes")).InnerHtml;
var status = document.QuerySelector("div#editstatus").InnerHtml;
var title = document.QuerySelector("div.w-blog-content > div.seriestitlenu").InnerHtml;
var obj = new NovelResult
{
Description = desc,
Authors = authors,
Genres = genres,
ImageUrl = imageUrl,
Link = link,
Score = score,
Status = status,
Title = title
};
await _cache.SetNovelDataAsync(link, JsonConvert.SerializeObject(obj));
return obj;
}
return JsonConvert.DeserializeObject<NovelResult>(data);
}
catch (Exception ex)
{
Log.Error(ex, "Error getting novel data");
return null;
}
}
public async Task<MangaResult> GetMangaData(string query)
{
if (string.IsNullOrWhiteSpace(query))
throw new ArgumentNullException(nameof(query));
TypedKey<MangaResult> GetKey(string link)
=> new TypedKey<MangaResult>($"manga2:{link}");
try
{
var link = "https://aniapi.nadeko.bot/manga/"
+ Uri.EscapeDataString(query.Replace("/", " ", StringComparison.InvariantCulture));
link = link.ToLowerInvariant();
var (ok, data) = await _cache.TryGetAnimeDataAsync(link);
if (!ok)
var result = await _cache.GetAsync(GetKey(link));
if (!result.TryPickT0(out var data, out _))
{
using (var http = _httpFactory.CreateClient())
{
data = await http.GetStringAsync(link);
}
using var http = _httpFactory.CreateClient();
data = await http.GetFromJsonAsync<MangaResult>(link);
await _cache.SetAnimeDataAsync(link, data);
await _cache.AddAsync(GetKey(link), data, expiry: TimeSpan.FromHours(3));
}
return JsonConvert.DeserializeObject<MangaResult>(data);
return data;
}
catch
{