jupiter_common/
lib.rs

1use std::convert::TryFrom;
2
3use anyhow::anyhow;
4use anyhow::Result;
5use chrono::offset::FixedOffset;
6use chrono::DateTime;
7use regex::Regex;
8use rss::Enclosure;
9use rss::{Channel, Item};
10use serde::{Deserialize, Serialize};
11
12impl TryFrom<String> for AllEpisodes {
13    fn try_from(value: String) -> Result<Self, Self::Error> {
14        let channel = Channel::read_from(value.as_bytes())?;
15        println!("deserialized items: {}", channel.items.len());
16
17        let episodes: Vec<Episode> = channel
18            .items
19            .into_iter()
20            .map(|i| i.try_into())
21            .collect::<Result<_>>()?;
22        Ok(AllEpisodes { episodes })
23    }
24
25    type Error = anyhow::Error;
26}
27
28pub struct AllEpisodes {
29    pub episodes: Vec<Episode>,
30}
31
32#[derive(Serialize, Deserialize, Debug, Clone)]
33pub struct Episode {
34    /// id has to contain only letters: a-zA-Z0-9 and has to be unique
35    pub id: String,
36    pub title: String,
37    pub description: Option<String>,
38    pub content: Option<String>,
39    pub link: String,
40    pub enclosure: Enclosure,
41    pub pub_date: DateTime<FixedOffset>,
42}
43
44impl TryFrom<Item> for Episode {
45    type Error = anyhow::Error;
46    fn try_from(episode: Item) -> Result<Self, Self::Error> {
47        //todo come up with better cleaning up... at least move it to lazy static
48        let re = Regex::new(r"[a-zA-Z0-9]").unwrap();
49        let title = episode.title.ok_or_else(|| anyhow!("missing title"))?;
50        let episode = Episode {
51            id: re
52                .find_iter(&title)
53                .map(|a| a.as_str())
54                .collect::<Vec<_>>()
55                .join(""),
56            title,
57            description: episode.description,
58            content: episode.content,
59            link: episode.link.ok_or_else(|| anyhow!("missing link!"))?,
60            enclosure: episode
61                .enclosure
62                .ok_or_else(|| anyhow!("missing enclosure url"))?,
63            pub_date: DateTime::parse_from_rfc2822(
64                &episode
65                    .pub_date
66                    .ok_or_else(|| anyhow!("missing pubValue"))?,
67            )?,
68        };
69
70        Ok(episode)
71    }
72}