using MangaReader.Core.HttpService; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Text.Json; using System.Text.RegularExpressions; namespace MangaReader.Core.Sources.NatoManga.Api; public interface INatoMangaClient { Task SearchAsync(string searchWord, CancellationToken cancellationToken); } public partial class NatoMangaClient(IHttpService httpService) : INatoMangaClient { [GeneratedRegex(@"[^a-z0-9]+")] private static partial Regex NonAlphaNumericCharactersRegex(); [GeneratedRegex("_{2,}")] private static partial Regex ExtendedUnderscoresRegex(); private static readonly JsonSerializerOptions _jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; public async Task SearchAsync(string searchWord, CancellationToken cancellationToken) { string formattedSearchWord = GetFormattedSearchWord(searchWord); string url = $"https://www.natomanga.com/home/search/json?searchword={formattedSearchWord}"; string response = await httpService.GetStringAsync(url, cancellationToken); return JsonSerializer.Deserialize(response, _jsonSerializerOptions) ?? []; } protected string GetSearchUrl(string keyword) { string formattedSeachWord = GetFormattedSearchWord(keyword); return $"https://www.natomanga.com/home/search/json?searchword={formattedSeachWord}"; } private static string GetFormattedSearchWord(string input) { if (string.IsNullOrWhiteSpace(input)) return string.Empty; // Convert to lowercase and normalize to decompose accents string normalized = input.ToLowerInvariant() .Normalize(NormalizationForm.FormD); // Remove diacritics var sb = new StringBuilder(); foreach (var c in normalized) { var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c); if (unicodeCategory != UnicodeCategory.NonSpacingMark) sb.Append(c); } // Replace non-alphanumeric characters with underscores string cleaned = NonAlphaNumericCharactersRegex().Replace(sb.ToString(), "_"); // Trim and collapse underscores cleaned = ExtendedUnderscoresRegex().Replace(cleaned, "_").Trim('_'); return cleaned; } }