deviantart/types/
scraped_stash_info.rs1use once_cell::sync::Lazy;
2use regex::Regex;
3use std::collections::HashMap;
4use url::Url;
5
6#[derive(Debug, thiserror::Error)]
8pub enum FromHtmlStrError {
9 #[error("missing pageData variable")]
11 MissingPageData,
12
13 #[error(transparent)]
15 InvalidJson(#[from] serde_json::Error),
16}
17
18#[derive(Debug, serde::Deserialize)]
20pub struct ScrapedStashInfo {
21 pub csrf: String,
23
24 pub deviationid: u64,
26
27 pub film: Option<Film>,
29
30 pub deviation_width: u64,
32
33 pub deviation_height: u64,
35
36 #[serde(flatten)]
38 pub unknown: HashMap<String, serde_json::Value>,
39}
40
41impl ScrapedStashInfo {
42 pub fn from_html_str(input: &str) -> Result<Self, FromHtmlStrError> {
44 static REGEX: Lazy<Regex> = Lazy::new(|| {
45 Regex::new(r#"deviantART.pageData=(.*);"#).expect("invalid `scrape_stash_info` regex")
46 });
47
48 let capture = REGEX
49 .captures(input)
50 .and_then(|captures| captures.get(1))
51 .ok_or(FromHtmlStrError::MissingPageData)?;
52 let scraped_stash: ScrapedStashInfo = serde_json::from_str(capture.as_str())?;
53
54 Ok(scraped_stash)
55 }
56}
57
58#[derive(Debug, serde::Deserialize)]
60pub struct Film {
61 pub sizes: HashMap<String, Size>,
63
64 #[serde(flatten)]
66 pub unknown: HashMap<String, serde_json::Value>,
67}
68
69impl Film {
70 pub fn get_best_size(&self) -> Option<&Size> {
72 self.sizes.values().max_by_key(|v| v.width * v.height)
73 }
74}
75
76#[derive(Debug, serde::Deserialize)]
78pub struct Size {
79 pub height: u32,
81
82 pub width: u32,
84
85 pub src: Url,
87
88 #[serde(flatten)]
90 pub unknown: HashMap<String, serde_json::Value>,
91}