freejse searches
This commit is contained in:
@@ -9,10 +9,10 @@ use crate::videos::{ServerOptions, VideoFormat, VideoItem};
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use error_chain::error_chain;
|
use error_chain::error_chain;
|
||||||
use htmlentity::entity::{ICodedDataTrait, decode};
|
use htmlentity::entity::{ICodedDataTrait, decode};
|
||||||
use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode};
|
|
||||||
use scraper::{Html, Selector};
|
use scraper::{Html, Selector};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
use url::form_urlencoded::Serializer;
|
||||||
|
|
||||||
pub const CHANNEL_METADATA: crate::providers::ProviderChannelMetadata =
|
pub const CHANNEL_METADATA: crate::providers::ProviderChannelMetadata =
|
||||||
crate::providers::ProviderChannelMetadata {
|
crate::providers::ProviderChannelMetadata {
|
||||||
@@ -151,19 +151,22 @@ impl FreeusepornProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_list_url(
|
fn append_sort_and_page(&self, base_url: &str, sort: &str, page: u8) -> String {
|
||||||
&self,
|
let mut params = vec![format!("o={}", Self::sort_param(sort))];
|
||||||
sort: &str,
|
if page > 1 {
|
||||||
page: u8,
|
params.push(format!("page={page}"));
|
||||||
query: Option<&str>,
|
}
|
||||||
category: Option<&str>,
|
|
||||||
) -> String {
|
if params.is_empty() {
|
||||||
let path = if let Some(query) = query.map(str::trim).filter(|value| !value.is_empty()) {
|
return base_url.to_string();
|
||||||
format!(
|
}
|
||||||
"/search/videos/{}",
|
|
||||||
utf8_percent_encode(query, NON_ALPHANUMERIC)
|
let separator = if base_url.contains('?') { "&" } else { "?" };
|
||||||
)
|
format!("{base_url}{separator}{}", params.join("&"))
|
||||||
} else if let Some(category) = category
|
}
|
||||||
|
|
||||||
|
fn build_list_url(&self, sort: &str, page: u8, category: Option<&str>) -> String {
|
||||||
|
let path = if let Some(category) = category
|
||||||
.map(str::trim)
|
.map(str::trim)
|
||||||
.filter(|value| !value.is_empty() && *value != "all")
|
.filter(|value| !value.is_empty() && *value != "all")
|
||||||
{
|
{
|
||||||
@@ -172,12 +175,34 @@ impl FreeusepornProvider {
|
|||||||
"/videos".to_string()
|
"/videos".to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut params = vec![format!("o={}", Self::sort_param(sort))];
|
let base_url = format!("{}{}", self.url, path);
|
||||||
if page > 1 {
|
self.append_sort_and_page(&base_url, sort, page)
|
||||||
params.push(format!("page={page}"));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
format!("{}{}?{}", self.url, path, params.join("&"))
|
fn build_search_request_body(query: &str) -> String {
|
||||||
|
let mut serializer = Serializer::new(String::new());
|
||||||
|
serializer.append_pair("search_query", query);
|
||||||
|
serializer.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn resolve_search_url(&self, query: &str, options: &ServerOptions) -> Result<String> {
|
||||||
|
let search_url = format!("{}/search/videos", self.url);
|
||||||
|
let search_body = Self::build_search_request_body(query);
|
||||||
|
let referer = format!("{}/videos", self.url);
|
||||||
|
let mut requester = requester_or_default(options, module_path!(), "missing_requester");
|
||||||
|
let response = requester
|
||||||
|
.post(
|
||||||
|
&search_url,
|
||||||
|
&search_body,
|
||||||
|
vec![
|
||||||
|
("Content-Type", "application/x-www-form-urlencoded"),
|
||||||
|
("Referer", referer.as_str()),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|error| format!("search submit failed url={search_url}; error={error}"))?;
|
||||||
|
|
||||||
|
Ok(response.uri().to_string().trim_end_matches('/').to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_formats(&self, id: &str) -> Vec<VideoFormat> {
|
fn build_formats(&self, id: &str) -> Vec<VideoFormat> {
|
||||||
@@ -380,7 +405,7 @@ impl FreeusepornProvider {
|
|||||||
sort: &str,
|
sort: &str,
|
||||||
options: ServerOptions,
|
options: ServerOptions,
|
||||||
) -> Result<Vec<VideoItem>> {
|
) -> Result<Vec<VideoItem>> {
|
||||||
let url = self.build_list_url(sort, page, None, options.category.as_deref());
|
let url = self.build_list_url(sort, page, options.category.as_deref());
|
||||||
self.fetch_listing(cache, url, options, "get.request").await
|
self.fetch_listing(cache, url, options, "get.request").await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +417,19 @@ impl FreeusepornProvider {
|
|||||||
sort: &str,
|
sort: &str,
|
||||||
options: ServerOptions,
|
options: ServerOptions,
|
||||||
) -> Result<Vec<VideoItem>> {
|
) -> Result<Vec<VideoItem>> {
|
||||||
let url = self.build_list_url(sort, page, Some(query), None);
|
let search_base = match self.resolve_search_url(query, &options).await {
|
||||||
|
Ok(url) => url,
|
||||||
|
Err(error) => {
|
||||||
|
report_provider_error(
|
||||||
|
"freeuseporn",
|
||||||
|
"query.search_submit",
|
||||||
|
&error.to_string(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
return Ok(vec![]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let url = self.append_sort_and_page(&search_base, sort, page);
|
||||||
self.fetch_listing(cache, url, options, "query.request").await
|
self.fetch_listing(cache, url, options, "query.request").await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -464,16 +501,28 @@ mod tests {
|
|||||||
let provider = provider();
|
let provider = provider();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
provider.build_list_url("recent", 1, None, None),
|
provider.build_list_url("recent", 1, None),
|
||||||
"https://www.freeuseporn.com/videos?o=mr"
|
"https://www.freeuseporn.com/videos?o=mr"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
provider.build_list_url("viewed", 2, None, Some("mind-control")),
|
provider.build_list_url("viewed", 2, Some("mind-control")),
|
||||||
"https://www.freeuseporn.com/videos/mind-control?o=mv&page=2"
|
"https://www.freeuseporn.com/videos/mind-control?o=mv&page=2"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
provider.build_list_url("favorites", 3, Some("mind control"), None),
|
provider.append_sort_and_page(
|
||||||
"https://www.freeuseporn.com/search/videos/mind%20control?o=tf&page=3"
|
"https://www.freeuseporn.com/search/videos/Nicole-Kitt",
|
||||||
|
"favorites",
|
||||||
|
3
|
||||||
|
),
|
||||||
|
"https://www.freeuseporn.com/search/videos/Nicole-Kitt?o=tf&page=3"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn builds_search_request_body_with_form_encoding() {
|
||||||
|
assert_eq!(
|
||||||
|
FreeusepornProvider::build_search_request_body("Nicole Kitt & Cory Chase"),
|
||||||
|
"search_query=Nicole+Kitt+%26+Cory+Chase"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -375,7 +375,11 @@ impl Requester {
|
|||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(not(hottub_single_provider), hottub_provider = "hypnotube"))]
|
#[cfg(any(
|
||||||
|
not(hottub_single_provider),
|
||||||
|
hottub_provider = "hypnotube",
|
||||||
|
hottub_provider = "freeuseporn",
|
||||||
|
))]
|
||||||
pub async fn post(
|
pub async fn post(
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &str,
|
url: &str,
|
||||||
|
|||||||
Reference in New Issue
Block a user