diff --git a/src/providers/sextb.rs b/src/providers/sextb.rs index 7431a93..b71456f 100644 --- a/src/providers/sextb.rs +++ b/src/providers/sextb.rs @@ -1,7 +1,8 @@ use crate::DbPool; use crate::api::ClientVersion; use crate::providers::{ - Provider, report_provider_error, report_provider_error_background, requester_or_default, + Provider, probe_first_archive, report_provider_error, report_provider_error_background, + requester_or_default, }; use crate::status::*; use crate::util::cache::VideoCache; @@ -517,6 +518,28 @@ impl SextbProvider { Target::Search { slug } } + /// A free-form query that names an actress or a studio outside the loaded + /// catalogs goes to that archive (probed on the site), else keyword search. + async fn resolve_keyword(&self, slug: &str, options: &ServerOptions) -> Option { + if slug.is_empty() { + return None; + } + let candidates = [ + Target::Actress { slug: slug.to_string() }, + Target::Studio { slug: slug.to_string() }, + ]; + let urls: Vec = candidates + .iter() + .map(|t| self.build_url_for_target(t, 1)) + .collect(); + let mut requester = requester_or_default(options, CHANNEL_ID, "resolve_keyword"); + let (index, _) = probe_first_archive(&mut requester, &urls, &format!("{}/", self.url), |body| { + body.contains("tray-item") && !body.contains("No Video were found") + }) + .await?; + candidates.into_iter().nth(index) + } + fn build_url_for_target(&self, target: &Target, page: u16) -> String { match target { Target::Section { section, sort } => { @@ -1092,7 +1115,12 @@ impl SextbProvider { per_page_limit: usize, options: ServerOptions, ) -> Result> { - let target = self.resolve_query_target(query, sort); + let mut target = self.resolve_query_target(query, sort); + if let Target::Search { slug } = &target { + if let Some(found) = self.resolve_keyword(slug, &options).await { + target = found; + } + } let url = self.build_url_for_target(&target, page); self.fetch_items_for_url(cache, url, per_page_limit, &options) .await