implement delete
This commit is contained in:
parent
92e5c3f985
commit
c9ec5ff082
@ -91,9 +91,44 @@ impl Client {
|
|||||||
.await
|
.await
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn file_detail(
|
||||||
|
&self,
|
||||||
|
req: types::request::FileDetailRequest,
|
||||||
|
) -> anyhow::Result<types::response::FileDetailResponse> {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let request = client
|
||||||
|
.post("https://forest.sendy.jp/cloud/service/file/v1/file")
|
||||||
|
.bearer_auth(&self.token)
|
||||||
|
.json(&req);
|
||||||
|
|
||||||
|
let response = request.send().await?;
|
||||||
|
response
|
||||||
|
.json::<types::response::FileDetailResponse>()
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_file(
|
||||||
|
&self,
|
||||||
|
req: types::request::DeleteFileRequest,
|
||||||
|
) -> anyhow::Result<types::response::JobKeyResponse> {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let request = client
|
||||||
|
.delete("https://forest.sendy.jp/cloud/service/file/v3/files")
|
||||||
|
.bearer_auth(&self.token)
|
||||||
|
.json(&req);
|
||||||
|
|
||||||
|
let response = request.send().await?;
|
||||||
|
response
|
||||||
|
.json::<types::response::JobKeyResponse>()
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.rakuten-drive.com/api/account/refreshtoken POST RefreshTokenRequest RefreshTokenResponse
|
// https://www.rakuten-drive.com/api/account/refreshtoken POST RefreshTokenRequest RefreshTokenResponse
|
||||||
|
// https://forest.sendy.jp/cloud/service/file/v1/file POST FileDetailRequest FileDetailResponse
|
||||||
// https://forest.sendy.jp/cloud/service/file/v1/files POST ListFilesRequest ListFilesResponse
|
// https://forest.sendy.jp/cloud/service/file/v1/files POST ListFilesRequest ListFilesResponse
|
||||||
// https://forest.sendy.jp/cloud/service/file/v3/files DELETE DeleteFileRequest JobKeyResponse
|
// https://forest.sendy.jp/cloud/service/file/v3/files DELETE DeleteFileRequest JobKeyResponse
|
||||||
// https://forest.sendy.jp/cloud/service/file/v1/files/create POST CreateFolderRequest
|
// https://forest.sendy.jp/cloud/service/file/v1/files/create POST CreateFolderRequest
|
||||||
|
67
src/main.rs
67
src/main.rs
@ -19,7 +19,7 @@ use types::response::ListFilesResponseFile;
|
|||||||
mod endpoints;
|
mod endpoints;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
const BEARER_TOKEN: &str = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxNTQwYWM3MWJiOTJhYTA2OTNjODI3MTkwYWNhYmU1YjA1NWNiZWMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoi5bm457-8IOW_l-adkSIsInBsYW4iOiJza2YiLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vc2VuZHktc2VydmljZSIsImF1ZCI6InNlbmR5LXNlcnZpY2UiLCJhdXRoX3RpbWUiOjE3MjEyMjYwMTUsInVzZXJfaWQiOiJHY2xUN0RybkxGaG83dm5JaXJVemp0TUxoUmsyIiwic3ViIjoiR2NsVDdEcm5MRmhvN3ZuSWlyVXpqdE1MaFJrMiIsImlhdCI6MTcyMTI1NTM1OCwiZXhwIjoxNzIxMjU4OTU4LCJlbWFpbCI6ImtvdXN1a2UxMTIzNjEyNEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiZW1haWwiOlsia291c3VrZTExMjM2MTI0QGdtYWlsLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6ImN1c3RvbSJ9fQ.uC-X4XCMTJ-Vv0bmm85cZy65LVdNxRKBlNXxsg8_QqyMV1rRzmpDMQpwWKk10OUDj6xovg1tfmlUW2syL0twANO8hKOSlI_wLZ1Rvvm0TF8EvDLvv8OGFc93nm3OIaSaiZj-xcORZzeJDVHsdraGoYDX3YbYPIJAhDaOsHX5_QbLwuxoz0dxd0fTAoDH7aEpDhcojjTmMImtbGqMzpvUpwNunJaJK2YZTYiHXZtcK7mr9cQLF5b3Exee--R5hGEU9E49jGtXKQNrP_6mkTXVivJh6TdKeFiMCrbc-6xZvuBnkEQ8g0GvU9cERhJTZ73U2jdHLzWbYitCh2nzkbQDNA";
|
const BEARER_TOKEN: &str = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxNTQwYWM3MWJiOTJhYTA2OTNjODI3MTkwYWNhYmU1YjA1NWNiZWMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoi5bm457-8IOW_l-adkSIsInBsYW4iOiJza2YiLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vc2VuZHktc2VydmljZSIsImF1ZCI6InNlbmR5LXNlcnZpY2UiLCJhdXRoX3RpbWUiOjE3MjEyMjYwMTUsInVzZXJfaWQiOiJHY2xUN0RybkxGaG83dm5JaXJVemp0TUxoUmsyIiwic3ViIjoiR2NsVDdEcm5MRmhvN3ZuSWlyVXpqdE1MaFJrMiIsImlhdCI6MTcyMTI2MDk2NSwiZXhwIjoxNzIxMjY0NTY1LCJlbWFpbCI6ImtvdXN1a2UxMTIzNjEyNEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiZW1haWwiOlsia291c3VrZTExMjM2MTI0QGdtYWlsLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6ImN1c3RvbSJ9fQ.qgMyyPkP992xCtsTjr28PhzjiqaNBn1O1Z6HYEk3cjgPyVoPRiMV5KaDuWWveP0Z2x5_jvd5We0zsYzpxnOcf1dlf4VmAUqNGrVjCRqWUBuU008EkTAFlKBZAk4yYON0xddNcoUR6OrmYSLKMR5OOOV9FkTbFzd72rydQpcbiy9nmint_uXnN3z_9th0yf0J8oBd4_aXUzGUw2YOG8mBlgJfAoFdO5gMxJCWkC2V9r1TbxYWDMrFwtj7QMLVN4TOz2Bcy8erPiA_T46ap2gc9T0wTaPrE8h436FkTLdiaSJaYBLMEbS7dtXNLZ7SxaA4JOfeIgt2KoN5BrZg4qqt4Q";
|
||||||
const HOST_ID: &str = "GclT7DrnLFho7vnIirUzjtMLhRk2";
|
const HOST_ID: &str = "GclT7DrnLFho7vnIirUzjtMLhRk2";
|
||||||
const CHUNK_SIZE: usize = 1024 * 1024 * 10; // 10MB
|
const CHUNK_SIZE: usize = 1024 * 1024 * 10; // 10MB
|
||||||
const APP_VERSION: &str = "v21.11.10";
|
const APP_VERSION: &str = "v21.11.10";
|
||||||
@ -38,7 +38,6 @@ enum Commands {
|
|||||||
prefix: Option<String>,
|
prefix: Option<String>,
|
||||||
},
|
},
|
||||||
Upload {
|
Upload {
|
||||||
#[clap(short, long)]
|
|
||||||
file: PathBuf,
|
file: PathBuf,
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
prefix: Option<String>,
|
prefix: Option<String>,
|
||||||
@ -46,13 +45,16 @@ enum Commands {
|
|||||||
recursive: bool,
|
recursive: bool,
|
||||||
},
|
},
|
||||||
Download {
|
Download {
|
||||||
#[clap(short, long)]
|
|
||||||
path: String,
|
path: String,
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
prefix: Option<String>,
|
prefix: Option<String>,
|
||||||
},
|
},
|
||||||
Move {},
|
Move {},
|
||||||
Delete {},
|
Delete {
|
||||||
|
path: String,
|
||||||
|
#[clap(long)]
|
||||||
|
recursive: bool,
|
||||||
|
},
|
||||||
MkDir {},
|
MkDir {},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ async fn main() {
|
|||||||
|
|
||||||
match &args.command {
|
match &args.command {
|
||||||
Commands::List { prefix } => {
|
Commands::List { prefix } => {
|
||||||
let res = list_files(prefix.clone()).await.unwrap();
|
let res = list_files(Some(&prefix.clone().unwrap_or("".to_string()))).await.unwrap();
|
||||||
res.file.iter().for_each(|f| {
|
res.file.iter().for_each(|f| {
|
||||||
let permission_string = if f.is_folder { "d" } else { "-" };
|
let permission_string = if f.is_folder { "d" } else { "-" };
|
||||||
println!(
|
println!(
|
||||||
@ -243,7 +245,7 @@ async fn main() {
|
|||||||
let file_path =
|
let file_path =
|
||||||
path.split('/').collect::<Vec<&str>>()[0..path.split('/').count() - 1].join("/");
|
path.split('/').collect::<Vec<&str>>()[0..path.split('/').count() - 1].join("/");
|
||||||
|
|
||||||
let list = list_files(Some(file_path.clone())).await.unwrap();
|
let list = list_files(Some(&file_path)).await.unwrap();
|
||||||
|
|
||||||
let file = list
|
let file = list
|
||||||
.file
|
.file
|
||||||
@ -286,8 +288,40 @@ async fn main() {
|
|||||||
Commands::Move {} => {
|
Commands::Move {} => {
|
||||||
println!("Move");
|
println!("Move");
|
||||||
}
|
}
|
||||||
Commands::Delete {} => {
|
Commands::Delete { path, recursive } => {
|
||||||
println!("Delete");
|
let client = endpoints::Client::new(BEARER_TOKEN.to_string(), HOST_ID.to_string());
|
||||||
|
let file = file_detail(path).await.unwrap();
|
||||||
|
if file.is_folder && !*recursive {
|
||||||
|
println!("Use --recursive option for folder delete");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let req = types::request::DeleteFileRequest {
|
||||||
|
file: vec![types::request::FileModifyRequestFile {
|
||||||
|
last_modified: file.last_modified,
|
||||||
|
path: file.path,
|
||||||
|
version_id: file.version_id,
|
||||||
|
size: file.size,
|
||||||
|
}],
|
||||||
|
host_id: client.host_id.clone(),
|
||||||
|
prefix: "".to_string(),
|
||||||
|
trash: true,
|
||||||
|
};
|
||||||
|
let res = client.delete_file(req).await.unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let req = types::request::CheckActionRequest {
|
||||||
|
key: res.key.clone(),
|
||||||
|
};
|
||||||
|
let res = client.check_action(req).await.unwrap();
|
||||||
|
|
||||||
|
if res.state == "complete" {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(200));
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Deleted");
|
||||||
}
|
}
|
||||||
Commands::MkDir {} => {
|
Commands::MkDir {} => {
|
||||||
println!("MkDir");
|
println!("MkDir");
|
||||||
@ -440,14 +474,25 @@ async fn multipart_upload(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_files(prefix: Option<String>) -> anyhow::Result<types::response::ListFilesResponse> {
|
async fn file_detail(path: &str) -> anyhow::Result<types::response::FileDetailResponseFile> {
|
||||||
|
let client = endpoints::Client::new(BEARER_TOKEN.to_string(), HOST_ID.to_string());
|
||||||
|
let req = types::request::FileDetailRequest {
|
||||||
|
host_id: client.host_id.clone(),
|
||||||
|
path: path.to_string(),
|
||||||
|
thumbnail_size: 130,
|
||||||
|
};
|
||||||
|
let res = client.file_detail(req).await?;
|
||||||
|
Ok(res.file)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_files(prefix: Option<&str>) -> anyhow::Result<types::response::ListFilesResponse> {
|
||||||
let client = endpoints::Client::new(BEARER_TOKEN.to_string(), HOST_ID.to_string());
|
let client = endpoints::Client::new(BEARER_TOKEN.to_string(), HOST_ID.to_string());
|
||||||
let pagination_size = 40;
|
let pagination_size = 40;
|
||||||
let mut files = Vec::<ListFilesResponseFile>::new();
|
let mut files = Vec::<ListFilesResponseFile>::new();
|
||||||
let req = types::request::ListFilesRequest {
|
let req = types::request::ListFilesRequest {
|
||||||
from: 0,
|
from: 0,
|
||||||
host_id: client.host_id.clone(),
|
host_id: client.host_id.clone(),
|
||||||
path: prefix.clone().unwrap_or("".to_string()),
|
path: prefix.clone().unwrap_or("").to_string(),
|
||||||
sort_type: "path".to_string(),
|
sort_type: "path".to_string(),
|
||||||
reverse: false,
|
reverse: false,
|
||||||
thumbnail_size: 130,
|
thumbnail_size: 130,
|
||||||
@ -463,7 +508,7 @@ async fn list_files(prefix: Option<String>) -> anyhow::Result<types::response::L
|
|||||||
let req = types::request::ListFilesRequest {
|
let req = types::request::ListFilesRequest {
|
||||||
from: cursor,
|
from: cursor,
|
||||||
host_id: client.host_id.clone(),
|
host_id: client.host_id.clone(),
|
||||||
path: prefix.clone().unwrap_or("".to_string()),
|
path: prefix.clone().unwrap_or("").to_string(),
|
||||||
sort_type: "path".to_string(),
|
sort_type: "path".to_string(),
|
||||||
reverse: false,
|
reverse: false,
|
||||||
thumbnail_size: 130,
|
thumbnail_size: 130,
|
||||||
|
@ -29,7 +29,7 @@ pub struct CreateFolderRequest {
|
|||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub struct RenameFileRequest {
|
pub struct RenameFileRequest {
|
||||||
pub file: Vec<RenameFileRequestFile>,
|
pub file: Vec<FileModifyRequestFile>,
|
||||||
pub host_id: String,
|
pub host_id: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
@ -37,7 +37,7 @@ pub struct RenameFileRequest {
|
|||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
|
||||||
pub struct RenameFileRequestFile {
|
pub struct FileModifyRequestFile {
|
||||||
pub last_modified: String, // 1970-01-20T22:07:12.804Z
|
pub last_modified: String, // 1970-01-20T22:07:12.804Z
|
||||||
pub path: String,
|
pub path: String,
|
||||||
pub size: i64,
|
pub size: i64,
|
||||||
@ -53,7 +53,7 @@ pub struct CheckActionRequest {
|
|||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub struct MoveFileRequest {
|
pub struct MoveFileRequest {
|
||||||
pub file: Vec<RenameFileRequestFile>,
|
pub file: Vec<FileModifyRequestFile>,
|
||||||
pub host_id: String,
|
pub host_id: String,
|
||||||
pub prefix: String,
|
pub prefix: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
@ -96,7 +96,7 @@ pub struct CompleteUploadRequestFile {
|
|||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub struct DeleteFileRequest {
|
pub struct DeleteFileRequest {
|
||||||
pub file: Vec<RenameFileRequestFile>,
|
pub file: Vec<FileModifyRequestFile>,
|
||||||
pub host_id: String,
|
pub host_id: String,
|
||||||
pub prefix: String,
|
pub prefix: String,
|
||||||
pub trash: bool,
|
pub trash: bool,
|
||||||
@ -117,8 +117,10 @@ pub struct GetFileLinkRequestFile {
|
|||||||
pub size: i64,
|
pub size: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
// pub struct GetFileLinkRequest {
|
#[serde(rename_all = "snake_case")]
|
||||||
// pub host_id: String,
|
pub struct FileDetailRequest {
|
||||||
// pub path: String,
|
pub host_id: String,
|
||||||
// }
|
pub path: String,
|
||||||
|
pub thumbnail_size: i64,
|
||||||
|
}
|
@ -109,3 +109,42 @@ pub struct GetFileLinkTokenResponse {
|
|||||||
pub struct GetFileLinkResponse {
|
pub struct GetFileLinkResponse {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub struct FileDetailResponse {
|
||||||
|
pub access_level: String,
|
||||||
|
pub file: FileDetailResponseFile,
|
||||||
|
pub owner: String,
|
||||||
|
pub prefix: String,
|
||||||
|
pub usage_size: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
pub struct FileDetailResponseFile {
|
||||||
|
pub access_level: String,
|
||||||
|
pub has_child_folder: bool,
|
||||||
|
|
||||||
|
#[serde(rename = "HostID")]
|
||||||
|
pub host_id: String,
|
||||||
|
pub is_backed_up: bool,
|
||||||
|
pub is_folder: bool,
|
||||||
|
pub is_latest: bool,
|
||||||
|
pub is_share: String,
|
||||||
|
pub items_count: i64,
|
||||||
|
pub last_modified: String, // 2024-07-16T06:18:06.595Z
|
||||||
|
|
||||||
|
#[serde(rename = "LastModifierID")]
|
||||||
|
pub last_modifier_id: String,
|
||||||
|
|
||||||
|
#[serde(rename = "OwnerID")]
|
||||||
|
pub owner_id: String, // OwnerID
|
||||||
|
pub path: String,
|
||||||
|
pub size: i64,
|
||||||
|
pub thumbnail: String,
|
||||||
|
pub version: serde_json::Value, // returns null
|
||||||
|
|
||||||
|
#[serde(rename = "VersionID")]
|
||||||
|
pub version_id: String,
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user