use std::collections::HashMap;
use url::Url;
#[derive(Debug)]
pub struct InvalidMediaTypeError(u8);
impl std::fmt::Display for InvalidMediaTypeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "`{}` is not a valid media type", self.0)
}
}
impl std::error::Error for InvalidMediaTypeError {}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, serde::Deserialize)]
#[serde(try_from = "u8")]
pub enum MediaType {
Photo,
Video,
Carousel,
}
impl TryFrom<u8> for MediaType {
type Error = InvalidMediaTypeError;
fn try_from(n: u8) -> Result<Self, Self::Error> {
match n {
1 => Ok(Self::Photo),
2 => Ok(Self::Video),
8 => Ok(Self::Carousel),
_ => Err(InvalidMediaTypeError(n)),
}
}
}
#[derive(Debug, serde::Deserialize)]
pub struct AdditionalDataLoaded {
pub num_results: u32,
pub items: Vec<AdditionalDataLoadedItem>,
pub auto_load_more_enabled: bool,
pub more_available: bool,
#[serde(flatten)]
pub extra: HashMap<String, serde_json::Value>,
}
#[derive(Debug, serde::Deserialize)]
pub struct AdditionalDataLoadedItem {
pub media_type: MediaType,
pub video_versions: Option<Vec<VideoVersion>>,
pub image_versions2: Option<ImageVersions2>,
pub carousel_media: Option<Vec<CarouselMediaItem>>,
pub code: String,
#[serde(flatten)]
pub extra: HashMap<String, serde_json::Value>,
}
impl AdditionalDataLoadedItem {
pub fn get_best_image_versions2_candidate(&self) -> Option<&ImageVersions2Candidate> {
self.image_versions2.as_ref()?.get_best()
}
pub fn get_best_video_version(&self) -> Option<&VideoVersion> {
self.video_versions
.as_ref()?
.iter()
.max_by_key(|video_version| video_version.height)
}
}
#[derive(Debug, serde::Deserialize)]
pub struct VideoVersion {
pub height: u32,
pub width: u32,
#[serde(rename = "type")]
pub kind: u32,
pub url: Url,
pub id: String,
#[serde(flatten)]
pub extra: HashMap<String, serde_json::Value>,
}
#[derive(Debug, serde::Deserialize)]
pub struct ImageVersions2 {
pub candidates: Vec<ImageVersions2Candidate>,
#[serde(flatten)]
pub extra: HashMap<String, serde_json::Value>,
}
impl ImageVersions2 {
pub fn get_best(&self) -> Option<&ImageVersions2Candidate> {
self.candidates
.iter()
.max_by_key(|image_versions2_candidate| image_versions2_candidate.height)
}
}
#[derive(Debug, serde::Deserialize)]
pub struct ImageVersions2Candidate {
pub width: u32,
pub height: u32,
pub url: Url,
#[serde(flatten)]
pub extra: HashMap<String, serde_json::Value>,
}
#[derive(Debug, serde::Deserialize)]
pub struct CarouselMediaItem {
pub media_type: MediaType,
pub image_versions2: Option<ImageVersions2>,
#[serde(flatten)]
pub extra: HashMap<String, serde_json::Value>,
}
impl CarouselMediaItem {
pub fn get_best_image_versions2_candidate(&self) -> Option<&ImageVersions2Candidate> {
self.image_versions2.as_ref()?.get_best()
}
}