313 lines
8.4 KiB
Rust
313 lines
8.4 KiB
Rust
use async_trait::async_trait;
|
|
use futures::FutureExt;
|
|
use once_cell::sync::Lazy;
|
|
use rustc_hash::FxHashMap as HashMap;
|
|
use std::future::Future;
|
|
use std::panic::AssertUnwindSafe;
|
|
use std::sync::Arc;
|
|
|
|
use crate::{
|
|
DbPool,
|
|
api::ClientVersion,
|
|
status::Channel,
|
|
util::{cache::VideoCache, discord::send_discord_error_report, requester::Requester},
|
|
videos::{ServerOptions, VideoItem},
|
|
};
|
|
|
|
pub mod all;
|
|
pub mod hanime;
|
|
pub mod perverzija;
|
|
pub mod pmvhaven;
|
|
pub mod pornhub;
|
|
// pub mod spankbang;
|
|
pub mod homoxxx;
|
|
pub mod okporn;
|
|
pub mod okxxx;
|
|
pub mod perfectgirls;
|
|
pub mod pornhat;
|
|
pub mod redtube;
|
|
pub mod rule34video;
|
|
// pub mod hentaimoon;
|
|
pub mod beeg;
|
|
pub mod missav;
|
|
pub mod omgxxx;
|
|
pub mod paradisehill;
|
|
pub mod porn00;
|
|
pub mod porn4fans;
|
|
pub mod pornzog;
|
|
pub mod sxyprn;
|
|
pub mod tnaflix;
|
|
pub mod viralxxxporn;
|
|
pub mod xfree;
|
|
pub mod xxthots;
|
|
pub mod youjizz;
|
|
// pub mod pornxp;
|
|
pub mod chaturbate;
|
|
pub mod freepornvideosxxx;
|
|
pub mod hentaihaven;
|
|
pub mod hqporner;
|
|
pub mod hypnotube;
|
|
pub mod javtiful;
|
|
pub mod noodlemagazine;
|
|
pub mod pimpbunny;
|
|
pub mod rule34gen;
|
|
pub mod xxdbx;
|
|
// pub mod tube8;
|
|
|
|
// convenient alias
|
|
pub type DynProvider = Arc<dyn Provider>;
|
|
|
|
pub static ALL_PROVIDERS: Lazy<HashMap<&'static str, DynProvider>> = Lazy::new(|| {
|
|
let mut m = HashMap::default();
|
|
m.insert("all", Arc::new(all::AllProvider::new()) as DynProvider);
|
|
m.insert(
|
|
"perverzija",
|
|
Arc::new(perverzija::PerverzijaProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"hanime",
|
|
Arc::new(hanime::HanimeProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"pornhub",
|
|
Arc::new(pornhub::PornhubProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"rule34video",
|
|
Arc::new(rule34video::Rule34videoProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"redtube",
|
|
Arc::new(redtube::RedtubeProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"okporn",
|
|
Arc::new(okporn::OkpornProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"pornhat",
|
|
Arc::new(pornhat::PornhatProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"perfectgirls",
|
|
Arc::new(perfectgirls::PerfectgirlsProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"okxxx",
|
|
Arc::new(okxxx::OkxxxProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"homoxxx",
|
|
Arc::new(homoxxx::HomoxxxProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"missav",
|
|
Arc::new(missav::MissavProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"xxthots",
|
|
Arc::new(xxthots::XxthotsProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"sxyprn",
|
|
Arc::new(sxyprn::SxyprnProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"porn00",
|
|
Arc::new(porn00::Porn00Provider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"youjizz",
|
|
Arc::new(youjizz::YoujizzProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"paradisehill",
|
|
Arc::new(paradisehill::ParadisehillProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"porn4fans",
|
|
Arc::new(porn4fans::Porn4fansProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"pornzog",
|
|
Arc::new(pornzog::PornzogProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"omgxxx",
|
|
Arc::new(omgxxx::OmgxxxProvider::new()) as DynProvider,
|
|
);
|
|
m.insert("beeg", Arc::new(beeg::BeegProvider::new()) as DynProvider);
|
|
m.insert(
|
|
"tnaflix",
|
|
Arc::new(tnaflix::TnaflixProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"viralxxxporn",
|
|
Arc::new(viralxxxporn::ViralxxxpornProvider::new()) as DynProvider,
|
|
);
|
|
// m.insert("pornxp", Arc::new(pornxp::PornxpProvider::new()) as DynProvider);
|
|
m.insert(
|
|
"rule34gen",
|
|
Arc::new(rule34gen::Rule34genProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"xxdbx",
|
|
Arc::new(xxdbx::XxdbxProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"xfree",
|
|
Arc::new(xfree::XfreeProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"hqporner",
|
|
Arc::new(hqporner::HqpornerProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"pmvhaven",
|
|
Arc::new(pmvhaven::PmvhavenProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"noodlemagazine",
|
|
Arc::new(noodlemagazine::NoodlemagazineProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"pimpbunny",
|
|
Arc::new(pimpbunny::PimpbunnyProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"javtiful",
|
|
Arc::new(javtiful::JavtifulProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"hypnotube",
|
|
Arc::new(hypnotube::HypnotubeProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"freepornvideosxxx",
|
|
Arc::new(freepornvideosxxx::FreepornvideosxxxProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"hentaihaven",
|
|
Arc::new(hentaihaven::HentaihavenProvider::new()) as DynProvider,
|
|
);
|
|
m.insert(
|
|
"chaturbate",
|
|
Arc::new(chaturbate::ChaturbateProvider::new()) as DynProvider,
|
|
);
|
|
// m.insert("tube8", Arc::new(tube8::Tube8Provider::new()) as DynProvider);
|
|
// add more here as you migrate them
|
|
m
|
|
});
|
|
|
|
pub fn init_providers_now() {
|
|
// Idempotent & thread-safe: runs the Lazy init exactly once.
|
|
Lazy::force(&ALL_PROVIDERS);
|
|
}
|
|
|
|
pub fn panic_payload_to_string(payload: Box<dyn std::any::Any + Send>) -> String {
|
|
if let Some(s) = payload.downcast_ref::<&str>() {
|
|
return (*s).to_string();
|
|
}
|
|
if let Some(s) = payload.downcast_ref::<String>() {
|
|
return s.clone();
|
|
}
|
|
"unknown panic payload".to_string()
|
|
}
|
|
|
|
pub async fn run_provider_guarded<F>(provider_name: &str, context: &str, fut: F) -> Vec<VideoItem>
|
|
where
|
|
F: Future<Output = Vec<VideoItem>>,
|
|
{
|
|
match AssertUnwindSafe(fut).catch_unwind().await {
|
|
Ok(videos) => videos,
|
|
Err(payload) => {
|
|
let panic_msg = panic_payload_to_string(payload);
|
|
let _ = send_discord_error_report(
|
|
format!("Provider panic: {}", provider_name),
|
|
None,
|
|
Some("Provider Guard"),
|
|
Some(&format!("context={}; panic={}", context, panic_msg)),
|
|
file!(),
|
|
line!(),
|
|
module_path!(),
|
|
)
|
|
.await;
|
|
vec![]
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn report_provider_error(provider_name: &str, context: &str, msg: &str) {
|
|
let _ = send_discord_error_report(
|
|
format!("Provider error: {}", provider_name),
|
|
None,
|
|
Some("Provider Guard"),
|
|
Some(&format!("context={}; error={}", context, msg)),
|
|
file!(),
|
|
line!(),
|
|
module_path!(),
|
|
)
|
|
.await;
|
|
}
|
|
|
|
pub fn report_provider_error_background(provider_name: &str, context: &str, msg: &str) {
|
|
let provider_name = provider_name.to_string();
|
|
let context = context.to_string();
|
|
let msg = msg.to_string();
|
|
tokio::spawn(async move {
|
|
report_provider_error(&provider_name, &context, &msg).await;
|
|
});
|
|
}
|
|
|
|
pub fn requester_or_default(
|
|
options: &ServerOptions,
|
|
provider_name: &str,
|
|
context: &str,
|
|
) -> Requester {
|
|
match options.requester.clone() {
|
|
Some(requester) => requester,
|
|
None => {
|
|
report_provider_error_background(
|
|
provider_name,
|
|
context,
|
|
"ServerOptions.requester missing; using default Requester",
|
|
);
|
|
Requester::new()
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
pub trait Provider: Send + Sync {
|
|
async fn get_videos(
|
|
&self,
|
|
cache: VideoCache,
|
|
pool: DbPool,
|
|
sort: String,
|
|
query: Option<String>,
|
|
page: String,
|
|
per_page: String,
|
|
options: ServerOptions,
|
|
) -> Vec<VideoItem>;
|
|
|
|
fn get_channel(&self, clientversion: ClientVersion) -> Option<Channel> {
|
|
println!(
|
|
"Getting channel for placeholder with client version: {:?}",
|
|
clientversion
|
|
);
|
|
let _ = clientversion;
|
|
Some(Channel {
|
|
id: "placeholder".to_string(),
|
|
name: "PLACEHOLDER".to_string(),
|
|
description: "PLACEHOLDER FOR PARENT CLASS".to_string(),
|
|
premium: false,
|
|
favicon: "https://www.google.com/s2/favicons?sz=64&domain=missav.ws".to_string(),
|
|
status: "active".to_string(),
|
|
categories: vec![],
|
|
options: vec![],
|
|
nsfw: true,
|
|
cacheDuration: None,
|
|
})
|
|
}
|
|
}
|