main
1use crate::config::{Action, Rule};
2use crate::github::{GitHubClient, Notification};
3
4fn truncate_str(s: &str, max: usize) -> String {
5 if s.len() > max {
6 format!("{}…", &s[..max - 1])
7 } else {
8 s.to_string()
9 }
10}
11
12
13pub struct ActionResult {
14 pub notification_id: String,
15 pub action: Action,
16 pub success: bool,
17 pub error: Option<String>,
18 pub rule_name: String,
19 pub repository: String,
20 pub subject_title: String,
21 pub subject_type: String,
22}
23
24pub struct ActionExecutor<'a> {
25 client: &'a GitHubClient,
26 dry_run: bool,
27}
28
29impl<'a> ActionExecutor<'a> {
30 pub fn new(client: &'a GitHubClient, dry_run: bool) -> Self {
31 Self { client, dry_run }
32 }
33
34 /// Execute an action on a notification
35 pub fn execute(
36 &self,
37 notification: &Notification,
38 action: &Action,
39 rule_name: &str,
40 ) -> ActionResult {
41 let mut result = ActionResult {
42 notification_id: notification.id.clone(),
43 action: action.clone(),
44 success: true,
45 error: None,
46 rule_name: rule_name.to_string(),
47 repository: notification.repository.full_name.clone(),
48 subject_title: notification.subject.title.clone(),
49 subject_type: notification.subject.subject_type.clone(),
50 };
51
52 // Skip action doesn't do anything
53 if matches!(action, Action::Skip) {
54 return result;
55 }
56
57 // In dry-run mode, just report success
58 if self.dry_run {
59 return result;
60 }
61
62 // Execute the actual action
63 let exec_result = match action {
64 Action::Done => self.client.mark_thread_done(¬ification.id),
65 Action::Skip => Ok(()), // Already handled above
66 };
67
68 if let Err(e) = exec_result {
69 result.success = false;
70 result.error = Some(e.to_string());
71 }
72
73 result
74 }
75
76 /// Execute actions on a batch of notifications
77 pub fn execute_batch(
78 &self,
79 notifications: &[Notification],
80 rules: &[&Rule],
81 progress: Option<&indicatif::ProgressBar>,
82 ) -> Vec<ActionResult> {
83 use crate::rules::RuleMatcher;
84
85 let mut results = Vec::new();
86
87 for (i, notification) in notifications.iter().enumerate() {
88 if let Some(pb) = progress {
89 pb.set_position(i as u64);
90 }
91
92 if let Some((rule_index, rule)) = RuleMatcher::find_matching_rule(notification, rules)
93 {
94 let default_name = format!("Rule {}", rule_index + 1);
95 let rule_name = rule
96 .name
97 .as_ref()
98 .map(|s| s.as_str())
99 .unwrap_or(&default_name);
100
101 if let Some(pb) = progress {
102 pb.set_message(format!(
103 "{} {}",
104 rule.action,
105 truncate_str(¬ification.repository.full_name, 30),
106 ));
107 }
108
109 let result = self.execute(notification, &rule.action, rule_name);
110 results.push(result);
111 }
112 }
113
114 if let Some(pb) = progress {
115 pb.finish_and_clear();
116 }
117
118 results
119 }
120}