collie_core/model/
item.rs

1use chrono::{DateTime, FixedOffset};
2use core::fmt::{self, Display, Formatter};
3use rusqlite::Row;
4use serde::{Deserialize, Serialize};
5use sha1_smol::Sha1;
6use std::str::FromStr;
7
8use crate::error::Error;
9
10#[derive(Serialize, Deserialize, Debug, Clone)]
11pub enum ItemStatus {
12    Unread,
13    Read,
14}
15
16impl Display for ItemStatus {
17    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
18        match self {
19            Self::Unread => write!(f, "unread"),
20            Self::Read => write!(f, "read"),
21        }
22    }
23}
24
25impl FromStr for ItemStatus {
26    type Err = Error;
27
28    fn from_str(x: &str) -> std::result::Result<Self, Self::Err> {
29        match x {
30            "unread" => Ok(Self::Unread),
31            "read" => Ok(Self::Read),
32            _ => Err(Error::InvalidEnumKey(
33                x.to_string(),
34                "ItemStatus".to_string(),
35            )),
36        }
37    }
38}
39
40#[derive(Serialize, Deserialize, Debug)]
41pub struct ItemFeed {
42    pub id: i32,
43    pub title: String,
44    pub link: String,
45}
46
47#[derive(Serialize, Deserialize, Debug)]
48pub struct Item {
49    pub id: i32,
50    pub fingerprint: String,
51    pub author: Option<String>,
52    pub title: String,
53    pub description: String,
54    pub link: String,
55    pub status: ItemStatus,
56    pub is_saved: bool,
57    pub published_at: DateTime<FixedOffset>,
58    pub feed: ItemFeed,
59}
60
61impl From<&Row<'_>> for Item {
62    fn from(row: &Row) -> Self {
63        Self {
64            id: row.get_unwrap("id"),
65            fingerprint: row.get_unwrap("fingerprint"),
66            author: row.get_unwrap("author"),
67            title: row.get_unwrap("title"),
68            description: row.get_unwrap("description"),
69            link: row.get_unwrap("link"),
70            status: ItemStatus::from_str(&row.get_unwrap::<&str, String>("status")).unwrap(),
71            is_saved: row.get_unwrap("is_saved"),
72            published_at: row.get_unwrap("published_at"),
73            feed: ItemFeed {
74                id: row.get_unwrap("feed_id"),
75                title: row.get_unwrap("feed_title"),
76                link: row.get_unwrap("feed_link"),
77            },
78        }
79    }
80}
81
82#[derive(Serialize, Deserialize, Debug)]
83pub struct ItemToCreate {
84    pub author: Option<String>,
85    pub title: String,
86    pub description: String,
87    pub link: String,
88    pub status: ItemStatus,
89    pub published_at: DateTime<FixedOffset>,
90    pub feed: i32,
91}
92
93impl ItemToCreate {
94    pub fn fingerprint(&self) -> String {
95        Sha1::from(format!("{}:{}", &self.title, &self.link)).hexdigest()
96    }
97}
98
99#[derive(Serialize, Deserialize)]
100pub struct ItemToUpdate {
101    pub id: i32,
102    pub status: Option<ItemStatus>,
103    pub is_saved: Option<bool>,
104}
105
106#[derive(Serialize, Deserialize)]
107pub struct ItemToUpdateAll {
108    pub status: Option<ItemStatus>,
109    pub is_saved: Option<bool>,
110    pub opt: Option<ItemReadOption>,
111}
112
113#[derive(Serialize, Deserialize)]
114pub enum ItemOrder {
115    ReceivedDateDesc,
116    PublishedDateDesc,
117    UnreadFirst,
118}
119
120#[derive(Serialize, Deserialize)]
121pub struct ItemReadOption {
122    pub ids: Option<Vec<i32>>,
123    pub feed: Option<i32>,
124    pub status: Option<ItemStatus>,
125    pub is_saved: Option<bool>,
126    pub order_by: Option<ItemOrder>,
127    pub limit: Option<u64>,
128    pub offset: Option<u64>,
129}