cull_gmail/
rule_processor.rs

1use google_gmail1::api::{BatchDeleteMessagesRequest, BatchModifyMessagesRequest};
2
3use crate::{EolAction, Error, GmailClient, Result, config::EolRule, message_list::MessageList};
4
5/// Rules processor to apply the configured rules to the mailbox.
6pub trait RuleProcessor {
7    /// Find the rule and the message for a specific label
8    fn find_rule_and_messages_for_label(
9        &mut self,
10        label: &str,
11    ) -> impl std::future::Future<Output = Result<()>> + Send;
12    /// Set the execute flag in the client
13    fn set_execute(&mut self, value: bool);
14    // /// Delete messages
15    // fn delete_messages(
16    //     &mut self,
17    //     label: &str,
18    // ) -> impl std::future::Future<Output = Result<()>> + Send;
19    // /// Trash Messages
20    // fn trash_messages(
21    //     &mut self,
22    //     label: &str,
23    // ) -> impl std::future::Future<Output = Result<()>> + Send;
24    /// Set rule to process
25    fn set_rule(&mut self, action: EolRule);
26    /// Report the action from the rule
27    fn action(&self) -> Option<EolAction>;
28    /// Prepare a list of messages to trash or delete
29    fn prepare(&mut self, pages: u32) -> impl std::future::Future<Output = Result<()>> + Send;
30    /// Batch delete of messages
31    fn batch_delete(&self) -> impl std::future::Future<Output = Result<()>> + Send;
32    /// Batch trash
33    fn batch_trash(&self) -> impl std::future::Future<Output = Result<()>> + Send;
34}
35
36impl RuleProcessor for GmailClient {
37    /// Add Action to the Client for processing
38    fn set_rule(&mut self, value: EolRule) {
39        self.rule = Some(value);
40    }
41
42    /// Set the execute flag
43    fn set_execute(&mut self, value: bool) {
44        self.execute = value;
45    }
46
47    /// The action set in the rule  
48    fn action(&self) -> Option<EolAction> {
49        if let Some(rule) = &self.rule {
50            return rule.action();
51        }
52        None
53    }
54
55    /// Find the rule and messages for the label
56    async fn find_rule_and_messages_for_label(&mut self, label: &str) -> Result<()> {
57        self.add_labels(&[label.to_string()])?;
58
59        if self.label_ids().is_empty() {
60            return Err(Error::LabelNotFoundInMailbox(label.to_string()));
61        }
62
63        let Some(rule) = &self.rule else {
64            return Err(Error::RuleNotFound(0));
65        };
66
67        let Some(query) = rule.eol_query() else {
68            return Err(Error::NoQueryStringCalculated(rule.id()));
69        };
70        self.set_query(&query);
71
72        log::info!("{:?}", self.messages());
73        log::info!("Ready to run");
74        self.prepare(0).await?;
75        if self.execute {
76            log::info!("***executing final delete messages***");
77            self.batch_trash().await
78        } else {
79            log::warn!("Execution stopped for dry run");
80            Ok(())
81        }
82    }
83
84    // /// Trash the messages
85    // async fn trash_messages(&mut self, label: &str) -> Result<()> {
86    //     self.add_labels(&[label.to_string()]).await?;
87
88    //     if self.label_ids().is_empty() {
89    //         return Err(Error::LabelNotFoundInMailbox(label.to_string()));
90    //     }
91
92    //     let Some(rule) = &self.rule else {
93    //         return Err(Error::RuleNotFound(0));
94    //     };
95
96    //     let Some(query) = rule.eol_query() else {
97    //         return Err(Error::NoQueryStringCalculated(rule.id()));
98    //     };
99    //     self.set_query(&query);
100
101    //     log::info!("{:?}", self.messages());
102    //     log::info!("Ready to run");
103    //     self.prepare(0).await?;
104    //     if self.execute {
105    //         log::info!("***executing final delete messages***");
106    //         self.batch_trash().await
107    //     } else {
108    //         log::warn!("Execution stopped for dry run");
109    //         Ok(())
110    //     }
111    // }
112
113    // /// Delete the messages
114    // async fn delete_messages(&mut self, label: &str) -> Result<()> {
115    //     self.add_labels(&[label.to_string()]).await?;
116
117    //     if self.label_ids().is_empty() {
118    //         return Err(Error::LabelNotFoundInMailbox(label.to_string()));
119    //     }
120
121    //     let Some(rule) = &self.rule else {
122    //         return Err(Error::RuleNotFound(0));
123    //     };
124
125    //     let Some(query) = rule.eol_query() else {
126    //         return Err(Error::NoQueryStringCalculated(rule.id()));
127    //     };
128    //     self.set_query(&query);
129
130    //     log::info!("{:?}", self.messages());
131    //     log::info!("Ready to run");
132    //     self.prepare(0).await?;
133    //     if self.execute {
134    //         log::info!("***executing final delete messages***");
135    //         self.batch_delete().await
136    //     } else {
137    //         log::warn!("Execution stopped for dry run");
138
139    //         Ok(())
140    //     }
141    // }
142    /// Prepare the message list for delete to be completed on execute by batch_delete
143    async fn prepare(&mut self, pages: u32) -> Result<()> {
144        self.get_messages(pages).await
145    }
146
147    /// Run the batch delete on the selected messages
148    async fn batch_delete(&self) -> Result<()> {
149        let ids = Some(self.message_ids());
150
151        let batch_request = BatchDeleteMessagesRequest { ids };
152
153        log::trace!("{batch_request:#?}");
154
155        let _res = self
156            .hub()
157            .users()
158            .messages_batch_delete(batch_request, "me")
159            .add_scope("https://mail.google.com/")
160            .doit()
161            .await
162            .map_err(Box::new)?;
163
164        for m in self.messages() {
165            log::info!("Message with subject `{}` deleted.", m.subject());
166        }
167
168        Ok(())
169    }
170    /// Move the messages to trash
171    async fn batch_trash(&self) -> Result<()> {
172        let add_label_ids = Some(Vec::from(["TRASH".to_string()]));
173        let ids = Some(self.message_ids());
174        let remove_label_ids = Some(self.label_ids());
175
176        let batch_request = BatchModifyMessagesRequest {
177            add_label_ids,
178            ids,
179            remove_label_ids,
180        };
181
182        log::trace!("{batch_request:#?}");
183
184        let _res = self
185            .hub()
186            .users()
187            .messages_batch_modify(batch_request, "me")
188            .add_scope("https://www.googleapis.com/auth/gmail.modify")
189            .doit()
190            .await
191            .map_err(Box::new)?;
192
193        for m in self.messages() {
194            log::info!("Message with subject `{}` moved to trash.", m.subject());
195        }
196
197        Ok(())
198    }
199}