Manga search provider updates.

This commit is contained in:
2025-05-25 19:19:45 -04:00
parent 1a752bb57e
commit 648aa95f32
8 changed files with 60 additions and 16 deletions

View File

@@ -0,0 +1,25 @@
using MangaReader.Core.Search;
using MangaReader.Core.Search.MangaDex;
using MangaReader.Core.Search.NatoManga;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
#pragma warning disable IDE0130 // Namespace does not match folder structure
namespace Microsoft.Extensions.DependencyInjection;
#pragma warning restore IDE0130 // Namespace does not match folder structure
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddMangaReader(this IServiceCollection services)
{
services.AddScoped<IMangaSearchProvider, NatoMangaSearchProvider>();
services.AddScoped<IMangaSearchProvider, MangaDexSearchProvider>();
services.AddScoped<IMangaSearchCoordinator, MangaSearchCoordinator>();
return services;
}
}

View File

@@ -0,0 +1,6 @@
namespace MangaReader.Core.Search;
public interface IMangaSearchCoordinator
{
Task<MangaSearchResult[]> SearchAsync(string keyword, CancellationToken cancellationToken);
}

View File

@@ -1,11 +1,6 @@
namespace MangaReader.Core.Search;
public interface IMangaSearchProvider<T>
public interface IMangaSearchProvider
{
Task<MangaSearchResult[]> SearchAsync(string keyword);
}
//public class MangaDexWebSearch : IMangaWebSearch
//{
// // https://api.mangadex.org/manga?title=gal can't be&limit=5
//}
Task<MangaSearchResult[]> SearchAsync(string keyword, CancellationToken cancellationToken);
}

View File

@@ -4,8 +4,14 @@ using System.Text.RegularExpressions;
namespace MangaReader.Core.Search.MangaDex;
public class MangaDexSearchProvider(IHttpService httpService) : MangaSearchProviderBase<MangaDexSearchResult>(httpService)
public partial class MangaDexSearchProvider(IHttpService httpService) : MangaSearchProviderBase<MangaDexSearchResult>(httpService)
{
[GeneratedRegex(@"[^a-z0-9\s-]")]
private static partial Regex InvalidSlugCharactersRegex();
[GeneratedRegex(@"\s+")]
private static partial Regex WhitespaceRegex();
protected override string GetSearchUrl(string keyword)
{
string normalizedKeyword = keyword.ToLowerInvariant().Normalize(NormalizationForm.FormD);
@@ -41,9 +47,9 @@ public class MangaDexSearchProvider(IHttpService httpService) : MangaSearchProvi
// title.ToLowerInvariant().Normalize(NormalizationForm.FormD);
title = title.ToLowerInvariant();
//title = Regex.Replace(title, @"[^a-z0-9\s-]", ""); // remove invalid chars
title = Regex.Replace(title, @"[^a-z0-9\s-]", "-"); // replace invalid chars with dash
title = Regex.Replace(title, @"\s+", "-"); // replace spaces with dash
//title = InvalidSlugCharactersRegex().Replace(title, ""); // remove invalid chars
title = InvalidSlugCharactersRegex().Replace(title, "-"); // replace invalid chars with dash
title = WhitespaceRegex().Replace(title, "-"); // replace spaces with dash
return title.Trim('-');
}

View File

@@ -0,0 +1,12 @@
namespace MangaReader.Core.Search;
public class MangaSearchCoordinator(IEnumerable<IMangaSearchProvider> searchProviders) : IMangaSearchCoordinator
{
public async Task<MangaSearchResult[]> SearchAsync(string keyword, CancellationToken cancellationToken)
{
var searchTasks = searchProviders.Select(searchProvider => searchProvider.SearchAsync(keyword, cancellationToken));
var allResults = await Task.WhenAll(searchTasks);
return [.. allResults.SelectMany(mangaSearchResults => mangaSearchResults)];
}
}

View File

@@ -3,14 +3,14 @@ using System.Text.Json;
namespace MangaReader.Core.Search;
public abstract class MangaSearchProviderBase<T>(IHttpService httpService) : IMangaSearchProvider<T>
public abstract class MangaSearchProviderBase<T>(IHttpService httpService) : IMangaSearchProvider
{
private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
{
PropertyNameCaseInsensitive = true
};
public async Task<MangaSearchResult[]> SearchAsync(string keyword)
public async Task<MangaSearchResult[]> SearchAsync(string keyword, CancellationToken cancellationToken)
{
T? searchResult = await GetSearchResultAsync(keyword);