baiduwangpan-cli 1.0.0 → 1.0.2
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/README.md +66 -3
- package/bin/bdp.js +247 -24
- package/lib/browser-login.js +432 -0
- package/lib/config.js +18 -2
- package/lib/group.js +345 -56
- package/lib/http.js +38 -6
- package/package.json +6 -2
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
const { spawn, execSync } = require("child_process");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const os = require("os");
|
|
5
|
+
const http = require("http");
|
|
6
|
+
|
|
7
|
+
const PAN_HOME = "https://pan.baidu.com/disk/main";
|
|
8
|
+
const DEFAULT_PROFILE_DIR = path.join(os.homedir(), ".bdp", "browser-profile");
|
|
9
|
+
const APP_ID = "250528";
|
|
10
|
+
|
|
11
|
+
let activeSession = null;
|
|
12
|
+
let disconnectTimer = null;
|
|
13
|
+
|
|
14
|
+
function findBrowser() {
|
|
15
|
+
const candidates = [];
|
|
16
|
+
|
|
17
|
+
if (os.platform() === "win32") {
|
|
18
|
+
const programFiles = [
|
|
19
|
+
process.env.PROGRAMFILES || "C:\\Program Files",
|
|
20
|
+
process.env["PROGRAMFILES(X86)"] || "C:\\Program Files (x86)",
|
|
21
|
+
process.env.LOCALAPPDATA || "",
|
|
22
|
+
];
|
|
23
|
+
for (const pf of programFiles) {
|
|
24
|
+
candidates.push(path.join(pf, "Google\\Chrome\\Application\\chrome.exe"));
|
|
25
|
+
candidates.push(path.join(pf, "Microsoft\\Edge\\Application\\msedge.exe"));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (os.platform() === "darwin") {
|
|
30
|
+
candidates.push("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome");
|
|
31
|
+
candidates.push("/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
for (const name of ["google-chrome", "chromium", "chromium-browser", "microsoft-edge", "chrome"]) {
|
|
35
|
+
try {
|
|
36
|
+
const out = execSync(`command -v ${name}`, { stdio: "pipe" }).toString().trim();
|
|
37
|
+
if (out) candidates.push(out);
|
|
38
|
+
} catch {}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const candidate of candidates) {
|
|
42
|
+
if (candidate && fs.existsSync(candidate)) return candidate;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function httpRequest(url, method = "GET") {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const req = http.request(url, { method }, (res) => {
|
|
50
|
+
let data = "";
|
|
51
|
+
res.on("data", (chunk) => (data += chunk));
|
|
52
|
+
res.on("end", () => resolve(data));
|
|
53
|
+
});
|
|
54
|
+
req.setTimeout(2000, () => req.destroy(new Error("DevTools request timed out")));
|
|
55
|
+
req.on("error", reject);
|
|
56
|
+
req.end();
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function getDevToolsVersion(port) {
|
|
61
|
+
const raw = await httpRequest(`http://127.0.0.1:${port}/json/version`);
|
|
62
|
+
const version = JSON.parse(raw);
|
|
63
|
+
if (!version.webSocketDebuggerUrl || !/Chrome|Chromium|Edg/i.test(version.Browser || "")) {
|
|
64
|
+
throw new Error("The configured DevTools port is not a Chromium browser");
|
|
65
|
+
}
|
|
66
|
+
return version;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function waitForDevTools(port, timeoutMs) {
|
|
70
|
+
const deadline = Date.now() + timeoutMs;
|
|
71
|
+
while (Date.now() < deadline) {
|
|
72
|
+
try {
|
|
73
|
+
return await getDevToolsVersion(port);
|
|
74
|
+
} catch {}
|
|
75
|
+
await delay(300);
|
|
76
|
+
}
|
|
77
|
+
throw new Error("DevTools 启动超时");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function listTabs(port) {
|
|
81
|
+
return JSON.parse(await httpRequest(`http://127.0.0.1:${port}/json/list`));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function openTab(port, url) {
|
|
85
|
+
const encoded = encodeURIComponent(url);
|
|
86
|
+
return JSON.parse(await httpRequest(`http://127.0.0.1:${port}/json/new?${encoded}`, "PUT"));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getWebSocketImpl() {
|
|
90
|
+
if (typeof WebSocket !== "undefined") return WebSocket;
|
|
91
|
+
try {
|
|
92
|
+
return require("ws");
|
|
93
|
+
} catch {
|
|
94
|
+
throw new Error("Browser login requires Node.js 22+ or the optional 'ws' package");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
class CDPClient {
|
|
99
|
+
constructor(wsUrl) {
|
|
100
|
+
const WebSocketImpl = getWebSocketImpl();
|
|
101
|
+
this.ws = new WebSocketImpl(wsUrl);
|
|
102
|
+
this.id = 0;
|
|
103
|
+
this.pending = new Map();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
connect() {
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
this.ws.onopen = resolve;
|
|
109
|
+
this.ws.onerror = () => reject(new Error("WebSocket 连接失败"));
|
|
110
|
+
this.ws.onclose = () => {
|
|
111
|
+
for (const pending of this.pending.values()) {
|
|
112
|
+
pending.reject(new Error("DevTools connection closed"));
|
|
113
|
+
}
|
|
114
|
+
this.pending.clear();
|
|
115
|
+
};
|
|
116
|
+
this.ws.onmessage = (event) => {
|
|
117
|
+
const raw = typeof event.data === "string" ? event.data : event.data.toString();
|
|
118
|
+
const msg = JSON.parse(raw);
|
|
119
|
+
if (msg.id && this.pending.has(msg.id)) {
|
|
120
|
+
const pending = this.pending.get(msg.id);
|
|
121
|
+
this.pending.delete(msg.id);
|
|
122
|
+
if (msg.error) pending.reject(new Error(msg.error.message));
|
|
123
|
+
else pending.resolve(msg.result);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
send(method, params = {}) {
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
const id = ++this.id;
|
|
132
|
+
this.pending.set(id, { resolve, reject });
|
|
133
|
+
this.ws.send(JSON.stringify({ id, method, params }));
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
close() {
|
|
138
|
+
try { this.ws.close(); } catch {}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function randomPort() {
|
|
143
|
+
return 9000 + Math.floor(Math.random() * 2000);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function launchBrowser(browser, profileDir, port, { minimized = false } = {}) {
|
|
147
|
+
fs.mkdirSync(profileDir, { recursive: true });
|
|
148
|
+
const args = [
|
|
149
|
+
`--remote-debugging-port=${port}`,
|
|
150
|
+
`--user-data-dir=${profileDir}`,
|
|
151
|
+
"--no-first-run",
|
|
152
|
+
"--no-default-browser-check",
|
|
153
|
+
"--disable-extensions",
|
|
154
|
+
"--disable-popup-blocking",
|
|
155
|
+
];
|
|
156
|
+
if (minimized) args.push("--start-minimized");
|
|
157
|
+
args.push("about:blank");
|
|
158
|
+
|
|
159
|
+
const proc = spawn(browser, args, {
|
|
160
|
+
stdio: "ignore",
|
|
161
|
+
detached: true,
|
|
162
|
+
windowsHide: minimized,
|
|
163
|
+
});
|
|
164
|
+
proc.unref();
|
|
165
|
+
return proc;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function connectPanTab(port) {
|
|
169
|
+
const tabs = await listTabs(port);
|
|
170
|
+
let tab = tabs.find((item) => item.type === "page" && /^https:\/\/pan\.baidu\.com\//.test(item.url));
|
|
171
|
+
if (!tab) tab = await openTab(port, PAN_HOME);
|
|
172
|
+
|
|
173
|
+
const cdp = new CDPClient(tab.webSocketDebuggerUrl);
|
|
174
|
+
await cdp.connect();
|
|
175
|
+
await cdp.send("Network.enable");
|
|
176
|
+
await cdp.send("Runtime.enable");
|
|
177
|
+
return { cdp, tab };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function waitForPanPage(cdp, timeoutMs = 20000) {
|
|
181
|
+
const deadline = Date.now() + timeoutMs;
|
|
182
|
+
while (Date.now() < deadline) {
|
|
183
|
+
try {
|
|
184
|
+
const result = await cdp.send("Runtime.evaluate", {
|
|
185
|
+
expression: "location.hostname === 'pan.baidu.com' && document.readyState !== 'loading'",
|
|
186
|
+
returnByValue: true,
|
|
187
|
+
});
|
|
188
|
+
if (result.result?.value === true) return;
|
|
189
|
+
} catch {}
|
|
190
|
+
await delay(300);
|
|
191
|
+
}
|
|
192
|
+
throw new Error("百度网盘页面加载超时");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function evaluateFetch(cdp, url, options = {}) {
|
|
196
|
+
const request = {
|
|
197
|
+
method: options.method || "GET",
|
|
198
|
+
credentials: "include",
|
|
199
|
+
headers: options.headers || {},
|
|
200
|
+
};
|
|
201
|
+
if (Object.prototype.hasOwnProperty.call(options, "body")) request.body = options.body;
|
|
202
|
+
|
|
203
|
+
const expression = `fetch(${JSON.stringify(url)}, ${JSON.stringify(request)})
|
|
204
|
+
.then(async response => ({
|
|
205
|
+
ok: response.ok,
|
|
206
|
+
status: response.status,
|
|
207
|
+
url: response.url,
|
|
208
|
+
text: await response.text()
|
|
209
|
+
}))`;
|
|
210
|
+
const evaluated = await cdp.send("Runtime.evaluate", {
|
|
211
|
+
expression,
|
|
212
|
+
awaitPromise: true,
|
|
213
|
+
returnByValue: true,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
if (evaluated.exceptionDetails) {
|
|
217
|
+
const message = evaluated.exceptionDetails.exception?.description ||
|
|
218
|
+
evaluated.exceptionDetails.text || "Browser fetch failed";
|
|
219
|
+
throw new Error(message);
|
|
220
|
+
}
|
|
221
|
+
const response = evaluated.result?.value;
|
|
222
|
+
if (!response || typeof response.text !== "string") {
|
|
223
|
+
throw new Error("Browser fetch returned no response");
|
|
224
|
+
}
|
|
225
|
+
return response;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async function openPersistentSession({ browser, profileDir, port, minimized }) {
|
|
229
|
+
let proc = null;
|
|
230
|
+
try {
|
|
231
|
+
await getDevToolsVersion(port);
|
|
232
|
+
} catch {
|
|
233
|
+
proc = launchBrowser(browser, profileDir, port, { minimized });
|
|
234
|
+
await waitForDevTools(port, 15000);
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
const { cdp, tab } = await connectPanTab(port);
|
|
238
|
+
return { browser, profileDir, port, proc, cdp, tab };
|
|
239
|
+
} catch (e) {
|
|
240
|
+
if (proc) killBrowser(proc);
|
|
241
|
+
throw e;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async function getBrowserSession(settings = {}) {
|
|
246
|
+
if (activeSession) {
|
|
247
|
+
try {
|
|
248
|
+
await activeSession.cdp.send("Runtime.evaluate", { expression: "1" });
|
|
249
|
+
return activeSession;
|
|
250
|
+
} catch {
|
|
251
|
+
activeSession.cdp.close();
|
|
252
|
+
activeSession = null;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const browser = settings.browser || findBrowser();
|
|
257
|
+
if (!browser) throw new Error("未找到 Chrome/Edge,无法使用扫码登录会话调用网页 API");
|
|
258
|
+
const profileDir = settings.profileDir || DEFAULT_PROFILE_DIR;
|
|
259
|
+
const configuredPort = Number(settings.port) || randomPort();
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
activeSession = await openPersistentSession({
|
|
263
|
+
browser,
|
|
264
|
+
profileDir,
|
|
265
|
+
port: configuredPort,
|
|
266
|
+
minimized: true,
|
|
267
|
+
});
|
|
268
|
+
} catch (error) {
|
|
269
|
+
if (!settings.port) throw error;
|
|
270
|
+
activeSession = await openPersistentSession({
|
|
271
|
+
browser,
|
|
272
|
+
profileDir,
|
|
273
|
+
port: randomPort(),
|
|
274
|
+
minimized: true,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
await waitForPanPage(activeSession.cdp);
|
|
278
|
+
if (settings.onPort) settings.onPort(activeSession.port);
|
|
279
|
+
return activeSession;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async function browserJson(url, options = {}, settings = {}) {
|
|
283
|
+
const session = await getBrowserSession(settings);
|
|
284
|
+
let response;
|
|
285
|
+
try {
|
|
286
|
+
response = await evaluateFetch(session.cdp, url, options);
|
|
287
|
+
} catch (error) {
|
|
288
|
+
session.cdp.close();
|
|
289
|
+
activeSession = null;
|
|
290
|
+
throw error;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
return JSON.parse(response.text.replace(/^\s+/, ""));
|
|
295
|
+
} catch {
|
|
296
|
+
return { _raw: response.text, _status: response.status, _url: response.url };
|
|
297
|
+
} finally {
|
|
298
|
+
scheduleDisconnect();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function getTemplateVariableUrl() {
|
|
303
|
+
const fields = encodeURIComponent('["bdstoken","token","uk","isdocuser","servertime"]');
|
|
304
|
+
return `https://pan.baidu.com/api/gettemplatevariable?clienttype=0&app_id=${APP_ID}&web=1&fields=${fields}`;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async function browserLogin({
|
|
308
|
+
timeoutMs = 180000,
|
|
309
|
+
onStatus,
|
|
310
|
+
profileDir = DEFAULT_PROFILE_DIR,
|
|
311
|
+
port = randomPort(),
|
|
312
|
+
} = {}) {
|
|
313
|
+
const browser = findBrowser();
|
|
314
|
+
if (!browser) {
|
|
315
|
+
throw new Error("未找到 Chrome/Edge。请手动获取 BDUSS/STOKEN 后使用 bdp login --bduss --stoken");
|
|
316
|
+
}
|
|
317
|
+
port = Number(port) || randomPort();
|
|
318
|
+
|
|
319
|
+
if (onStatus) onStatus("启动浏览器...");
|
|
320
|
+
let proc = null;
|
|
321
|
+
|
|
322
|
+
let cdp;
|
|
323
|
+
try {
|
|
324
|
+
try {
|
|
325
|
+
await getDevToolsVersion(port);
|
|
326
|
+
} catch {
|
|
327
|
+
proc = launchBrowser(browser, profileDir, port);
|
|
328
|
+
await waitForDevTools(port, 15000);
|
|
329
|
+
}
|
|
330
|
+
const tab = await openTab(port, PAN_HOME);
|
|
331
|
+
if (onStatus) onStatus("浏览器已打开,请登录百度网盘(扫码或账号密码均可)...");
|
|
332
|
+
|
|
333
|
+
cdp = new CDPClient(tab.webSocketDebuggerUrl);
|
|
334
|
+
await cdp.connect();
|
|
335
|
+
await cdp.send("Network.enable");
|
|
336
|
+
await cdp.send("Runtime.enable");
|
|
337
|
+
|
|
338
|
+
const deadline = Date.now() + timeoutMs;
|
|
339
|
+
let lastStatus = "";
|
|
340
|
+
let authRetries = 0;
|
|
341
|
+
|
|
342
|
+
while (Date.now() < deadline) {
|
|
343
|
+
try {
|
|
344
|
+
const { cookies } = await cdp.send("Network.getCookies", {
|
|
345
|
+
urls: ["https://pan.baidu.com/", "https://passport.baidu.com/"],
|
|
346
|
+
});
|
|
347
|
+
const bduss = cookies.find((cookie) => cookie.name === "BDUSS")?.value || "";
|
|
348
|
+
const stoken = cookies.find((cookie) => cookie.name === "STOKEN")?.value || "";
|
|
349
|
+
const status = bduss ? (stoken ? "both" : "bduss-only") : "none";
|
|
350
|
+
|
|
351
|
+
if (status !== lastStatus) {
|
|
352
|
+
lastStatus = status;
|
|
353
|
+
if (status === "both" && onStatus) onStatus("检测到登录凭证,正在浏览器会话内验证...");
|
|
354
|
+
if (status === "bduss-only" && onStatus) onStatus("已检测到 BDUSS,等待 STOKEN...");
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (bduss && stoken) {
|
|
358
|
+
await waitForPanPage(cdp, 5000);
|
|
359
|
+
const response = await evaluateFetch(cdp, getTemplateVariableUrl());
|
|
360
|
+
const data = JSON.parse(response.text.replace(/^\s+/, ""));
|
|
361
|
+
const bdstoken = data?.result?.bdstoken;
|
|
362
|
+
if (data?.errno === 0 && bdstoken) {
|
|
363
|
+
await minimizeWindow(cdp, tab.id);
|
|
364
|
+
cdp.close();
|
|
365
|
+
return { bduss, stoken, bdstoken, browserProfile: profileDir, browserPort: port };
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
authRetries++;
|
|
369
|
+
if (onStatus && authRetries % 3 === 0) {
|
|
370
|
+
onStatus("登录凭证尚未通过网页 API 验证,请等待页面完成跳转...");
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
} catch {}
|
|
374
|
+
await delay(1500);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
throw new Error(`等待登录超时(${Math.round(timeoutMs / 1000)}秒)`);
|
|
378
|
+
} catch (error) {
|
|
379
|
+
if (cdp) cdp.close();
|
|
380
|
+
killBrowser(proc);
|
|
381
|
+
throw error;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function scheduleDisconnect() {
|
|
386
|
+
if (disconnectTimer) clearTimeout(disconnectTimer);
|
|
387
|
+
// 空闲 30 秒后断开浏览器会话(批处理请求间隔通常 <30s)
|
|
388
|
+
disconnectTimer = setTimeout(disconnectBrowserSession, 30000);
|
|
389
|
+
disconnectTimer.unref();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function disconnectBrowserSession() {
|
|
393
|
+
if (disconnectTimer) {
|
|
394
|
+
clearTimeout(disconnectTimer);
|
|
395
|
+
disconnectTimer = null;
|
|
396
|
+
}
|
|
397
|
+
if (activeSession) {
|
|
398
|
+
activeSession.cdp.close();
|
|
399
|
+
activeSession = null;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
async function minimizeWindow(cdp, targetId) {
|
|
404
|
+
try {
|
|
405
|
+
const { windowId } = await cdp.send("Browser.getWindowForTarget", { targetId });
|
|
406
|
+
await cdp.send("Browser.setWindowBounds", { windowId, bounds: { windowState: "minimized" } });
|
|
407
|
+
} catch {}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function killBrowser(proc) {
|
|
411
|
+
if (!proc || proc.killed) return;
|
|
412
|
+
try {
|
|
413
|
+
if (os.platform() === "win32") {
|
|
414
|
+
execSync(`taskkill /pid ${proc.pid} /T /F`, { stdio: "ignore" });
|
|
415
|
+
} else {
|
|
416
|
+
try { process.kill(-proc.pid, "SIGKILL"); } catch { proc.kill("SIGKILL"); }
|
|
417
|
+
}
|
|
418
|
+
} catch {}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function delay(ms) {
|
|
422
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
module.exports = {
|
|
426
|
+
browserLogin,
|
|
427
|
+
browserJson,
|
|
428
|
+
findBrowser,
|
|
429
|
+
DEFAULT_PROFILE_DIR,
|
|
430
|
+
disconnectBrowserSession,
|
|
431
|
+
_internals: { CDPClient, evaluateFetch, getTemplateVariableUrl },
|
|
432
|
+
};
|
package/lib/config.js
CHANGED
|
@@ -2,7 +2,7 @@ const fs = require("fs");
|
|
|
2
2
|
const path = require("path");
|
|
3
3
|
const os = require("os");
|
|
4
4
|
|
|
5
|
-
const CONFIG_DIR = path.join(os.homedir(), ".bdp");
|
|
5
|
+
const CONFIG_DIR = process.env.BDP_CONFIG_DIR || path.join(os.homedir(), ".bdp");
|
|
6
6
|
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
7
7
|
|
|
8
8
|
function load() {
|
|
@@ -24,6 +24,10 @@ function get() {
|
|
|
24
24
|
return {
|
|
25
25
|
bduss: fileCfg.bduss || process.env.BDP_BDUSS || "",
|
|
26
26
|
stoken: fileCfg.stoken || process.env.BDP_STOKEN || "",
|
|
27
|
+
cookie: fileCfg.cookie || process.env.BDP_COOKIE || "",
|
|
28
|
+
webTransport: fileCfg.webTransport || "curl",
|
|
29
|
+
browserProfile: fileCfg.browserProfile || "",
|
|
30
|
+
browserPort: parseInt(fileCfg.browserPort || "0", 10) || 0,
|
|
27
31
|
pcsPath: fileCfg.pcsPath || process.env.BAIDUPCS_CMD || findPCS(),
|
|
28
32
|
ua: fileCfg.ua || process.env.NETDISK_UA ||
|
|
29
33
|
"netdisk;P2SP;3.0.0.8;netdisk;11.12.3;ANG-AN00;android-android;10.0;JSbridge4.4.0;jointBridge;1.1.0;",
|
|
@@ -37,6 +41,18 @@ function set(key, value) {
|
|
|
37
41
|
save(cfg);
|
|
38
42
|
}
|
|
39
43
|
|
|
44
|
+
function update(values) {
|
|
45
|
+
save({ ...load(), ...values });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function setAuth(values) {
|
|
49
|
+
const cfg = load();
|
|
50
|
+
for (const key of ["bduss", "stoken", "cookie", "webTransport", "browserProfile", "browserPort"]) {
|
|
51
|
+
delete cfg[key];
|
|
52
|
+
}
|
|
53
|
+
save({ ...cfg, ...values });
|
|
54
|
+
}
|
|
55
|
+
|
|
40
56
|
function findPCS() {
|
|
41
57
|
// 1. Look in package root (postinstall target)
|
|
42
58
|
const pkgRoot = path.join(__dirname, "..");
|
|
@@ -56,4 +72,4 @@ function isLoggedIn() {
|
|
|
56
72
|
return !!(cfg.bduss && cfg.stoken);
|
|
57
73
|
}
|
|
58
74
|
|
|
59
|
-
module.exports = { get, set, load, save, isLoggedIn, CONFIG_DIR, CONFIG_FILE };
|
|
75
|
+
module.exports = { get, set, update, setAuth, load, save, isLoggedIn, CONFIG_DIR, CONFIG_FILE };
|