Files
hottub/src/videos.rs
2025-08-16 18:46:10 +00:00

276 lines
9.4 KiB
Rust

use std::collections::HashMap;
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct VideosRequest {
//"versionInstallDate":"2025-06-03T18:20:20Z","languageCode":"en","appInstallDate":"2025-06-03T18:20:20Z","server":"spacemoehre","sexu
pub clientHash: Option<String>, // "a07b23c9b07813c65050e2a4041ca777",
pub blockedKeywords: Option<String>, // "kittens",
pub countryCode: Option<String>, // "DE",
pub clientVersion: Option<String>, // "2.1.4-22b",
pub timestamp: Option<String>, // "1748976686",
pub blockedUploaders: Option<String>, // "",
pub anonId: Option<String>, // "1AB8A060-A47D-47EF-B9CB-63980ED84C8A",
pub debugTools: Option<bool>, // false,
pub versionInstallDate: Option<String>, // "2025-06-03T18:20:20Z",
pub languageCode: Option<String>, // "en",
pub appInstallDate: Option<String>, // "2025-06-03T18:20:20Z",
pub server: Option<String>, // "spacemoehre",
pub sexuality: Option<String>, // "straight",
pub channel: Option<String>, //"youtube",
pub sort: Option<String>, //"new",
pub query: Option<String>, //"kittens",
pub page: Option<String>, //1,
pub perPage: Option<String>, //10,
// Your server's global options will be sent in the videos request
// pub flavor: "mint chocolate chip"
pub featured: Option<String>, // "featured",
pub category: Option<String>, // "pmv"
pub sites: Option<String>, //
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct ServerOptions{
pub featured: Option<String>, // "featured",
pub category: Option<String>, // "pmv"
pub sites: Option<String>, //
}
#[derive(serde::Serialize, Debug)]
pub struct PageInfo {
pub hasNextPage: bool, // true,
pub resultsPerPage: u32, // 10
}
#[derive(serde::Serialize, Debug, Clone)]
pub struct VideoEmbed{
pub html: String,
pub source: String,
}
impl VideoEmbed {
pub fn new(html: String, source: String) -> Self {
VideoEmbed {
html,
source,
}
}
}
#[derive(serde::Serialize, Debug, Clone)]
pub struct VideoItem {
pub duration: u32, // 110,
#[serde(skip_serializing_if = "Option::is_none")]
pub views: Option<u32>, // 14622653,
#[serde(skip_serializing_if = "Option::is_none")]
pub rating: Option<f32>, // 0.0,
pub id: String, // "c85017ca87477168d648727753c4ded8a35f173e22ef93743e707b296becb299",
pub title: String, // "20 Minutes of Adorable Kittens BEST Compilation",
pub url: String, // "https://www.youtube.com/watch?v=y0sF5xhGreA",
pub channel: String, // "youtube",
pub thumb: String, // "https://i.ytimg.com/vi/y0sF5xhGreA/hqdefault.jpg",
#[serde(skip_serializing_if = "Option::is_none")]
pub uploader: Option<String>, // "The Pet Collective",
#[serde(skip_serializing_if = "Option::is_none")]
pub uploaderUrl: Option<String>, // "https://www.youtube.com/@petcollective",
#[serde(skip_serializing_if = "Option::is_none")]
pub verified: Option<bool>, // false,
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<String>>, // [],
#[serde(skip_serializing_if = "Option::is_none")]
pub uploadedAt: Option<u64>, // 1741142954
#[serde(skip_serializing_if = "Option::is_none")]
pub formats: Option<Vec<VideoFormat>>, // Additional HTTP headers if needed
#[serde(skip_serializing_if = "Option::is_none")]
pub embed: Option<VideoEmbed>, // Optional embed information
#[serde(skip_serializing_if = "Option::is_none")]
pub preview: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub aspectRation: Option<f32>
}
#[allow(dead_code)]
impl VideoItem {
pub fn new(
id: String,
title: String,
url: String,
channel: String,
thumb: String,
duration: u32,
) -> Self {
VideoItem {
duration: duration, // Placeholder, adjust as needed
views: None, // Placeholder, adjust as needed
rating: None, // Placeholder, adjust as needed
id,
title,
url,
channel,
thumb,
uploader: None,
uploaderUrl: None,
verified: None,
tags: None, // Placeholder, adjust as needed
uploadedAt: None,
formats: None, // Placeholder for formats
embed: None, // Placeholder for embed information
preview: None,
aspectRation: None
}
}
pub fn tags(mut self, tags: Vec<String>) -> Self {
self.tags = Some(tags);
self
}
pub fn uploader(mut self, uploader: String) -> Self {
self.uploader = Some(uploader);
self
}
pub fn uploader_url(mut self, uploader_url: String) -> Self {
self.uploaderUrl = Some(uploader_url);
self
}
pub fn verified(mut self, verified: bool) -> Self {
self.verified = Some(verified);
self
}
pub fn views(mut self, views: u32) -> Self {
self.views = Some(views);
self
}
pub fn rating(mut self, rating: f32) -> Self {
self.rating = Some(rating);
self
}
pub fn uploaded_at(mut self, uploaded_at: u64) -> Self {
self.uploadedAt = Some(uploaded_at);
self
}
pub fn formats(mut self, formats: Vec<VideoFormat>) -> Self {
self.formats = Some(formats);
self
}
pub fn add_format(mut self, format: VideoFormat){
if let Some(formats) = self.formats.as_mut() {
formats.push(format);
} else {
self.formats = Some(vec![format]);
}
}
pub fn embed(mut self, embed: VideoEmbed) -> Self {
self.embed = Some(embed);
self
}
pub fn preview(mut self, preview: String) -> Self {
self.preview = Some(preview);
self
}
pub fn aspect_ratio(mut self, aspect_ratio: f32) -> Self {
self.aspectRation = Some(aspect_ratio);
self
}
}
#[derive(serde::Serialize, Debug, Clone)]
pub struct VideoFormat {
url: String,
quality: String,
format: String,
#[serde(skip_serializing_if = "Option::is_none")]
format_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
format_note: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
filesize: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
asr: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
fps: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
height: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
tbr: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
language: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
language_preference: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
ext: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
vcodec: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
acodec: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
dynamic_range: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
abr: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
vbr: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
container: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
protocol: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
audio_ext: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
video_ext: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
resolution: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
http_headers: Option<HashMap<String, String>>,
}
impl VideoFormat {
pub fn new(url: String, quality: String, format: String) -> Self {
let _ = format;
VideoFormat {
url,
quality,
format: "mp4".to_string(), // Default format
format_id: Some("mp4-1080".to_string()),
format_note: None,
filesize: None,
asr: None,
fps: None,
width: None,
height: None,
tbr: None,
language: None,
language_preference: None,
ext: Some("mp4".to_string()),
vcodec: None,
acodec: None,
dynamic_range: None,
abr: None,
vbr: None,
container: None,
protocol: Some("m3u8_native".to_string()),
audio_ext: Some("none".to_string()),
video_ext: Some("mp4".to_string()),
resolution: None,
http_headers: None,
}
}
pub fn add_http_header(&mut self, key: String, value: String) {
if self.http_headers.is_none() {
self.http_headers = Some(HashMap::new());
}
if let Some(headers) = &mut self.http_headers {
headers.insert(key, value);
}
}
pub fn protocol(mut self, protocol: String) -> Self {
self.protocol = Some(protocol);
self
}
}
#[derive(serde::Serialize, Debug)]
pub struct Videos {
pub pageInfo: PageInfo,
pub items: Vec<VideoItem>,
}