From edf6732f8e3af51682aa9f42130290e3d39e3e4d Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 17 Oct 2026 06:19:18 +0000 Subject: [PATCH] Query resolution todo, slug helper tests, fix txxx decoder test fixture Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01MUYdCh2nCVsQYgJAT7gwSi --- docs/query-resolution-todo.md | 23 +++++++++++++++++++++++ src/providers/mod.rs | 13 +++++++++++++ src/providers/txxx.rs | 2 +- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/query-resolution-todo.md b/docs/query-resolution-todo.md index 94eda71..cf7f315 100644 --- a/docs/query-resolution-todo.md +++ b/docs/query-resolution-todo.md @@ -17,3 +17,26 @@ Status: `[ ]` open, `[x]` done and verified live (feed of the archive + unknown |---|---|---|---| | [x] | `hooporn` | cat, pornstar, studio | reference implementation | | [x] | `cumlouder` | cat, tag, series, girl | reference implementation (girl page, then tag) | +| [x] | `fullporner` | cat, pornstar | probes `/pornstar/{slug}` (unknown = 404 with a suggestion grid, so status decides); `pornstar:` slug now dashed | +| [x] | `fullpornerorg` | pornstar | probes `/videos/pornstar/{slug}/` (404 for unknown) | +| [x] | `tube8` | tag, cat, channel, pornstar | probes pornstar then channel | +| [x] | `youporn` | tag, channel, pornstar, amateur | probes pornstar, channel, amateur (plus existing background shortcut map) | +| [x] | `porn4fans` | tag, cat, model | probes `/models/{slug}/` then `/tags/{slug}/` (both 404 when unknown) | +| [x] | `xvideos` | tag, cat, uploader/channel/profile | probes `/channels/{slug}/videos/new/0` (JSON; pornstar profiles redirect there). **Also fixed**: the old `channel:`/`uploader:` prefix returned nothing (landing page cards are `/prof-video-click/` links); channels are now read from the JSON video list | +| [x] | `xhamster` | cat, channel | added `Pornstar` target; probes pornstar then channel | +| [x] | `xgroovy` | cat, pornstar, channel | probes pornstar then channel | +| [x] | `thepornbunny` | tag, cat, studio, pornstar | probes pornstar, studio, tag (unknown slugs redirect home: `get_probe` now treats a redirect to another path as a miss) | +| [x] | `pornhub` | channel, pornstar, model, user | background catalogs already matched listed names; unknown names are probed (`pornstar`, `model`, `channels`) and cached in `tag_map` (misses remembered) | +| [x] | `clapdat` | tag, user | probes tag then user | +| [x] | `fikfap` | tag, user | single-word query that is an existing profile (profile endpoint) goes to its posts, empty profile falls back to search | +| [x] | `erome` | uploader, user | single-word query that is an existing `/{name}` with albums goes to the uploader | +| [x] | `redgifs` | tag, user | single-word query that is an existing creator (users endpoint) goes to the creator, empty falls back | +| [x] | `sextb` | (catalog matched) | catalog (actress/studio/genre) match first, then probes `/actress/{slug}` and `/studio/{slug}` for names outside the catalog | +| [x] | `coomer` | u:, @service:user | single-word query that is an existing creator id (`/api/v1/{service}/user/{id}/profile`) goes to the creator. **Also fixed**: creator feeds are a bare JSON array, which the parser rejected (every creator feed was empty) | +| [-] | `ripnsfw`, `hsex`, `omgxxx`, `eporner`, `borntobefuck`, `archivebate` | various | already seamless: bare names match background-loaded creator / studio / tag catalogs (or the whole catalog is filtered client-side) | +| [-] | `perfectgirls`, `okxxx`, `pornhat`, `perverzija`, `porntrex` | sites/models/stars | bare names already resolve through the background-loaded `tag_map`; these clones build their own `wreq` client with no `ServerOptions`, so a live probe needs a separate refactor onto the shared requester | +| [-] | `homoxxx` | models, pornstars, channels, categories, tags | legacy provider (own client, unpaginated archives, no `/models/` index on the site); not worth a probe until it is rewritten | +| [-] | `kwiky`, `animeidhentai`, `hentaitv`, `xnxx`, `blowjobspro`, `txxx` | tag/cat | search already is the entity lookup, or the site has no pornstar/studio archives to probe (txxx: the API rejects `models`/`channels` sections) | +| [-] | `fyptt` | cat | by design: bare category words are common search terms and must not be hijacked | +| [-] | `notfans` | tag, category | tag URLs are hashed ids, so an unknown name cannot be probed; search covers it | +| [-] | `allpornstream`, `jable`, `wowxxx`, `hornyleak`, `hotbunny`, `hentaimama`, `tikporn`, `camsoda` | actor/producer, model, studio, ... | Cloudflare-gated or down from this host (403/522, FlareSolverr wedged), so a probe cannot be verified here; each would add one or two FlareSolverr solves per search. Candidates for the same pattern once checked from the production network | diff --git a/src/providers/mod.rs b/src/providers/mod.rs index 4de9546..3fdc285 100644 --- a/src/providers/mod.rs +++ b/src/providers/mod.rs @@ -1837,3 +1837,16 @@ mod tests { ); } } + +#[cfg(test)] +mod slug_tests { + use super::{slug_dashed, slug_joined}; + + #[test] + fn slugs_names_for_archive_urls() { + assert_eq!(slug_dashed(" Gal Ritchie "), "gal-ritchie"); + assert_eq!(slug_dashed("Mia Khalifa!!"), "mia-khalifa"); + assert_eq!(slug_joined("Family Strokes"), "familystrokes"); + assert_eq!(slug_dashed("???"), ""); + } +} diff --git a/src/providers/txxx.rs b/src/providers/txxx.rs index 6dba0db..1e4dd9c 100644 --- a/src/providers/txxx.rs +++ b/src/providers/txxx.rs @@ -592,7 +592,7 @@ mod tests { #[test] fn decodes_cyrillic_obfuscated_video_url() { - let raw = "L2dldF9maWxlLzI1Lzg2\u{041c}D\u{0415}zNWFkND\u{0415}zODNm\u{041c}zI0ZmJhYjJlZTg3\u{041c}jRkYm\u{041c}zOWNiZTIwNjJl\u{041c}ci8y\u{041c}TgwOD\u{0410}w\u{041c}\u{0421}8y\u{041c}TgwODcwNS8y\u{041c}TgwODcwNV9ocS5tcDQvP2Q9\u{041c}czQ4NSZicj0y\u{041c}TgmdGk9\u{041c}Tc5\u{041c}TY0NjYyOQ~~"; + let raw = "L2dldF9maWxlLzI1Lzg2\u{041c}D\u{0415}zNWFkND\u{0415}zODNm\u{041c}zI0ZmJhYjJlZTg3\u{041c}jRkYm\u{041c}zOWNiZTIwNjJl\u{041c}i8y\u{041c}TgwOD\u{0410}w\u{041c}\u{0421}8y\u{041c}TgwODcwNS8y\u{041c}TgwODcwNV9ocS5tcDQvP2Q9\u{041c}zQ4NSZicj0y\u{041c}TgmdGk9\u{041c}Tc5\u{041c}TY0NjYyOQ~~"; assert_eq!( TxxxProvider::decode_video_url(raw).as_deref(), Some("https://txxx.me/get_file/25/860135ad41383f324fbab2ee8724dbc39cbe2062e2/21808000/21808705/21808705_hq.mp4/?d=3485&br=218&ti=1791646629")