using JSMR.Application.Enums; using JSMR.Domain.ValueObjects; namespace JSMR.Infrastructure.Scanning; public sealed class DLSiteSearchFilterBuilder { private readonly List _optionsAnd = []; private readonly List _optionsNot = []; private readonly List _excludedMakers = []; private Locale _locale = Locale.Japanese; private void AddToOptionsAnd(string value) { if (_optionsAnd.Contains(value)) return; _optionsAnd.Add(value); } private void AddToOptionsNot(string value) { if (_optionsNot.Contains(value)) return; _optionsNot.Add(value); } public DLSiteSearchFilterBuilder UseLocale(Locale locale) { _locale = locale; return this; } public DLSiteSearchFilterBuilder IncludeSupportedLanguages(SupportedLanguage[] languages) { foreach (SupportedLanguage language in languages) { IncludeSupportedLanguage(language); } return this; } public DLSiteSearchFilterBuilder IncludeSupportedLanguage(SupportedLanguage language) { AddToOptionsAnd(language.Code); return this; } public DLSiteSearchFilterBuilder ExcludeMakers(string[] makerIds) { foreach (var makerId in makerIds) ExcludeMaker(makerId); return this; } public DLSiteSearchFilterBuilder ExcludeMaker(string makerId) { if (string.IsNullOrWhiteSpace(makerId)) return this; string trimmedMakerId = makerId.Trim(); if (_excludedMakers.Contains(trimmedMakerId)) return this; _excludedMakers.Add(trimmedMakerId); return this; } public DLSiteSearchFilterBuilder ExcludePartiallyAIGeneratedWorks() { AddToOptionsNot("AIP"); return this; } public DLSiteSearchFilterBuilder ExcludeAIGeneratedWorks() { AddToOptionsNot("AIG"); return this; } public string BuildSearchQuery(int pageNumber, int pageSize) { var (localeAbbreviation, localeCode) = LocaleMap.Map[_locale]; using (var writer = new StringWriter()) { writer.Write($"https://www.dlsite.com/maniax/"); writer.Write($"fsr/=/language/{localeAbbreviation}/"); writer.Write("sex_category[0]/male/"); writer.Write("ana_flg/all/"); writer.Write("work_category[0]/doujin/"); writer.Write("order[0]/release_d/"); writer.Write("work_type_category[0]/audio/"); writer.Write("work_type_category_name[0]/ボイス・ASMR/"); if (_optionsAnd.Count > 0) { writer.Write("options_and_or/and/"); for (int index = 0; index < _optionsAnd.Count; index++) { writer.Write($"options[{index}]/{_optionsAnd[index]}/"); } } if (_excludedMakers.Count > 0) { List spamMakers = [.. _excludedMakers.Select(x => "-" + x)]; string makerFilterValue = string.Join("+", spamMakers).Trim(); writer.Write($"keyword_maker_name/{makerFilterValue}/"); } for (int index = 0; index < _optionsNot.Count; index++) { writer.Write($"options_not[{index}]/{_optionsNot[index]}/"); } writer.Write($"per_page/{pageSize}/"); writer.Write($"page/{pageNumber}/"); writer.Write("show_type/1/"); writer.Write($"?locale={localeCode}"); return writer.ToString(); } } }