♻️ refactor(processor): implement RuleProcessor trait for GmailClient

- move rule processing logic into the GmailClient struct
- implement RuleProcessor trait for GmailClient to handle trash and delete actions
- add set_rule method to set the rule for processing
- update trash_messages and delete_messages to use the GmailClient's internal state
This commit is contained in:
Jeremiah Russell
2025-10-13 17:21:39 +01:00
committed by Jeremiah Russell
parent 7c397c84d9
commit 4eea2c6135

View File

@@ -1,97 +1,123 @@
// use crate::EolRule;
use std::fmt;
use crate::{
EolAction, Error, GmailClient, Result, config::EolRule, delete::Delete,
message_list::MessageList, trash::Trash,
};
/// Rule processor
#[derive()]
pub struct Processor<'a> {
client: GmailClient,
rule: &'a EolRule,
execute: bool,
// /// Rule processor
// #[derive()]
// pub struct Processor<'a> {
// client: GmailClient,
// rule: &'a EolRule,
// execute: bool,
// }
// impl<'a> fmt::Debug for Processor<'a> {
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// f.debug_struct("Processor")
// .field("rule", &self.rule)
// .field("execute", &self.execute)
// .finish()
// }
// }
// /// Rule processor builder
// #[derive()]
// pub struct ProcessorBuilder<'a> {
// client: GmailClient,
// rule: &'a EolRule,
// execute: bool,
// }
// impl<'a> fmt::Debug for ProcessorBuilder<'a> {
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// f.debug_struct("ProcessorBuilder")
// .field("rule", &self.rule)
// .field("execute", &self.execute)
// .finish()
// }
// }
// impl<'a> ProcessorBuilder<'a> {
// /// Set the execute flag
// pub fn set_execute(&mut self, value: bool) -> &mut Self {
// self.execute = value;
// self
// }
// /// Build the Processor
// pub fn build(&'_ self) -> Processor<'_> {
// Processor {
// client: self.client.clone(),
// rule: self.rule,
// execute: self.execute,
// }
// }
// }
/// Rules processor to apply the configured rules to the mailbox.
pub trait RuleProcessor {
/// 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>;
}
impl<'a> fmt::Debug for Processor<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Processor")
.field("rule", &self.rule)
.field("execute", &self.execute)
.finish()
}
}
impl RuleProcessor for GmailClient {
// /// Initialise a new processor
// pub fn builder(client: &GmailClient, rule: &'a EolRule) -> ProcessorBuilder<'a> {
// ProcessorBuilder {
// client: client.clone(),
// rule,
// execute: false,
// }
// }
/// Rule processor builder
#[derive()]
pub struct ProcessorBuilder<'a> {
client: GmailClient,
rule: &'a EolRule,
execute: bool,
}
impl<'a> fmt::Debug for ProcessorBuilder<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ProcessorBuilder")
.field("rule", &self.rule)
.field("execute", &self.execute)
.finish()
}
}
impl<'a> ProcessorBuilder<'a> {
/// Set the execute flag
pub fn set_execute(&mut self, value: bool) -> &mut Self {
self.execute = value;
self
}
/// Build the Processor
pub fn build(&'_ self) -> Processor<'_> {
Processor {
client: self.client.clone(),
rule: self.rule,
execute: self.execute,
}
}
}
impl<'a> Processor<'a> {
/// Initialise a new processor
pub fn builder(client: &GmailClient, rule: &'a EolRule) -> ProcessorBuilder<'a> {
ProcessorBuilder {
client: client.clone(),
rule,
execute: false,
}
/// Add Action to the Client for processing
fn set_rule(&mut self, rule: EolRule) {
self.rule = Some(rule);
}
/// The action set in the rule
pub fn action(&self) -> Option<EolAction> {
self.rule.action()
fn action(&self) -> Option<EolAction> {
if let Some(rule) = &self.rule {
return rule.action();
}
None
}
/// Trash the messages
pub async fn trash_messages(&mut self, label: &str) -> Result<()> {
self.client.add_labels(&[label.to_string()]).await?;
async fn trash_messages(&mut self, label: &str) -> Result<()> {
self.add_labels(&[label.to_string()]).await?;
if self.client.label_ids().is_empty() {
if self.label_ids().is_empty() {
return Err(Error::LabelNotFoundInMailbox(label.to_string()));
}
let Some(query) = self.rule.eol_query() else {
return Err(Error::NoQueryStringCalculated(self.rule.id()));
let Some(rule) = &self.rule else {
return Err(Error::RuleNotFound(0));
};
self.client.set_query(&query);
log::info!("{:?}", self.client.messages());
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.client.prepare(0).await?;
self.prepare(0).await?;
if self.execute {
log::info!("***executing final delete messages***");
self.client.batch_trash().await
self.batch_trash().await
} else {
log::warn!("Execution stopped for dry run");
Ok(())
@@ -99,24 +125,28 @@ impl<'a> Processor<'a> {
}
/// Delete the messages
pub async fn delete_messages(&mut self, label: &str) -> Result<()> {
self.client.add_labels(&[label.to_string()]).await?;
async fn delete_messages(&mut self, label: &str) -> Result<()> {
self.add_labels(&[label.to_string()]).await?;
if self.client.label_ids().is_empty() {
if self.label_ids().is_empty() {
return Err(Error::LabelNotFoundInMailbox(label.to_string()));
}
let Some(query) = self.rule.eol_query() else {
return Err(Error::NoQueryStringCalculated(self.rule.id()));
let Some(rule) = &self.rule else {
return Err(Error::RuleNotFound(0));
};
self.client.set_query(&query);
log::info!("{:?}", self.client.messages());
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.client.prepare(0).await?;
self.prepare(0).await?;
if self.execute {
log::info!("***executing final delete messages***");
self.client.batch_delete().await
self.batch_delete().await
} else {
log::warn!("Execution stopped for dry run");