use once_cell::sync::Lazy;
use regex::Regex;
use std::collections::HashMap;
use url::Url;
#[derive(Debug, thiserror::Error)]
pub enum FromHtmlStrError {
#[error("missing pageData variable")]
MissingPageData,
#[error(transparent)]
InvalidJson(#[from] serde_json::Error),
}
#[derive(Debug, serde::Deserialize)]
pub struct ScrapedStashInfo {
pub csrf: String,
pub deviationid: u64,
pub film: Option<Film>,
pub deviation_width: u64,
pub deviation_height: u64,
#[serde(flatten)]
pub unknown: HashMap<String, serde_json::Value>,
}
impl ScrapedStashInfo {
pub fn from_html_str(input: &str) -> Result<Self, FromHtmlStrError> {
static REGEX: Lazy<Regex> = Lazy::new(|| {
Regex::new(r#"deviantART.pageData=(.*);"#).expect("invalid `scrape_stash_info` regex")
});
let capture = REGEX
.captures(input)
.and_then(|captures| captures.get(1))
.ok_or(FromHtmlStrError::MissingPageData)?;
let scraped_stash: ScrapedStashInfo = serde_json::from_str(capture.as_str())?;
Ok(scraped_stash)
}
}
#[derive(Debug, serde::Deserialize)]
pub struct Film {
pub sizes: HashMap<String, Size>,
#[serde(flatten)]
pub unknown: HashMap<String, serde_json::Value>,
}
impl Film {
pub fn get_best_size(&self) -> Option<&Size> {
self.sizes.values().max_by_key(|v| v.width * v.height)
}
}
#[derive(Debug, serde::Deserialize)]
pub struct Size {
pub height: u32,
pub width: u32,
pub src: Url,
#[serde(flatten)]
pub unknown: HashMap<String, serde_json::Value>,
}