bililive-cli 3.10.2 → 3.11.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.
|
@@ -4,7 +4,7 @@ var path$7 = require('node:path');
|
|
|
4
4
|
var require$$2$1 = require('node:http');
|
|
5
5
|
var require$$1$2 = require('node:url');
|
|
6
6
|
var a = require('node:https');
|
|
7
|
-
var index = require('./index-
|
|
7
|
+
var index = require('./index-aJuLOmr2.cjs');
|
|
8
8
|
var require$$0$4 = require('tty');
|
|
9
9
|
var require$$1$3 = require('util');
|
|
10
10
|
var require$$0$b = require('assert');
|
|
@@ -277,7 +277,7 @@ class BaiduPCS extends index.TypedEmitter {
|
|
|
277
277
|
try {
|
|
278
278
|
// 执行上传
|
|
279
279
|
this.logger.info(`开始上传: ${localFilePath} 到 ${targetDir}`);
|
|
280
|
-
const args = ["upload", localFilePath, targetDir];
|
|
280
|
+
const args = ["upload", localFilePath, targetDir, "--norapid"];
|
|
281
281
|
console.log(options);
|
|
282
282
|
// if (options?.retry !== undefined) {
|
|
283
283
|
// args.push("--retry", options.retry.toString());
|
|
@@ -368,6 +368,25 @@ class BaiduPCS extends index.TypedEmitter {
|
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
+
const createdDirCache = new Set();
|
|
372
|
+
const pendingDirRequests = new Map();
|
|
373
|
+
const driveIdCache = new Map();
|
|
374
|
+
const pendingDriveIdRequests = new Map();
|
|
375
|
+
const driveLabels = {
|
|
376
|
+
backup: ["备份盘", "文件网盘"],
|
|
377
|
+
resource: ["资源库"],
|
|
378
|
+
};
|
|
379
|
+
function normalizeRemotePath(remotePath) {
|
|
380
|
+
return path$7.posix.normalize(remotePath.replace(/\\/g, "/"));
|
|
381
|
+
}
|
|
382
|
+
function isDirectoryAlreadyExistsError(error) {
|
|
383
|
+
if (!(error instanceof Error))
|
|
384
|
+
return false;
|
|
385
|
+
const errorMessage = error.message.toLowerCase();
|
|
386
|
+
return (errorMessage.includes("already exists") ||
|
|
387
|
+
errorMessage.includes("file exists") ||
|
|
388
|
+
errorMessage.includes("已存在"));
|
|
389
|
+
}
|
|
371
390
|
/**
|
|
372
391
|
* 阿里云盘上传类
|
|
373
392
|
* 使用 aliyunpan 工具进行文件上传
|
|
@@ -376,6 +395,7 @@ class AliyunPan extends index.TypedEmitter {
|
|
|
376
395
|
binary;
|
|
377
396
|
remotePath;
|
|
378
397
|
logger;
|
|
398
|
+
driveType;
|
|
379
399
|
cmd = null;
|
|
380
400
|
loginCmd = null; // 专门用于登录的进程
|
|
381
401
|
constructor(options) {
|
|
@@ -383,9 +403,16 @@ class AliyunPan extends index.TypedEmitter {
|
|
|
383
403
|
this.binary = options?.binary || "aliyunpan";
|
|
384
404
|
this.remotePath = options?.remotePath || "/录播";
|
|
385
405
|
this.logger = options?.logger || index.logObj;
|
|
406
|
+
this.driveType = options?.driveType || "backup";
|
|
386
407
|
// 检查aliyunpan是否安装
|
|
387
408
|
// this.checkInstallation();
|
|
388
409
|
}
|
|
410
|
+
static clearCaches() {
|
|
411
|
+
createdDirCache.clear();
|
|
412
|
+
pendingDirRequests.clear();
|
|
413
|
+
driveIdCache.clear();
|
|
414
|
+
pendingDriveIdRequests.clear();
|
|
415
|
+
}
|
|
389
416
|
/**
|
|
390
417
|
* 检查aliyunpan是否已安装
|
|
391
418
|
*/
|
|
@@ -410,6 +437,109 @@ class AliyunPan extends index.TypedEmitter {
|
|
|
410
437
|
return false;
|
|
411
438
|
}
|
|
412
439
|
}
|
|
440
|
+
getDriveIdCacheKey() {
|
|
441
|
+
return `${this.binary}:${this.driveType}`;
|
|
442
|
+
}
|
|
443
|
+
async resolveDriveId() {
|
|
444
|
+
const cacheKey = this.getDriveIdCacheKey();
|
|
445
|
+
const cachedDriveId = driveIdCache.get(cacheKey);
|
|
446
|
+
if (cachedDriveId) {
|
|
447
|
+
return cachedDriveId;
|
|
448
|
+
}
|
|
449
|
+
const pendingRequest = pendingDriveIdRequests.get(cacheKey);
|
|
450
|
+
if (pendingRequest) {
|
|
451
|
+
return pendingRequest;
|
|
452
|
+
}
|
|
453
|
+
const requestPromise = new Promise((resolve, reject) => {
|
|
454
|
+
const driveCmd = require$$1$1.spawn(this.binary, ["drive"], {
|
|
455
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
456
|
+
windowsHide: true,
|
|
457
|
+
});
|
|
458
|
+
let stdout = "";
|
|
459
|
+
let stderr = "";
|
|
460
|
+
let isSettled = false;
|
|
461
|
+
const timer = setTimeout(() => {
|
|
462
|
+
isSettled = true;
|
|
463
|
+
driveCmd.kill();
|
|
464
|
+
reject(new Error("解析阿里云盘 driveId 超时"));
|
|
465
|
+
}, 10000);
|
|
466
|
+
const cleanup = () => {
|
|
467
|
+
clearTimeout(timer);
|
|
468
|
+
pendingDriveIdRequests.delete(cacheKey);
|
|
469
|
+
};
|
|
470
|
+
const tryResolveDriveId = (data) => {
|
|
471
|
+
stdout += data.toString();
|
|
472
|
+
const driveId = this.parseDriveId(stdout, this.driveType);
|
|
473
|
+
if (!driveId || isSettled)
|
|
474
|
+
return;
|
|
475
|
+
isSettled = true;
|
|
476
|
+
cleanup();
|
|
477
|
+
driveIdCache.set(cacheKey, driveId);
|
|
478
|
+
resolve(driveId);
|
|
479
|
+
driveCmd.kill();
|
|
480
|
+
};
|
|
481
|
+
driveCmd.stdout.on("data", tryResolveDriveId);
|
|
482
|
+
driveCmd.stderr.on("data", (data) => {
|
|
483
|
+
stderr += data.toString();
|
|
484
|
+
});
|
|
485
|
+
driveCmd.on("close", (code) => {
|
|
486
|
+
cleanup();
|
|
487
|
+
if (isSettled)
|
|
488
|
+
return;
|
|
489
|
+
reject(new Error(`解析阿里云盘 driveId 失败: ${stderr || stdout || code}`));
|
|
490
|
+
});
|
|
491
|
+
driveCmd.on("error", (error) => {
|
|
492
|
+
cleanup();
|
|
493
|
+
if (isSettled)
|
|
494
|
+
return;
|
|
495
|
+
reject(error);
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
pendingDriveIdRequests.set(cacheKey, requestPromise);
|
|
499
|
+
return requestPromise;
|
|
500
|
+
}
|
|
501
|
+
parseDriveId(output, driveType) {
|
|
502
|
+
const lines = output.split("\n");
|
|
503
|
+
for (const line of lines) {
|
|
504
|
+
if (!driveLabels[driveType].some((label) => line.includes(label)))
|
|
505
|
+
continue;
|
|
506
|
+
const tokens = line.match(/[A-Za-z0-9_-]{6,}/g);
|
|
507
|
+
if (tokens?.length) {
|
|
508
|
+
return tokens.at(-1) ?? null;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return null;
|
|
512
|
+
}
|
|
513
|
+
getDirCacheKey(remotePath, driveId) {
|
|
514
|
+
return `${this.binary}:${driveId}:${remotePath}`;
|
|
515
|
+
}
|
|
516
|
+
async ensureRemoteDir(remotePath, driveId) {
|
|
517
|
+
const normalizedPath = normalizeRemotePath(remotePath);
|
|
518
|
+
const cacheKey = this.getDirCacheKey(normalizedPath, driveId);
|
|
519
|
+
if (createdDirCache.has(cacheKey)) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
const pendingRequest = pendingDirRequests.get(cacheKey);
|
|
523
|
+
if (pendingRequest) {
|
|
524
|
+
return pendingRequest;
|
|
525
|
+
}
|
|
526
|
+
const requestPromise = (async () => {
|
|
527
|
+
try {
|
|
528
|
+
await this.executeCommand(["mkdir", normalizedPath, "--driveId", driveId]);
|
|
529
|
+
}
|
|
530
|
+
catch (error) {
|
|
531
|
+
if (!isDirectoryAlreadyExistsError(error)) {
|
|
532
|
+
throw error;
|
|
533
|
+
}
|
|
534
|
+
this.logger.warn(`目录已存在,跳过创建: ${normalizedPath}`);
|
|
535
|
+
}
|
|
536
|
+
createdDirCache.add(cacheKey);
|
|
537
|
+
})().finally(() => {
|
|
538
|
+
pendingDirRequests.delete(cacheKey);
|
|
539
|
+
});
|
|
540
|
+
pendingDirRequests.set(cacheKey, requestPromise);
|
|
541
|
+
return requestPromise;
|
|
542
|
+
}
|
|
413
543
|
/**
|
|
414
544
|
* 执行aliyunpan命令
|
|
415
545
|
* @param args 命令参数
|
|
@@ -511,13 +641,13 @@ class AliyunPan extends index.TypedEmitter {
|
|
|
511
641
|
this.emit("error", error);
|
|
512
642
|
throw error;
|
|
513
643
|
}
|
|
514
|
-
|
|
515
|
-
const targetDir = path$7.join(this.remotePath, remoteDir)
|
|
516
|
-
await this.
|
|
644
|
+
const driveId = await this.resolveDriveId();
|
|
645
|
+
const targetDir = normalizeRemotePath(path$7.join(this.remotePath, remoteDir));
|
|
646
|
+
await this.ensureRemoteDir(targetDir, driveId);
|
|
517
647
|
try {
|
|
518
648
|
// 执行上传
|
|
519
649
|
this.logger.info(`开始上传: ${localFilePath} 到 ${targetDir}`);
|
|
520
|
-
const args = ["upload", localFilePath, targetDir, "--norapid"];
|
|
650
|
+
const args = ["upload", localFilePath, targetDir, "--norapid", "--driveId", driveId];
|
|
521
651
|
// 添加覆盖策略选项
|
|
522
652
|
if (options?.policy === "overwrite") {
|
|
523
653
|
args.push("--ow");
|
|
@@ -596,6 +726,7 @@ class AliyunPan extends index.TypedEmitter {
|
|
|
596
726
|
this.loginCmd.on("close", (code) => {
|
|
597
727
|
if (code === 0) {
|
|
598
728
|
if (hasLoginSuccess) {
|
|
729
|
+
AliyunPan.clearCaches();
|
|
599
730
|
this.logger.info("close: 阿里云盘登录成功");
|
|
600
731
|
this.loginCmd = null;
|
|
601
732
|
resolve();
|
|
@@ -717,8 +848,9 @@ class AliyunPan extends index.TypedEmitter {
|
|
|
717
848
|
*/
|
|
718
849
|
async mkdir(remotePath) {
|
|
719
850
|
try {
|
|
720
|
-
const
|
|
721
|
-
|
|
851
|
+
const driveId = await this.resolveDriveId();
|
|
852
|
+
const targetPath = normalizeRemotePath(path$7.join(this.remotePath, remotePath));
|
|
853
|
+
await this.ensureRemoteDir(targetPath, driveId);
|
|
722
854
|
this.logger.info(`创建目录成功: ${targetPath}`);
|
|
723
855
|
return true;
|
|
724
856
|
}
|
|
@@ -30850,6 +30982,48 @@ async function getLiveInfo(ids) {
|
|
|
30850
30982
|
.map((item) => item.value);
|
|
30851
30983
|
return list;
|
|
30852
30984
|
}
|
|
30985
|
+
async function batchStartRecord(ids) {
|
|
30986
|
+
const recorderManager = exports.container.resolve("recorderManager");
|
|
30987
|
+
const requests = ids.map(async (id) => {
|
|
30988
|
+
try {
|
|
30989
|
+
await recorderManager.manager.startRecord(id);
|
|
30990
|
+
return { id, success: true };
|
|
30991
|
+
}
|
|
30992
|
+
catch (error) {
|
|
30993
|
+
return { id, success: false, error: error.message || "开始录制失败" };
|
|
30994
|
+
}
|
|
30995
|
+
});
|
|
30996
|
+
const results = await Promise.allSettled(requests);
|
|
30997
|
+
const finalResults = results
|
|
30998
|
+
.filter((item) => item.status === "fulfilled")
|
|
30999
|
+
.map((item) => item.value);
|
|
31000
|
+
return {
|
|
31001
|
+
results: finalResults,
|
|
31002
|
+
successCount: finalResults.filter((r) => r.success).length,
|
|
31003
|
+
failedCount: finalResults.filter((r) => !r.success).length,
|
|
31004
|
+
};
|
|
31005
|
+
}
|
|
31006
|
+
async function batchStopRecord(ids) {
|
|
31007
|
+
const recorderManager = exports.container.resolve("recorderManager");
|
|
31008
|
+
const requests = ids.map(async (id) => {
|
|
31009
|
+
try {
|
|
31010
|
+
await recorderManager.manager.stopRecord(id);
|
|
31011
|
+
return { id, success: true };
|
|
31012
|
+
}
|
|
31013
|
+
catch (error) {
|
|
31014
|
+
return { id, success: false, error: error.message || "停止录制失败" };
|
|
31015
|
+
}
|
|
31016
|
+
});
|
|
31017
|
+
const results = await Promise.allSettled(requests);
|
|
31018
|
+
const finalResults = results
|
|
31019
|
+
.filter((item) => item.status === "fulfilled")
|
|
31020
|
+
.map((item) => item.value);
|
|
31021
|
+
return {
|
|
31022
|
+
results: finalResults,
|
|
31023
|
+
successCount: finalResults.filter((r) => r.success).length,
|
|
31024
|
+
failedCount: finalResults.filter((r) => !r.success).length,
|
|
31025
|
+
};
|
|
31026
|
+
}
|
|
30853
31027
|
var recorderService = {
|
|
30854
31028
|
getRecorders,
|
|
30855
31029
|
getRecorderNum,
|
|
@@ -30861,6 +31035,8 @@ var recorderService = {
|
|
|
30861
31035
|
stopRecord,
|
|
30862
31036
|
cutRecord,
|
|
30863
31037
|
getLiveInfo,
|
|
31038
|
+
batchStartRecord,
|
|
31039
|
+
batchStopRecord,
|
|
30864
31040
|
resolveChannel,
|
|
30865
31041
|
batchResolveChannel,
|
|
30866
31042
|
getBiliStream,
|
|
@@ -76719,10 +76895,36 @@ router$9.post("/:id/stop_record", async (ctx) => {
|
|
|
76719
76895
|
const { id } = ctx.params;
|
|
76720
76896
|
ctx.body = { payload: await recorderService.stopRecord({ id }) };
|
|
76721
76897
|
});
|
|
76898
|
+
/**
|
|
76899
|
+
* 切割录制
|
|
76900
|
+
* @route POST /recorder/:recorderId/cut
|
|
76901
|
+
* @param recorderId 直播间ID
|
|
76902
|
+
* @returns 录制任务信息
|
|
76903
|
+
*/
|
|
76722
76904
|
router$9.post("/:id/cut", async (ctx) => {
|
|
76723
76905
|
const { id } = ctx.params;
|
|
76724
76906
|
ctx.body = { payload: await recorderService.cutRecord({ id }) };
|
|
76725
76907
|
});
|
|
76908
|
+
/**
|
|
76909
|
+
* 批量开始录制
|
|
76910
|
+
* @route POST /recorder/manager/batch_start_record
|
|
76911
|
+
* @param ids 直播间ID列表
|
|
76912
|
+
* @returns 批量操作结果
|
|
76913
|
+
*/
|
|
76914
|
+
router$9.post("/manager/batch_start_record", async (ctx) => {
|
|
76915
|
+
const { ids } = ctx.request.body;
|
|
76916
|
+
ctx.body = { payload: await recorderService.batchStartRecord(ids) };
|
|
76917
|
+
});
|
|
76918
|
+
/**
|
|
76919
|
+
* 批量停止录制
|
|
76920
|
+
* @route POST /recorder/manager/batch_stop_record
|
|
76921
|
+
* @param ids 直播间ID列表
|
|
76922
|
+
* @returns 批量操作结果
|
|
76923
|
+
*/
|
|
76924
|
+
router$9.post("/manager/batch_stop_record", async (ctx) => {
|
|
76925
|
+
const { ids } = ctx.request.body;
|
|
76926
|
+
ctx.body = { payload: await recorderService.batchStopRecord(ids) };
|
|
76927
|
+
});
|
|
76726
76928
|
/**
|
|
76727
76929
|
* 解析直播间地址,获取对应的直播间信息
|
|
76728
76930
|
* @route GET /recorder/manager/resolveChannel
|
|
@@ -77682,14 +77884,27 @@ router$6.get("/download/:id", async (ctx) => {
|
|
|
77682
77884
|
async function download$1(output, url, options) {
|
|
77683
77885
|
if ((await index.fs.pathExists(output)) && !options.override)
|
|
77684
77886
|
throw new Error(`${output}已存在`);
|
|
77887
|
+
const { dir, name } = require$$0$6.parse(output);
|
|
77888
|
+
const tsOutput = require$$0$6.join(dir, `${name}.ts`);
|
|
77685
77889
|
const { ffmpegPath } = index.getBinPath();
|
|
77686
|
-
const downloader = new index.M3U8Downloader(url,
|
|
77687
|
-
convert2Mp4:
|
|
77890
|
+
const downloader = new index.M3U8Downloader(url, tsOutput, {
|
|
77891
|
+
convert2Mp4: false,
|
|
77688
77892
|
ffmpegPath: ffmpegPath,
|
|
77689
77893
|
segmentsDir: require$$0$6.join(index.getTempPath(), index.uuid()),
|
|
77690
77894
|
});
|
|
77691
77895
|
const task = new index.KuaishouDownloadVideoTask(downloader, {
|
|
77692
77896
|
name: `下载任务:${require$$0$6.parse(output).name}`,
|
|
77897
|
+
}, {
|
|
77898
|
+
onEnd: async () => {
|
|
77899
|
+
const outputName = `${name}.mp4`;
|
|
77900
|
+
await index.transcode(tsOutput, outputName, { encoder: "copy", audioCodec: "copy" }, {
|
|
77901
|
+
saveType: 2,
|
|
77902
|
+
savePath: dir,
|
|
77903
|
+
override: false,
|
|
77904
|
+
removeOrigin: true,
|
|
77905
|
+
autoRun: true,
|
|
77906
|
+
});
|
|
77907
|
+
},
|
|
77693
77908
|
});
|
|
77694
77909
|
index.taskQueue.addTask(task, true);
|
|
77695
77910
|
return task;
|
|
@@ -78418,6 +78633,7 @@ const createUploadInstance = async (opts) => {
|
|
|
78418
78633
|
return new AliyunPan({
|
|
78419
78634
|
binary: opts.execPath,
|
|
78420
78635
|
remotePath: opts.remotePath ?? "",
|
|
78636
|
+
driveType: opts.aliyunpanDriveType,
|
|
78421
78637
|
});
|
|
78422
78638
|
}
|
|
78423
78639
|
else if (opts.type === "alist") {
|
|
@@ -78448,7 +78664,7 @@ const createUploadInstance = async (opts) => {
|
|
|
78448
78664
|
throw new Error("Unsupported type");
|
|
78449
78665
|
}
|
|
78450
78666
|
};
|
|
78451
|
-
const addSyncTask = async ({ input, remotePath, execPath, policy, type, removeOrigin, apiUrl, username, password, clientId, clientSecret, stringFilters, }) => {
|
|
78667
|
+
const addSyncTask = async ({ input, remotePath, execPath, policy, type, removeOrigin, apiUrl, username, password, clientId, clientSecret, aliyunpanDriveType, stringFilters, }) => {
|
|
78452
78668
|
const { binary: binaryPath, apiUrl: iApiUrl, username: iUsername, password: iPassword, clientId: iClientId, clientSecret: iClientSecret, limitRate, retry, } = getConfig(type);
|
|
78453
78669
|
const instance = await createUploadInstance({
|
|
78454
78670
|
type,
|
|
@@ -78459,6 +78675,7 @@ const addSyncTask = async ({ input, remotePath, execPath, policy, type, removeOr
|
|
|
78459
78675
|
password: password ?? iPassword,
|
|
78460
78676
|
clientId: clientId ?? iClientId,
|
|
78461
78677
|
clientSecret: clientSecret ?? iClientSecret,
|
|
78678
|
+
aliyunpanDriveType,
|
|
78462
78679
|
limitRate: limitRate ?? 0,
|
|
78463
78680
|
stringFilters,
|
|
78464
78681
|
retry,
|
|
@@ -78661,12 +78878,13 @@ router$2.get("/aliyunpanLogin", async (ctx) => {
|
|
|
78661
78878
|
router$2.post("/sync", async (ctx) => {
|
|
78662
78879
|
const params = ctx.request.body;
|
|
78663
78880
|
// @ts-ignore
|
|
78664
|
-
const { file, type, options, targetPath } = params;
|
|
78881
|
+
const { file, type, options, targetPath, aliyunpanDriveType } = params;
|
|
78665
78882
|
const task = await addSyncTask({
|
|
78666
78883
|
input: file,
|
|
78667
78884
|
type: type,
|
|
78668
78885
|
removeOrigin: options.removeOrigin,
|
|
78669
78886
|
remotePath: targetPath,
|
|
78887
|
+
aliyunpanDriveType,
|
|
78670
78888
|
});
|
|
78671
78889
|
ctx.body = task.taskId;
|
|
78672
78890
|
});
|
|
@@ -80427,6 +80645,7 @@ class WebhookHandler {
|
|
|
80427
80645
|
retry: 3,
|
|
80428
80646
|
policy: "skip",
|
|
80429
80647
|
type: syncConfig.syncSource,
|
|
80648
|
+
aliyunpanDriveType: syncConfig.aliyunpanDriveType,
|
|
80430
80649
|
});
|
|
80431
80650
|
index.logObj.info(`开始同步${fileType}文件: ${filePath}`);
|
|
80432
80651
|
task.on("task-end", async () => {
|
|
@@ -80718,12 +80937,12 @@ class WebhookHandler {
|
|
|
80718
80937
|
* 处理审核后删除的引用计数和回调
|
|
80719
80938
|
* @private
|
|
80720
80939
|
*/
|
|
80721
|
-
setupDeleteAfterCheckLock(pathArray) {
|
|
80940
|
+
setupDeleteAfterCheckLock(pathArray, afterUploadDeletAction) {
|
|
80722
80941
|
// 返回 checkCallback
|
|
80723
80942
|
return async (status) => {
|
|
80724
|
-
console.log(`审核状态: ${status}`, pathArray);
|
|
80725
|
-
if (status === "completed") {
|
|
80726
|
-
//
|
|
80943
|
+
// console.log(`审核状态: ${status}`, pathArray);
|
|
80944
|
+
if (status === "completed" && afterUploadDeletAction === "deleteAfterCheck") {
|
|
80945
|
+
// 审核通过且配置为审核后删除,释放引用(会自动删除)
|
|
80727
80946
|
for (const { path } of pathArray) {
|
|
80728
80947
|
await this.fileRefManager.releaseRef(path);
|
|
80729
80948
|
}
|
|
@@ -80731,7 +80950,7 @@ class WebhookHandler {
|
|
|
80731
80950
|
};
|
|
80732
80951
|
}
|
|
80733
80952
|
addUploadTask = async (uid, pathArray, options, limitedUploadTime, afterUploadDeletAction) => {
|
|
80734
|
-
const checkCallback = this.setupDeleteAfterCheckLock(pathArray);
|
|
80953
|
+
const checkCallback = this.setupDeleteAfterCheckLock(pathArray, afterUploadDeletAction);
|
|
80735
80954
|
const task = await index.biliApi.addMedia(pathArray, options, uid, {
|
|
80736
80955
|
limitedUploadTime,
|
|
80737
80956
|
afterUploadDeletAction: "none",
|
|
@@ -80741,7 +80960,7 @@ class WebhookHandler {
|
|
|
80741
80960
|
return this.handleUploadTask(task, pathArray);
|
|
80742
80961
|
};
|
|
80743
80962
|
addEditMediaTask = async (uid, aid, pathArray, uploadPreset, limitedUploadTime, afterUploadDeletAction) => {
|
|
80744
|
-
const checkCallback = this.setupDeleteAfterCheckLock(pathArray);
|
|
80963
|
+
const checkCallback = this.setupDeleteAfterCheckLock(pathArray, afterUploadDeletAction);
|
|
80745
80964
|
const task = await index.biliApi.editMedia(aid, pathArray, uploadPreset, uid, {
|
|
80746
80965
|
limitedUploadTime,
|
|
80747
80966
|
afterUploadDeletAction: "none",
|
|
@@ -80993,7 +81212,7 @@ exports.handler = void 0;
|
|
|
80993
81212
|
exports.appConfig = void 0;
|
|
80994
81213
|
exports.container = void 0;
|
|
80995
81214
|
const fileCache = createFileCache();
|
|
80996
|
-
path$7.dirname(require$$1$2.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-
|
|
81215
|
+
path$7.dirname(require$$1$2.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-DmrbnwzK.cjs', document.baseURI).href))));
|
|
80997
81216
|
const authMiddleware = (passKey) => {
|
|
80998
81217
|
return async (ctx, next) => {
|
|
80999
81218
|
const authHeader = ctx.headers["authorization"] || ctx.request.query.auth;
|
|
@@ -11408,6 +11408,7 @@ const APP_DEFAULT_CONFIG = {
|
|
|
11408
11408
|
fileSync: {
|
|
11409
11409
|
removeOrigin: false,
|
|
11410
11410
|
syncType: undefined,
|
|
11411
|
+
aliyunpanDriveType: "backup",
|
|
11411
11412
|
targetPath: "/",
|
|
11412
11413
|
},
|
|
11413
11414
|
danmu: {
|
|
@@ -44555,7 +44556,7 @@ async function trash(paths, options) {
|
|
|
44555
44556
|
} else if (process$2.platform === 'win32') {
|
|
44556
44557
|
module = await Promise.resolve().then(function () { return require('./windows-OmnJ7a39.cjs'); });
|
|
44557
44558
|
} else {
|
|
44558
|
-
module = await Promise.resolve().then(function () { return require('./linux-
|
|
44559
|
+
module = await Promise.resolve().then(function () { return require('./linux-fd_XbwNY.cjs'); });
|
|
44559
44560
|
}
|
|
44560
44561
|
|
|
44561
44562
|
return module.default(paths);
|
|
@@ -192718,9 +192719,11 @@ async function download$1(output, decodeData, options) {
|
|
|
192718
192719
|
}
|
|
192719
192720
|
if (!m3u8Url)
|
|
192720
192721
|
throw new Error("无法找到对应的流");
|
|
192722
|
+
const { dir, name } = path$y.parse(output);
|
|
192723
|
+
const tsOutput = path$y.join(dir, `${name}.ts`);
|
|
192721
192724
|
const { ffmpegPath } = getBinPath();
|
|
192722
|
-
const downloader = new M3U8Downloader(m3u8Url,
|
|
192723
|
-
convert2Mp4:
|
|
192725
|
+
const downloader = new M3U8Downloader(m3u8Url, tsOutput, {
|
|
192726
|
+
convert2Mp4: false,
|
|
192724
192727
|
ffmpegPath: ffmpegPath,
|
|
192725
192728
|
segmentsDir: path$y.join(getTempPath(), uuid$4()),
|
|
192726
192729
|
});
|
|
@@ -192733,6 +192736,14 @@ async function download$1(output, decodeData, options) {
|
|
|
192733
192736
|
const xml = convert2Xml(danmu, options.danmuMeta || {});
|
|
192734
192737
|
fs$k.writeFile(path$y.join(path$y.dirname(output), `${path$y.parse(output).name}.xml`), xml);
|
|
192735
192738
|
}
|
|
192739
|
+
const outputName = `${name}.mp4`;
|
|
192740
|
+
await transcode(tsOutput, outputName, { encoder: "copy", audioCodec: "copy" }, {
|
|
192741
|
+
saveType: 2,
|
|
192742
|
+
savePath: dir,
|
|
192743
|
+
override: false,
|
|
192744
|
+
removeOrigin: true,
|
|
192745
|
+
autoRun: true,
|
|
192746
|
+
});
|
|
192736
192747
|
},
|
|
192737
192748
|
});
|
|
192738
192749
|
taskQueue.addTask(task, false);
|
|
@@ -192774,14 +192785,27 @@ var douyu = { download: download$1, parseVideo: parseVideo$1, getAvailableStream
|
|
|
192774
192785
|
async function download(output, url, options) {
|
|
192775
192786
|
if ((await fs$k.pathExists(output)) && !options.override)
|
|
192776
192787
|
throw new Error(`${output}已存在`);
|
|
192788
|
+
const { dir, name } = path$y.parse(output);
|
|
192789
|
+
const tsOutput = path$y.join(dir, `${name}.ts`);
|
|
192777
192790
|
const { ffmpegPath } = getBinPath();
|
|
192778
|
-
const downloader = new M3U8Downloader(url,
|
|
192779
|
-
convert2Mp4:
|
|
192791
|
+
const downloader = new M3U8Downloader(url, tsOutput, {
|
|
192792
|
+
convert2Mp4: false,
|
|
192780
192793
|
ffmpegPath: ffmpegPath,
|
|
192781
192794
|
segmentsDir: path$y.join(getTempPath(), uuid$4()),
|
|
192782
192795
|
});
|
|
192783
192796
|
const task = new HuyaDownloadVideoTask(downloader, {
|
|
192784
192797
|
name: `下载任务:${path$y.parse(output).name}`,
|
|
192798
|
+
}, {
|
|
192799
|
+
onEnd: async () => {
|
|
192800
|
+
const outputName = `${name}.mp4`;
|
|
192801
|
+
await transcode(tsOutput, outputName, { encoder: "copy", audioCodec: "copy" }, {
|
|
192802
|
+
saveType: 2,
|
|
192803
|
+
savePath: dir,
|
|
192804
|
+
override: false,
|
|
192805
|
+
removeOrigin: true,
|
|
192806
|
+
autoRun: true,
|
|
192807
|
+
});
|
|
192808
|
+
},
|
|
192785
192809
|
});
|
|
192786
192810
|
taskQueue.addTask(task, true);
|
|
192787
192811
|
return task;
|
|
@@ -246422,7 +246446,6 @@ const checkLiveStatusAndRecord$1 = async function ({ getSavePath, banLiveId, isM
|
|
|
246422
246446
|
// },
|
|
246423
246447
|
},
|
|
246424
246448
|
};
|
|
246425
|
-
console.log("Message", JSON.stringify(msg), null, 2);
|
|
246426
246449
|
this.emit("Message", comment);
|
|
246427
246450
|
extraDataController.addMessage(comment);
|
|
246428
246451
|
});
|
|
@@ -287595,17 +287618,11 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
|
|
|
287595
287618
|
roomId = info.roomId;
|
|
287596
287619
|
liveStartTimeFromSearch = info.liveStartTime;
|
|
287597
287620
|
}
|
|
287621
|
+
console.log("roomid", roomId);
|
|
287598
287622
|
if (!roomId)
|
|
287599
287623
|
return null;
|
|
287600
|
-
if (this.liveInfo?.liveId === banLiveId) {
|
|
287601
|
-
this.tempStopIntervalCheck = true;
|
|
287602
|
-
}
|
|
287603
|
-
else {
|
|
287604
|
-
this.tempStopIntervalCheck = false;
|
|
287605
|
-
}
|
|
287606
|
-
if (this.tempStopIntervalCheck)
|
|
287607
|
-
return null;
|
|
287608
287624
|
const liveInfo = await getInfo(roomId);
|
|
287625
|
+
console.log("liveInfo", liveInfo);
|
|
287609
287626
|
// @ts-ignore
|
|
287610
287627
|
this.liveInfo = liveInfo;
|
|
287611
287628
|
if (liveStartTimeFromSearch) {
|
|
@@ -287618,6 +287635,14 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
|
|
|
287618
287635
|
throw error;
|
|
287619
287636
|
}
|
|
287620
287637
|
const { living, owner, title, liveStartTime, recordStartTime } = this.liveInfo;
|
|
287638
|
+
if (this.liveInfo?.liveId === banLiveId) {
|
|
287639
|
+
this.tempStopIntervalCheck = true;
|
|
287640
|
+
}
|
|
287641
|
+
else {
|
|
287642
|
+
this.tempStopIntervalCheck = false;
|
|
287643
|
+
}
|
|
287644
|
+
if (this.tempStopIntervalCheck)
|
|
287645
|
+
return null;
|
|
287621
287646
|
if (!living)
|
|
287622
287647
|
return null;
|
|
287623
287648
|
// 检查标题是否包含关键词
|
package/lib/index.cjs
CHANGED
|
@@ -3715,7 +3715,7 @@ const {
|
|
|
3715
3715
|
Help,
|
|
3716
3716
|
} = commander;
|
|
3717
3717
|
|
|
3718
|
-
var version = "3.
|
|
3718
|
+
var version = "3.11.0";
|
|
3719
3719
|
|
|
3720
3720
|
process.on("uncaughtException", function (error) {
|
|
3721
3721
|
console.error(`${new Date().toISOString()} uncaughtException`, error);
|
|
@@ -3741,8 +3741,8 @@ program
|
|
|
3741
3741
|
throw new Error(`${c.configFolder}参数不存在,请先重新运行 config gen 命令`);
|
|
3742
3742
|
}
|
|
3743
3743
|
// 下面两行顺序不能换(
|
|
3744
|
-
const { init } = await Promise.resolve().then(function () { return require('./index-
|
|
3745
|
-
const { serverStart } = await Promise.resolve().then(function () { return require('./index-
|
|
3744
|
+
const { init } = await Promise.resolve().then(function () { return require('./index-aJuLOmr2.cjs'); }).then(function (n) { return n.index; });
|
|
3745
|
+
const { serverStart } = await Promise.resolve().then(function () { return require('./index-DmrbnwzK.cjs'); });
|
|
3746
3746
|
const globalConfig = {
|
|
3747
3747
|
ffmpegPresetPath: path$1.join(c.configFolder, "ffmpeg_presets.json"),
|
|
3748
3748
|
videoPresetPath: path$1.join(c.configFolder, "presets.json"),
|
|
@@ -4,7 +4,7 @@ var os$3 = require('node:os');
|
|
|
4
4
|
var path$5 = require('node:path');
|
|
5
5
|
var fs$3 = require('node:fs');
|
|
6
6
|
var crypto = require('node:crypto');
|
|
7
|
-
var index = require('./index-
|
|
7
|
+
var index = require('./index-aJuLOmr2.cjs');
|
|
8
8
|
var require$$0$1 = require('fs');
|
|
9
9
|
var require$$0 = require('path');
|
|
10
10
|
var require$$0$2 = require('child_process');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bililive-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "biliLive-tools的cli程序",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"commander": "^12.1.0",
|
|
40
40
|
"rimraf": "^6.0.1",
|
|
41
41
|
"tsx": "^4.19.2",
|
|
42
|
-
"@biliLive-tools/http": "3.
|
|
43
|
-
"@biliLive-tools/
|
|
44
|
-
"@biliLive-tools/
|
|
42
|
+
"@biliLive-tools/http": "3.11.0",
|
|
43
|
+
"@biliLive-tools/types": "3.11.0",
|
|
44
|
+
"@biliLive-tools/shared": "3.11.0"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"start": "tsx src/index.ts",
|