xhamster: resolve pornstar/channel names without prefix
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
use crate::DbPool;
|
use crate::DbPool;
|
||||||
use crate::api::ClientVersion;
|
use crate::api::ClientVersion;
|
||||||
use crate::providers::{Provider, report_provider_error, requester_or_default};
|
use crate::providers::{
|
||||||
|
Provider, probe_first_archive, report_provider_error, requester_or_default, slug_dashed,
|
||||||
|
};
|
||||||
use crate::status::*;
|
use crate::status::*;
|
||||||
use crate::util::cache::VideoCache;
|
use crate::util::cache::VideoCache;
|
||||||
use crate::util::parse_abbreviated_number;
|
use crate::util::parse_abbreviated_number;
|
||||||
@@ -94,6 +96,7 @@ enum Target {
|
|||||||
Search(String),
|
Search(String),
|
||||||
Category(String),
|
Category(String),
|
||||||
Channel(String),
|
Channel(String),
|
||||||
|
Pornstar(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -208,6 +211,7 @@ impl XhamsterProvider {
|
|||||||
}
|
}
|
||||||
Target::Category(slug) => format!("{BASE_URL}/categories/{slug}"),
|
Target::Category(slug) => format!("{BASE_URL}/categories/{slug}"),
|
||||||
Target::Channel(slug) => format!("{BASE_URL}/channels/{slug}"),
|
Target::Channel(slug) => format!("{BASE_URL}/channels/{slug}"),
|
||||||
|
Target::Pornstar(slug) => format!("{BASE_URL}/pornstars/{slug}"),
|
||||||
};
|
};
|
||||||
if page <= 1 {
|
if page <= 1 {
|
||||||
base
|
base
|
||||||
@@ -385,6 +389,7 @@ impl XhamsterProvider {
|
|||||||
match kind.trim().to_ascii_lowercase().as_str() {
|
match kind.trim().to_ascii_lowercase().as_str() {
|
||||||
"cat" | "category" => return Target::Category(slug),
|
"cat" | "category" => return Target::Category(slug),
|
||||||
"channel" | "channels" => return Target::Channel(slug),
|
"channel" | "channels" => return Target::Channel(slug),
|
||||||
|
"pornstar" | "pornstars" | "star" | "model" => return Target::Pornstar(slug),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,6 +406,23 @@ impl XhamsterProvider {
|
|||||||
Target::Search(trimmed.to_string())
|
Target::Search(trimmed.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A free-form query that names a pornstar or a channel goes to that
|
||||||
|
/// archive (probed on the site; unknown names 404), else keyword search.
|
||||||
|
async fn resolve_keyword(query: &str, options: &ServerOptions) -> Option<Target> {
|
||||||
|
let slug = slug_dashed(query);
|
||||||
|
if slug.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let candidates = [Target::Pornstar(slug.clone()), Target::Channel(slug)];
|
||||||
|
let urls: Vec<String> = candidates.iter().map(|t| Self::target_url(t, 1)).collect();
|
||||||
|
let mut requester = requester_or_default(options, CHANNEL_ID, "resolve_keyword");
|
||||||
|
let (index, _) = probe_first_archive(&mut requester, &urls, &format!("{BASE_URL}/"), |body| {
|
||||||
|
body.contains("video-thumb-info__name")
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
candidates.into_iter().nth(index)
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_sort_target(sort: &str) -> Target {
|
fn resolve_sort_target(sort: &str) -> Target {
|
||||||
match sort.trim().to_ascii_lowercase().as_str() {
|
match sort.trim().to_ascii_lowercase().as_str() {
|
||||||
"popular" | "viewed" | "most_viewed" | "mostviewed" => Target::MostViewed,
|
"popular" | "viewed" | "most_viewed" | "mostviewed" => Target::MostViewed,
|
||||||
@@ -472,10 +494,15 @@ impl Provider for XhamsterProvider {
|
|||||||
let page = page.parse::<u16>().unwrap_or(1).max(1);
|
let page = page.parse::<u16>().unwrap_or(1).max(1);
|
||||||
let per_page = per_page.parse::<usize>().unwrap_or(10).clamp(1, 60);
|
let per_page = per_page.parse::<usize>().unwrap_or(10).clamp(1, 60);
|
||||||
|
|
||||||
let target = match query {
|
let mut target = match query {
|
||||||
Some(q) if !q.trim().is_empty() => self.resolve_query_target(q.trim()),
|
Some(q) if !q.trim().is_empty() => self.resolve_query_target(q.trim()),
|
||||||
_ => self.resolve_option_target(&options, &sort),
|
_ => self.resolve_option_target(&options, &sort),
|
||||||
};
|
};
|
||||||
|
if let Target::Search(query) = &target {
|
||||||
|
if let Some(found) = Self::resolve_keyword(query, &options).await {
|
||||||
|
target = found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match self
|
match self
|
||||||
.fetch_target(cache, target, page, per_page, options)
|
.fetch_target(cache, target, page, per_page, options)
|
||||||
|
|||||||
Reference in New Issue
Block a user