initial commit
This commit is contained in:
91
src/rss.rs
Normal file
91
src/rss.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
// See https://support.google.com/podcast-publishers/answer/9889544
|
||||
// for some reasonably guidelines for how a podcast RSS feed should look.
|
||||
|
||||
use std::fmt;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct Feed<'a> {
|
||||
pub (crate) rss : Rss<'a>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct Rss<'a> {
|
||||
pub (crate) channel : Channel<'a>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct Channel<'a> {
|
||||
#[serde(rename = "item", default)]
|
||||
pub (crate) items : Vec<Item<'a>>,
|
||||
pub (crate) link : Cow<'a, str>,
|
||||
pub (crate) title : Cow<'a, str>,
|
||||
pub (crate) description : Option<Cow<'a, str>>,
|
||||
#[serde(rename = "{http://www.itunes.com/dtds/podcast-1.0.dtd}itunes:author")]
|
||||
pub (crate) author : Option<Cow<'a, str>>,
|
||||
#[serde(rename = "{http://www.itunes.com/dtds/podcast-1.0.dtd}itunes:summary")]
|
||||
pub (crate) summary : Option<Cow<'a, str>>,
|
||||
#[serde(rename = "{http://www.itunes.com/dtds/podcast-1.0.dtd}itunes:image")]
|
||||
pub (crate) itunes_image : Option<ItunesImage<'a>>,
|
||||
pub (crate) image : Option<Image<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct Image<'a> {
|
||||
pub (crate) link : Cow<'a, str>,
|
||||
pub (crate) title : Cow<'a, str>,
|
||||
pub (crate) url : Cow<'a, str>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct ItunesImage<'a> {
|
||||
#[serde(rename = "$attr:href")]
|
||||
pub (crate) href : Cow<'a, str>,
|
||||
}
|
||||
|
||||
fn deserialize_publish_date<'de, D : serde::de::Deserializer<'de>> (
|
||||
deserializer : D
|
||||
) -> Result<chrono::NaiveDateTime, D::Error> {
|
||||
struct Visitor;
|
||||
impl<'de> serde::de::Visitor<'de> for Visitor {
|
||||
type Value = chrono::NaiveDateTime;
|
||||
|
||||
fn expecting(&self, formatter : &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a string containing json data")
|
||||
}
|
||||
|
||||
fn visit_str<E : serde::de::Error>(self, input : &str) -> Result<Self::Value, E> {
|
||||
chrono::NaiveDateTime::parse_from_str(
|
||||
input,
|
||||
"%a, %d %b %Y %H:%M:%S %Z"
|
||||
).map_err(E::custom)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(Visitor)
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct Item<'a> {
|
||||
pub (crate) title : Cow<'a, str>,
|
||||
pub (crate) enclosure : Option<Enclosure<'a>>,
|
||||
pub (crate) description : Option<Cow<'a, str>>,
|
||||
#[serde(rename = "{http://www.itunes.com/dtds/podcast-1.0.dtd}itunes:summary")]
|
||||
pub (crate) summary : Option<Cow<'a, str>>,
|
||||
#[serde(rename = "pubDate", deserialize_with = "deserialize_publish_date")]
|
||||
pub (crate) published : chrono::NaiveDateTime,
|
||||
pub (crate) guid : Option<Cow<'a, str>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct Enclosure<'a> {
|
||||
#[serde(rename = "$attr:url")]
|
||||
pub (crate) url : Cow<'a, str>,
|
||||
#[serde(rename = "$attr:type")]
|
||||
pub (crate) mime_type : Option<Cow<'a, str>>,
|
||||
#[serde(rename = "$attr:length")]
|
||||
pub (crate) length : Option<u64>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user