supjav tags-fixes
This commit is contained in:
@@ -13,7 +13,7 @@ use htmlentity::entity::{ICodedDataTrait, decode};
|
||||
use regex::Regex;
|
||||
use scraper::{ElementRef, Html, Selector};
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::process::Command;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::thread;
|
||||
@@ -454,12 +454,54 @@ impl SupjavProvider {
|
||||
Ok(url.to_string())
|
||||
}
|
||||
|
||||
fn match_filter(options: &[FilterOption], query: &str) -> Option<String> {
|
||||
let normalized_query = Self::normalize_title(query);
|
||||
options
|
||||
.iter()
|
||||
.find(|value| Self::normalize_title(&value.title) == normalized_query)
|
||||
.map(|value| value.id.clone())
|
||||
fn extend_filter_lookup(lookup: &mut HashMap<String, String>, options: &[FilterOption]) {
|
||||
for option in options {
|
||||
for key in Self::filter_lookup_keys(option) {
|
||||
lookup.entry(key).or_insert_with(|| option.id.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_filter_lookup(&self) -> HashMap<String, String> {
|
||||
let mut lookup = HashMap::new();
|
||||
|
||||
if let Ok(uploaders) = self.uploaders.read() {
|
||||
Self::extend_filter_lookup(&mut lookup, &uploaders);
|
||||
}
|
||||
if let Ok(stars) = self.stars.read() {
|
||||
Self::extend_filter_lookup(&mut lookup, &stars);
|
||||
}
|
||||
Self::extend_filter_lookup(&mut lookup, &self.categories);
|
||||
if let Ok(tags) = self.tags.read() {
|
||||
Self::extend_filter_lookup(&mut lookup, &tags);
|
||||
}
|
||||
|
||||
lookup
|
||||
}
|
||||
|
||||
fn filter_lookup_keys(option: &FilterOption) -> Vec<String> {
|
||||
let mut keys = vec![Self::normalize_title(&option.title)];
|
||||
|
||||
let slug = option
|
||||
.id
|
||||
.trim_end_matches('/')
|
||||
.rsplit('/')
|
||||
.next()
|
||||
.unwrap_or_default()
|
||||
.trim();
|
||||
if !slug.is_empty() {
|
||||
keys.push(Self::normalize_title(&slug.replace('-', " ")));
|
||||
|
||||
if let Some(base_slug) = slug.strip_suffix("-jav") {
|
||||
if !base_slug.is_empty() {
|
||||
keys.push(Self::normalize_title(&base_slug.replace('-', " ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keys.sort();
|
||||
keys.dedup();
|
||||
keys
|
||||
}
|
||||
|
||||
fn resolve_option_target(&self, options: &ServerOptions) -> Option<String> {
|
||||
@@ -481,23 +523,10 @@ impl SupjavProvider {
|
||||
}
|
||||
|
||||
fn resolve_query_target(&self, query: &str) -> Option<String> {
|
||||
if let Ok(uploaders) = self.uploaders.read() {
|
||||
if let Some(target) = Self::match_filter(&uploaders, query) {
|
||||
return self.normalize_archive_target(&target);
|
||||
}
|
||||
}
|
||||
if let Ok(stars) = self.stars.read() {
|
||||
if let Some(target) = Self::match_filter(&stars, query) {
|
||||
return self.normalize_archive_target(&target);
|
||||
}
|
||||
}
|
||||
if let Ok(tags) = self.tags.read() {
|
||||
if let Some(target) = Self::match_filter(&tags, query) {
|
||||
return self.normalize_archive_target(&target);
|
||||
}
|
||||
}
|
||||
Self::match_filter(&self.categories, query)
|
||||
.and_then(|target| self.normalize_archive_target(&target))
|
||||
let normalized_query = Self::normalize_title(query);
|
||||
self.resolve_filter_lookup()
|
||||
.get(&normalized_query)
|
||||
.and_then(|target| self.normalize_archive_target(target))
|
||||
}
|
||||
|
||||
fn filters_need_loading(&self) -> bool {
|
||||
@@ -1581,7 +1610,7 @@ print(json.dumps({
|
||||
let items = self
|
||||
.fetch_items_for_url(cache, url, sort, per_page_limit)
|
||||
.await?;
|
||||
if exact_target.is_some() || items.len() >= 5 || !items.is_empty() {
|
||||
if !items.is_empty() {
|
||||
return Ok(items);
|
||||
}
|
||||
|
||||
@@ -1647,13 +1676,23 @@ mod tests {
|
||||
fn test_provider() -> SupjavProvider {
|
||||
SupjavProvider {
|
||||
url: BASE_URL.to_string(),
|
||||
categories: vec![FilterOption {
|
||||
id: format!("{BASE_URL}/category/censored-jav"),
|
||||
title: "Censored JAV".to_string(),
|
||||
}],
|
||||
categories: vec![
|
||||
FilterOption {
|
||||
id: format!("{BASE_URL}/category/censored-jav"),
|
||||
title: "Censored JAV".to_string(),
|
||||
},
|
||||
FilterOption {
|
||||
id: format!("{BASE_URL}/category/uncensored-jav"),
|
||||
title: "Uncensored JAV".to_string(),
|
||||
},
|
||||
],
|
||||
tags: Arc::new(RwLock::new(vec![FilterOption {
|
||||
id: "/tag/creampie".to_string(),
|
||||
title: "Creampie".to_string(),
|
||||
},
|
||||
FilterOption {
|
||||
id: "/tag/uncensored-jav".to_string(),
|
||||
title: "Uncensored JAV".to_string(),
|
||||
}])),
|
||||
uploaders: Arc::new(RwLock::new(vec![])),
|
||||
stars: Arc::new(RwLock::new(vec![])),
|
||||
@@ -1666,6 +1705,18 @@ mod tests {
|
||||
assert_eq!(SupjavProvider::strip_count_suffix("Censored JAV"), "Censored JAV");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_lookup_stores_title_and_slug_aliases() {
|
||||
let option = FilterOption {
|
||||
id: format!("{BASE_URL}/category/uncensored-jav"),
|
||||
title: "Uncensored JAV".to_string(),
|
||||
};
|
||||
let keys = SupjavProvider::filter_lookup_keys(&option);
|
||||
|
||||
assert!(keys.iter().any(|value| value == "uncensored jav"));
|
||||
assert!(keys.iter().any(|value| value == "uncensored"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_archive_page_url_with_query() {
|
||||
assert_eq!(
|
||||
@@ -1756,6 +1807,50 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolves_category_queries_with_or_without_jav_suffix() {
|
||||
let provider = test_provider();
|
||||
assert_eq!(
|
||||
provider.resolve_query_target("Uncensored JAV").as_deref(),
|
||||
Some("https://supjav.com/category/uncensored-jav")
|
||||
);
|
||||
assert_eq!(
|
||||
provider.resolve_query_target("Uncensored").as_deref(),
|
||||
Some("https://supjav.com/category/uncensored-jav")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn category_lookup_wins_over_same_named_tag() {
|
||||
let provider = test_provider();
|
||||
let lookup = provider.resolve_filter_lookup();
|
||||
|
||||
assert_eq!(
|
||||
lookup.get("uncensored jav").map(String::as_str),
|
||||
Some("https://supjav.com/category/uncensored-jav")
|
||||
);
|
||||
assert_eq!(
|
||||
lookup.get("uncensored").map(String::as_str),
|
||||
Some("https://supjav.com/category/uncensored-jav")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn item_query_matching_uses_full_query_text() {
|
||||
let mut item = VideoItem::new(
|
||||
"abc".to_string(),
|
||||
"Sample".to_string(),
|
||||
"https://supjav.com/sample".to_string(),
|
||||
CHANNEL_ID.to_string(),
|
||||
String::new(),
|
||||
0,
|
||||
);
|
||||
item.tags = Some(vec!["Uncensored".to_string()]);
|
||||
|
||||
assert!(SupjavProvider::item_matches_query(&item, "Uncensored"));
|
||||
assert!(!SupjavProvider::item_matches_query(&item, "Uncensored JAV"));
|
||||
}
|
||||
|
||||
fn test_db_pool() -> DbPool {
|
||||
let unique = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
|
||||
Reference in New Issue
Block a user