pcs-cli 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pcs.js +1 -1
- package/package.json +1 -1
package/dist/pcs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as e}from"@commander-js/extra-typings";import t from"chalk";import o,{mkdtempSync as r,statSync as n,mkdirSync as a,createReadStream as s,createWriteStream as i,existsSync as c}from"fs";import p from"open";import d from"prompts";import l from"axios";import"crypto";import m,{tmpdir as h}from"os";import u,{basename as f,join as g,sep as y,dirname as w,relative as k}from"path";import{pipeline as _}from"stream/promises";import{homedir as b}from"node:os";import $ from"node:path";import{promises as v}from"node:fs";import x from"bytes";import S from"cliui";import C from"dayjs";import O from"progress";import{glob as z}from"glob";import{sep as T,join as E}from"node:path/posix";import N from"https";class B{config;axios;constructor(e){this.config=e,this.config={scope:"basic,netdisk",...e},this.axios=l.create({timeout:1e4})}async getUserInfo(e){const{data:t}=await l.get("https://pan.baidu.com/rest/2.0/xpan/nas",{params:{method:"uinfo",access_token:e}});return t}async refreshToken(e){const{client_secret:t,client_id:o}=this.config,{data:r}=await l.get("https://openapi.baidu.com/oauth/2.0/token",{params:{grant_type:"refresh_token",client_id:o,client_secret:t,refresh_token:e}});return r}}class q extends B{constructor(e){super({...e,response_type:"device_code"})}async getDeviceCode(){const{data:e}=await this.axios.get("https://openapi.baidu.com/oauth/2.0/device/code",{params:{response_type:"device_code",client_id:this.config.client_id,scope:this.config.scope}});return e}getAuthorizeURL(e){return`${e.verification_url}?code=${e.user_code}`}async authorize(e){const{client_id:t,client_secret:o,scope:r}=this.config,{data:n}=await this.axios.get("https://openapi.baidu.com/oauth/2.0/token",{params:{grant_type:"device_token",code:e,client_id:t,client_secret:o,scope:r}});return n}}function I(e,t){return`]8;;${t}${e}]8;;`}async function P(e,t,o=r(g(h(),"splitFile-"))){if(!e||"string"!=typeof e)throw new TypeError("path must be a non-empty string");if(!Number.isInteger(t)||t<=0)throw new TypeError("chunkSize must be a positive integer");if(!o||"string"!=typeof o)throw new TypeError("outputDir must be a non-empty string");const c=[],{size:p}=n(e),d=f(e);a(o,{recursive:!0});for(let r=0;r<p;r+=t){const n=Math.min(r+t-1,p-1),a=g(o,`${d}.${c.length+1}`),l=s(e,{start:r,end:n}),m=i(a);await _(l,m),c.push(a)}return c}const V=$.join(b(),".pcs"),D=$.join(V,"config.json"),L="https://pan.baidu.com/union/console/createapp";async function j(e,t){try{const o=u.dirname(e);await v.mkdir(o,{recursive:!0}),await v.writeFile(e,JSON.stringify(t,null,2),"utf8")}catch(e){if(e instanceof Error)throw new Error(`写入文件失败: ${e.message}`)}}const A=new e("init").description("initialize baidu pcs").option("-n, --name <string>","app name","").option("-k, --key <string>","app key","").option("-s, --secret <string>","app secret","").action(async e=>{if(c(D)){const{confirm:e}=await d({type:"confirm",name:"confirm",message:"Baidu pcs initialization will be begin. If you have already configured before, your old settings will be overwritten. Can you confirm?",initial:!1});if(!e)return}const o=[];if(["name","key","secret"].forEach(t=>{e[t]||o.push({type:"text",name:t,message:`Please enter baidu app ${t}`})}),!(e={...e,...await d(o)}).key||!e.secret)return;const r=await async function(e){const o=new q({client_id:e.key,client_secret:e.secret}),r=await o.getDeviceCode(),n=o.getAuthorizeURL(r);console.log("Launch your favorite web browser and visit: "),console.log(I(n,n)),console.log(`Input ${t.bold.red(r.user_code)} as the user code if asked.`),console.log("After granting access to the application, come back here and "),await p(n);const{confirm:a}=await d({type:"confirm",name:"confirm",message:"Press Enter to continue",initial:!0});if(a){const e=await o.authorize(r.device_code);return console.log(t.green("Successfully initialized")),console.log(`access_token: ${t.yellowBright(e.access_token)}`),console.log(`refresh_token: ${t.yellowBright(e.refresh_token)}`),e}}(e);r&&await j(D,{...e,...r})}),U=new e("list").description("list directory contents").argument("[path]","path","/").alias("ll").option("-t --token <token>","access token","").action(async(e,o,r)=>{const{pcs:n}=r;try{const o=S({}),{list:r}=await n.list(e);r.map(e=>{const{server_mtime:r,size:n,server_filename:a,isdir:s}=e,i=1===s?t.blueBright(a):a;return o.div({text:t.gray(C.unix(r).format("YYYY/MM/DD HH:mm:ss")),width:22,padding:[0,0,0,0]},{text:x(n),width:15,align:"right",padding:[0,2,0,0]},{text:i,padding:[0,0,0,0]}),e}),console.log(o.toString())}catch(e){const{response:{data:o}}=e;console.error(t.red(`error code ${o.error_code} : ${o.error_msg}`))}}),Y=new e("meta").description("get path meta").argument("[path]","meta path","/").option("-t --token [token]","access token").action(async(e,o,r)=>{const{pcs:n}=r;try{const{list:t}=await n.meta(e);console.log(t[0])}catch(e){const{response:{data:o}}=e;console.log(t.red(`error code ${o.error_code}: ${o.error_msg}`))}}),F=new e("quota").description("check your pcs status").option("-t --token [token]","access token").action(async(e,o)=>{const{pcs:r}=o;try{const{quota:e,used:o}=await r.quota();new O(":bar :used/:quota :percent",{complete:"█",incomplete:t.green("░"),width:30,total:e}).tick(o,{used:x(o),quota:x(e)}),console.log("")}catch(e){const{response:{data:o}}=e;console.log(t.red`error code ${o.error_code} : ${o.error_msg}`)}}),J=new e("fetch").description("fetch source to remote").argument("[source]","source path",y).argument("[remote]","remote path",".").option("-t --token <token>","access token","").action(async(e,o,r,n)=>{const{pcs:a}=n;try{await a.fetch(e,o)}catch(e){const{response:{data:o}}=e;console.log(t.red(`error code ${o.error_code} : ${o.error_msg}`))}}),M=new e("delete").alias("rm").description("delete remote file").argument("<remote>","remote path").option("-t --token <token>","access token","").action(async(e,o,r)=>{const{pcs:n}=r;if(n.resolve(e)===n.resolve("/")){console.log(t.red("You are about to delete the root directory of the application, which will lose all data"));const{confirm:e}=await d({type:"confirm",name:"confirm",message:"Are you sure you want to continue?",initial:!1});if(!e)return}try{await n.delete(e)}catch(e){const{response:{data:o}}=e;console.log(t.red(`error code ${o.error_code} : ${o.error_msg}`))}}),R=new e("upload").description("upload local file").argument("[pattern]","glob pattern","*").argument("[remote]","remote path",y).option("-t --token [token]","access token").option("-b --bytes <number>","split upload bytes size",Number,1073741824).option("--thread","Thread").action(async(e,o,r,{pcs:a})=>{const s=await z(e,{nodir:!0}),{bytes:i}=r,c=g(m.tmpdir(),"pcs-cli");try{for await(const e of s){const r=n(e);if(Number.isInteger(i)&&r.size>i){const t=await P(e,i,c),r=[];for(const e of t){const{md5:t}=await a.upload(e,"","overwrite","tmpfile");r.push(t)}const n={block_list:r};await a.createSuperFile(g(o,e),n)}console.log(`${t.blueBright("==>")} Uploading ${e}`),await a.upload(e,g(o,e))}}catch(e){const{response:{data:t}}=e;console.log(`error code ${t.error_code} : ${t.error_msg}`)}}),H=new e("refresh").description("refresh token").option("-k, --key <string>","app key","").option("-s, --secret <string>","app secret","").option("-t --refresh-token <refresh token>","refresh token","").action(async e=>{const o=new q({client_id:e.key,client_secret:e.secret});try{const r=await o.refreshToken(e.refreshToken);await j(D,{...e,...r}),console.log(t.green("Successfully refreshed token"))}catch(e){const{response:{data:o}}=e;console.log(t.red(`OAuth error ${o.error} : ${o.error_description}`))}}),W=new e("download").alias("dl").description("download remote file").argument("[remote]","remote path",T).argument("[local]","local path",".").option("-t --token <token>","access token","").action(async(e,o,r,n)=>{const{pcs:a}=n;try{const{list:r}=await a.list(e);r.reduce(async(e,r)=>{await e;const n=E(o,a.normalize(r.path));return 1===r.isdir?Promise.resolve():(console.log(`${t.blueBright("==>")} Downloading ${t.green(n)}`),a.download(r.path,n))},Promise.resolve())}catch(e){const{response:{data:o}}=e;console.log(t.red(`error code ${o.error_code||o.statusCode} : ${o.error_msg||o.statusMessage}`))}});class G{name;token;axios;constructor(e,t){this.name=e,this.token=t,this.axios=l.create({timeout:1e4,baseURL:"https://pcs.baidu.com/rest/2.0"})}async quota(){const{data:e}=await this.axios.get("/pcs/quota",{params:{method:"info",access_token:this.token}});return e}async meta(e){const{data:t}=await this.axios.get("/pcs/file",{params:{method:"meta",access_token:this.token,path:this.resolve(e)}});return t}async list(e){const{data:t}=await this.axios.get("/pcs/file",{params:{method:"list",access_token:this.token,path:this.resolve(e)}});return t}async delete(e){const{data:t}=await l.get("/pcs/file",{params:{method:"delete",access_token:this.token,path:this.resolve(e)}});return t}async fetch(e,t){const{data:o}=await l.get("/pcs/services/cloud_dl",{params:{method:"add_task",access_token:this.token,save_path:this.resolve(t),source_url:e}});return o}async download(e,t){o.mkdirSync(w(t),{recursive:!0});const r=o.createWriteStream(t),{data:n,headers:a}=await this.axios.get("/pcs/file",{params:{method:"download",access_token:this.token,path:this.resolve(e)},responseType:"stream"}),s=a["content-length"],i=new O(" downloading [:bar] :rate/bps :percent :etas",{complete:"=",incomplete:" ",width:40,total:parseInt(s,10)});return n.on("data",e=>i.tick(e.length)),n.pipe(r),new Promise((e,t)=>{r.on("finish",e),r.on("error",t)})}async upload(e,t,r="overwrite",n){let a=`/rest/2.0/pcs/file?method=upload&access_token=${this.token}&path=${encodeURIComponent(t)}&ondup=${r}`;n&&(a=`${a}&type=${n}`);const s=o.statSync(e),i=Math.random().toString(16),c=`--${i}\r\nContent-Type: text/plain\r\nContent-Disposition: form-data; name="file"; filename="${t}"\r\n\r\n`,p=`\r\n--${i}--`,d=Buffer.byteLength(c)+Buffer.byteLength(p)+s.size,l=new O("[:bar] :rate/bps :percent :etas",{complete:"=",incomplete:" ",width:40,total:s.size});return new Promise((t,r)=>{const n=N.request({hostname:"pcs.baidu.com",method:"POST",path:a},e=>{e.on("data",e=>{t(JSON.parse(e))}),e.on("end",()=>{}),e.on("error",e=>{r(e)})});n.setHeader("Content-Type",`multipart/form-data; boundary=${i}`),n.setHeader("Content-Length",d),n.write(c);const s=o.createReadStream(e);s.pipe(n,{end:!1}),s.on("end",()=>{n.end(p)}),s.on("data",e=>{l.tick(e.length)})})}async createSuperFile(e,t){const{data:o}=await l.get("/pcs/file",{params:{method:"createsuperfile",access_token:this.token,path:e,param:JSON.stringify(t)}});return o}get rootdir(){return g("/apps",this.name)}resolve(e){return g(this.rootdir,e)}normalize(e){return k(this.rootdir,e)}}const K=new e("pcs-cli").description(`Baidu Personal Cloud Storage Scaffold.\n\nYou can get app key by visit ${I(L,L)}.\nIf you have already created an app, you can visit ${t.blue.underline("https://pan.baidu.com/union/console/applist")} and get it in your app's info.`).version("1.4.0").hook("preAction",async(e,t)=>{const o=t.name();if("init"!==o)try{const e=await async function(e){try{return JSON.parse(await v.readFile(e,"utf8"))}catch(t){if(t instanceof Error&&"code"in t&&"ENOENT"===t.code)throw new Error(`文件不存在: ${e}`);if(t instanceof SyntaxError)throw new Error(`JSON 格式错误: ${t.message}`);throw t}}(D);"refresh"===o?(t.setOptionValue("key",t.getOptionValue("key")||e.key),t.setOptionValue("secret",t.getOptionValue("secret")||e.secret),t.setOptionValue("refreshToken",t.getOptionValue("refreshToken")||e.refresh_token)):t.pcs=new G(t.getOptionValue("name")||e.name,t.getOptionValue("token")||e.access_token)}catch(e){}});K.addCommand(A).addCommand(U).addCommand(Y).addCommand(F).addCommand(J).addCommand(M).addCommand(R).addCommand(H).addCommand(W);try{K.exitOverride(),K.parse(process.argv)}catch(e){}
|
|
2
|
+
import{Command as e}from"@commander-js/extra-typings";import t from"chalk";import o,{mkdtempSync as r,statSync as n,mkdirSync as s,createReadStream as a,createWriteStream as i,existsSync as c}from"fs";import p from"open";import d from"prompts";import l from"axios";import"crypto";import m,{tmpdir as h}from"os";import u,{basename as g,join as f,sep as y,dirname as w,relative as k}from"path";import{pipeline as _}from"stream/promises";import{homedir as b}from"node:os";import $ from"node:path";import{promises as v}from"node:fs";import x from"bytes";import S from"cliui";import z from"dayjs";import C from"progress";import{glob as O}from"glob";import{sep as T,join as E}from"node:path/posix";import A from"https";class U{config;axios;constructor(e){this.config=e,this.config={scope:"basic,netdisk",...e},this.axios=l.create({timeout:1e4})}async getUserInfo(e){const{data:t}=await l.get("https://pan.baidu.com/rest/2.0/xpan/nas",{params:{method:"uinfo",access_token:e}});return t}async refreshToken(e){const{client_secret:t,client_id:o}=this.config,{data:r}=await l.get("https://openapi.baidu.com/oauth/2.0/token",{params:{grant_type:"refresh_token",client_id:o,client_secret:t,refresh_token:e}});return r}}class B extends U{constructor(e){super({...e,response_type:"device_code"})}async getDeviceCode(){const{data:e}=await this.axios.get("https://openapi.baidu.com/oauth/2.0/device/code",{params:{response_type:"device_code",client_id:this.config.client_id,scope:this.config.scope}});return e}getAuthorizeURL(e){return`${e.verification_url}?code=${e.user_code}`}async authorize(e){const{client_id:t,client_secret:o,scope:r}=this.config,{data:n}=await this.axios.get("https://openapi.baidu.com/oauth/2.0/token",{params:{grant_type:"device_token",code:e,client_id:t,client_secret:o,scope:r}});return n}}class L extends U{constructor(e){super({...e,response_type:"token",redirect_uri:"oob"})}getAuthorizeURL(){const{client_secret:e,...t}=this.config;return`https://openapi.baidu.com/oauth/2.0/authorize?${new URLSearchParams(t)}`}async authorize(e){let t;return t=e.startsWith("http")?this.parseTokenFromUrl(e):e.includes("access_token=")?this.parseTokenFromHash(e):{access_token:e,expires_in:2592e3,scope:this.config.scope},t}parseTokenFromUrl(e){const t=new URL(e);return this.parseTokenFromHash(t.hash.substring(1))}parseTokenFromHash(e){const t=new URLSearchParams(e),o=t.get("access_token"),r=t.get("expires_in"),n=t.get("error");if(n)throw new Error(`OAuth error: ${n}`);if(!o)throw new Error("Access token not found");return{access_token:o,expires_in:parseInt(r||"2592000",10),scope:t.get("scope")||this.config.scope,session_key:t.get("session_key")||void 0,session_secret:t.get("session_secret")||void 0}}}function F(e,t){return`]8;;${t}${e}]8;;`}async function P(e,t,o=r(f(h(),"splitFile-"))){if(!e||"string"!=typeof e)throw new TypeError("path must be a non-empty string");if(!Number.isInteger(t)||t<=0)throw new TypeError("chunkSize must be a positive integer");if(!o||"string"!=typeof o)throw new TypeError("outputDir must be a non-empty string");const c=[],{size:p}=n(e),d=g(e);s(o,{recursive:!0});for(let r=0;r<p;r+=t){const n=Math.min(r+t-1,p-1),s=f(o,`${d}.${c.length+1}`),l=a(e,{start:r,end:n}),m=i(s);await _(l,m),c.push(s)}return c}const R=$.join(b(),".pcs"),N=$.join(R,"config.json"),q="https://pan.baidu.com/union/console/createapp",I="https://pan.baidu.com/union/console/applist";async function V(e,t){try{const o=u.dirname(e);await v.mkdir(o,{recursive:!0}),await v.writeFile(e,JSON.stringify(t,null,2),"utf8")}catch(e){if(e instanceof Error)throw new Error(`写入文件失败: ${e.message}`)}}const D=new e("init").description("initialize baidu pcs").option("-n, --name <string>","app name","").option("-k, --key <string>","app key","").option("-s, --secret <string>","app secret","").action(async e=>{if(c(N)){console.log(t.redBright("Baidu pcs initialization will be begin. If you have already configured before, your old settings will be overwritten."));const{confirm:e}=await d({type:"confirm",name:"confirm",message:"Can you confirm?",initial:!1});if(!e)return}const o=[];["name","key","secret"].forEach(t=>{e[t]||o.push({type:"text",name:t,message:`Please enter baidu app ${t}`})}),(e={...e,...await d(o)}).key&&(e.secret?await async function(e){const o=new B({client_id:e.key,client_secret:e.secret}),r=await o.getDeviceCode(),n=o.getAuthorizeURL(r);console.log("Launch your favorite web browser and visit: "),console.log(F(n,n)),console.log(`Input ${t.bold.red(r.user_code)} as the user code if asked.`),console.log("After granting access to the application, come back here and "),await p(n);const{confirm:s}=await d({type:"confirm",name:"confirm",message:"Press Enter to continue",initial:!0});if(s){const n=await o.authorize(r.device_code);console.log(t.green("Successfully initialized")),console.log(`access_token: ${t.yellowBright(n.access_token)}`),console.log(`refresh_token: ${t.yellowBright(n.refresh_token)}`),await V(N,{...e,...n})}}(e):await async function(e){const o=new L({client_id:e.key}).getAuthorizeURL();await p(o),console.log(t.hex("#FFA500")("You'll have to grab the access_token generated by Baidu.")),console.log(""),console.log(`1. Visit ${t.blue.underline(F(o,o))}`),console.log("2. After the page is being redirected (it should show something like OAuth 2.0), copy the current URL to your favorite text editor"),console.log('3. Grab the access_token part, take only the part between "access_token=" and the next "&" symbol (without quotes).'),console.log("4. Copy it and paste here, then press Enter.");const{access_token:r}=await d({type:"text",name:"access_token",message:"access_token"});r&&await V(N,{...e,access_token:r})}(e))}),H=new e("list").description("list directory contents").argument("[path]","path","/").alias("ll").option("-t --token <token>","access token","").action(async(e,o,{pcs:r})=>{try{const o=S({}),{list:n}=await r.list(e);n.map(e=>{const{server_mtime:r,size:n,server_filename:s,isdir:a}=e,i=1===a?t.blueBright(s):s;return o.div({text:t.gray(z.unix(r).format("YYYY/MM/DD HH:mm:ss")),width:22,padding:[0,0,0,0]},{text:x(n),width:15,align:"right",padding:[0,2,0,0]},{text:i,padding:[0,0,0,0]}),e}),console.log(o.toString())}catch(e){const{response:{data:o}}=e;console.error(t.red(`error code ${o.error_code} : ${o.error_msg}`))}}),Y=new e("meta").description("get path meta").argument("[path]","meta path","/").option("-t --token [token]","access token").action(async(e,o,{pcs:r})=>{try{const{list:t}=await r.meta(e);console.log(t[0])}catch(e){const{response:{data:o}}=e;console.log(t.red(`error code ${o.error_code}: ${o.error_msg}`))}}),j=new e("quota").description("check your pcs status").option("-t --token [token]","access token").action(async(e,{pcs:o})=>{try{const{quota:e,used:r}=await o.quota();new C(":bar :used/:quota :percent",{complete:"█",incomplete:t.green("░"),width:30,total:e}).tick(r,{used:x(r),quota:x(e)}),console.log("")}catch(e){const{response:{data:o}}=e;console.log(t.red`error code ${o.error_code} : ${o.error_msg}`)}}),J=new e("fetch").description("offline download").argument("[url]","url",y).argument("[remote]","remote path",".").option("-t --token <token>","access token","").action(async(e,o,r,{pcs:n})=>{try{await n.fetch(e,o)}catch(e){const{response:{data:o}}=e;console.log(t.red(`error code ${o.error_code} : ${o.error_msg}`))}}),M=new e("delete").alias("rm").description("delete remote file").argument("<remote>","remote path").option("-t --token <token>","access token","").action(async(e,o,{pcs:r})=>{if(r.resolve(e)===r.resolve("/")){console.log(t.redBright("You are about to delete the root directory of the application, which will lose all data"));const{confirm:e}=await d({type:"confirm",name:"confirm",message:"Are you sure you want to continue?",initial:!1});if(!e)return}try{await r.delete(e)}catch(e){const{response:{data:o}}=e;console.log(t.red(`error code ${o.error_code} : ${o.error_msg}`))}}),W=new e("upload").description("upload local file").argument("[pattern]","glob pattern","*").argument("[remote]","remote path",y).option("-t --token [token]","access token").option("-b --bytes <number>","split upload bytes size",Number,1073741824).option("--thread","Thread").action(async(e,o,r,{pcs:s})=>{const a=await O(e,{nodir:!0}),{bytes:i}=r,c=f(m.tmpdir(),"pcs-cli");try{for await(const e of a){const r=n(e);if(Number.isInteger(i)&&r.size>i){const t=await P(e,i,c),r=[];for(const e of t){const{md5:t}=await s.upload(e,"","overwrite","tmpfile");r.push(t)}const n={block_list:r};await s.createSuperFile(f(o,e),n)}console.log(`${t.blueBright("==>")} Uploading ${e}`),await s.upload(e,f(o,e))}}catch(e){const{response:{data:t}}=e;console.log(`error code ${t.error_code} : ${t.error_msg}`)}}),G=new e("refresh").description("refresh token").option("-k, --key <string>","app key","").option("-s, --secret <string>","app secret","").option("-t --refresh-token <refresh token>","refresh token","").action(async e=>{const o=new B({client_id:e.key,client_secret:e.secret});try{const r=await o.refreshToken(e.refreshToken);await V(N,{...e,...r}),console.log(t.green("Successfully refreshed token"))}catch(e){const{response:{data:o}}=e;console.log(t.red(`OAuth error ${o.error} : ${o.error_description}`))}}),K=new e("download").alias("dl").description("download remote file").argument("[remote]","remote path",T).argument("[local]","local path",".").option("-t --token <token>","access token","").action(async(e,o,r,{pcs:n})=>{try{const{list:r}=await n.list(e);r.reduce(async(e,r)=>{await e;const s=E(o,n.normalize(r.path));return 1===r.isdir?Promise.resolve():(console.log(`${t.blueBright("==>")} Downloading ${t.green(s)}`),n.download(r.path,s))},Promise.resolve())}catch(e){const{response:{data:o}}=e;console.log(t.red(`error code ${o.error_code||o.statusCode} : ${o.error_msg||o.statusMessage}`))}});class Q{name;token;axios;constructor(e,t){this.name=e,this.token=t,this.axios=l.create({timeout:1e4,baseURL:"https://pcs.baidu.com/rest/2.0"})}async quota(){const{data:e}=await this.axios.get("/pcs/quota",{params:{method:"info",access_token:this.token}});return e}async meta(e){const{data:t}=await this.axios.get("/pcs/file",{params:{method:"meta",access_token:this.token,path:this.resolve(e)}});return t}async list(e){const{data:t}=await this.axios.get("/pcs/file",{params:{method:"list",access_token:this.token,path:this.resolve(e)}});return t}async delete(e){const{data:t}=await l.get("/pcs/file",{params:{method:"delete",access_token:this.token,path:this.resolve(e)}});return t}async fetch(e,t){const{data:o}=await l.get("/pcs/services/cloud_dl",{params:{method:"add_task",access_token:this.token,save_path:this.resolve(t),source_url:e}});return o}async download(e,t){o.mkdirSync(w(t),{recursive:!0});const r=o.createWriteStream(t),{data:n,headers:s}=await this.axios.get("/pcs/file",{params:{method:"download",access_token:this.token,path:this.resolve(e)},responseType:"stream"}),a=s["content-length"],i=new C(" downloading [:bar] :rate/bps :percent :etas",{complete:"=",incomplete:" ",width:40,total:parseInt(a,10)});return n.on("data",e=>i.tick(e.length)),n.pipe(r),new Promise((e,t)=>{r.on("finish",e),r.on("error",t)})}async upload(e,t,r="overwrite",n){let s=`/rest/2.0/pcs/file?method=upload&access_token=${this.token}&path=${encodeURIComponent(t)}&ondup=${r}`;n&&(s=`${s}&type=${n}`);const a=o.statSync(e),i=Math.random().toString(16),c=`--${i}\r\nContent-Type: text/plain\r\nContent-Disposition: form-data; name="file"; filename="${t}"\r\n\r\n`,p=`\r\n--${i}--`,d=Buffer.byteLength(c)+Buffer.byteLength(p)+a.size,l=new C("[:bar] :rate/bps :percent :etas",{complete:"=",incomplete:" ",width:40,total:a.size});return new Promise((t,r)=>{const n=A.request({hostname:"pcs.baidu.com",method:"POST",path:s},e=>{e.on("data",e=>{t(JSON.parse(e))}),e.on("end",()=>{}),e.on("error",e=>{r(e)})});n.setHeader("Content-Type",`multipart/form-data; boundary=${i}`),n.setHeader("Content-Length",d),n.write(c);const a=o.createReadStream(e);a.pipe(n,{end:!1}),a.on("end",()=>{n.end(p)}),a.on("data",e=>{l.tick(e.length)})})}async createSuperFile(e,t){const{data:o}=await l.get("/pcs/file",{params:{method:"createsuperfile",access_token:this.token,path:e,param:JSON.stringify(t)}});return o}get rootdir(){return f("/apps",this.name)}resolve(e){return f(this.rootdir,e)}normalize(e){return k(this.rootdir,e)}}const X=new e("pcs-cli").description(`${t.bold("Baidu Personal Cloud Storage Scaffold")}.\n\nYou can get app key by visit ${t.blue.underline(F(q,q))}.\nIf you have already created an app, you can visit ${t.blue.underline(F(I,I))} and get it in your app's info.`).version("1.5.0").hook("preAction",async(e,o)=>{const r=o.name();if("init"!==r)try{const e=await async function(e){try{return JSON.parse(await v.readFile(e,"utf8"))}catch(t){if(t instanceof Error&&"code"in t&&"ENOENT"===t.code)throw new Error(`文件不存在: ${e}`);if(t instanceof SyntaxError)throw new Error(`JSON 格式错误: ${t.message}`);throw t}}(N);"refresh"===r?(o.setOptionValue("key",o.getOptionValue("key")||e.key),o.setOptionValue("secret",o.getOptionValue("secret")||e.secret),o.setOptionValue("refreshToken",o.getOptionValue("refreshToken")||e.refresh_token)):o.pcs=new Q(o.getOptionValue("name")||e.name,o.getOptionValue("token")||e.access_token)}catch(e){throw new Error(t.redBright('Please use the "pcs init" command to initialize'))}});X.addCommand(D).addCommand(H).addCommand(Y).addCommand(j).addCommand(J).addCommand(M).addCommand(W).addCommand(G).addCommand(K);try{X.exitOverride(),await X.parseAsync(process.argv)}catch(e){console.log(e.message)}
|