using JSMR.Infrastructure.Common.Locales; using JSMR.Infrastructure.Common.SupportedLanguages; namespace JSMR.Infrastructure.Scanning; public class DLSiteSearchFilterBuilder { private readonly List _optionsAnd = []; private readonly List _optionsNot = []; private readonly List _excludedMakers = []; private ILocale _locale = new JapaneseLocale(); 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(ILocale locale) { _locale = locale; return this; } public DLSiteSearchFilterBuilder IncludeSupportedLanguages(ISupportedLanguage[] languages) { foreach (ISupportedLanguage language in languages) { IncludeSupportedLanguage(language); } return this; } public DLSiteSearchFilterBuilder IncludeSupportedLanguage(ISupportedLanguage 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) { ILocale locale = _locale ?? new JapaneseLocale(); using (var writer = new StringWriter()) { writer.Write($"https://www.dlsite.com/maniax/"); writer.Write($"fsr/=/language/{locale.Abbreviation}/"); 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={locale.Code}"); return writer.ToString(); } } }