Skip to main content

news_flash/models/
feed.rs

1use crate::models::{FeedID, Url};
2use crate::schema::feeds;
3use feed_rs::model::Feed as FeedRS;
4use std::hash::{Hash, Hasher};
5
6#[derive(Identifiable, Clone, Insertable, Queryable, Eq, Debug)]
7#[diesel(primary_key(feed_id))]
8#[diesel(table_name = feeds)]
9#[diesel(check_for_backend(SQLite))]
10pub struct Feed {
11    pub feed_id: FeedID,
12    pub label: String,
13    pub website: Option<Url>,
14    pub feed_url: Option<Url>,
15    pub icon_url: Option<Url>,
16    pub error_count: i32,
17    pub error_message: Option<String>,
18}
19
20impl Hash for Feed {
21    fn hash<H: Hasher>(&self, state: &mut H) {
22        self.feed_id.hash(state);
23    }
24}
25
26impl PartialEq for Feed {
27    fn eq(&self, other: &Feed) -> bool {
28        self.feed_id == other.feed_id
29    }
30}
31
32impl Feed {
33    pub fn from_feed_rs(feed: &FeedRS, title: Option<String>, url: &Url) -> Self {
34        let title = match title {
35            Some(title) => title,
36            None => match &feed.title {
37                Some(title) => title.content.clone(),
38                None => "Unknown Feed".into(),
39            },
40        };
41
42        // see if there is a link with rel='alternate' -> this is probably what we want
43        let website = feed
44            .links
45            .iter()
46            .find(|link| link.rel == Some("alternate".to_owned()))
47            .and_then(|link| Url::parse(&link.href).ok());
48
49        // if no link with rel='alternate' could be found, try for a link without rel
50        let website = match website {
51            Some(website) => Some(website),
52            None => feed
53                .links
54                .iter()
55                .find(|link| link.rel.is_none())
56                .and_then(|link| Url::parse(&link.href).ok()),
57        };
58
59        // otherwise just take the first link
60        let website = match website {
61            Some(website) => Some(website),
62            None => feed.links.first().and_then(|link| Url::parse(&link.href).ok()),
63        };
64
65        let icon_url = match feed.icon.as_ref().and_then(|icon| Url::parse(&icon.uri).ok()) {
66            Some(url) => Some(url),
67            None => feed.logo.as_ref().and_then(|logo| Url::parse(&logo.uri).ok()),
68        };
69
70        Feed {
71            feed_id: FeedID::new(url.as_str()),
72            label: title,
73            website,
74            feed_url: Some(url.clone()),
75            icon_url,
76            error_count: 0,
77            error_message: None,
78        }
79    }
80}
81
82//------------------------------------------------------------------
83
84#[derive(Queryable, Debug)]
85#[diesel(check_for_backend(SQLite))]
86pub struct FeedCount {
87    pub feed_id: FeedID,
88    pub count: i64,
89}