use reqwest::Method;
use serde::{Deserialize, Serialize};
use crate::{
core::{
api_req::ApiRequest,
api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
config::Config,
constants::AccessTokenType,
http::Transport,
req_option::RequestOption,
SDKResult,
},
impl_executable_builder_owned,
};
pub struct FileService {
config: Config,
}
impl FileService {
pub fn new(config: Config) -> Self {
Self { config }
}
pub async fn get_file_meta(
&self,
request: GetFileMetaRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<GetFileMetaRespData>> {
let api_req = ApiRequest {
http_method: Method::POST,
api_path: "/open-apis/drive/v1/metas/batch_query".to_string(),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
body: serde_json::to_vec(&request)?,
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn get_file_statistics(
&self,
request: GetFileStatisticsRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<GetFileStatisticsRespData>> {
let api_req = ApiRequest {
http_method: Method::GET,
api_path: format!(
"/open-apis/drive/v1/files/{}/statistics",
request.file_token
),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn list_file_view_records(
&self,
request: ListFileViewRecordsRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<ListFileViewRecordsRespData>> {
let mut api_req = ApiRequest {
http_method: Method::GET,
api_path: format!(
"/open-apis/drive/v1/files/{}/view_records",
request.file_token
),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
..Default::default()
};
if let Some(page_token) = request.page_token {
api_req
.query_params
.insert("page_token".to_string(), page_token);
}
if let Some(page_size) = request.page_size {
api_req
.query_params
.insert("page_size".to_string(), page_size.to_string());
}
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn create_file(
&self,
request: CreateFileRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<CreateFileRespData>> {
let api_req = ApiRequest {
http_method: Method::POST,
api_path: "/open-apis/drive/v1/files".to_string(),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
body: serde_json::to_vec(&request)?,
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn copy_file(
&self,
request: CopyFileRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<CopyFileRespData>> {
let body = serde_json::json!({
"name": request.name,
"type": request.copy_type,
"parent_token": request.parent_token
});
let api_req = ApiRequest {
http_method: Method::POST,
api_path: format!("/open-apis/drive/v1/files/{}/copy", request.file_token),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
body: serde_json::to_vec(&body)?,
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn delete_file(
&self,
request: DeleteFileRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<DeleteFileRespData>> {
let api_req = ApiRequest {
http_method: Method::DELETE,
api_path: format!("/open-apis/drive/v1/files/{}", request.file_token),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn create_file_shortcut(
&self,
request: CreateFileShortcutRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<CreateFileShortcutRespData>> {
let api_req = ApiRequest {
http_method: Method::POST,
api_path: "/open-apis/drive/v1/files/create_shortcut".to_string(),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
body: serde_json::to_vec(&request)?,
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn search_files(
&self,
request: SearchFilesRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<SearchFilesRespData>> {
let mut api_req = ApiRequest {
http_method: Method::GET,
api_path: "/open-apis/drive/v1/files/search".to_string(),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
..Default::default()
};
api_req
.query_params
.insert("search_key".to_string(), request.search_key);
if let Some(count) = request.count {
api_req
.query_params
.insert("count".to_string(), count.to_string());
}
if let Some(offset) = request.offset {
api_req
.query_params
.insert("offset".to_string(), offset.to_string());
}
if let Some(owner_ids) = request.owner_ids {
api_req
.query_params
.insert("owner_ids".to_string(), owner_ids.join(","));
}
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn upload_prepare(
&self,
request: FileUploadPrepareRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<FileUploadPrepareRespData>> {
let api_req = ApiRequest {
http_method: Method::POST,
api_path: "/open-apis/drive/v1/files/upload_prepare".to_string(),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
body: serde_json::to_vec(&request)?,
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn upload_part(
&self,
request: FileUploadPartRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<FileUploadPartRespData>> {
let mut api_req = request.api_req;
api_req.http_method = Method::POST;
api_req.api_path = "/open-apis/drive/v1/files/upload_part".to_string();
api_req.supported_access_token_types = vec![AccessTokenType::User, AccessTokenType::Tenant];
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn upload_finish(
&self,
request: FileUploadFinishRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<FileUploadFinishRespData>> {
let api_req = ApiRequest {
http_method: Method::POST,
api_path: "/open-apis/drive/v1/files/upload_finish".to_string(),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
body: serde_json::to_vec(&request)?,
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn create_import_task(
&self,
request: CreateImportTaskRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<CreateImportTaskRespData>> {
let api_req = ApiRequest {
http_method: Method::POST,
api_path: "/open-apis/drive/v1/import_tasks".to_string(),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
body: serde_json::to_vec(&request)?,
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
pub async fn get_import_task(
&self,
request: GetImportTaskRequest,
option: Option<RequestOption>,
) -> SDKResult<BaseResponse<GetImportTaskRespData>> {
let api_req = ApiRequest {
http_method: Method::GET,
api_path: format!("/open-apis/drive/v1/import_tasks/{}", request.ticket),
supported_access_token_types: vec![AccessTokenType::User, AccessTokenType::Tenant],
..Default::default()
};
let api_resp = Transport::request(api_req, &self.config, option).await?;
Ok(api_resp)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetFileMetaRequest {
pub request_docs: Vec<RequestDoc>,
pub with_url: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RequestDoc {
pub doc_token: String,
pub doc_type: String,
}
impl GetFileMetaRequest {
pub fn new(docs: Vec<(String, String)>) -> Self {
Self {
request_docs: docs
.into_iter()
.map(|(token, doc_type)| RequestDoc {
doc_token: token,
doc_type,
})
.collect(),
with_url: Some(true),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetFileMetaRespData {
pub metas: Vec<FileMeta>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileMeta {
pub doc_token: String,
pub doc_type: String,
pub title: String,
pub owner_id: String,
pub create_time: String,
pub update_time: String,
pub url: Option<String>,
}
impl ApiResponseTrait for GetFileMetaRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetFileStatisticsRequest {
pub file_token: String,
}
impl GetFileStatisticsRequest {
pub fn new(file_token: impl Into<String>) -> Self {
Self {
file_token: file_token.into(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetFileStatisticsRespData {
pub uv: i64,
pub pv: i64,
pub like_count: i64,
pub comment_count: i64,
}
impl ApiResponseTrait for GetFileStatisticsRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListFileViewRecordsRequest {
pub file_token: String,
pub page_token: Option<String>,
pub page_size: Option<i32>,
}
impl ListFileViewRecordsRequest {
pub fn new(file_token: impl Into<String>) -> Self {
Self {
file_token: file_token.into(),
page_token: None,
page_size: None,
}
}
pub fn with_page_token(mut self, page_token: impl Into<String>) -> Self {
self.page_token = Some(page_token.into());
self
}
pub fn with_page_size(mut self, page_size: i32) -> Self {
self.page_size = Some(page_size);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListFileViewRecordsRespData {
pub has_more: bool,
pub page_token: Option<String>,
pub items: Vec<FileViewRecord>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileViewRecord {
pub viewer_id: String,
pub viewer_name: String,
pub view_time: String,
pub view_device: String,
}
impl ApiResponseTrait for ListFileViewRecordsRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateFileRequest {
pub title: String,
#[serde(rename = "type")]
pub file_type: String,
pub parent_token: String,
}
impl CreateFileRequest {
pub fn new(
title: impl Into<String>,
file_type: impl Into<String>,
parent_token: impl Into<String>,
) -> Self {
Self {
title: title.into(),
file_type: file_type.into(),
parent_token: parent_token.into(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateFileRespData {
pub token: String,
pub url: String,
}
impl ApiResponseTrait for CreateFileRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CopyFileRequest {
pub file_token: String,
pub name: String,
#[serde(rename = "type")]
pub copy_type: String,
pub parent_token: String,
}
impl CopyFileRequest {
pub fn new(
file_token: impl Into<String>,
name: impl Into<String>,
parent_token: impl Into<String>,
) -> Self {
Self {
file_token: file_token.into(),
name: name.into(),
copy_type: "copy".to_string(),
parent_token: parent_token.into(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CopyFileRespData {
pub token: String,
pub url: String,
}
impl ApiResponseTrait for CopyFileRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteFileRequest {
pub file_token: String,
}
impl DeleteFileRequest {
pub fn new(file_token: impl Into<String>) -> Self {
Self {
file_token: file_token.into(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteFileRespData {
pub task_id: Option<String>,
}
impl ApiResponseTrait for DeleteFileRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateFileShortcutRequest {
pub refer_entity: ReferEntity,
pub name: String,
pub parent_token: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReferEntity {
#[serde(rename = "type")]
pub entity_type: String,
pub token: String,
}
impl CreateFileShortcutRequest {
pub fn new(
file_type: impl Into<String>,
file_token: impl Into<String>,
name: impl Into<String>,
parent_token: impl Into<String>,
) -> Self {
Self {
refer_entity: ReferEntity {
entity_type: file_type.into(),
token: file_token.into(),
},
name: name.into(),
parent_token: parent_token.into(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateFileShortcutRespData {
pub token: String,
pub url: String,
}
impl ApiResponseTrait for CreateFileShortcutRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchFilesRequest {
pub search_key: String,
pub count: Option<i32>,
pub offset: Option<i32>,
pub owner_ids: Option<Vec<String>>,
}
impl SearchFilesRequest {
pub fn new(search_key: impl Into<String>) -> Self {
Self {
search_key: search_key.into(),
count: None,
offset: None,
owner_ids: None,
}
}
pub fn with_count(mut self, count: i32) -> Self {
self.count = Some(count);
self
}
pub fn with_offset(mut self, offset: i32) -> Self {
self.offset = Some(offset);
self
}
pub fn with_owner_ids(mut self, owner_ids: Vec<String>) -> Self {
self.owner_ids = Some(owner_ids);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchFilesRespData {
pub files: Vec<SearchFileItem>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchFileItem {
pub token: String,
pub name: String,
#[serde(rename = "type")]
pub file_type: String,
pub url: String,
pub owner_id: String,
}
impl ApiResponseTrait for SearchFilesRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileUploadPrepareRequest {
pub file_name: String,
pub parent_token: String,
pub size: i64,
pub block_size: Option<i32>,
pub checksum: Option<String>,
}
impl FileUploadPrepareRequest {
pub fn new(file_name: impl Into<String>, parent_token: impl Into<String>, size: i64) -> Self {
Self {
file_name: file_name.into(),
parent_token: parent_token.into(),
size,
block_size: None,
checksum: None,
}
}
pub fn with_block_size(mut self, block_size: i32) -> Self {
self.block_size = Some(block_size);
self
}
pub fn with_checksum(mut self, checksum: impl Into<String>) -> Self {
self.checksum = Some(checksum.into());
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileUploadPrepareRespData {
pub upload_id: String,
pub block_size: i32,
pub block_num: i32,
}
impl ApiResponseTrait for FileUploadPrepareRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct FileUploadPartRequest {
#[serde(skip)]
pub api_req: ApiRequest,
upload_id: String,
seq: i32,
size: i32,
checksum: Option<String>,
}
impl FileUploadPartRequest {
pub fn builder() -> FileUploadPartRequestBuilder {
FileUploadPartRequestBuilder::default()
}
}
#[derive(Default)]
pub struct FileUploadPartRequestBuilder {
request: FileUploadPartRequest,
}
impl FileUploadPartRequestBuilder {
pub fn upload_id(mut self, upload_id: impl Into<String>) -> Self {
self.request.upload_id = upload_id.into();
self
}
pub fn seq(mut self, seq: i32) -> Self {
self.request.seq = seq;
self
}
pub fn size(mut self, size: i32) -> Self {
self.request.size = size;
self
}
pub fn checksum(mut self, checksum: impl Into<String>) -> Self {
self.request.checksum = Some(checksum.into());
self
}
pub fn file_chunk(mut self, chunk: Vec<u8>) -> Self {
self.request.api_req.file = chunk;
self
}
pub fn build(mut self) -> FileUploadPartRequest {
self.request.api_req.body = serde_json::to_vec(&self.request).unwrap();
self.request
}
}
impl_executable_builder_owned!(
FileUploadPartRequestBuilder,
FileService,
FileUploadPartRequest,
BaseResponse<FileUploadPartRespData>,
upload_part
);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileUploadPartRespData {
pub etag: String,
}
impl ApiResponseTrait for FileUploadPartRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileUploadFinishRequest {
pub upload_id: String,
pub block_infos: Vec<FileBlockInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileBlockInfo {
pub etag: String,
pub seq: i32,
}
impl FileUploadFinishRequest {
pub fn new(upload_id: impl Into<String>, block_infos: Vec<FileBlockInfo>) -> Self {
Self {
upload_id: upload_id.into(),
block_infos,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileUploadFinishRespData {
pub file_token: String,
}
impl ApiResponseTrait for FileUploadFinishRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateImportTaskRequest {
pub file_extension: String,
pub file_token: String,
#[serde(rename = "type")]
pub import_type: String,
pub parent_token: String,
pub file_name: String,
pub parent_type: String,
}
impl CreateImportTaskRequest {
pub fn new(
file_extension: impl Into<String>,
file_token: impl Into<String>,
import_type: impl Into<String>,
parent_token: impl Into<String>,
file_name: impl Into<String>,
parent_type: impl Into<String>,
) -> Self {
Self {
file_extension: file_extension.into(),
file_token: file_token.into(),
import_type: import_type.into(),
parent_token: parent_token.into(),
file_name: file_name.into(),
parent_type: parent_type.into(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateImportTaskRespData {
pub ticket: String,
}
impl ApiResponseTrait for CreateImportTaskRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetImportTaskRequest {
pub ticket: String,
}
impl GetImportTaskRequest {
pub fn new(ticket: impl Into<String>) -> Self {
Self {
ticket: ticket.into(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetImportTaskRespData {
pub result: ImportTaskResult,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ImportTaskResult {
#[serde(rename = "type")]
pub task_type: String,
pub ticket: String,
pub job_status: i32,
pub job_error_msg: Option<String>,
pub token: Option<String>,
pub url: Option<String>,
}
impl ApiResponseTrait for GetImportTaskRespData {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}
}