1use super::FileMetadata;
2use crate::config::SyncTask;
3use crate::error::SyncError;
4use crate::report::SyncReport;
5use async_trait::async_trait;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub enum PluginHook {
10 PreSync {
12 task_id: String,
13 priority: HookPriority,
14 },
15 PostSync {
17 task_id: String,
18 priority: HookPriority,
19 },
20 PreFileUpload {
22 task_id: String,
23 priority: HookPriority,
24 },
25 PostFileUpload {
27 task_id: String,
28 priority: HookPriority,
29 },
30 OnError { priority: HookPriority },
32 FileFilter { priority: HookPriority },
34 FilenameTransform { priority: HookPriority },
36 PreEncryption { priority: HookPriority },
38 PostDecryption { priority: HookPriority },
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
43pub enum HookPriority {
44 Highest = 100,
46 High = 80,
48 Normal = 50,
50 Low = 20,
52 Lowest = 0,
54}
55
56impl PluginHook {
57 pub fn name(&self) -> &'static str {
58 match self {
59 Self::PreSync { .. } => "pre_sync",
60 Self::PostSync { .. } => "post_sync",
61 Self::PreFileUpload { .. } => "pre_file_upload",
62 Self::PostFileUpload { .. } => "post_file_upload",
63 Self::OnError { .. } => "on_error",
64 Self::FileFilter { .. } => "file_filter",
65 Self::FilenameTransform { .. } => "filename_transform",
66 Self::PreEncryption { .. } => "pre_encryption",
67 Self::PostDecryption { .. } => "post_decryption",
68 }
69 }
70
71 pub fn priority(&self) -> HookPriority {
72 match self {
73 Self::PreSync { priority, .. } => priority.clone(),
74 Self::PostSync { priority, .. } => priority.clone(),
75 Self::PreFileUpload { priority, .. } => priority.clone(),
76 Self::PostFileUpload { priority, .. } => priority.clone(),
77 Self::OnError { priority, .. } => priority.clone(),
78 Self::FileFilter { priority, .. } => priority.clone(),
79 Self::FilenameTransform { priority, .. } => priority.clone(),
80 Self::PreEncryption { priority, .. } => priority.clone(),
81 Self::PostDecryption { priority, .. } => priority.clone(),
82 }
83 }
84
85 pub fn set_priority(&mut self, priority: HookPriority) {
86 match self {
87 Self::PreSync { priority: p, .. } => *p = priority,
88 Self::PostSync { priority: p, .. } => *p = priority,
89 Self::PreFileUpload { priority: p, .. } => *p = priority,
90 Self::PostFileUpload { priority: p, .. } => *p = priority,
91 Self::OnError { priority: p, .. } => *p = priority,
92 Self::FileFilter { priority: p, .. } => *p = priority,
93 Self::FilenameTransform { priority: p, .. } => *p = priority,
94 Self::PreEncryption { priority: p, .. } => *p = priority,
95 Self::PostDecryption { priority: p, .. } => *p = priority,
96 }
97 }
98}
99
100#[derive(Debug)]
101pub struct HookContext {
102 pub task: Option<SyncTask>,
103 pub report: Option<SyncReport>,
104 pub file: Option<FileMetadata>,
105 pub error: Option<SyncError>,
106 pub custom_data: std::collections::HashMap<String, serde_json::Value>,
107}
108
109impl HookContext {
110 pub fn new() -> Self {
111 Self {
112 task: None,
113 report: None,
114 file: None,
115 error: None,
116 custom_data: std::collections::HashMap::new(),
117 }
118 }
119
120 pub fn with_task(mut self, task: SyncTask) -> Self {
121 self.task = Some(task);
122 self
123 }
124
125 pub fn with_report(mut self, report: SyncReport) -> Self {
126 self.report = Some(report);
127 self
128 }
129
130 pub fn with_file(mut self, file: FileMetadata) -> Self {
131 self.file = Some(file);
132 self
133 }
134
135 pub fn with_error(mut self, error: SyncError) -> Self {
136 self.error = Some(error);
137 self
138 }
139
140 pub fn set_custom_data(&mut self, key: String, value: serde_json::Value) {
141 self.custom_data.insert(key, value);
142 }
143
144 pub fn get_custom_data(&self, key: &str) -> Option<&serde_json::Value> {
145 self.custom_data.get(key)
146 }
147}
148
149#[async_trait]
150pub trait HookHandler: Send + Sync {
151 async fn handle_hook(
153 &self,
154 hook: PluginHook,
155 context: &mut HookContext,
156 ) -> Result<(), SyncError>;
157
158 fn supports_hook(&self, hook: &PluginHook) -> bool;
160
161 fn get_priority(&self, hook: &PluginHook) -> HookPriority;
163}