entertainarr-adapter-http 0.1.0

HTTP adapter for entertainarr
Documentation
use std::collections::HashSet;

use crate::entity::{
    Couple, Entity,
    prelude::{AsStr, Page, Sort},
};

crate::create_kind!(PodcastEpisodeKind, "podcast-episodes");

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PodcastEpisodeDocument {
    pub id: u64,
    #[serde(rename = "type")]
    pub kind: PodcastEpisodeKind,
    pub attributes: PodcastEpisodeAttributes,
    pub relationships: PodcastEpisodeRelationships,
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PodcastEpisodeAttributes {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub guid: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub published_at: Option<chrono::DateTime<chrono::Utc>>,
    pub title: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub link: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub duration: Option<u64>,
    pub file_url: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub file_size: Option<u64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub file_type: Option<String>,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub updated_at: chrono::DateTime<chrono::Utc>,
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[cfg_attr(feature = "facet", repr(C))]
#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum PodcastEpisodeField {
    #[default]
    PublishedAt,
}

impl AsStr for PodcastEpisodeField {
    fn as_str(&self) -> &str {
        match self {
            Self::PublishedAt => "published_at",
        }
    }
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[cfg_attr(feature = "facet", repr(C))]
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum PodcastEpisodeInclude {
    #[default]
    Podcast,
    PodcastEpisodeProgress,
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[cfg_attr(feature = "facet", repr(C))]
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(untagged)]
pub enum PodcastEpisodeRelation {
    Podcast(super::podcast::PodcastDocument),
    PodcastEpisodeProgress(PodcastEpisodeProgressDocument),
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct PodcastEpisodeRelationships {
    pub podcast: super::Relation<super::podcast::PodcastEntity>,
    pub progress: super::Relation<PodcastEpisodeProgressEntity>,
}

crate::create_kind!(PodcastEpisodeProgressKind, "podcast-episode-progresses");

pub type PodcastEpisodeProgressEntity = Entity<Couple, PodcastEpisodeProgressKind>;

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct PodcastEpisodeProgressInputDocument {
    pub id: Couple,
    #[serde(rename = "type")]
    pub kind: PodcastEpisodeProgressKind,
    pub attributes: PodcastEpisodeProgressInputAttributes,
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PodcastEpisodeProgressInputAttributes {
    pub progress: u64,
    pub completed: bool,
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct PodcastEpisodeProgressDocument {
    pub id: Couple,
    #[serde(rename = "type")]
    pub kind: PodcastEpisodeProgressKind,
    pub attributes: PodcastEpisodeProgressAttributes,
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PodcastEpisodeProgressAttributes {
    pub progress: u64,
    pub completed: bool,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub updated_at: chrono::DateTime<chrono::Utc>,
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ListPodcastEpisodeFilter {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub filtered: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub subscribed: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub watched: Option<bool>,
}

impl ListPodcastEpisodeFilter {
    pub const fn is_default(&self) -> bool {
        self.filtered.is_none() && self.subscribed.is_none() && self.watched.is_none()
    }
}

#[cfg_attr(feature = "facet", derive(facet::Facet))]
#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ListPodcastEpisodeParams {
    #[serde(default, skip_serializing_if = "ListPodcastEpisodeFilter::is_default")]
    pub filter: ListPodcastEpisodeFilter,
    #[serde(default, skip_serializing_if = "HashSet::is_empty")]
    pub include: HashSet<PodcastEpisodeInclude>,
    #[serde(default, skip_serializing_if = "Sort::is_default")]
    pub sort: Sort<PodcastEpisodeField>,
    #[serde(default, skip_serializing_if = "Page::is_default")]
    pub page: Page,
}

#[derive(Debug)]
pub struct ParsePodcastEpisodeFieldError;

impl std::fmt::Display for ParsePodcastEpisodeFieldError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("invalid podcast episode field")
    }
}

impl std::str::FromStr for PodcastEpisodeField {
    type Err = ParsePodcastEpisodeFieldError;

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        match input {
            "published_at" => Ok(Self::PublishedAt),
            _ => Err(ParsePodcastEpisodeFieldError),
        }
    }
}