Skip to main content

openlark_docs/common/api_endpoints/
drive.rs

1//! Drive、Explorer 与 Permission API 端点目录。
2
3use super::CatalogEndpoint;
4use openlark_core::api::{ApiRequest, HttpMethod};
5
6/// CCM Drive Explorer API Old V2 端点枚举
7/// 对应 meta.project = ccm_drive_explorer, meta.version = old
8#[derive(Debug, Clone, PartialEq)]
9#[cfg_attr(test, derive(strum_macros::EnumIter))]
10pub enum CcmDriveExplorerApiOld {
11    /// 获取我的空间(根文件夹)元数据
12    RootFolderMeta,
13    /// 获取文件夹元数据
14    FolderMeta(String), // folder_token
15    /// 新建文件
16    File(String), // folder_token
17    /// 删除Sheet
18    FileSpreadsheets(String), // spreadsheet_token
19    /// 复制文档
20    FileCopy(String), // file_token
21    /// 删除Doc
22    FileDocs(String), // doc_token
23    /// 获取文件夹下的文档清单
24    FolderChildren(String), // folder_token
25    /// 新建文件夹
26    Folder(String), // folder_token
27}
28
29impl CcmDriveExplorerApiOld {
30    /// 生成对应的 URL
31    pub fn to_url(&self) -> String {
32        match self {
33            CcmDriveExplorerApiOld::RootFolderMeta => {
34                "/open-apis/drive/explorer/v2/root_folder/meta".to_string()
35            }
36            CcmDriveExplorerApiOld::FolderMeta(folder_token) => {
37                format!("/open-apis/drive/explorer/v2/folder/{folder_token}/meta")
38            }
39            CcmDriveExplorerApiOld::File(folder_token) => {
40                format!("/open-apis/drive/explorer/v2/file/{folder_token}")
41            }
42            CcmDriveExplorerApiOld::FileSpreadsheets(spreadsheet_token) => {
43                format!("/open-apis/drive/explorer/v2/file/spreadsheets/{spreadsheet_token}")
44            }
45            CcmDriveExplorerApiOld::FileCopy(file_token) => {
46                format!("/open-apis/drive/explorer/v2/file/copy/files/{file_token}")
47            }
48            CcmDriveExplorerApiOld::FileDocs(doc_token) => {
49                format!("/open-apis/drive/explorer/v2/file/docs/{doc_token}")
50            }
51            CcmDriveExplorerApiOld::FolderChildren(folder_token) => {
52                format!("/open-apis/drive/explorer/v2/folder/{folder_token}/children")
53            }
54            CcmDriveExplorerApiOld::Folder(folder_token) => {
55                format!("/open-apis/drive/explorer/v2/folder/{folder_token}")
56            }
57        }
58    }
59
60    /// 返回配置了稳定请求语义的请求。
61    pub fn to_request<R>(&self) -> ApiRequest<R> {
62        <Self as CatalogEndpoint>::to_request(self)
63    }
64}
65
66impl CatalogEndpoint for CcmDriveExplorerApiOld {
67    fn to_url(&self) -> String {
68        CcmDriveExplorerApiOld::to_url(self)
69    }
70
71    fn method(&self) -> HttpMethod {
72        match self {
73            Self::RootFolderMeta | Self::FolderMeta(_) | Self::FolderChildren(_) => HttpMethod::Get,
74            Self::File(_) | Self::FileCopy(_) | Self::Folder(_) => HttpMethod::Post,
75            Self::FileSpreadsheets(_) | Self::FileDocs(_) => HttpMethod::Delete,
76        }
77    }
78
79    // supported_access_token_types 使用 trait 默认实现(User + Tenant)
80}
81
82/// CCM Drive Explorer API V1 端点枚举
83/// 对应 meta.project = ccm_drive_explorer, meta.version = v1
84#[derive(Debug, Clone, PartialEq)]
85#[cfg_attr(test, derive(strum_macros::EnumIter))]
86pub enum CcmDriveExplorerApi {
87    /// 获取根目录元数据
88    RootFolderMeta,
89    /// 获取文件夹元数据
90    FolderMeta(String), // folder_token
91    /// 获取文件元数据
92    File(String), // file_token
93    /// 复制文件
94    FileCopy(String), // file_token
95    /// 获取文档文件信息
96    FileDocs(String), // file_token
97    /// 获取表格文件信息
98    FileSpreadsheets(String), // file_token
99    /// 获取文件夹子内容
100    FolderChildren(String), // folder_token
101    /// 创建文件夹
102    Folder,
103}
104
105impl CcmDriveExplorerApi {
106    /// 生成对应的 URL
107    pub fn to_url(&self) -> String {
108        match self {
109            CcmDriveExplorerApi::RootFolderMeta => {
110                "/open-apis/drive/v1/explorer/root_folder/meta".to_string()
111            }
112            CcmDriveExplorerApi::FolderMeta(folder_token) => {
113                format!("/open-apis/drive/v1/explorer/folder/{folder_token}/meta")
114            }
115            CcmDriveExplorerApi::File(file_token) => {
116                format!("/open-apis/drive/v1/explorer/file/{file_token}")
117            }
118            CcmDriveExplorerApi::FileCopy(file_token) => {
119                format!("/open-apis/drive/v1/explorer/file/copy/files/{file_token}")
120            }
121            CcmDriveExplorerApi::FileDocs(file_token) => {
122                format!("/open-apis/drive/v1/explorer/file/docs/{file_token}")
123            }
124            CcmDriveExplorerApi::FileSpreadsheets(file_token) => {
125                format!("/open-apis/drive/v1/explorer/file/spreadsheets/{file_token}")
126            }
127            CcmDriveExplorerApi::FolderChildren(folder_token) => {
128                format!("/open-apis/drive/v1/explorer/folder/{folder_token}/children")
129            }
130            CcmDriveExplorerApi::Folder => "/open-apis/drive/v1/explorer/folder".to_string(),
131        }
132    }
133
134    /// 生成带参数的 URL
135    pub fn to_url_with_params(&self, params: &[(&str, String)]) -> String {
136        let base_url = self.to_url();
137        if params.is_empty() {
138            return base_url;
139        }
140
141        let query_string = params
142            .iter()
143            .map(|(key, value)| format!("{}={}", key, simple_url_encode(value)))
144            .collect::<Vec<_>>()
145            .join("&");
146
147        format!("{base_url}?{query_string}")
148    }
149
150    /// 返回配置了稳定请求语义的请求。
151    pub fn to_request<R>(&self) -> ApiRequest<R> {
152        <Self as CatalogEndpoint>::to_request(self)
153    }
154}
155
156impl CatalogEndpoint for CcmDriveExplorerApi {
157    fn to_url(&self) -> String {
158        CcmDriveExplorerApi::to_url(self)
159    }
160
161    fn method(&self) -> HttpMethod {
162        match self {
163            Self::RootFolderMeta
164            | Self::FolderMeta(_)
165            | Self::File(_)
166            | Self::FileDocs(_)
167            | Self::FileSpreadsheets(_)
168            | Self::FolderChildren(_) => HttpMethod::Get,
169            Self::FileCopy(_) | Self::Folder => HttpMethod::Post,
170        }
171    }
172
173    // supported_access_token_types 使用 trait 默认实现(User + Tenant)
174}
175
176/// 简单的URL编码函数,用于查询参数编码
177fn simple_url_encode(input: &str) -> String {
178    input
179        .chars()
180        .map(|c| match c {
181            'A'..='Z' | 'a'..='z' | '0'..='9' | '-' | '_' | '.' | '~' => c.to_string(),
182            _ => format!("%{:02X}", c as u8),
183        })
184        .collect()
185}
186
187/// CCM Drive Permission API V1 端点枚举
188/// 对应 meta.project = permission, meta.version = v1
189#[derive(Debug, Clone, PartialEq)]
190#[cfg_attr(test, derive(strum_macros::EnumIter))]
191pub enum PermissionApi {
192    /// 判断协作者是否有某权限
193    MemberPermitted,
194    /// 转移拥有者
195    MemberTransfer,
196    /// 获取云文档权限设置V2
197    Public,
198}
199
200impl PermissionApi {
201    /// 生成对应的 URL
202    pub fn to_url(&self) -> String {
203        match self {
204            PermissionApi::MemberPermitted => {
205                "/open-apis/drive/v1/permission/member/permitted".to_string()
206            }
207            PermissionApi::MemberTransfer => {
208                "/open-apis/drive/v1/permission/member/transfer".to_string()
209            }
210            PermissionApi::Public => "/open-apis/drive/v1/permission/v2/public/".to_string(),
211        }
212    }
213
214    /// 返回配置了稳定请求语义的请求。
215    pub fn to_request<R>(&self) -> ApiRequest<R> {
216        <Self as CatalogEndpoint>::to_request(self)
217    }
218}
219
220impl CatalogEndpoint for PermissionApi {
221    fn to_url(&self) -> String {
222        PermissionApi::to_url(self)
223    }
224
225    fn method(&self) -> HttpMethod {
226        HttpMethod::Post
227    }
228
229    // supported_access_token_types 使用 trait 默认实现(User + Tenant)
230}
231
232/// CCM Drive Permission API Old V2 端点枚举
233/// 对应 meta.project = permission, meta.version = old
234#[derive(Debug, Clone, PartialEq)]
235#[cfg_attr(test, derive(strum_macros::EnumIter))]
236pub enum PermissionApiOld {
237    /// 判断协作者是否有某权限
238    MemberPermitted,
239    /// 转移拥有者
240    MemberTransfer,
241    /// 获取云文档权限设置V2
242    Public,
243}
244
245impl PermissionApiOld {
246    /// 生成对应的 URL
247    pub fn to_url(&self) -> String {
248        match self {
249            PermissionApiOld::MemberPermitted => {
250                "/open-apis/drive/v1/permission/member/permitted".to_string()
251            }
252            PermissionApiOld::MemberTransfer => {
253                "/open-apis/drive/v1/permission/member/transfer".to_string()
254            }
255            PermissionApiOld::Public => "/open-apis/drive/v1/permission/v2/public/".to_string(),
256        }
257    }
258
259    /// 返回配置了稳定请求语义的请求。
260    pub fn to_request<R>(&self) -> ApiRequest<R> {
261        <Self as CatalogEndpoint>::to_request(self)
262    }
263}
264
265impl CatalogEndpoint for PermissionApiOld {
266    fn to_url(&self) -> String {
267        PermissionApiOld::to_url(self)
268    }
269
270    fn method(&self) -> HttpMethod {
271        HttpMethod::Post
272    }
273
274    // supported_access_token_types 使用 trait 默认实现(User + Tenant)
275}
276
277/// Drive API 端点枚举
278#[derive(Debug, Clone, PartialEq)]
279#[cfg_attr(test, derive(strum_macros::EnumIter))]
280pub enum DriveApi {
281    // V1 APIs - 文件操作
282    /// 获取文件夹中的文件清单
283    ListFiles,
284    /// 新建文件夹
285    CreateFolder,
286    /// 查询异步任务状态
287    TaskCheck,
288    /// 获取文件元数据(批量查询)
289    BatchQueryMetas,
290    /// 获取文件统计信息
291    GetFileStatistics(String), // file_token
292    /// 获取文件访问记录
293    ListFileViewRecords(String), // file_token
294    /// 复制文件
295    CopyFile(String), // file_token
296    /// 移动文件或文件夹
297    MoveFile(String), // file_token
298    /// 删除文件或文件夹
299    DeleteFile(String), // file_token
300    /// 创建文件快捷方式
301    CreateShortcut,
302    /// 上传文件
303    UploadFile,
304    /// 分片上传文件-预上传
305    UploadPrepare,
306    /// 分片上传文件-上传分片
307    UploadPart,
308    /// 分片上传文件-完成上传
309    UploadFinish,
310    /// 下载文件
311    DownloadFile(String), // file_token
312    /// 创建导入任务
313    CreateImportTask,
314    /// 查询导入任务结果
315    GetImportTask(String), // ticket
316    /// 创建导出任务
317    CreateExportTask,
318    /// 查询导出任务结果
319    GetExportTask(String), // ticket
320    /// 下载导出文件
321    DownloadExportFile(String), // file_token
322    /// 上传素材
323    UploadMedia,
324    /// 分片上传素材-预上传
325    UploadMediaPrepare,
326    /// 分片上传素材-上传分片
327    UploadMediaPart,
328    /// 分片上传素材-完成上传
329    UploadMediaFinish,
330    /// 下载素材
331    DownloadMedia(String), // file_token
332    /// 获取素材临时下载链接
333    GetMediaTempDownloadUrls,
334    /// 创建文档版本
335    CreateFileVersion(String), // file_token
336    /// 获取文档版本列表
337    ListFileVersions(String), // file_token
338    /// 获取文档版本信息
339    GetFileVersion(String, String), // file_token, version_id
340    /// 删除文档版本
341    DeleteFileVersion(String, String), // file_token, version_id
342    /// 订阅云文档事件
343    SubscribeFile(String), // file_token
344    /// 查询云文档事件订阅状态
345    GetFileSubscribe(String), // file_token
346    /// 取消云文档事件订阅
347    DeleteFileSubscribe(String), // file_token
348    /// 增加协作者权限
349    CreatePermissionMember(String), // token
350    /// 批量增加协作者权限
351    BatchCreatePermissionMember(String), // token
352    /// 更新协作者权限
353    UpdatePermissionMember(String, String), // token, member_id
354    /// 获取云文档协作者
355    ListPermissionMembers(String), // token
356    /// 移除云文档协作者权限
357    DeletePermissionMember(String, String), // token, member_id
358    /// 转移云文档所有者
359    TransferOwner(String), // token
360    /// 判断用户云文档权限
361    AuthPermissionMember(String), // token
362    /// 更新云文档权限设置
363    UpdatePublicPermission(String), // token
364    /// 获取云文档权限设置
365    GetPublicPermission(String), // token
366    /// 启用云文档密码
367    CreatePublicPassword(String), // token
368    /// 刷新云文档密码
369    UpdatePublicPassword(String), // token
370    /// 停用云文档密码
371    DeletePublicPassword(String), // token
372    /// 获取云文档所有评论
373    ListFileComments(String), // file_token
374    /// 批量获取评论
375    BatchQueryComments(String), // file_token
376    /// 解决/恢复评论
377    PatchComment(String, String), // file_token, comment_id
378    /// 添加全文评论
379    CreateComment(String), // file_token
380    /// 获取全文评论
381    GetComment(String, String), // file_token, comment_id
382    /// 获取回复信息
383    ListCommentReplies(String, String), // file_token, comment_id
384    /// 添加回复
385    CreateCommentReply(String, String), // file_token, comment_id
386    /// 更新回复的内容
387    UpdateCommentReply(String, String, String), // file_token, comment_id, reply_id
388    /// 删除回复
389    DeleteCommentReply(String, String, String), // file_token, comment_id, reply_id
390    /// 订阅用户云文档事件
391    UserSubscription,
392    /// 取消用户云文档事件订阅
393    UserRemoveSubscription,
394    /// 查询用户云文档事件订阅状态
395    UserSubscriptionStatus,
396    /// 获取订阅状态
397    GetFileSubscription(String, String), // file_token, subscription_id
398    /// 创建订阅
399    CreateFileSubscription(String), // file_token
400    /// 更新订阅状态
401    UpdateFileSubscription(String, String), // file_token, subscription_id
402
403    // V2 APIs
404    /// 获取云文档的点赞者列表
405    ListFileLikes(String), // file_token
406    /// 获取云文档权限设置(v2)
407    GetPublicPermissionV2(String), // token
408    /// 更新云文档权限设置(v2)
409    UpdatePublicPermissionV2(String), // token
410    /// 添加或取消评论表情回应
411    UpdateCommentReaction(String), // file_token
412
413    // Media Upload Task APIs
414    /// 创建媒体上传任务
415    MediaUploadTasks,
416    /// 获取媒体上传任务
417    MediaUploadTask(String), // task_id
418    /// 创建媒体分享链接
419    CreateMediaShareLink(String), // file_token
420    /// 获取公开密码
421    GetPublicPassword(String), // file_token
422}
423
424impl DriveApi {
425    /// 生成对应的 URL
426    pub fn to_url(&self) -> String {
427        match self {
428            // V1 File APIs
429            DriveApi::ListFiles => "/open-apis/drive/v1/files".to_string(),
430            DriveApi::CreateFolder => "/open-apis/drive/v1/files/create_folder".to_string(),
431            DriveApi::TaskCheck => "/open-apis/drive/v1/files/task_check".to_string(),
432            DriveApi::BatchQueryMetas => "/open-apis/drive/v1/metas/batch_query".to_string(),
433            DriveApi::GetFileStatistics(file_token) => {
434                format!("/open-apis/drive/v1/files/{file_token}/statistics")
435            }
436            DriveApi::ListFileViewRecords(file_token) => {
437                format!("/open-apis/drive/v1/files/{file_token}/view_records")
438            }
439            DriveApi::CopyFile(file_token) => {
440                format!("/open-apis/drive/v1/files/{file_token}/copy")
441            }
442            DriveApi::MoveFile(file_token) => {
443                format!("/open-apis/drive/v1/files/{file_token}/move")
444            }
445            DriveApi::DeleteFile(file_token) => {
446                format!("/open-apis/drive/v1/files/{file_token}")
447            }
448            DriveApi::CreateShortcut => "/open-apis/drive/v1/files/create_shortcut".to_string(),
449            DriveApi::UploadFile => "/open-apis/drive/v1/files/upload_all".to_string(),
450            DriveApi::UploadPrepare => "/open-apis/drive/v1/files/upload_prepare".to_string(),
451            DriveApi::UploadPart => "/open-apis/drive/v1/files/upload_part".to_string(),
452            DriveApi::UploadFinish => "/open-apis/drive/v1/files/upload_finish".to_string(),
453            DriveApi::DownloadFile(file_token) => {
454                format!("/open-apis/drive/v1/files/{file_token}/download")
455            }
456
457            // Import/Export Task APIs
458            DriveApi::CreateImportTask => "/open-apis/drive/v1/import_tasks".to_string(),
459            DriveApi::GetImportTask(ticket) => {
460                format!("/open-apis/drive/v1/import_tasks/{ticket}")
461            }
462            DriveApi::CreateExportTask => "/open-apis/drive/v1/export_tasks".to_string(),
463            DriveApi::GetExportTask(ticket) => {
464                format!("/open-apis/drive/v1/export_tasks/{ticket}")
465            }
466            DriveApi::DownloadExportFile(file_token) => {
467                format!("/open-apis/drive/v1/export_tasks/file/{file_token}/download")
468            }
469
470            // Media APIs
471            DriveApi::UploadMedia => "/open-apis/drive/v1/medias/upload_all".to_string(),
472            DriveApi::UploadMediaPrepare => "/open-apis/drive/v1/medias/upload_prepare".to_string(),
473            DriveApi::UploadMediaPart => "/open-apis/drive/v1/medias/upload_part".to_string(),
474            DriveApi::UploadMediaFinish => "/open-apis/drive/v1/medias/upload_finish".to_string(),
475            DriveApi::DownloadMedia(file_token) => {
476                format!("/open-apis/drive/v1/medias/{file_token}/download")
477            }
478            DriveApi::GetMediaTempDownloadUrls => {
479                "/open-apis/drive/v1/medias/batch_get_tmp_download_url".to_string()
480            }
481
482            // File Version APIs
483            DriveApi::CreateFileVersion(file_token) => {
484                format!("/open-apis/drive/v1/files/{file_token}/versions")
485            }
486            DriveApi::ListFileVersions(file_token) => {
487                format!("/open-apis/drive/v1/files/{file_token}/versions")
488            }
489            DriveApi::GetFileVersion(file_token, version_id) => {
490                format!("/open-apis/drive/v1/files/{file_token}/versions/{version_id}")
491            }
492            DriveApi::DeleteFileVersion(file_token, version_id) => {
493                format!("/open-apis/drive/v1/files/{file_token}/versions/{version_id}")
494            }
495
496            // Subscription APIs
497            DriveApi::SubscribeFile(file_token) => {
498                format!("/open-apis/drive/v1/files/{file_token}/subscribe")
499            }
500            DriveApi::GetFileSubscribe(file_token) => {
501                format!("/open-apis/drive/v1/files/{file_token}/get_subscribe")
502            }
503            DriveApi::DeleteFileSubscribe(file_token) => {
504                format!("/open-apis/drive/v1/files/{file_token}/delete_subscribe")
505            }
506
507            // Permission Member APIs
508            DriveApi::CreatePermissionMember(token) => {
509                format!("/open-apis/drive/v1/permissions/{token}/members")
510            }
511            DriveApi::BatchCreatePermissionMember(token) => {
512                format!("/open-apis/drive/v1/permissions/{token}/members/batch_create")
513            }
514            DriveApi::UpdatePermissionMember(token, member_id) => {
515                format!("/open-apis/drive/v1/permissions/{token}/members/{member_id}")
516            }
517            DriveApi::ListPermissionMembers(token) => {
518                format!("/open-apis/drive/v1/permissions/{token}/members")
519            }
520            DriveApi::DeletePermissionMember(token, member_id) => {
521                format!("/open-apis/drive/v1/permissions/{token}/members/{member_id}")
522            }
523            DriveApi::TransferOwner(token) => {
524                format!("/open-apis/drive/v1/permissions/{token}/members/transfer_owner")
525            }
526            DriveApi::AuthPermissionMember(token) => {
527                format!("/open-apis/drive/v1/permissions/{token}/members/auth")
528            }
529
530            // Permission Public APIs
531            DriveApi::UpdatePublicPermission(token) => {
532                format!("/open-apis/drive/v1/permissions/{token}/public")
533            }
534            DriveApi::GetPublicPermission(token) => {
535                format!("/open-apis/drive/v1/permissions/{token}/public")
536            }
537            DriveApi::CreatePublicPassword(token) => {
538                format!("/open-apis/drive/v1/permissions/{token}/public/password")
539            }
540            DriveApi::UpdatePublicPassword(token) => {
541                format!("/open-apis/drive/v1/permissions/{token}/public/password")
542            }
543            DriveApi::DeletePublicPassword(token) => {
544                format!("/open-apis/drive/v1/permissions/{token}/public/password")
545            }
546
547            // Comment APIs
548            DriveApi::ListFileComments(file_token) => {
549                format!("/open-apis/drive/v1/files/{file_token}/comments")
550            }
551            DriveApi::BatchQueryComments(file_token) => {
552                format!("/open-apis/drive/v1/files/{file_token}/comments/batch_query")
553            }
554            DriveApi::PatchComment(file_token, comment_id) => {
555                format!("/open-apis/drive/v1/files/{file_token}/comments/{comment_id}")
556            }
557            DriveApi::CreateComment(file_token) => {
558                format!("/open-apis/drive/v1/files/{file_token}/comments")
559            }
560            DriveApi::GetComment(file_token, comment_id) => {
561                format!("/open-apis/drive/v1/files/{file_token}/comments/{comment_id}")
562            }
563            DriveApi::ListCommentReplies(file_token, comment_id) => {
564                format!("/open-apis/drive/v1/files/{file_token}/comments/{comment_id}/replies")
565            }
566            DriveApi::CreateCommentReply(file_token, comment_id) => {
567                format!("/open-apis/drive/v1/files/{file_token}/comments/{comment_id}/replies")
568            }
569            DriveApi::UpdateCommentReply(file_token, comment_id, reply_id) => {
570                format!(
571                    "/open-apis/drive/v1/files/{file_token}/comments/{comment_id}/replies/{reply_id}"
572                )
573            }
574            DriveApi::DeleteCommentReply(file_token, comment_id, reply_id) => {
575                format!(
576                    "/open-apis/drive/v1/files/{file_token}/comments/{comment_id}/replies/{reply_id}"
577                )
578            }
579            DriveApi::UserSubscription => "/open-apis/drive/v1/user/subscription".to_string(),
580            DriveApi::UserRemoveSubscription => {
581                "/open-apis/drive/v1/user/remove_subscription".to_string()
582            }
583            DriveApi::UserSubscriptionStatus => {
584                "/open-apis/drive/v1/user/subscription_status".to_string()
585            }
586
587            // File Subscription APIs
588            DriveApi::GetFileSubscription(file_token, subscription_id) => {
589                format!("/open-apis/drive/v1/files/{file_token}/subscriptions/{subscription_id}")
590            }
591            DriveApi::CreateFileSubscription(file_token) => {
592                format!("/open-apis/drive/v1/files/{file_token}/subscriptions")
593            }
594            DriveApi::UpdateFileSubscription(file_token, subscription_id) => {
595                format!("/open-apis/drive/v1/files/{file_token}/subscriptions/{subscription_id}")
596            }
597
598            // V2 APIs
599            DriveApi::ListFileLikes(file_token) => {
600                format!("/open-apis/drive/v2/files/{file_token}/likes")
601            }
602            DriveApi::GetPublicPermissionV2(token) => {
603                format!("/open-apis/drive/v2/permissions/{token}/public")
604            }
605            DriveApi::UpdatePublicPermissionV2(token) => {
606                format!("/open-apis/drive/v2/permissions/{token}/public")
607            }
608            DriveApi::UpdateCommentReaction(file_token) => {
609                format!("/open-apis/drive/v2/files/{file_token}/comments/reaction")
610            }
611
612            // Media Upload Task APIs
613            DriveApi::MediaUploadTasks => "/open-apis/drive/v1/medias/upload_tasks".to_string(),
614            DriveApi::MediaUploadTask(task_id) => {
615                format!("/open-apis/drive/v1/medias/upload_tasks/{task_id}")
616            }
617            DriveApi::CreateMediaShareLink(file_token) => {
618                format!("/open-apis/drive/v1/medias/{file_token}/share_link")
619            }
620            DriveApi::GetPublicPassword(file_token) => {
621                format!("/open-apis/drive/v1/publics/{file_token}/password")
622            }
623        }
624    }
625
626    /// 返回配置了稳定请求语义的请求。
627    pub fn to_request<R>(&self) -> ApiRequest<R> {
628        <Self as CatalogEndpoint>::to_request(self)
629    }
630
631    /// 使用补充了动态 query 的 URL 构建请求。
632    pub fn to_request_with_url<R>(&self, url: impl Into<String>) -> ApiRequest<R> {
633        <Self as CatalogEndpoint>::to_request_with_url(self, url)
634    }
635}
636
637impl CatalogEndpoint for DriveApi {
638    fn to_url(&self) -> String {
639        DriveApi::to_url(self)
640    }
641
642    fn method(&self) -> HttpMethod {
643        match self {
644            Self::ListFiles
645            | Self::TaskCheck
646            | Self::GetFileStatistics(_)
647            | Self::ListFileViewRecords(_)
648            | Self::GetImportTask(_)
649            | Self::GetExportTask(_)
650            | Self::DownloadFile(_)
651            | Self::DownloadExportFile(_)
652            | Self::DownloadMedia(_)
653            | Self::GetMediaTempDownloadUrls
654            | Self::ListFileVersions(_)
655            | Self::GetFileVersion(_, _)
656            | Self::GetFileSubscribe(_)
657            | Self::ListPermissionMembers(_)
658            | Self::AuthPermissionMember(_)
659            | Self::GetPublicPermission(_)
660            | Self::ListFileComments(_)
661            | Self::GetComment(_, _)
662            | Self::ListCommentReplies(_, _)
663            | Self::GetFileSubscription(_, _)
664            | Self::ListFileLikes(_)
665            | Self::GetPublicPermissionV2(_)
666            | Self::MediaUploadTask(_)
667            | Self::GetPublicPassword(_) => HttpMethod::Get,
668            Self::UserSubscriptionStatus => HttpMethod::Get,
669            Self::CreateFolder
670            | Self::CopyFile(_)
671            | Self::MoveFile(_)
672            | Self::CreateShortcut
673            | Self::UploadFile
674            | Self::UploadPrepare
675            | Self::UploadPart
676            | Self::UploadFinish
677            | Self::CreateImportTask
678            | Self::CreateExportTask
679            | Self::UploadMedia
680            | Self::UploadMediaPrepare
681            | Self::UploadMediaPart
682            | Self::UploadMediaFinish
683            | Self::CreateFileVersion(_)
684            | Self::SubscribeFile(_)
685            | Self::CreatePermissionMember(_)
686            | Self::BatchCreatePermissionMember(_)
687            | Self::TransferOwner(_)
688            | Self::CreatePublicPassword(_)
689            | Self::CreateComment(_)
690            | Self::CreateCommentReply(_, _)
691            | Self::UserSubscription
692            | Self::UpdateCommentReaction(_)
693            | Self::CreateFileSubscription(_)
694            | Self::MediaUploadTasks
695            | Self::CreateMediaShareLink(_)
696            | Self::BatchQueryMetas
697            | Self::BatchQueryComments(_) => HttpMethod::Post,
698            Self::UpdatePermissionMember(_, _)
699            | Self::UpdatePublicPassword(_)
700            | Self::UpdateCommentReply(_, _, _) => HttpMethod::Put,
701            Self::UpdatePublicPermission(_)
702            | Self::PatchComment(_, _)
703            | Self::UpdateFileSubscription(_, _)
704            | Self::UpdatePublicPermissionV2(_) => HttpMethod::Patch,
705            Self::DeleteFile(_)
706            | Self::DeleteFileVersion(_, _)
707            | Self::DeleteFileSubscribe(_)
708            | Self::DeletePermissionMember(_, _)
709            | Self::DeletePublicPassword(_)
710            | Self::DeleteCommentReply(_, _, _) => HttpMethod::Delete,
711            Self::UserRemoveSubscription => HttpMethod::Delete,
712        }
713    }
714
715    // supported_access_token_types 使用 trait 默认实现(User + Tenant)
716}
717
718#[cfg(test)]
719mod tests {
720    use super::*;
721    use crate::common::api_endpoints::test_support::catalog_semantics_snapshot;
722
723    #[test]
724    fn drive_catalog_semantics_snapshots() {
725        insta::assert_snapshot!(
726            "ccm_drive_explorer_old_catalog_semantics",
727            catalog_semantics_snapshot::<CcmDriveExplorerApiOld>()
728        );
729        insta::assert_snapshot!(
730            "ccm_drive_explorer_catalog_semantics",
731            catalog_semantics_snapshot::<CcmDriveExplorerApi>()
732        );
733        insta::assert_snapshot!(
734            "permission_catalog_semantics",
735            catalog_semantics_snapshot::<PermissionApi>()
736        );
737        insta::assert_snapshot!(
738            "permission_old_catalog_semantics",
739            catalog_semantics_snapshot::<PermissionApiOld>()
740        );
741        insta::assert_snapshot!(
742            "drive_catalog_semantics",
743            catalog_semantics_snapshot::<DriveApi>()
744        );
745    }
746}