melonstube fix
This commit is contained in:
@@ -10,9 +10,9 @@ use async_trait::async_trait;
|
||||
use base64::{Engine as _, engine::general_purpose::STANDARD};
|
||||
use chrono::{Duration as ChronoDuration, Utc};
|
||||
use error_chain::error_chain;
|
||||
use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode};
|
||||
use regex::Regex;
|
||||
use scraper::{Html, Selector};
|
||||
use url::form_urlencoded::Serializer;
|
||||
|
||||
pub const CHANNEL_METADATA: crate::providers::ProviderChannelMetadata =
|
||||
crate::providers::ProviderChannelMetadata {
|
||||
@@ -118,14 +118,9 @@ impl MelonstubeProvider {
|
||||
format!("{BASE_URL}/rating")
|
||||
}
|
||||
}
|
||||
Target::Search { query, page } => {
|
||||
let encoded = utf8_percent_encode(query, NON_ALPHANUMERIC).to_string();
|
||||
if *page > 1 {
|
||||
format!("{BASE_URL}/search?q={encoded}&page={page}")
|
||||
} else {
|
||||
format!("{BASE_URL}/search?q={encoded}")
|
||||
}
|
||||
}
|
||||
Target::Search { .. } => unreachable!(
|
||||
"Target::Search is resolved asynchronously via resolve_search_base_url"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,13 +381,58 @@ impl MelonstubeProvider {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_search_request_body(query: &str) -> String {
|
||||
let mut serializer = Serializer::new(String::new());
|
||||
serializer.append_pair("search_query[query]", query);
|
||||
serializer.finish()
|
||||
}
|
||||
|
||||
async fn resolve_search_base_url(query: &str, options: &ServerOptions) -> Result<String> {
|
||||
let search_url = format!("{BASE_URL}/searching/by-form");
|
||||
let body = Self::build_search_request_body(query);
|
||||
|
||||
let mut requester = requester_or_default(options, CHANNEL_ID, "resolve_search_base_url");
|
||||
|
||||
let response = requester
|
||||
.post(
|
||||
&search_url,
|
||||
&body,
|
||||
vec![
|
||||
("Content-Type", "application/x-www-form-urlencoded"),
|
||||
("Referer", BASE_URL),
|
||||
("User-Agent", BROWSER_UA),
|
||||
],
|
||||
)
|
||||
.await
|
||||
.map_err(|e| Error::from(format!("search submit failed url={search_url}: {e}")))?;
|
||||
|
||||
Ok(response.url().to_string().trim_end_matches('/').to_string())
|
||||
}
|
||||
|
||||
async fn fetch_and_parse(
|
||||
&self,
|
||||
cache: VideoCache,
|
||||
target: Target,
|
||||
options: ServerOptions,
|
||||
) -> Result<Vec<VideoItem>> {
|
||||
let url = Self::build_url(&target);
|
||||
let url = match &target {
|
||||
Target::Search { query, page } => {
|
||||
let base = match Self::resolve_search_base_url(query, &options).await {
|
||||
Ok(base) => base,
|
||||
Err(e) => {
|
||||
report_provider_error(CHANNEL_ID, "fetch_and_parse.search", &e.to_string())
|
||||
.await;
|
||||
return Ok(vec![]);
|
||||
}
|
||||
};
|
||||
if *page > 1 {
|
||||
format!("{base}?page={page}")
|
||||
} else {
|
||||
base
|
||||
}
|
||||
}
|
||||
_ => Self::build_url(&target),
|
||||
};
|
||||
|
||||
if let Some((time, items)) = cache.get(&url) {
|
||||
if time.elapsed().unwrap_or_default().as_secs() < 300 {
|
||||
@@ -513,20 +553,10 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_search_urls() {
|
||||
fn builds_search_request_body() {
|
||||
assert_eq!(
|
||||
MelonstubeProvider::build_url(&super::Target::Search {
|
||||
query: "teen".to_string(),
|
||||
page: 1
|
||||
}),
|
||||
"https://www.melonstube.com/search?q=teen"
|
||||
);
|
||||
assert_eq!(
|
||||
MelonstubeProvider::build_url(&super::Target::Search {
|
||||
query: "teen".to_string(),
|
||||
page: 2
|
||||
}),
|
||||
"https://www.melonstube.com/search?q=teen&page=2"
|
||||
MelonstubeProvider::build_search_request_body("adriana chechik"),
|
||||
"search_query%5Bquery%5D=adriana+chechik"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user