use refresh token

This commit is contained in:
sim1222 2024-07-18 10:16:49 +09:00
parent 4a2fdffc74
commit 0d1a50a010
Signed by: sim1222
GPG Key ID: D1AE30E316E44E5D
4 changed files with 53 additions and 14 deletions

View File

@ -1,3 +1,5 @@
use anyhow::Ok;
use crate::types; use crate::types;
pub struct Client { pub struct Client {
@ -42,7 +44,9 @@ impl Client {
.map_err(Into::into) .map_err(Into::into)
} }
pub async fn get_upload_token(&self) -> anyhow::Result<types::response::GetFileLinkTokenResponse> { pub async fn get_upload_token(
&self,
) -> anyhow::Result<types::response::GetFileLinkTokenResponse> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let request = client let request = client
.get(&format!( .get(&format!(
@ -127,6 +131,28 @@ impl Client {
} }
} }
pub async fn refresh_token(
req: types::request::RefreshTokenRequest,
) -> anyhow::Result<types::response::RefreshTokenResponse> {
let client = reqwest::Client::new();
let request = client
.post("https://www.rakuten-drive.com/api/account/refreshtoken")
.json(&req);
let response = request.send().await?;
let text = response.text().await?;
// println!("{}", text);
let json: types::response::RefreshTokenResponse = serde_json::from_str(&text)?;
Ok(json)
// response
// .json::<types::response::RefreshTokenResponse>()
// .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/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

View File

@ -20,6 +20,7 @@ mod endpoints;
mod types; mod types;
const BEARER_TOKEN: &str = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxNTQwYWM3MWJiOTJhYTA2OTNjODI3MTkwYWNhYmU1YjA1NWNiZWMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoi5bm457-8IOW_l-adkSIsInBsYW4iOiJza2YiLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vc2VuZHktc2VydmljZSIsImF1ZCI6InNlbmR5LXNlcnZpY2UiLCJhdXRoX3RpbWUiOjE3MjEyMjYwMTUsInVzZXJfaWQiOiJHY2xUN0RybkxGaG83dm5JaXJVemp0TUxoUmsyIiwic3ViIjoiR2NsVDdEcm5MRmhvN3ZuSWlyVXpqdE1MaFJrMiIsImlhdCI6MTcyMTI2MzA4NCwiZXhwIjoxNzIxMjY2Njg0LCJlbWFpbCI6ImtvdXN1a2UxMTIzNjEyNEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiZW1haWwiOlsia291c3VrZTExMjM2MTI0QGdtYWlsLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6ImN1c3RvbSJ9fQ.F7gbJ41DOBk6lmOEYzJTYOKPOn0xVleQm2ZQGKGc5rVHudIjhahfkc5av5LsooLA8SI_BZf70Tic6MUz5yOtmSVKDk67pYgJLPpDvWnVgfhcQz-MV4qOmZkvQRLsmsRlG5kcP0BhZSRfIt3DdMQ1FCcqrw6G0Kirvj7C5OJvPnwtqNjDgI9J1HFH71t_5Q7Mx2OHRYSjUM1jZR6bAngG-aNpJC9BpcF-1dgITIrvNGXkcWO1W0tQwwovQSMVq9on_bOq2arnvq8hj0BK7cu4yntBBNY2Mx_qhng7kNWoTFK4pd9p3GQc_kUacJ0PZIxE_63JiQuwiGJVuiSYjbu8iw"; const BEARER_TOKEN: &str = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxNTQwYWM3MWJiOTJhYTA2OTNjODI3MTkwYWNhYmU1YjA1NWNiZWMiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoi5bm457-8IOW_l-adkSIsInBsYW4iOiJza2YiLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vc2VuZHktc2VydmljZSIsImF1ZCI6InNlbmR5LXNlcnZpY2UiLCJhdXRoX3RpbWUiOjE3MjEyMjYwMTUsInVzZXJfaWQiOiJHY2xUN0RybkxGaG83dm5JaXJVemp0TUxoUmsyIiwic3ViIjoiR2NsVDdEcm5MRmhvN3ZuSWlyVXpqdE1MaFJrMiIsImlhdCI6MTcyMTI2MzA4NCwiZXhwIjoxNzIxMjY2Njg0LCJlbWFpbCI6ImtvdXN1a2UxMTIzNjEyNEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiZW1haWwiOlsia291c3VrZTExMjM2MTI0QGdtYWlsLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6ImN1c3RvbSJ9fQ.F7gbJ41DOBk6lmOEYzJTYOKPOn0xVleQm2ZQGKGc5rVHudIjhahfkc5av5LsooLA8SI_BZf70Tic6MUz5yOtmSVKDk67pYgJLPpDvWnVgfhcQz-MV4qOmZkvQRLsmsRlG5kcP0BhZSRfIt3DdMQ1FCcqrw6G0Kirvj7C5OJvPnwtqNjDgI9J1HFH71t_5Q7Mx2OHRYSjUM1jZR6bAngG-aNpJC9BpcF-1dgITIrvNGXkcWO1W0tQwwovQSMVq9on_bOq2arnvq8hj0BK7cu4yntBBNY2Mx_qhng7kNWoTFK4pd9p3GQc_kUacJ0PZIxE_63JiQuwiGJVuiSYjbu8iw";
const REFRESH_TOKEN: &str = "AMf-vBwuDNdrMsPlvESgMqZWGCdVlBxMvrQVNvHOWb-FdDRV0Ozeq26POxH2tzy463DGlZTZpPYYhWCSi-KI0-8pSYEXtuCG_8DlVRyqwm4POeobYWkrw3dMgiEDNjFCfXIN4-k65CsizmCFbWQz6ASsi-XGAwMn_mXyFj9JirB7vyzTTr2ugbA";
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";
@ -70,9 +71,16 @@ struct TargetFile {
async fn main() { async fn main() {
let args = Args::parse(); let args = Args::parse();
let refresh_token_req = types::request::RefreshTokenRequest {
refresh_token: REFRESH_TOKEN.to_string(),
};
let token = endpoints::refresh_token(refresh_token_req).await.unwrap();
// println!("{:?}", token);
let token = token.id_token;
match &args.command { match &args.command {
Commands::List { prefix } => { Commands::List { prefix } => {
let res = list_files(Some(&prefix.clone().unwrap_or("".to_string()))) let res = list_files(Some(&prefix.clone().unwrap_or("".to_string())), &token)
.await .await
.unwrap(); .unwrap();
res.file.iter().for_each(|f| { res.file.iter().for_each(|f| {
@ -148,7 +156,7 @@ async fn main() {
}); });
} }
let client = endpoints::Client::new(BEARER_TOKEN.to_string(), HOST_ID.to_string()); let client = endpoints::Client::new(token.to_string(), HOST_ID.to_string());
let req = types::request::CheckUploadRequest { let req = types::request::CheckUploadRequest {
host_id: client.host_id.clone(), host_id: client.host_id.clone(),
@ -244,13 +252,13 @@ async fn main() {
println!("Uploaded"); println!("Uploaded");
} }
Commands::Download { path, prefix } => { Commands::Download { path, prefix } => {
let client = endpoints::Client::new(BEARER_TOKEN.to_string(), HOST_ID.to_string()); let client = endpoints::Client::new(token.to_string(), HOST_ID.to_string());
let file_name = path.split('/').last().unwrap(); let file_name = path.split('/').last().unwrap();
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)).await.unwrap(); let list = list_files(Some(&file_path), &token).await.unwrap();
let file = list let file = list
.file .file
@ -294,8 +302,8 @@ async fn main() {
println!("Move"); println!("Move");
} }
Commands::Delete { path, recursive } => { Commands::Delete { path, recursive } => {
let client = endpoints::Client::new(BEARER_TOKEN.to_string(), HOST_ID.to_string()); let client = endpoints::Client::new(token.to_string(), HOST_ID.to_string());
let file = file_detail(path).await.unwrap(); let file = file_detail(path, &token).await.unwrap();
if file.is_folder && !*recursive { if file.is_folder && !*recursive {
println!("Use --recursive option for folder delete"); println!("Use --recursive option for folder delete");
return; return;
@ -479,8 +487,11 @@ async fn multipart_upload(
Ok(()) Ok(())
} }
async fn file_detail(path: &str) -> anyhow::Result<types::response::FileDetailResponseFile> { async fn file_detail(
let client = endpoints::Client::new(BEARER_TOKEN.to_string(), HOST_ID.to_string()); path: &str,
token: &str,
) -> anyhow::Result<types::response::FileDetailResponseFile> {
let client = endpoints::Client::new(token.to_string(), HOST_ID.to_string());
let req = types::request::FileDetailRequest { let req = types::request::FileDetailRequest {
host_id: client.host_id.clone(), host_id: client.host_id.clone(),
path: path.to_string(), path: path.to_string(),
@ -490,8 +501,11 @@ async fn file_detail(path: &str) -> anyhow::Result<types::response::FileDetailRe
Ok(res.file) Ok(res.file)
} }
async fn list_files(prefix: Option<&str>) -> anyhow::Result<types::response::ListFilesResponse> { async fn list_files(
let client = endpoints::Client::new(BEARER_TOKEN.to_string(), HOST_ID.to_string()); prefix: Option<&str>,
token: &str,
) -> anyhow::Result<types::response::ListFilesResponse> {
let client = endpoints::Client::new(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 {

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "snake_case")]
pub struct RefreshTokenRequest { pub struct RefreshTokenRequest {
pub refresh_token: String, pub refresh_token: String,
} }

View File

@ -17,14 +17,13 @@ pub struct RefreshTokenResponse {
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RefreshTokenResponseMetadata { pub struct RefreshTokenResponseMetadata {
pub last_sign_in_time: String, // Wed, 17 Jul 2024 14:20:15 GMT pub last_sign_in_time: String, // Wed, 17 Jul 2024 14:20:15 GMT
pub creation_time: String, // Wed, 17 Jul 2024 14:20:15 GMT pub creation_time: String, // Wed, 17 Jul 2024 14:20:15 GMT
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct RefreshTokenResponseCustomClaims { pub struct RefreshTokenResponseCustomClaims {
pub plan: String, // skf = 50GB free pub plan: String, // skf = 50GB free
} }