porn4fans: resolve model/tag names without prefix

This commit is contained in:
Simon
2026-10-17 05:40:28 +00:00
parent 1f95549167
commit 59ea0495a6

View File

@@ -2,6 +2,7 @@ use crate::DbPool;
use crate::api::ClientVersion; use crate::api::ClientVersion;
use crate::providers::{ use crate::providers::{
Provider, report_provider_error, report_provider_error_background, requester_or_default, Provider, report_provider_error, report_provider_error_background, requester_or_default,
probe_first_archive,
}; };
use crate::status::*; use crate::status::*;
use crate::util::cache::VideoCache; use crate::util::cache::VideoCache;
@@ -260,6 +261,34 @@ impl Porn4fansProvider {
Target::Latest Target::Latest
} }
/// A free-form query that names a model or a tag goes to that archive
/// (probed on the site; unknown names 404), else keyword search.
async fn resolve_keyword(&self, query: &str, options: &ServerOptions) -> Option<Target> {
let slug = Self::slugify(query);
if slug.is_empty() {
return None;
}
let candidates = [
Target::Model { slug: slug.clone() },
Target::Tag { slug },
];
let urls: Vec<String> = candidates
.iter()
.map(|t| match t {
Target::Model { slug } => format!("{}/models/{slug}/", self.url),
Target::Tag { slug } => format!("{}/tags/{slug}/", self.url),
_ => String::new(),
})
.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("custom_list_videos")
})
.await?;
candidates.into_iter().nth(index)
}
/// Build the async `get_block` URL plus the Referer to send with it. /// Build the async `get_block` URL plus the Referer to send with it.
fn build_block_url(&self, target: &Target, sort: &str, page: u32) -> (String, String) { fn build_block_url(&self, target: &Target, sort: &str, page: u32) -> (String, String) {
let sort_by = Self::sort_by(sort); let sort_by = Self::sort_by(sort);
@@ -788,7 +817,12 @@ impl Provider for Porn4fansProvider {
options: ServerOptions, options: ServerOptions,
) -> Vec<VideoItem> { ) -> Vec<VideoItem> {
let page = page.parse::<u32>().unwrap_or(1).max(1); let page = page.parse::<u32>().unwrap_or(1).max(1);
let target = self.target_from_request(query.as_deref(), options.categories.as_deref()); let mut target = self.target_from_request(query.as_deref(), options.categories.as_deref());
if let Target::Search { query } = &target {
if let Some(found) = self.resolve_keyword(query, &options).await {
target = found;
}
}
match self match self
.get_videos_for_target(cache, &target, &sort, page, options) .get_videos_for_target(cache, &target, &sort, page, options)