1use chrono::{DateTime, Utc};
13use serde::Serialize;
14
15use crate::{
16 core::{
17 query::{self, QueryObject},
18 set::from_timestamp,
19 },
20 Set,
21};
22
23use super::{Email, QueryArguments};
24
25#[derive(Serialize, Clone, Debug)]
26#[serde(untagged)]
27pub enum Filter {
28 InMailbox {
29 #[serde(rename = "inMailbox")]
30 value: String,
31 },
32 InMailboxOtherThan {
33 #[serde(rename = "inMailboxOtherThan")]
34 value: Vec<String>,
35 },
36 Before {
37 #[serde(rename = "before")]
38 value: DateTime<Utc>,
39 },
40 After {
41 #[serde(rename = "after")]
42 value: DateTime<Utc>,
43 },
44 MinSize {
45 #[serde(rename = "minSize")]
46 value: u32,
47 },
48 MaxSize {
49 #[serde(rename = "maxSize")]
50 value: u32,
51 },
52 AllInThreadHaveKeyword {
53 #[serde(rename = "allInThreadHaveKeyword")]
54 value: String,
55 },
56 SomeInThreadHaveKeyword {
57 #[serde(rename = "someInThreadHaveKeyword")]
58 value: String,
59 },
60 NoneInThreadHaveKeyword {
61 #[serde(rename = "noneInThreadHaveKeyword")]
62 value: String,
63 },
64 HasKeyword {
65 #[serde(rename = "hasKeyword")]
66 value: String,
67 },
68 NotKeyword {
69 #[serde(rename = "notKeyword")]
70 value: String,
71 },
72 HasAttachment {
73 #[serde(rename = "hasAttachment")]
74 value: bool,
75 },
76 Text {
77 #[serde(rename = "text")]
78 value: String,
79 },
80 From {
81 #[serde(rename = "from")]
82 value: String,
83 },
84 To {
85 #[serde(rename = "to")]
86 value: String,
87 },
88 Cc {
89 #[serde(rename = "cc")]
90 value: String,
91 },
92 Bcc {
93 #[serde(rename = "bcc")]
94 value: String,
95 },
96 Subject {
97 #[serde(rename = "subject")]
98 value: String,
99 },
100 Body {
101 #[serde(rename = "body")]
102 value: String,
103 },
104 Header {
105 #[serde(rename = "header")]
106 value: Vec<String>,
107 },
108
109 Id {
111 #[serde(rename = "id")]
112 value: Vec<String>,
113 },
114 SentBefore {
115 #[serde(rename = "sentBefore")]
116 value: DateTime<Utc>,
117 },
118 SentAfter {
119 #[serde(rename = "sentAfter")]
120 value: DateTime<Utc>,
121 },
122 InThread {
123 #[serde(rename = "inThread")]
124 value: String,
125 },
126}
127
128#[derive(Serialize, Debug, Clone)]
129#[serde(tag = "property")]
130pub enum Comparator {
131 #[serde(rename = "receivedAt")]
132 ReceivedAt,
133 #[serde(rename = "size")]
134 Size,
135 #[serde(rename = "from")]
136 From,
137 #[serde(rename = "to")]
138 To,
139 #[serde(rename = "subject")]
140 Subject,
141 #[serde(rename = "sentAt")]
142 SentAt,
143 #[serde(rename = "hasKeyword")]
144 HasKeyword { keyword: String },
145 #[serde(rename = "allInThreadHaveKeyword")]
146 AllInThreadHaveKeyword { keyword: String },
147 #[serde(rename = "someInThreadHaveKeyword")]
148 SomeInThreadHaveKeyword { keyword: String },
149
150 #[serde(rename = "cc")]
152 Cc,
153}
154
155impl Filter {
156 pub fn in_mailbox(value: impl Into<String>) -> Self {
157 Filter::InMailbox {
158 value: value.into(),
159 }
160 }
161
162 pub fn in_mailbox_other_than<U, V>(value: U) -> Self
163 where
164 U: IntoIterator<Item = V>,
165 V: Into<String>,
166 {
167 Filter::InMailboxOtherThan {
168 value: value.into_iter().map(|v| v.into()).collect(),
169 }
170 }
171
172 pub fn before(value: i64) -> Self {
173 Filter::Before {
174 value: from_timestamp(value),
175 }
176 }
177
178 pub fn after(value: i64) -> Self {
179 Filter::After {
180 value: from_timestamp(value),
181 }
182 }
183
184 pub fn min_size(value: u32) -> Self {
185 Filter::MinSize { value }
186 }
187
188 pub fn max_size(value: u32) -> Self {
189 Filter::MaxSize { value }
190 }
191
192 pub fn all_in_thread_have_keyword(value: impl Into<String>) -> Self {
193 Filter::AllInThreadHaveKeyword {
194 value: value.into(),
195 }
196 }
197
198 pub fn some_in_thread_have_keyword(value: impl Into<String>) -> Self {
199 Filter::SomeInThreadHaveKeyword {
200 value: value.into(),
201 }
202 }
203
204 pub fn none_in_thread_have_keyword(value: impl Into<String>) -> Self {
205 Filter::NoneInThreadHaveKeyword {
206 value: value.into(),
207 }
208 }
209
210 pub fn has_keyword(value: impl Into<String>) -> Self {
211 Filter::HasKeyword {
212 value: value.into(),
213 }
214 }
215
216 pub fn not_keyword(value: impl Into<String>) -> Self {
217 Filter::NotKeyword {
218 value: value.into(),
219 }
220 }
221
222 pub fn has_attachment(value: bool) -> Self {
223 Filter::HasAttachment { value }
224 }
225
226 pub fn text(value: impl Into<String>) -> Self {
227 Filter::Text {
228 value: value.into(),
229 }
230 }
231
232 pub fn from(value: impl Into<String>) -> Self {
233 Filter::From {
234 value: value.into(),
235 }
236 }
237
238 pub fn to(value: impl Into<String>) -> Self {
239 Filter::To {
240 value: value.into(),
241 }
242 }
243
244 pub fn cc(value: impl Into<String>) -> Self {
245 Filter::Cc {
246 value: value.into(),
247 }
248 }
249
250 pub fn bcc(value: impl Into<String>) -> Self {
251 Filter::Bcc {
252 value: value.into(),
253 }
254 }
255
256 pub fn subject(value: impl Into<String>) -> Self {
257 Filter::Subject {
258 value: value.into(),
259 }
260 }
261
262 pub fn body(value: impl Into<String>) -> Self {
263 Filter::Body {
264 value: value.into(),
265 }
266 }
267
268 pub fn header(header: impl Into<String>, v: Option<impl Into<String>>) -> Self {
269 let mut value = Vec::with_capacity(2);
270 value.push(header.into());
271 if let Some(v) = v {
272 value.push(v.into());
273 }
274 Filter::Header { value }
275 }
276
277 pub fn id<U, V>(value: U) -> Self
279 where
280 U: IntoIterator<Item = V>,
281 V: Into<String>,
282 {
283 Filter::Id {
284 value: value.into_iter().map(|v| v.into()).collect(),
285 }
286 }
287
288 pub fn sent_before(value: i64) -> Self {
289 Filter::SentBefore {
290 value: from_timestamp(value),
291 }
292 }
293
294 pub fn sent_after(value: i64) -> Self {
295 Filter::SentAfter {
296 value: from_timestamp(value),
297 }
298 }
299
300 pub fn in_thread(value: impl Into<String>) -> Self {
301 Filter::InThread {
302 value: value.into(),
303 }
304 }
305}
306
307impl Comparator {
308 pub fn received_at() -> query::Comparator<Comparator> {
309 query::Comparator::new(Comparator::ReceivedAt)
310 }
311
312 pub fn size() -> query::Comparator<Comparator> {
313 query::Comparator::new(Comparator::Size)
314 }
315
316 pub fn from() -> query::Comparator<Comparator> {
317 query::Comparator::new(Comparator::From)
318 }
319
320 pub fn to() -> query::Comparator<Comparator> {
321 query::Comparator::new(Comparator::To)
322 }
323
324 pub fn cc() -> query::Comparator<Comparator> {
325 query::Comparator::new(Comparator::Cc)
326 }
327
328 pub fn subject() -> query::Comparator<Comparator> {
329 query::Comparator::new(Comparator::Subject)
330 }
331
332 pub fn sent_at() -> query::Comparator<Comparator> {
333 query::Comparator::new(Comparator::SentAt)
334 }
335
336 pub fn has_keyword(keyword: impl Into<String>) -> query::Comparator<Comparator> {
337 query::Comparator::new(Comparator::HasKeyword {
338 keyword: keyword.into(),
339 })
340 }
341
342 pub fn all_in_thread_have_keyword(keyword: impl Into<String>) -> query::Comparator<Comparator> {
343 query::Comparator::new(Comparator::AllInThreadHaveKeyword {
344 keyword: keyword.into(),
345 })
346 }
347
348 pub fn some_in_thread_have_keyword(
349 keyword: impl Into<String>,
350 ) -> query::Comparator<Comparator> {
351 query::Comparator::new(Comparator::SomeInThreadHaveKeyword {
352 keyword: keyword.into(),
353 })
354 }
355}
356
357impl QueryObject for Email<Set> {
358 type QueryArguments = QueryArguments;
359
360 type Filter = Filter;
361
362 type Sort = Comparator;
363}