deviantart/types/
scraped_stash_info.rs

1use once_cell::sync::Lazy;
2use regex::Regex;
3use std::collections::HashMap;
4use url::Url;
5
6/// An error that may occur while parsing a [`ScrapedStashInfo`] from a html str.
7#[derive(Debug, thiserror::Error)]
8pub enum FromHtmlStrError {
9    /// Missing the pageData variable
10    #[error("missing pageData variable")]
11    MissingPageData,
12
13    /// Failed to parse json
14    #[error(transparent)]
15    InvalidJson(#[from] serde_json::Error),
16}
17
18/// Scraped info from a sta.sh link
19#[derive(Debug, serde::Deserialize)]
20pub struct ScrapedStashInfo {
21    /// Csrf token
22    pub csrf: String,
23
24    /// ?
25    pub deviationid: u64,
26
27    /// Present only if it is a video
28    pub film: Option<Film>,
29
30    /// The width
31    pub deviation_width: u64,
32
33    /// The height
34    pub deviation_height: u64,
35
36    /// Unknown data
37    #[serde(flatten)]
38    pub unknown: HashMap<String, serde_json::Value>,
39}
40
41impl ScrapedStashInfo {
42    /// Parse this from a html str
43    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/// Film data from a sta.sh link
59#[derive(Debug, serde::Deserialize)]
60pub struct Film {
61    /// Video sizes
62    pub sizes: HashMap<String, Size>,
63
64    /// Unknown data
65    #[serde(flatten)]
66    pub unknown: HashMap<String, serde_json::Value>,
67}
68
69impl Film {
70    /// Get the best size
71    pub fn get_best_size(&self) -> Option<&Size> {
72        self.sizes.values().max_by_key(|v| v.width * v.height)
73    }
74}
75
76/// Film size
77#[derive(Debug, serde::Deserialize)]
78pub struct Size {
79    /// Video height
80    pub height: u32,
81
82    /// Video width
83    pub width: u32,
84
85    /// Video src
86    pub src: Url,
87
88    /// Unknown data
89    #[serde(flatten)]
90    pub unknown: HashMap<String, serde_json::Value>,
91}