news_flash/models/
article_filter.rs1use std::collections::HashSet;
2
3use crate::models::{ArticleID, ArticleOrder, CategoryID, FeedID, Marked, OrderBy, Read, TagID};
4use chrono::{DateTime, Utc};
5
6use super::{CategoryMapping, FeedMapping};
7
8#[derive(Clone, Debug, Default)]
9pub struct ArticleFilter {
10 pub limit: Option<i64>,
11 pub offset: Option<i64>,
12 pub order: Option<ArticleOrder>,
13 pub order_by: Option<OrderBy>,
14 pub unread: Option<Read>,
15 pub marked: Option<Marked>,
16 pub feeds: Option<Vec<FeedID>>,
17 pub feed_blacklist: Option<Vec<FeedID>>,
18 pub categories: Option<Vec<CategoryID>>,
19 pub category_blacklist: Option<Vec<CategoryID>>,
20 pub tags: Option<Vec<TagID>>,
21 pub ids: Option<Vec<ArticleID>>,
22 pub newer_than: Option<DateTime<Utc>>,
23 pub older_than: Option<DateTime<Utc>>,
24 pub synced_before: Option<DateTime<Utc>>,
25 pub synced_after: Option<DateTime<Utc>>,
26 pub search_term: Option<String>,
27}
28
29impl ArticleFilter {
30 pub fn ids(article_ids: Vec<ArticleID>) -> Self {
31 Self {
32 ids: Some(article_ids),
33 ..Self::default()
34 }
35 }
36
37 pub fn read_ids(article_ids: Vec<ArticleID>, read: Read) -> Self {
38 Self {
39 unread: Some(read),
40 ids: Some(article_ids),
41 ..Self::default()
42 }
43 }
44
45 pub fn marked_ids(article_ids: Vec<ArticleID>, marked: Marked) -> Self {
46 Self {
47 marked: Some(marked),
48 ids: Some(article_ids),
49 ..Self::default()
50 }
51 }
52
53 pub fn feed_unread(feed_id: &FeedID) -> Self {
54 Self {
55 unread: Some(Read::Unread),
56 feeds: Some([feed_id.clone()].into()),
57 ..Self::default()
58 }
59 }
60
61 pub fn category_unread(category_id: &CategoryID) -> Self {
62 Self {
63 unread: Some(Read::Unread),
64 categories: Some([category_id.clone()].into()),
65 ..Self::default()
66 }
67 }
68
69 pub fn tag_unread(tag_id: &TagID) -> Self {
70 Self {
71 unread: Some(Read::Unread),
72 tags: Some([tag_id.clone()].into()),
73 ..Self::default()
74 }
75 }
76
77 pub fn all_unread() -> Self {
78 Self {
79 unread: Some(Read::Unread),
80 ..Self::default()
81 }
82 }
83
84 pub fn all_marked() -> Self {
85 Self {
86 marked: Some(Marked::Marked),
87 ..Self::default()
88 }
89 }
90
91 pub fn feeds_to_load(&self, category_mappings: &Vec<CategoryMapping>, feed_mappings: &Vec<FeedMapping>) -> HashSet<FeedID> {
92 let mut result = HashSet::new();
93
94 if let Some(feeds) = &self.feeds {
95 for feed_id in feeds {
96 result.insert(feed_id.clone());
97 }
98 }
99
100 if let Some(categories) = &self.categories {
101 for category_id in categories {
102 let feed_ids = Self::find_all_feeds(category_id, category_mappings, feed_mappings);
103 for feed_id in feed_ids {
104 result.insert(feed_id);
105 }
106 }
107 }
108
109 result
110 }
111
112 pub fn feeds_to_blacklist(&self, category_mappings: &Vec<CategoryMapping>, feed_mappings: &Vec<FeedMapping>) -> HashSet<FeedID> {
113 let mut result = HashSet::new();
114
115 if let Some(feed_blacklist) = &self.feed_blacklist {
116 for feed_id in feed_blacklist {
117 result.insert(feed_id.clone());
118 }
119 }
120
121 if let Some(category_blacklist) = &self.category_blacklist {
122 for category_id in category_blacklist {
123 let feed_ids = Self::find_all_feeds(category_id, category_mappings, feed_mappings);
124 for feed_id in feed_ids {
125 result.insert(feed_id);
126 }
127 }
128 }
129
130 result
131 }
132
133 fn find_all_feeds(category_id: &CategoryID, category_mappings: &Vec<CategoryMapping>, feed_mappings: &Vec<FeedMapping>) -> HashSet<FeedID> {
134 fn find_all_feeds_impl(
135 category_id: &CategoryID,
136 category_mappings: &Vec<CategoryMapping>,
137 feed_mappings: &Vec<FeedMapping>,
138 result: &mut HashSet<FeedID>,
139 ) {
140 for mapping in feed_mappings {
141 if &mapping.category_id == category_id {
142 result.insert(mapping.feed_id.clone());
143 }
144 }
145
146 for mapping in category_mappings {
147 if &mapping.parent_id == category_id {
148 find_all_feeds_impl(&mapping.category_id, category_mappings, feed_mappings, result);
149 }
150 }
151 }
152
153 let mut result = HashSet::new();
154 find_all_feeds_impl(category_id, category_mappings, feed_mappings, &mut result);
155 result
156 }
157}