From the 2026-05-21 code-quality sprint (PR A grandfather list, fingerprint `e12f9e5e11985162`).
`build_api_search_url` is duplicated structurally in two extractors:
- `crates/rdlp-extractor/src/extractors/pornhub/search_patterns.rs:20-56`
- `crates/rdlp-extractor/src/extractors/redtube/patterns.rs:50-90`
The functions are structurally identical but use different base URLs and filter sets. Per Sandi Metz / AHA Programming Rule of Three: two instances is "tolerate"; three instances is "extract." Defer the extraction until a third extractor needs the same pattern.
When activated, the work is: extract a shared helper in `crates/rdlp-extractor/src/extractors/common/` (new module) accepting `(base_url, filters: &[(K, V)])` and replace both call sites. Remove the cargo-dupes grandfather entry for fingerprint `e12f9e5e11985162` from `.dupes-ignore.toml` in the same change.
References
- Spec: `docs/superpowers/specs/2026-05-21-code-quality-sprint-design.md` (PR A non-goals + decision log)
- Grandfather entry: `.dupes-ignore.toml` (fingerprint `e12f9e5e11985162`)
From the 2026-05-21 code-quality sprint (PR A grandfather list, fingerprint `e12f9e5e11985162`).
`build_api_search_url` is duplicated structurally in two extractors:
The functions are structurally identical but use different base URLs and filter sets. Per Sandi Metz / AHA Programming Rule of Three: two instances is "tolerate"; three instances is "extract." Defer the extraction until a third extractor needs the same pattern.
When activated, the work is: extract a shared helper in `crates/rdlp-extractor/src/extractors/common/` (new module) accepting `(base_url, filters: &[(K, V)])` and replace both call sites. Remove the cargo-dupes grandfather entry for fingerprint `e12f9e5e11985162` from `.dupes-ignore.toml` in the same change.
References