🎨 style(rule_processor): apply rustfmt and resolve clippy warnings
This commit is contained in:
committed by
Jeremiah Russell
parent
f16eb0a768
commit
06d63fbd03
@@ -28,7 +28,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ```text
|
//! ```text
|
||||||
//! use cull_gmail::{GmailClient, RuleProcessor, ClientConfig};
|
//! use cull_gmail::{GmailClient, RuleProcessor, ClientConfig};
|
||||||
//!
|
//!
|
||||||
//! async fn example() -> Result<(), Box<dyn std::error::Error>> {
|
//! async fn example() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
//! // Configure Gmail client with credentials
|
//! // Configure Gmail client with credentials
|
||||||
//! let config = ClientConfig::builder()
|
//! let config = ClientConfig::builder()
|
||||||
@@ -59,7 +59,7 @@ use crate::{EolAction, Error, GmailClient, Result, message_list::MessageList, ru
|
|||||||
const TRASH_LABEL: &str = "TRASH";
|
const TRASH_LABEL: &str = "TRASH";
|
||||||
|
|
||||||
/// Gmail API scope for modifying messages (recommended scope for most operations).
|
/// Gmail API scope for modifying messages (recommended scope for most operations).
|
||||||
///
|
///
|
||||||
/// This scope allows adding/removing labels, moving messages to trash, and other
|
/// This scope allows adding/removing labels, moving messages to trash, and other
|
||||||
/// modification operations. Preferred over broader scopes for security.
|
/// modification operations. Preferred over broader scopes for security.
|
||||||
const GMAIL_MODIFY_SCOPE: &str = "https://www.googleapis.com/auth/gmail.modify";
|
const GMAIL_MODIFY_SCOPE: &str = "https://www.googleapis.com/auth/gmail.modify";
|
||||||
@@ -73,16 +73,16 @@ const GMAIL_MODIFY_SCOPE: &str = "https://www.googleapis.com/auth/gmail.modify";
|
|||||||
pub(crate) trait MailOperations {
|
pub(crate) trait MailOperations {
|
||||||
/// Add labels to the client for filtering
|
/// Add labels to the client for filtering
|
||||||
fn add_labels(&mut self, labels: &[String]) -> Result<()>;
|
fn add_labels(&mut self, labels: &[String]) -> Result<()>;
|
||||||
|
|
||||||
/// Get the current label IDs
|
/// Get the current label IDs
|
||||||
fn label_ids(&self) -> Vec<String>;
|
fn label_ids(&self) -> Vec<String>;
|
||||||
|
|
||||||
/// Set the query string for message filtering
|
/// Set the query string for message filtering
|
||||||
fn set_query(&mut self, query: &str);
|
fn set_query(&mut self, query: &str);
|
||||||
|
|
||||||
/// Prepare messages by fetching from Gmail API
|
/// Prepare messages by fetching from Gmail API
|
||||||
fn prepare(&mut self, pages: u32) -> impl std::future::Future<Output = Result<()>> + Send;
|
fn prepare(&mut self, pages: u32) -> impl std::future::Future<Output = Result<()>> + Send;
|
||||||
|
|
||||||
/// Execute trash operation on prepared messages
|
/// Execute trash operation on prepared messages
|
||||||
fn batch_trash(&self) -> impl std::future::Future<Output = Result<()>> + Send;
|
fn batch_trash(&self) -> impl std::future::Future<Output = Result<()>> + Send;
|
||||||
}
|
}
|
||||||
@@ -100,22 +100,22 @@ async fn process_label_with_rule<T: MailOperations>(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Add the label for filtering
|
// Add the label for filtering
|
||||||
client.add_labels(&[label.to_owned()])?;
|
client.add_labels(&[label.to_owned()])?;
|
||||||
|
|
||||||
// Validate label exists in mailbox
|
// Validate label exists in mailbox
|
||||||
if client.label_ids().is_empty() {
|
if client.label_ids().is_empty() {
|
||||||
return Err(Error::LabelNotFoundInMailbox(label.to_owned()));
|
return Err(Error::LabelNotFoundInMailbox(label.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get query from rule
|
// Get query from rule
|
||||||
let Some(query) = rule.eol_query() else {
|
let Some(query) = rule.eol_query() else {
|
||||||
return Err(Error::NoQueryStringCalculated(rule.id()));
|
return Err(Error::NoQueryStringCalculated(rule.id()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the query and prepare messages
|
// Set the query and prepare messages
|
||||||
client.set_query(&query);
|
client.set_query(&query);
|
||||||
log::info!("Ready to process messages for label: {label}");
|
log::info!("Ready to process messages for label: {label}");
|
||||||
client.prepare(pages).await?;
|
client.prepare(pages).await?;
|
||||||
|
|
||||||
// Execute or dry-run based on execute flag
|
// Execute or dry-run based on execute flag
|
||||||
if execute {
|
if execute {
|
||||||
log::info!("Execute mode: applying rule action to messages");
|
log::info!("Execute mode: applying rule action to messages");
|
||||||
@@ -131,19 +131,19 @@ impl MailOperations for GmailClient {
|
|||||||
fn add_labels(&mut self, labels: &[String]) -> Result<()> {
|
fn add_labels(&mut self, labels: &[String]) -> Result<()> {
|
||||||
MessageList::add_labels(self, labels)
|
MessageList::add_labels(self, labels)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn label_ids(&self) -> Vec<String> {
|
fn label_ids(&self) -> Vec<String> {
|
||||||
MessageList::label_ids(self)
|
MessageList::label_ids(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_query(&mut self, query: &str) {
|
fn set_query(&mut self, query: &str) {
|
||||||
MessageList::set_query(self, query);
|
MessageList::set_query(self, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn prepare(&mut self, pages: u32) -> Result<()> {
|
async fn prepare(&mut self, pages: u32) -> Result<()> {
|
||||||
self.get_messages(pages).await
|
self.get_messages(pages).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn batch_trash(&self) -> Result<()> {
|
async fn batch_trash(&self) -> Result<()> {
|
||||||
RuleProcessor::batch_trash(self).await
|
RuleProcessor::batch_trash(self).await
|
||||||
}
|
}
|
||||||
@@ -332,9 +332,9 @@ impl RuleProcessor for GmailClient {
|
|||||||
let Some(rule) = self.rule.clone() else {
|
let Some(rule) = self.rule.clone() else {
|
||||||
return Err(Error::RuleNotFound(0));
|
return Err(Error::RuleNotFound(0));
|
||||||
};
|
};
|
||||||
|
|
||||||
let execute = self.execute;
|
let execute = self.execute;
|
||||||
|
|
||||||
// Delegate to internal orchestration function
|
// Delegate to internal orchestration function
|
||||||
process_label_with_rule(self, &rule, label, 0, execute).await
|
process_label_with_rule(self, &rule, label, 0, execute).await
|
||||||
}
|
}
|
||||||
@@ -449,15 +449,15 @@ impl RuleProcessor for GmailClient {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{rules::EolRule, EolAction, Error};
|
use crate::{EolAction, Error, rules::EolRule};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
/// Test helper to create a simple EolRule with or without a query
|
/// Test helper to create a simple EolRule with or without a query
|
||||||
fn create_test_rule(id: usize, has_query: bool) -> EolRule {
|
fn create_test_rule(id: usize, has_query: bool) -> EolRule {
|
||||||
use crate::{MessageAge, Retention};
|
use crate::{MessageAge, Retention};
|
||||||
|
|
||||||
let mut rule = EolRule::new(id);
|
let mut rule = EolRule::new(id);
|
||||||
|
|
||||||
if has_query {
|
if has_query {
|
||||||
// Create a rule that will generate a query (using retention days)
|
// Create a rule that will generate a query (using retention days)
|
||||||
let retention = Retention::new(MessageAge::Days(30), false);
|
let retention = Retention::new(MessageAge::Days(30), false);
|
||||||
@@ -465,7 +465,7 @@ mod tests {
|
|||||||
rule.add_label("test-label");
|
rule.add_label("test-label");
|
||||||
}
|
}
|
||||||
// For rules without query, we just return the basic rule with no retention set
|
// For rules without query, we just return the basic rule with no retention set
|
||||||
|
|
||||||
rule
|
rule
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +482,7 @@ mod tests {
|
|||||||
should_fail_batch_trash: bool,
|
should_fail_batch_trash: bool,
|
||||||
simulate_missing_labels: bool, // Flag to simulate labels not being found
|
simulate_missing_labels: bool, // Flag to simulate labels not being found
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FakeClient {
|
impl Default for FakeClient {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -504,14 +504,13 @@ mod tests {
|
|||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a client that simulates missing labels (add_labels succeeds but no label_ids)
|
/// Create a client that simulates missing labels (add_labels succeeds but no label_ids)
|
||||||
fn with_missing_labels() -> Self {
|
fn with_missing_labels() -> Self {
|
||||||
let mut client = Self::default();
|
Self {
|
||||||
client.simulate_missing_labels = true;
|
simulate_missing_labels: true,
|
||||||
// This client will accept add_labels but won't populate label_ids,
|
..Default::default()
|
||||||
// simulating the case where labels don't exist in the mailbox
|
}
|
||||||
client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_labels(label_ids: Vec<String>) -> Self {
|
fn with_labels(label_ids: Vec<String>) -> Self {
|
||||||
@@ -522,16 +521,23 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn with_failure(failure_type: &str) -> Self {
|
fn with_failure(failure_type: &str) -> Self {
|
||||||
let mut client = Self::default();
|
|
||||||
match failure_type {
|
match failure_type {
|
||||||
"add_labels" => client.should_fail_add_labels = true,
|
"add_labels" => Self {
|
||||||
"prepare" => client.should_fail_prepare = true,
|
should_fail_add_labels: true,
|
||||||
"batch_trash" => client.should_fail_batch_trash = true,
|
..Default::default()
|
||||||
_ => {},
|
},
|
||||||
|
"prepare" => Self {
|
||||||
|
should_fail_prepare: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
"batch_trash" => Self {
|
||||||
|
should_fail_batch_trash: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
_ => Self::default(),
|
||||||
}
|
}
|
||||||
client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_batch_trash_call_count(&self) -> u32 {
|
fn get_batch_trash_call_count(&self) -> u32 {
|
||||||
*self.batch_trash_call_count.lock().unwrap()
|
*self.batch_trash_call_count.lock().unwrap()
|
||||||
}
|
}
|
||||||
@@ -562,7 +568,7 @@ mod tests {
|
|||||||
async fn prepare(&mut self, _pages: u32) -> Result<()> {
|
async fn prepare(&mut self, _pages: u32) -> Result<()> {
|
||||||
// Always increment the counter to track that prepare was called
|
// Always increment the counter to track that prepare was called
|
||||||
self.prepare_call_count += 1;
|
self.prepare_call_count += 1;
|
||||||
|
|
||||||
if self.should_fail_prepare {
|
if self.should_fail_prepare {
|
||||||
return Err(Error::NoLabelsFound); // Use a valid error variant
|
return Err(Error::NoLabelsFound); // Use a valid error variant
|
||||||
}
|
}
|
||||||
@@ -573,7 +579,7 @@ mod tests {
|
|||||||
async fn batch_trash(&self) -> Result<()> {
|
async fn batch_trash(&self) -> Result<()> {
|
||||||
// Always increment the counter to track that batch_trash was called
|
// Always increment the counter to track that batch_trash was called
|
||||||
*self.batch_trash_call_count.lock().unwrap() += 1;
|
*self.batch_trash_call_count.lock().unwrap() += 1;
|
||||||
|
|
||||||
if self.should_fail_batch_trash {
|
if self.should_fail_batch_trash {
|
||||||
return Err(Error::InvalidPagingMode); // Use a valid error variant
|
return Err(Error::InvalidPagingMode); // Use a valid error variant
|
||||||
}
|
}
|
||||||
@@ -642,7 +648,7 @@ mod tests {
|
|||||||
// Create a client that will fail on prepare but has valid labels
|
// Create a client that will fail on prepare but has valid labels
|
||||||
let mut client = FakeClient::with_labels(vec!["test-label".to_string()]);
|
let mut client = FakeClient::with_labels(vec!["test-label".to_string()]);
|
||||||
client.should_fail_prepare = true; // Set the failure flag directly
|
client.should_fail_prepare = true; // Set the failure flag directly
|
||||||
|
|
||||||
let rule = create_test_rule(5, true);
|
let rule = create_test_rule(5, true);
|
||||||
let label = "test-label";
|
let label = "test-label";
|
||||||
|
|
||||||
@@ -658,7 +664,7 @@ mod tests {
|
|||||||
// Create a client that will fail on batch_trash but has valid labels
|
// Create a client that will fail on batch_trash but has valid labels
|
||||||
let mut client = FakeClient::with_labels(vec!["test-label".to_string()]);
|
let mut client = FakeClient::with_labels(vec!["test-label".to_string()]);
|
||||||
client.should_fail_batch_trash = true; // Set the failure flag directly
|
client.should_fail_batch_trash = true; // Set the failure flag directly
|
||||||
|
|
||||||
let rule = create_test_rule(6, true);
|
let rule = create_test_rule(6, true);
|
||||||
let label = "test-label";
|
let label = "test-label";
|
||||||
|
|
||||||
@@ -689,7 +695,7 @@ mod tests {
|
|||||||
fn test_rule_processor_setters_and_getters() {
|
fn test_rule_processor_setters_and_getters() {
|
||||||
// Note: This test would need a mock GmailClient implementation
|
// Note: This test would need a mock GmailClient implementation
|
||||||
// For now, we'll create a simple struct that implements RuleProcessor
|
// For now, we'll create a simple struct that implements RuleProcessor
|
||||||
|
|
||||||
struct MockProcessor {
|
struct MockProcessor {
|
||||||
rule: Option<EolRule>,
|
rule: Option<EolRule>,
|
||||||
execute: bool,
|
execute: bool,
|
||||||
@@ -743,7 +749,7 @@ mod tests {
|
|||||||
// Test execute flag setting
|
// Test execute flag setting
|
||||||
processor.set_execute(true);
|
processor.set_execute(true);
|
||||||
assert!(processor.execute);
|
assert!(processor.execute);
|
||||||
|
|
||||||
processor.set_execute(false);
|
processor.set_execute(false);
|
||||||
assert!(!processor.execute);
|
assert!(!processor.execute);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user