✨ feat(rule_processor): implement rule processing for Gmail
- implements RuleProcessor trait for GmailClient - adds functionality to find rules, prepare and execute actions on messages - supports batch delete and trash operations
This commit is contained in:
committed by
Jeremiah Russell
parent
e02f0ee3d1
commit
74d1488ecd
199
src/rule_processor.rs
Normal file
199
src/rule_processor.rs
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
use google_gmail1::api::{BatchDeleteMessagesRequest, BatchModifyMessagesRequest};
|
||||||
|
|
||||||
|
use crate::{EolAction, Error, GmailClient, Result, config::EolRule, message_list::MessageList};
|
||||||
|
|
||||||
|
/// Rules processor to apply the configured rules to the mailbox.
|
||||||
|
pub trait RuleProcessor {
|
||||||
|
/// Find the rule and the message for a specific label
|
||||||
|
fn find_rule_and_messages_for_label(
|
||||||
|
&mut self,
|
||||||
|
label: &str,
|
||||||
|
) -> impl std::future::Future<Output = Result<()>> + Send;
|
||||||
|
/// Set the execute flag in the client
|
||||||
|
fn set_execute(&mut self, value: bool);
|
||||||
|
// /// Delete messages
|
||||||
|
// fn delete_messages(
|
||||||
|
// &mut self,
|
||||||
|
// label: &str,
|
||||||
|
// ) -> impl std::future::Future<Output = Result<()>> + Send;
|
||||||
|
// /// Trash Messages
|
||||||
|
// fn trash_messages(
|
||||||
|
// &mut self,
|
||||||
|
// label: &str,
|
||||||
|
// ) -> impl std::future::Future<Output = Result<()>> + Send;
|
||||||
|
/// Set rule to process
|
||||||
|
fn set_rule(&mut self, action: EolRule);
|
||||||
|
/// Report the action from the rule
|
||||||
|
fn action(&self) -> Option<EolAction>;
|
||||||
|
/// Prepare a list of messages to trash or delete
|
||||||
|
fn prepare(&mut self, pages: u32) -> impl std::future::Future<Output = Result<()>> + Send;
|
||||||
|
/// Batch delete of messages
|
||||||
|
fn batch_delete(&self) -> impl std::future::Future<Output = Result<()>> + Send;
|
||||||
|
/// Batch trash
|
||||||
|
fn batch_trash(&self) -> impl std::future::Future<Output = Result<()>> + Send;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RuleProcessor for GmailClient {
|
||||||
|
/// Add Action to the Client for processing
|
||||||
|
fn set_rule(&mut self, value: EolRule) {
|
||||||
|
self.rule = Some(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the execute flag
|
||||||
|
fn set_execute(&mut self, value: bool) {
|
||||||
|
self.execute = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The action set in the rule
|
||||||
|
fn action(&self) -> Option<EolAction> {
|
||||||
|
if let Some(rule) = &self.rule {
|
||||||
|
return rule.action();
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the rule and messages for the label
|
||||||
|
async fn find_rule_and_messages_for_label(&mut self, label: &str) -> Result<()> {
|
||||||
|
self.add_labels(&[label.to_string()]).await?;
|
||||||
|
|
||||||
|
if self.label_ids().is_empty() {
|
||||||
|
return Err(Error::LabelNotFoundInMailbox(label.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(rule) = &self.rule else {
|
||||||
|
return Err(Error::RuleNotFound(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(query) = rule.eol_query() else {
|
||||||
|
return Err(Error::NoQueryStringCalculated(rule.id()));
|
||||||
|
};
|
||||||
|
self.set_query(&query);
|
||||||
|
|
||||||
|
log::info!("{:?}", self.messages());
|
||||||
|
log::info!("Ready to run");
|
||||||
|
self.prepare(0).await?;
|
||||||
|
if self.execute {
|
||||||
|
log::info!("***executing final delete messages***");
|
||||||
|
self.batch_trash().await
|
||||||
|
} else {
|
||||||
|
log::warn!("Execution stopped for dry run");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// /// Trash the messages
|
||||||
|
// async fn trash_messages(&mut self, label: &str) -> Result<()> {
|
||||||
|
// self.add_labels(&[label.to_string()]).await?;
|
||||||
|
|
||||||
|
// if self.label_ids().is_empty() {
|
||||||
|
// return Err(Error::LabelNotFoundInMailbox(label.to_string()));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let Some(rule) = &self.rule else {
|
||||||
|
// return Err(Error::RuleNotFound(0));
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let Some(query) = rule.eol_query() else {
|
||||||
|
// return Err(Error::NoQueryStringCalculated(rule.id()));
|
||||||
|
// };
|
||||||
|
// self.set_query(&query);
|
||||||
|
|
||||||
|
// log::info!("{:?}", self.messages());
|
||||||
|
// log::info!("Ready to run");
|
||||||
|
// self.prepare(0).await?;
|
||||||
|
// if self.execute {
|
||||||
|
// log::info!("***executing final delete messages***");
|
||||||
|
// self.batch_trash().await
|
||||||
|
// } else {
|
||||||
|
// log::warn!("Execution stopped for dry run");
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// Delete the messages
|
||||||
|
// async fn delete_messages(&mut self, label: &str) -> Result<()> {
|
||||||
|
// self.add_labels(&[label.to_string()]).await?;
|
||||||
|
|
||||||
|
// if self.label_ids().is_empty() {
|
||||||
|
// return Err(Error::LabelNotFoundInMailbox(label.to_string()));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let Some(rule) = &self.rule else {
|
||||||
|
// return Err(Error::RuleNotFound(0));
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let Some(query) = rule.eol_query() else {
|
||||||
|
// return Err(Error::NoQueryStringCalculated(rule.id()));
|
||||||
|
// };
|
||||||
|
// self.set_query(&query);
|
||||||
|
|
||||||
|
// log::info!("{:?}", self.messages());
|
||||||
|
// log::info!("Ready to run");
|
||||||
|
// self.prepare(0).await?;
|
||||||
|
// if self.execute {
|
||||||
|
// log::info!("***executing final delete messages***");
|
||||||
|
// self.batch_delete().await
|
||||||
|
// } else {
|
||||||
|
// log::warn!("Execution stopped for dry run");
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
/// Prepare the message list for delete to be completed on execute by batch_delete
|
||||||
|
async fn prepare(&mut self, pages: u32) -> Result<()> {
|
||||||
|
self.run(pages).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the batch delete on the selected messages
|
||||||
|
async fn batch_delete(&self) -> Result<()> {
|
||||||
|
let ids = Some(self.message_ids());
|
||||||
|
|
||||||
|
let batch_request = BatchDeleteMessagesRequest { ids };
|
||||||
|
|
||||||
|
log::trace!("{batch_request:#?}");
|
||||||
|
|
||||||
|
let _res = self
|
||||||
|
.hub()
|
||||||
|
.users()
|
||||||
|
.messages_batch_delete(batch_request, "me")
|
||||||
|
.add_scope("https://mail.google.com/")
|
||||||
|
.doit()
|
||||||
|
.await
|
||||||
|
.map_err(Box::new)?;
|
||||||
|
|
||||||
|
for m in self.messages() {
|
||||||
|
log::info!("Message with subject `{}` deleted.", m.subject());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
/// Move the messages to trash
|
||||||
|
async fn batch_trash(&self) -> Result<()> {
|
||||||
|
let add_label_ids = Some(Vec::from(["TRASH".to_string()]));
|
||||||
|
let ids = Some(self.message_ids());
|
||||||
|
let remove_label_ids = Some(self.label_ids());
|
||||||
|
|
||||||
|
let batch_request = BatchModifyMessagesRequest {
|
||||||
|
add_label_ids,
|
||||||
|
ids,
|
||||||
|
remove_label_ids,
|
||||||
|
};
|
||||||
|
|
||||||
|
log::trace!("{batch_request:#?}");
|
||||||
|
|
||||||
|
let _res = self
|
||||||
|
.hub()
|
||||||
|
.users()
|
||||||
|
.messages_batch_modify(batch_request, "me")
|
||||||
|
.add_scope("https://www.googleapis.com/auth/gmail.modify")
|
||||||
|
.doit()
|
||||||
|
.await
|
||||||
|
.map_err(Box::new)?;
|
||||||
|
|
||||||
|
for m in self.messages() {
|
||||||
|
log::info!("Message with subject `{}` moved to trash.", m.subject());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user