1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use super::category::Category;
use crate::{CategoryID, FeedID, IconID, UserID};
use serde_derive::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize)]
pub struct Feed {
    pub id: FeedID,
    pub user_id: UserID,
    pub title: String,
    pub site_url: String,
    pub feed_url: String,
    pub rewrite_rules: String,
    pub scraper_rules: String,
    pub crawler: bool,
    pub checked_at: String,
    pub etag_header: String,
    pub last_modified_header: String,
    pub parsing_error_count: i64,
    pub parsing_error_message: String,
    pub category: Category,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub icon: Option<FeedIcon>,
}

impl Feed {
    /// destroy this feed and gain ownership of all the data it contains
    #[allow(clippy::type_complexity)]
    pub fn decompose(
        self,
    ) -> (
        FeedID,
        UserID,
        String,
        String,
        String,
        String,
        String,
        bool,
        String,
        String,
        String,
        i64,
        String,
        Category,
        Option<FeedIcon>,
    ) {
        (
            self.id,
            self.user_id,
            self.title,
            self.site_url,
            self.feed_url,
            self.rewrite_rules,
            self.scraper_rules,
            self.crawler,
            self.checked_at,
            self.etag_header,
            self.last_modified_header,
            self.parsing_error_count,
            self.parsing_error_message,
            self.category,
            self.icon,
        )
    }
}

#[derive(Clone, Debug, Deserialize)]
pub struct FeedIcon {
    pub feed_id: FeedID,
    pub icon_id: IconID,
}

#[derive(Debug, Serialize)]
pub struct FeedDiscovery {
    pub url: String,
}

#[derive(Debug, Serialize)]
pub struct FeedCreation {
    pub feed_url: String,
    pub category_id: CategoryID,
}

#[derive(Debug, Deserialize)]
pub struct FeedCreationResponse {
    pub feed_id: FeedID,
}

#[derive(Debug, Serialize)]
pub struct FeedModification {
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub title: Option<String>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub category_id: Option<CategoryID>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub feed_url: Option<String>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub site_url: Option<String>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub username: Option<String>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub password: Option<String>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub scraper_rules: Option<String>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rewrite_rules: Option<String>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub crawler: Option<bool>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub user_agent: Option<String>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub disabled: Option<bool>,
}