bililive-cli 3.12.1 → 3.13.1
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-CgpPN0zA.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');
|
|
@@ -30477,8 +30477,9 @@ const errorMiddleware = async (ctx, next) => {
|
|
|
30477
30477
|
await next();
|
|
30478
30478
|
}
|
|
30479
30479
|
catch (error) {
|
|
30480
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
30480
30481
|
ctx.status = 500;
|
|
30481
|
-
ctx.body =
|
|
30482
|
+
ctx.body = message;
|
|
30482
30483
|
ctx.app.emit("error", error, ctx);
|
|
30483
30484
|
index.logObj.error(error);
|
|
30484
30485
|
}
|
|
@@ -49131,6 +49132,50 @@ router$f.post("/set", async (ctx) => {
|
|
|
49131
49132
|
exports.appConfig.set(data.key, data.value);
|
|
49132
49133
|
ctx.body = "success";
|
|
49133
49134
|
});
|
|
49135
|
+
router$f.post("/verifyBiliKey", async (ctx) => {
|
|
49136
|
+
try {
|
|
49137
|
+
const serverKey = process.env.BILILIVE_TOOLS_BILIKEY;
|
|
49138
|
+
const configured = typeof serverKey === "string" && serverKey.trim().length > 0;
|
|
49139
|
+
const requestBody = ctx.request.body;
|
|
49140
|
+
const rawInput = typeof requestBody?.key === "string" ? requestBody.key : "";
|
|
49141
|
+
const inputKey = rawInput.trim();
|
|
49142
|
+
let response;
|
|
49143
|
+
if (!configured) {
|
|
49144
|
+
response = {
|
|
49145
|
+
configured: false,
|
|
49146
|
+
valid: false,
|
|
49147
|
+
matched: false,
|
|
49148
|
+
reason: "missing",
|
|
49149
|
+
};
|
|
49150
|
+
}
|
|
49151
|
+
else if (inputKey === serverKey) {
|
|
49152
|
+
response = {
|
|
49153
|
+
configured: true,
|
|
49154
|
+
valid: true,
|
|
49155
|
+
matched: true,
|
|
49156
|
+
reason: "ok",
|
|
49157
|
+
};
|
|
49158
|
+
}
|
|
49159
|
+
else {
|
|
49160
|
+
response = {
|
|
49161
|
+
configured: true,
|
|
49162
|
+
valid: false,
|
|
49163
|
+
matched: false,
|
|
49164
|
+
reason: "mismatch",
|
|
49165
|
+
};
|
|
49166
|
+
}
|
|
49167
|
+
ctx.body = response;
|
|
49168
|
+
}
|
|
49169
|
+
catch {
|
|
49170
|
+
const response = {
|
|
49171
|
+
configured: false,
|
|
49172
|
+
valid: false,
|
|
49173
|
+
matched: false,
|
|
49174
|
+
reason: "error",
|
|
49175
|
+
};
|
|
49176
|
+
ctx.body = response;
|
|
49177
|
+
}
|
|
49178
|
+
});
|
|
49134
49179
|
router$f.post("/resetBin", async (ctx) => {
|
|
49135
49180
|
const data = ctx.request.body;
|
|
49136
49181
|
const type = data.type;
|
|
@@ -56428,7 +56473,6 @@ router$d.get("/files", async (ctx) => {
|
|
|
56428
56473
|
const allFiles = filterExts.length === 0 || filterExts.includes(".*");
|
|
56429
56474
|
if (root == "/" && process.platform === "win32") {
|
|
56430
56475
|
const drives = await getDriveLetters();
|
|
56431
|
-
root = drives[0];
|
|
56432
56476
|
ctx.body = {
|
|
56433
56477
|
list: drives.map((drive) => ({ type: "directory", name: drive, path: `${drive}\\` })),
|
|
56434
56478
|
parent: "",
|
|
@@ -56454,6 +56498,7 @@ router$d.get("/files", async (ctx) => {
|
|
|
56454
56498
|
type: type,
|
|
56455
56499
|
name: name,
|
|
56456
56500
|
path: filePath,
|
|
56501
|
+
size: type === "file" ? fileStat.size : undefined,
|
|
56457
56502
|
});
|
|
56458
56503
|
}
|
|
56459
56504
|
catch (error) {
|
|
@@ -57074,6 +57119,47 @@ router$c.post("/get_cookie", async (ctx) => {
|
|
|
57074
57119
|
ctx.body = "获取失败,请重试";
|
|
57075
57120
|
}
|
|
57076
57121
|
});
|
|
57122
|
+
router$c.get("/export", async (ctx) => {
|
|
57123
|
+
const list = index.biliApi.readUserList();
|
|
57124
|
+
ctx.body = list;
|
|
57125
|
+
});
|
|
57126
|
+
router$c.post("/export_single", async (ctx) => {
|
|
57127
|
+
const { uid } = ctx.request.body;
|
|
57128
|
+
const user = index.biliApi.readUser(uid);
|
|
57129
|
+
if (!user) {
|
|
57130
|
+
ctx.status = 404;
|
|
57131
|
+
ctx.body = "用户不存在";
|
|
57132
|
+
return;
|
|
57133
|
+
}
|
|
57134
|
+
ctx.body = user;
|
|
57135
|
+
});
|
|
57136
|
+
router$c.post("/import", async (ctx) => {
|
|
57137
|
+
const { users } = ctx.request.body;
|
|
57138
|
+
if (!Array.isArray(users)) {
|
|
57139
|
+
ctx.status = 400;
|
|
57140
|
+
ctx.body = "参数错误";
|
|
57141
|
+
return;
|
|
57142
|
+
}
|
|
57143
|
+
for (const item of users) {
|
|
57144
|
+
if (!item?.mid || !item?.accessToken || !item?.refreshToken || !item?.cookie) {
|
|
57145
|
+
ctx.status = 400;
|
|
57146
|
+
ctx.body = "账号数据不完整";
|
|
57147
|
+
return;
|
|
57148
|
+
}
|
|
57149
|
+
await index.biliApi.writeUser(item);
|
|
57150
|
+
}
|
|
57151
|
+
ctx.status = 200;
|
|
57152
|
+
});
|
|
57153
|
+
router$c.post("/import_single", async (ctx) => {
|
|
57154
|
+
const { user } = ctx.request.body;
|
|
57155
|
+
if (!user?.mid || !user?.accessToken || !user?.refreshToken || !user?.cookie) {
|
|
57156
|
+
ctx.status = 400;
|
|
57157
|
+
ctx.body = "账号数据不完整";
|
|
57158
|
+
return;
|
|
57159
|
+
}
|
|
57160
|
+
await index.biliApi.writeUser(user);
|
|
57161
|
+
ctx.status = 200;
|
|
57162
|
+
});
|
|
57077
57163
|
|
|
57078
57164
|
const router$b = new Router$1({
|
|
57079
57165
|
prefix: "/preset",
|
|
@@ -76579,7 +76665,7 @@ const router$a = new Router$1({
|
|
|
76579
76665
|
*/
|
|
76580
76666
|
router$a.get("/streamLogs", sse({
|
|
76581
76667
|
maxClients: 5000,
|
|
76582
|
-
pingInterval:
|
|
76668
|
+
pingInterval: 60 * 60 * 1000,
|
|
76583
76669
|
}), async (ctx) => {
|
|
76584
76670
|
const logFilePath = exports.config.logPath;
|
|
76585
76671
|
// 初始化logSize为文件当前大小
|
|
@@ -78181,7 +78267,7 @@ async function parseVideo({ url, }) {
|
|
|
78181
78267
|
}
|
|
78182
78268
|
}
|
|
78183
78269
|
async function downloadVideo(options) {
|
|
78184
|
-
|
|
78270
|
+
let filepath = path$7.join(options.savePath, options.filename);
|
|
78185
78271
|
if (options.platform === "douyu") {
|
|
78186
78272
|
if (!options?.extra?.decodeData) {
|
|
78187
78273
|
throw new Error("decodeData is required for douyu download");
|
|
@@ -78241,6 +78327,7 @@ async function downloadVideo(options) {
|
|
|
78241
78327
|
if (!options?.extra?.bvid) {
|
|
78242
78328
|
throw new Error("bvid is required for bilibili download");
|
|
78243
78329
|
}
|
|
78330
|
+
filepath = index.replaceExtName(filepath, ".mp4");
|
|
78244
78331
|
await index.biliApi.download({
|
|
78245
78332
|
bvid: options.extra.bvid,
|
|
78246
78333
|
cid: Number(options.id),
|
|
@@ -78709,7 +78796,7 @@ async function uploadTest(params) {
|
|
|
78709
78796
|
const tempDir = index.getTempPath();
|
|
78710
78797
|
// 在临时文件新建一个文件,内容为"biliLive-tools"
|
|
78711
78798
|
const tempFilePath = path$7.join(tempDir, "biliLive-tools-upload-test.txt");
|
|
78712
|
-
await index.fs.writeFile(tempFilePath,
|
|
78799
|
+
await index.fs.writeFile(tempFilePath, `biliLive-tools-${index.uuid()}`);
|
|
78713
78800
|
return new Promise(async (resolve, reject) => {
|
|
78714
78801
|
const task = await addSyncTask({
|
|
78715
78802
|
input: tempFilePath,
|
|
@@ -79218,9 +79305,23 @@ class FileRefManager {
|
|
|
79218
79305
|
*/
|
|
79219
79306
|
class ConfigManager {
|
|
79220
79307
|
appConfig;
|
|
79308
|
+
static APP_CONFIG_CACHE_TTL = 30 * 1000;
|
|
79309
|
+
appConfigCache;
|
|
79221
79310
|
constructor(appConfig) {
|
|
79222
79311
|
this.appConfig = appConfig;
|
|
79223
79312
|
}
|
|
79313
|
+
getAppConfigAll() {
|
|
79314
|
+
const now = Date.now();
|
|
79315
|
+
if (this.appConfigCache && this.appConfigCache.expiresAt > now) {
|
|
79316
|
+
return this.appConfigCache.value;
|
|
79317
|
+
}
|
|
79318
|
+
const value = this.appConfig.getAll();
|
|
79319
|
+
this.appConfigCache = {
|
|
79320
|
+
value,
|
|
79321
|
+
expiresAt: now + ConfigManager.APP_CONFIG_CACHE_TTL,
|
|
79322
|
+
};
|
|
79323
|
+
return value;
|
|
79324
|
+
}
|
|
79224
79325
|
/**
|
|
79225
79326
|
* 判断房间是否开启
|
|
79226
79327
|
*/
|
|
@@ -79245,7 +79346,7 @@ class ConfigManager {
|
|
|
79245
79346
|
* @returns 房间配置对象
|
|
79246
79347
|
*/
|
|
79247
79348
|
getConfig(roomId) {
|
|
79248
|
-
const appConfigAll = this.
|
|
79349
|
+
const appConfigAll = this.getAppConfigAll();
|
|
79249
79350
|
const roomSetting = appConfigAll.webhook?.rooms?.[roomId];
|
|
79250
79351
|
const danmu = this.getRoomSetting("danmu", roomSetting) ?? false;
|
|
79251
79352
|
const mergePart = this.getRoomSetting("autoPartMerge", roomSetting) ?? false;
|
|
@@ -79271,9 +79372,7 @@ class ConfigManager {
|
|
|
79271
79372
|
];
|
|
79272
79373
|
const syncId = this.getRoomSetting("syncId", roomSetting);
|
|
79273
79374
|
const afterConvertAction = this.getRoomSetting("afterConvertAction", roomSetting) ?? [];
|
|
79274
|
-
|
|
79275
|
-
const removeSourceAferrConvert2Mp4Before = this.getRoomSetting("removeSourceAferrConvert2Mp4", roomSetting);
|
|
79276
|
-
const removeSourceAferrConvert2Mp4 = afterConvertAction.includes("removeAfterConvert2Mp4") || !!removeSourceAferrConvert2Mp4Before;
|
|
79375
|
+
const removeSourceAferrConvert2Mp4 = afterConvertAction.includes("removeAfterConvert2Mp4");
|
|
79277
79376
|
const afterConvertRemoveVideoRaw = afterConvertAction.includes("removeVideo");
|
|
79278
79377
|
const afterConvertRemoveXmlRaw = afterConvertAction.includes("removeXml");
|
|
79279
79378
|
const afterConvertRemoveFlvRaw = afterConvertAction.includes("removeAfterFlvRepair");
|
|
@@ -79284,6 +79383,7 @@ class ConfigManager {
|
|
|
79284
79383
|
"23:59:59",
|
|
79285
79384
|
];
|
|
79286
79385
|
const uploadNoDanmu = this.getRoomSetting("uploadNoDanmu", roomSetting) ?? false;
|
|
79386
|
+
const uploadToSameMedia = this.getRoomSetting("uploadToSameMedia", roomSetting) ?? false;
|
|
79287
79387
|
const noDanmuVideoPreset = this.getRoomSetting("noDanmuVideoPreset", roomSetting) || "default";
|
|
79288
79388
|
// 如果没有开启断播续传,那么不需要合并part
|
|
79289
79389
|
if (!mergePart)
|
|
@@ -79333,6 +79433,7 @@ class ConfigManager {
|
|
|
79333
79433
|
limitUploadTime,
|
|
79334
79434
|
uploadHandleTime,
|
|
79335
79435
|
uploadNoDanmu,
|
|
79436
|
+
uploadToSameMedia,
|
|
79336
79437
|
noDanmuVideoPreset,
|
|
79337
79438
|
videoHandleTime: limitVideoConvertTime ? videoHandleTime : undefined,
|
|
79338
79439
|
partTitleTemplate: this.getRoomSetting("partTitleTemplate", roomSetting) || "{{filename}}",
|
|
@@ -79353,7 +79454,7 @@ class ConfigManager {
|
|
|
79353
79454
|
* @returns 配置值
|
|
79354
79455
|
*/
|
|
79355
79456
|
getRoomSetting(key, roomSetting) {
|
|
79356
|
-
const appConfigAll = this.
|
|
79457
|
+
const appConfigAll = this.getAppConfigAll();
|
|
79357
79458
|
if (roomSetting) {
|
|
79358
79459
|
if (roomSetting.noGlobal?.includes(key)) {
|
|
79359
79460
|
return roomSetting[key];
|
|
@@ -79373,7 +79474,7 @@ class ConfigManager {
|
|
|
79373
79474
|
const { syncId } = this.getConfig(roomId);
|
|
79374
79475
|
if (!syncId)
|
|
79375
79476
|
return null;
|
|
79376
|
-
const appConfig = this.
|
|
79477
|
+
const appConfig = this.getAppConfigAll();
|
|
79377
79478
|
const syncConfig = appConfig.sync?.syncConfigs?.find((cfg) => cfg.id === syncId);
|
|
79378
79479
|
if (!syncConfig)
|
|
79379
79480
|
return null;
|
|
@@ -80149,6 +80250,7 @@ class EventBufferManager extends EventEmitter$3.EventEmitter {
|
|
|
80149
80250
|
}
|
|
80150
80251
|
}
|
|
80151
80252
|
|
|
80253
|
+
const SAME_MEDIA_UPLOAD_ORDER = ["handled", "raw"];
|
|
80152
80254
|
class WebhookHandler {
|
|
80153
80255
|
liveManager = new LiveManager();
|
|
80154
80256
|
ffmpegPreset;
|
|
@@ -80860,11 +80962,58 @@ class WebhookHandler {
|
|
|
80860
80962
|
* 通用上传任务处理逻辑
|
|
80861
80963
|
* @private
|
|
80862
80964
|
*/
|
|
80863
|
-
|
|
80965
|
+
getRuntimePart(part) {
|
|
80966
|
+
return part;
|
|
80967
|
+
}
|
|
80968
|
+
setPartCid(part, type, cid) {
|
|
80969
|
+
if (!cid)
|
|
80970
|
+
return;
|
|
80971
|
+
const runtimePart = this.getRuntimePart(part);
|
|
80972
|
+
if (type === "handled") {
|
|
80973
|
+
runtimePart.handledCid = cid;
|
|
80974
|
+
}
|
|
80975
|
+
else {
|
|
80976
|
+
runtimePart.rawCid = cid;
|
|
80977
|
+
}
|
|
80978
|
+
}
|
|
80979
|
+
getPartCid(part, type) {
|
|
80980
|
+
const runtimePart = this.getRuntimePart(part);
|
|
80981
|
+
return type === "handled" ? runtimePart.handledCid : runtimePart.rawCid;
|
|
80982
|
+
}
|
|
80983
|
+
toPathArray(items) {
|
|
80984
|
+
return items.map((item) => ({
|
|
80985
|
+
path: item.path,
|
|
80986
|
+
title: item.title,
|
|
80987
|
+
}));
|
|
80988
|
+
}
|
|
80989
|
+
createUploadItems(filePaths, type) {
|
|
80990
|
+
return filePaths.map((item) => ({
|
|
80991
|
+
...item,
|
|
80992
|
+
type,
|
|
80993
|
+
}));
|
|
80994
|
+
}
|
|
80995
|
+
writeUploadResultToParts(uploadedItems, data) {
|
|
80996
|
+
const itemQueue = new Map();
|
|
80997
|
+
for (const item of uploadedItems) {
|
|
80998
|
+
const queue = itemQueue.get(item.path) ?? [];
|
|
80999
|
+
queue.push(item);
|
|
81000
|
+
itemQueue.set(item.path, queue);
|
|
81001
|
+
}
|
|
81002
|
+
for (const result of data) {
|
|
81003
|
+
const queue = itemQueue.get(result.filePath);
|
|
81004
|
+
const item = queue?.shift();
|
|
81005
|
+
if (!item)
|
|
81006
|
+
continue;
|
|
81007
|
+
this.setPartCid(item.part, item.type, result.cid);
|
|
81008
|
+
}
|
|
81009
|
+
}
|
|
81010
|
+
async handleUploadTask(task, uploadedItems) {
|
|
80864
81011
|
return new Promise((resolve, reject) => {
|
|
80865
|
-
task.on("task-end", async () => {
|
|
81012
|
+
task.on("task-end", async (payload) => {
|
|
81013
|
+
const data = payload?.data ?? [];
|
|
81014
|
+
this.writeUploadResultToParts(uploadedItems, data);
|
|
80866
81015
|
// 释放所有文件的引用
|
|
80867
|
-
for (const { path } of
|
|
81016
|
+
for (const { path } of uploadedItems) {
|
|
80868
81017
|
await this.fileRefManager.releaseRef(path);
|
|
80869
81018
|
}
|
|
80870
81019
|
resolve(task.output);
|
|
@@ -80893,25 +81042,31 @@ class WebhookHandler {
|
|
|
80893
81042
|
}
|
|
80894
81043
|
};
|
|
80895
81044
|
}
|
|
80896
|
-
addUploadTask = async (uid,
|
|
81045
|
+
addUploadTask = async (uid, uploadedItems, options, limitedUploadTime, afterUploadDeletAction) => {
|
|
81046
|
+
const pathArray = this.toPathArray(uploadedItems);
|
|
80897
81047
|
const checkCallback = this.setupDeleteAfterCheckLock(pathArray, afterUploadDeletAction);
|
|
81048
|
+
// console.log("upload", pathArray);
|
|
80898
81049
|
const task = await index.biliApi.addMedia(pathArray, options, uid, {
|
|
80899
81050
|
limitedUploadTime,
|
|
80900
81051
|
afterUploadDeletAction: "none",
|
|
80901
81052
|
forceCheck: afterUploadDeletAction === "deleteAfterCheck",
|
|
80902
81053
|
checkCallback,
|
|
80903
81054
|
});
|
|
80904
|
-
return this.handleUploadTask(task,
|
|
81055
|
+
return this.handleUploadTask(task, uploadedItems);
|
|
80905
81056
|
};
|
|
80906
|
-
addEditMediaTask = async (uid, aid,
|
|
81057
|
+
addEditMediaTask = async (uid, aid, uploadedItems, uploadPreset, limitedUploadTime, afterUploadDeletAction, sortParams) => {
|
|
81058
|
+
const pathArray = this.toPathArray(uploadedItems);
|
|
80907
81059
|
const checkCallback = this.setupDeleteAfterCheckLock(pathArray, afterUploadDeletAction);
|
|
81060
|
+
// console.log("sortParams111111111", sortParams, pathArray);
|
|
81061
|
+
// 参数sortParams: array<{filePath:string;cid?:number}>,表示按照 filePath 对历史分P和当前上传文件统一排序
|
|
80908
81062
|
const task = await index.biliApi.editMedia(aid, pathArray, uploadPreset, uid, {
|
|
80909
81063
|
limitedUploadTime,
|
|
80910
81064
|
afterUploadDeletAction: "none",
|
|
80911
81065
|
forceCheck: afterUploadDeletAction === "deleteAfterCheck",
|
|
80912
81066
|
checkCallback,
|
|
81067
|
+
sortParams,
|
|
80913
81068
|
});
|
|
80914
|
-
return this.handleUploadTask(task,
|
|
81069
|
+
return this.handleUploadTask(task, uploadedItems);
|
|
80915
81070
|
};
|
|
80916
81071
|
/**
|
|
80917
81072
|
* 构建上传文件列表
|
|
@@ -80945,6 +81100,110 @@ class WebhookHandler {
|
|
|
80945
81100
|
}
|
|
80946
81101
|
return { filePaths, cover };
|
|
80947
81102
|
}
|
|
81103
|
+
isSameMediaUploadEnabled(config) {
|
|
81104
|
+
return config.uploadNoDanmu && config.uploadToSameMedia;
|
|
81105
|
+
}
|
|
81106
|
+
updateUploadStatusForItems(filePaths, status) {
|
|
81107
|
+
for (const item of filePaths) {
|
|
81108
|
+
item.part.updateUploadStatus(status, item.type === "raw");
|
|
81109
|
+
}
|
|
81110
|
+
}
|
|
81111
|
+
getSameMediaUploadCandidate(part, type, config) {
|
|
81112
|
+
if (type === "handled") {
|
|
81113
|
+
return {
|
|
81114
|
+
type,
|
|
81115
|
+
path: part.filePath,
|
|
81116
|
+
status: part.uploadStatus,
|
|
81117
|
+
canUpload: part.canUpload("handled"),
|
|
81118
|
+
enabled: true,
|
|
81119
|
+
};
|
|
81120
|
+
}
|
|
81121
|
+
return {
|
|
81122
|
+
type,
|
|
81123
|
+
path: part.rawFilePath,
|
|
81124
|
+
status: part.rawUploadStatus,
|
|
81125
|
+
canUpload: part.canUpload("raw"),
|
|
81126
|
+
enabled: config.uploadNoDanmu,
|
|
81127
|
+
};
|
|
81128
|
+
}
|
|
81129
|
+
buildSameMediaSortParams(live, config) {
|
|
81130
|
+
const sortParams = [];
|
|
81131
|
+
for (const type of SAME_MEDIA_UPLOAD_ORDER) {
|
|
81132
|
+
for (const part of live.parts) {
|
|
81133
|
+
const item = this.getSameMediaUploadCandidate(part, type, config);
|
|
81134
|
+
if (item.enabled === false || item.status === "error") {
|
|
81135
|
+
continue;
|
|
81136
|
+
}
|
|
81137
|
+
const cid = this.getPartCid(part, item.type);
|
|
81138
|
+
sortParams.push({
|
|
81139
|
+
filePath: item.path,
|
|
81140
|
+
cid,
|
|
81141
|
+
});
|
|
81142
|
+
if (item.status !== "uploaded" && !item.canUpload) {
|
|
81143
|
+
return sortParams;
|
|
81144
|
+
}
|
|
81145
|
+
}
|
|
81146
|
+
}
|
|
81147
|
+
return sortParams;
|
|
81148
|
+
}
|
|
81149
|
+
getUploadedItemCountForSameMedia(live, config) {
|
|
81150
|
+
let uploadedCount = 0;
|
|
81151
|
+
for (const part of live.parts) {
|
|
81152
|
+
if (part.uploadStatus === "uploaded") {
|
|
81153
|
+
uploadedCount++;
|
|
81154
|
+
}
|
|
81155
|
+
if (config.uploadNoDanmu && part.rawUploadStatus === "uploaded") {
|
|
81156
|
+
uploadedCount++;
|
|
81157
|
+
}
|
|
81158
|
+
}
|
|
81159
|
+
return uploadedCount;
|
|
81160
|
+
}
|
|
81161
|
+
buildSameMediaUploadFileList(live, config) {
|
|
81162
|
+
let cover;
|
|
81163
|
+
const filePaths = [];
|
|
81164
|
+
let currentIndex = this.getUploadedItemCountForSameMedia(live, config) + 1;
|
|
81165
|
+
for (const type of SAME_MEDIA_UPLOAD_ORDER) {
|
|
81166
|
+
for (const part of live.parts) {
|
|
81167
|
+
const item = this.getSameMediaUploadCandidate(part, type, config);
|
|
81168
|
+
if (item.enabled === false)
|
|
81169
|
+
continue;
|
|
81170
|
+
if (item.status === "uploaded" || item.status === "error")
|
|
81171
|
+
continue;
|
|
81172
|
+
if (!item.canUpload)
|
|
81173
|
+
continue;
|
|
81174
|
+
const filename = path$7.parse(item.path).name;
|
|
81175
|
+
const baseTitle = index.formatPartTitle({
|
|
81176
|
+
title: part.title,
|
|
81177
|
+
username: live.username,
|
|
81178
|
+
roomId: live.roomId,
|
|
81179
|
+
time: part?.startTime
|
|
81180
|
+
? new Date(part.startTime).toISOString()
|
|
81181
|
+
: new Date().toISOString(),
|
|
81182
|
+
filename,
|
|
81183
|
+
index: currentIndex,
|
|
81184
|
+
}, config.partTitleTemplate ?? "{{filename}}");
|
|
81185
|
+
filePaths.push({
|
|
81186
|
+
part,
|
|
81187
|
+
path: item.path,
|
|
81188
|
+
title: baseTitle,
|
|
81189
|
+
type: item.type,
|
|
81190
|
+
});
|
|
81191
|
+
if (!cover) {
|
|
81192
|
+
cover = part.cover;
|
|
81193
|
+
}
|
|
81194
|
+
currentIndex++;
|
|
81195
|
+
}
|
|
81196
|
+
}
|
|
81197
|
+
return { filePaths, cover };
|
|
81198
|
+
}
|
|
81199
|
+
validateCombinedUploadConfig(filePaths, config) {
|
|
81200
|
+
if (!config.uid) {
|
|
81201
|
+
this.updateUploadStatusForItems(filePaths, "error");
|
|
81202
|
+
index.logObj.error("无须上传,uid未配置");
|
|
81203
|
+
return false;
|
|
81204
|
+
}
|
|
81205
|
+
return true;
|
|
81206
|
+
}
|
|
80948
81207
|
/**
|
|
80949
81208
|
* 验证上传配置
|
|
80950
81209
|
* @private
|
|
@@ -80990,6 +81249,9 @@ class WebhookHandler {
|
|
|
80990
81249
|
}
|
|
80991
81250
|
return uploadPreset;
|
|
80992
81251
|
}
|
|
81252
|
+
async prepareSharedUploadPreset(config, live, cover) {
|
|
81253
|
+
return this.prepareUploadPreset("handled", config, live, cover);
|
|
81254
|
+
}
|
|
80993
81255
|
/**
|
|
80994
81256
|
* 格式化上传视频标题
|
|
80995
81257
|
* @private
|
|
@@ -81031,11 +81293,9 @@ class WebhookHandler {
|
|
|
81031
81293
|
*/
|
|
81032
81294
|
async performContinueUpload(live, aid, filePaths, type, config, uploadPreset, limitedUploadTime) {
|
|
81033
81295
|
index.logObj.info("续传", filePaths);
|
|
81296
|
+
const uploadedItems = this.createUploadItems(filePaths, type);
|
|
81034
81297
|
live.batchUpdateUploadStatus(filePaths.map((item) => item.part), "uploading", type);
|
|
81035
|
-
await this.addEditMediaTask(config.uid, aid,
|
|
81036
|
-
path: item.path,
|
|
81037
|
-
title: item.title,
|
|
81038
|
-
})), uploadPreset, limitedUploadTime, config.afterUploadDeletAction);
|
|
81298
|
+
await this.addEditMediaTask(config.uid, aid, uploadedItems, uploadPreset, limitedUploadTime, config.afterUploadDeletAction);
|
|
81039
81299
|
live.batchUpdateUploadStatus(filePaths.map((item) => item.part), "uploaded", type);
|
|
81040
81300
|
}
|
|
81041
81301
|
/**
|
|
@@ -81044,17 +81304,61 @@ class WebhookHandler {
|
|
|
81044
81304
|
*/
|
|
81045
81305
|
async performNewUpload(live, filePaths, type, config, uploadPreset, limitedUploadTime) {
|
|
81046
81306
|
const aidField = type === "handled" ? "aid" : "rawAid";
|
|
81307
|
+
const uploadedItems = this.createUploadItems(filePaths, type);
|
|
81047
81308
|
live.batchUpdateUploadStatus(filePaths.map((item) => item.part), "uploading", type);
|
|
81048
81309
|
// 格式化标题
|
|
81049
81310
|
const videoTitle = this.formatUploadTitle(live, filePaths[0].part, type, uploadPreset, config);
|
|
81050
81311
|
uploadPreset.title = videoTitle;
|
|
81051
|
-
const aid = (await this.addUploadTask(config.uid,
|
|
81052
|
-
path: item.path,
|
|
81053
|
-
title: item.title,
|
|
81054
|
-
})), uploadPreset, limitedUploadTime, config.afterUploadDeletAction));
|
|
81312
|
+
const aid = (await this.addUploadTask(config.uid, uploadedItems, uploadPreset, limitedUploadTime, config.afterUploadDeletAction));
|
|
81055
81313
|
live[aidField] = Number(aid);
|
|
81056
81314
|
live.batchUpdateUploadStatus(filePaths.map((item) => item.part), "uploaded", type);
|
|
81057
81315
|
}
|
|
81316
|
+
async performContinueUploadForSameMedia(live, aid, filePaths, config, uploadPreset, limitedUploadTime) {
|
|
81317
|
+
// log.info("同稿件续传", filePaths);
|
|
81318
|
+
const sortParams = this.buildSameMediaSortParams(live, config);
|
|
81319
|
+
live.aid = aid;
|
|
81320
|
+
this.updateUploadStatusForItems(filePaths, "uploading");
|
|
81321
|
+
await this.addEditMediaTask(config.uid, aid, filePaths, uploadPreset, limitedUploadTime, config.afterUploadDeletAction, sortParams);
|
|
81322
|
+
this.updateUploadStatusForItems(filePaths, "uploaded");
|
|
81323
|
+
}
|
|
81324
|
+
async performNewUploadForSameMedia(live, filePaths, config, uploadPreset, limitedUploadTime) {
|
|
81325
|
+
this.updateUploadStatusForItems(filePaths, "uploading");
|
|
81326
|
+
const videoTitle = this.formatUploadTitle(live, filePaths[0].part, "handled", uploadPreset, config);
|
|
81327
|
+
uploadPreset.title = videoTitle;
|
|
81328
|
+
const aid = (await this.addUploadTask(config.uid, filePaths, uploadPreset, limitedUploadTime, config.afterUploadDeletAction));
|
|
81329
|
+
live.aid = Number(aid);
|
|
81330
|
+
this.updateUploadStatusForItems(filePaths, "uploaded");
|
|
81331
|
+
}
|
|
81332
|
+
async uploadVideoToSameMedia(live, config) {
|
|
81333
|
+
if (live.hasUploadingParts("handled") || live.hasUploadingParts("raw")) {
|
|
81334
|
+
return;
|
|
81335
|
+
}
|
|
81336
|
+
const { filePaths, cover } = this.buildSameMediaUploadFileList(live, config);
|
|
81337
|
+
// console.log("同稿件上传候选列表", filePaths);
|
|
81338
|
+
if (filePaths.length === 0) {
|
|
81339
|
+
return;
|
|
81340
|
+
}
|
|
81341
|
+
if (!this.validateCombinedUploadConfig(filePaths, config)) {
|
|
81342
|
+
return;
|
|
81343
|
+
}
|
|
81344
|
+
const uploadPreset = await this.prepareSharedUploadPreset(config, live, cover);
|
|
81345
|
+
const limitedUploadTime = config.limitUploadTime
|
|
81346
|
+
? config.uploadHandleTime
|
|
81347
|
+
: [];
|
|
81348
|
+
const sharedAid = live.aid ?? live.rawAid;
|
|
81349
|
+
try {
|
|
81350
|
+
if (sharedAid) {
|
|
81351
|
+
await this.performContinueUploadForSameMedia(live, sharedAid, filePaths, config, uploadPreset, limitedUploadTime);
|
|
81352
|
+
}
|
|
81353
|
+
else {
|
|
81354
|
+
await this.performNewUploadForSameMedia(live, filePaths, config, uploadPreset, limitedUploadTime);
|
|
81355
|
+
}
|
|
81356
|
+
}
|
|
81357
|
+
catch (error) {
|
|
81358
|
+
index.logObj.error(error);
|
|
81359
|
+
this.updateUploadStatusForItems(filePaths, "error");
|
|
81360
|
+
}
|
|
81361
|
+
}
|
|
81058
81362
|
/**
|
|
81059
81363
|
* 上传单个类型的视频(弹幕版或原始版)
|
|
81060
81364
|
* @private
|
|
@@ -81100,9 +81404,14 @@ class WebhookHandler {
|
|
|
81100
81404
|
/**
|
|
81101
81405
|
* 处理直播上传
|
|
81102
81406
|
* @param live 直播数据
|
|
81103
|
-
* @param type 上传类型:handled-弹幕版,raw
|
|
81407
|
+
* @param type 上传类型:handled-弹幕版,raw-原始版
|
|
81104
81408
|
*/
|
|
81105
81409
|
handleLive = async (live, type) => {
|
|
81410
|
+
const config = this.configManager.getConfig(live.roomId);
|
|
81411
|
+
if (this.isSameMediaUploadEnabled(config)) {
|
|
81412
|
+
await this.uploadVideoToSameMedia(live, config);
|
|
81413
|
+
return;
|
|
81414
|
+
}
|
|
81106
81415
|
if (type) {
|
|
81107
81416
|
if (type === "handled") {
|
|
81108
81417
|
await this.uploadVideoByType(live, "handled");
|
|
@@ -81156,7 +81465,7 @@ exports.handler = void 0;
|
|
|
81156
81465
|
exports.appConfig = void 0;
|
|
81157
81466
|
exports.container = void 0;
|
|
81158
81467
|
const fileCache = createFileCache();
|
|
81159
|
-
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-
|
|
81468
|
+
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-DG03bxlI.cjs', document.baseURI).href))));
|
|
81160
81469
|
const authMiddleware = (passKey) => {
|
|
81161
81470
|
return async (ctx, next) => {
|
|
81162
81471
|
const authHeader = ctx.headers["authorization"] || ctx.request.query.auth;
|
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.13.1";
|
|
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-CgpPN0zA.cjs'); }).then(function (n) { return n.index; });
|
|
3745
|
+
const { serverStart } = await Promise.resolve().then(function () { return require('./index-DG03bxlI.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-CgpPN0zA.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.13.1",
|
|
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.13.1",
|
|
43
|
+
"@biliLive-tools/types": "3.13.1",
|
|
44
|
+
"@biliLive-tools/shared": "3.13.1"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"start": "tsx src/index.ts",
|