cloud_disk_sync/plugins/
hooks.rs

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    /// 同步前钩子
11    PreSync {
12        task_id: String,
13        priority: HookPriority,
14    },
15    /// 同步后钩子
16    PostSync {
17        task_id: String,
18        priority: HookPriority,
19    },
20    /// 文件上传前钩子
21    PreFileUpload {
22        task_id: String,
23        priority: HookPriority,
24    },
25    /// 文件上传后钩子
26    PostFileUpload {
27        task_id: String,
28        priority: HookPriority,
29    },
30    /// 错误处理钩子
31    OnError { priority: HookPriority },
32    /// 文件过滤器钩子
33    FileFilter { priority: HookPriority },
34    /// 文件名转换钩子
35    FilenameTransform { priority: HookPriority },
36    /// 加密前钩子
37    PreEncryption { priority: HookPriority },
38    /// 解密后钩子
39    PostDecryption { priority: HookPriority },
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
43pub enum HookPriority {
44    /// 最高优先级(最先执行)
45    Highest = 100,
46    /// 高优先级
47    High = 80,
48    /// 普通优先级(默认)
49    Normal = 50,
50    /// 低优先级
51    Low = 20,
52    /// 最低优先级(最后执行)
53    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    /// 处理钩子
152    async fn handle_hook(
153        &self,
154        hook: PluginHook,
155        context: &mut HookContext,
156    ) -> Result<(), SyncError>;
157
158    /// 钩子是否支持特定类型
159    fn supports_hook(&self, hook: &PluginHook) -> bool;
160
161    /// 获取钩子优先级
162    fn get_priority(&self, hook: &PluginHook) -> HookPriority;
163}