From 517617860769e434299b2538ad307fff6a72a2fb Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 10 Oct 2026 09:24:56 +0000 Subject: [PATCH] vjav: fall back to keyword search when an implicit uploader/tag match is empty Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01MUYdCh2nCVsQYgJAT7gwSi --- docs/provider-fix-todo.md | 2 +- src/providers/vjav.rs | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/provider-fix-todo.md b/docs/provider-fix-todo.md index 9c7f487..8839c6b 100644 --- a/docs/provider-fix-todo.md +++ b/docs/provider-fix-todo.md @@ -46,7 +46,7 @@ Status: `[ ]` open, `[~]` in progress, `[x]` fixed and verified, `[-]` not repro | [-] | `fapello` | "girl" and "milf" both 0 | by design, documented in the provider: the site's search returns photo models, not videos; no keyword video search exists, so queries are literal-filtered over the feed | | [x] | `chaturbate` | "girl" and "milf" both 0 | format arguments swapped in the search URL (`girl/api/...?keywords=https://chaturbate.com`, a relative-URL builder error); fixed + unit test. Also stale-cache branch never refreshed. 90 results per query, yt-dlp resolves the live stream | | [x] | `cumlouder` | unknown tag takes 146s before returning 0 | a real 404 went through the requester's Jina/FlareSolverr fallback chain; now the raw response is read, 404 returns empty immediately (0s), 5xx/429 still retried. check.py passes | -| [ ] | `vjav` | "girl" 0, "milf" 10 | may be term-specific | +| [x] | `vjav` | "girl" 0, "milf" 10 | not term-specific: "girl" exactly matches a member username with no uploads, so the implicit uploader match hijacked the keyword search. Empty uploader/tag matches now fall back to keyword search (site API returns 34k results for "girl"). check.py passes | | [ ] | `xxxtik` | "girl" 0 (not re-run serially) | | | [x] | `hypnotube` | "milf" 0, "girl" 20 | same root cause as above (second search on a session returned nothing), not term-specific | diff --git a/src/providers/vjav.rs b/src/providers/vjav.rs index 04711b0..834bf1b 100644 --- a/src/providers/vjav.rs +++ b/src/providers/vjav.rs @@ -1568,11 +1568,28 @@ impl Provider for VjavProvider { .filter(|value| !value.is_empty()) .map(ToOwned::to_owned); let target = self.pick_target(normalized_query.as_deref(), &options).await; + // A generic keyword can exactly match a category or member name + // ("girl" is a member with no uploads), which would hijack the search + // and return nothing. Remember to fall back to keyword search then. + let keyword_fallback = normalized_query + .as_ref() + .filter(|_| matches!(target, Target::Uploader { .. } | Target::Tag { .. })) + .map(|query| Target::Search { + query: query.clone(), + }); - match self + let result = self .fetch_target_items(target, &sort, page, per_page, &options) - .await - { + .await; + let result = match (result, keyword_fallback) { + (Ok(items), Some(fallback)) if items.is_empty() => { + self.fetch_target_items(fallback, &sort, page, per_page, &options) + .await + } + (result, _) => result, + }; + + match result { Ok(items) => items, Err(error) => { report_provider_error(CHANNEL_ID, "get_videos", &error.to_string()).await;