bililive-cli 3.12.0 → 3.13.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-Bw3nOSUH.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;
|
|
@@ -55005,46 +55050,54 @@ const coerce$1 = (version, options) => {
|
|
|
55005
55050
|
};
|
|
55006
55051
|
var coerce_1 = coerce$1;
|
|
55007
55052
|
|
|
55008
|
-
|
|
55009
|
-
|
|
55010
|
-
this.max = 1000;
|
|
55011
|
-
this.map = new Map();
|
|
55012
|
-
}
|
|
55053
|
+
var lrucache;
|
|
55054
|
+
var hasRequiredLrucache;
|
|
55013
55055
|
|
|
55014
|
-
|
|
55015
|
-
|
|
55016
|
-
|
|
55017
|
-
|
|
55018
|
-
|
|
55019
|
-
|
|
55020
|
-
|
|
55021
|
-
|
|
55022
|
-
return value
|
|
55023
|
-
}
|
|
55024
|
-
}
|
|
55056
|
+
function requireLrucache () {
|
|
55057
|
+
if (hasRequiredLrucache) return lrucache;
|
|
55058
|
+
hasRequiredLrucache = 1;
|
|
55059
|
+
class LRUCache {
|
|
55060
|
+
constructor () {
|
|
55061
|
+
this.max = 1000;
|
|
55062
|
+
this.map = new Map();
|
|
55063
|
+
}
|
|
55025
55064
|
|
|
55026
|
-
|
|
55027
|
-
|
|
55028
|
-
|
|
55065
|
+
get (key) {
|
|
55066
|
+
const value = this.map.get(key);
|
|
55067
|
+
if (value === undefined) {
|
|
55068
|
+
return undefined
|
|
55069
|
+
} else {
|
|
55070
|
+
// Remove the key from the map and add it to the end
|
|
55071
|
+
this.map.delete(key);
|
|
55072
|
+
this.map.set(key, value);
|
|
55073
|
+
return value
|
|
55074
|
+
}
|
|
55075
|
+
}
|
|
55029
55076
|
|
|
55030
|
-
|
|
55031
|
-
|
|
55077
|
+
delete (key) {
|
|
55078
|
+
return this.map.delete(key)
|
|
55079
|
+
}
|
|
55032
55080
|
|
|
55033
|
-
|
|
55034
|
-
|
|
55035
|
-
if (this.map.size >= this.max) {
|
|
55036
|
-
const firstKey = this.map.keys().next().value;
|
|
55037
|
-
this.delete(firstKey);
|
|
55038
|
-
}
|
|
55081
|
+
set (key, value) {
|
|
55082
|
+
const deleted = this.delete(key);
|
|
55039
55083
|
|
|
55040
|
-
|
|
55041
|
-
|
|
55084
|
+
if (!deleted && value !== undefined) {
|
|
55085
|
+
// If cache is full, delete the least recently used item
|
|
55086
|
+
if (this.map.size >= this.max) {
|
|
55087
|
+
const firstKey = this.map.keys().next().value;
|
|
55088
|
+
this.delete(firstKey);
|
|
55089
|
+
}
|
|
55042
55090
|
|
|
55043
|
-
|
|
55044
|
-
|
|
55045
|
-
}
|
|
55091
|
+
this.map.set(key, value);
|
|
55092
|
+
}
|
|
55046
55093
|
|
|
55047
|
-
|
|
55094
|
+
return this
|
|
55095
|
+
}
|
|
55096
|
+
}
|
|
55097
|
+
|
|
55098
|
+
lrucache = LRUCache;
|
|
55099
|
+
return lrucache;
|
|
55100
|
+
}
|
|
55048
55101
|
|
|
55049
55102
|
var range;
|
|
55050
55103
|
var hasRequiredRange;
|
|
@@ -55266,7 +55319,7 @@ function requireRange () {
|
|
|
55266
55319
|
|
|
55267
55320
|
range = Range;
|
|
55268
55321
|
|
|
55269
|
-
const LRU =
|
|
55322
|
+
const LRU = requireLrucache();
|
|
55270
55323
|
const cache = new LRU();
|
|
55271
55324
|
|
|
55272
55325
|
const parseOptions = parseOptions_1;
|
|
@@ -56428,7 +56481,6 @@ router$d.get("/files", async (ctx) => {
|
|
|
56428
56481
|
const allFiles = filterExts.length === 0 || filterExts.includes(".*");
|
|
56429
56482
|
if (root == "/" && process.platform === "win32") {
|
|
56430
56483
|
const drives = await getDriveLetters();
|
|
56431
|
-
root = drives[0];
|
|
56432
56484
|
ctx.body = {
|
|
56433
56485
|
list: drives.map((drive) => ({ type: "directory", name: drive, path: `${drive}\\` })),
|
|
56434
56486
|
parent: "",
|
|
@@ -56454,6 +56506,7 @@ router$d.get("/files", async (ctx) => {
|
|
|
56454
56506
|
type: type,
|
|
56455
56507
|
name: name,
|
|
56456
56508
|
path: filePath,
|
|
56509
|
+
size: type === "file" ? fileStat.size : undefined,
|
|
56457
56510
|
});
|
|
56458
56511
|
}
|
|
56459
56512
|
catch (error) {
|
|
@@ -57074,6 +57127,47 @@ router$c.post("/get_cookie", async (ctx) => {
|
|
|
57074
57127
|
ctx.body = "获取失败,请重试";
|
|
57075
57128
|
}
|
|
57076
57129
|
});
|
|
57130
|
+
router$c.get("/export", async (ctx) => {
|
|
57131
|
+
const list = index.biliApi.readUserList();
|
|
57132
|
+
ctx.body = list;
|
|
57133
|
+
});
|
|
57134
|
+
router$c.post("/export_single", async (ctx) => {
|
|
57135
|
+
const { uid } = ctx.request.body;
|
|
57136
|
+
const user = index.biliApi.readUser(uid);
|
|
57137
|
+
if (!user) {
|
|
57138
|
+
ctx.status = 404;
|
|
57139
|
+
ctx.body = "用户不存在";
|
|
57140
|
+
return;
|
|
57141
|
+
}
|
|
57142
|
+
ctx.body = user;
|
|
57143
|
+
});
|
|
57144
|
+
router$c.post("/import", async (ctx) => {
|
|
57145
|
+
const { users } = ctx.request.body;
|
|
57146
|
+
if (!Array.isArray(users)) {
|
|
57147
|
+
ctx.status = 400;
|
|
57148
|
+
ctx.body = "参数错误";
|
|
57149
|
+
return;
|
|
57150
|
+
}
|
|
57151
|
+
for (const item of users) {
|
|
57152
|
+
if (!item?.mid || !item?.accessToken || !item?.refreshToken || !item?.cookie) {
|
|
57153
|
+
ctx.status = 400;
|
|
57154
|
+
ctx.body = "账号数据不完整";
|
|
57155
|
+
return;
|
|
57156
|
+
}
|
|
57157
|
+
await index.biliApi.writeUser(item);
|
|
57158
|
+
}
|
|
57159
|
+
ctx.status = 200;
|
|
57160
|
+
});
|
|
57161
|
+
router$c.post("/import_single", async (ctx) => {
|
|
57162
|
+
const { user } = ctx.request.body;
|
|
57163
|
+
if (!user?.mid || !user?.accessToken || !user?.refreshToken || !user?.cookie) {
|
|
57164
|
+
ctx.status = 400;
|
|
57165
|
+
ctx.body = "账号数据不完整";
|
|
57166
|
+
return;
|
|
57167
|
+
}
|
|
57168
|
+
await index.biliApi.writeUser(user);
|
|
57169
|
+
ctx.status = 200;
|
|
57170
|
+
});
|
|
57077
57171
|
|
|
57078
57172
|
const router$b = new Router$1({
|
|
57079
57173
|
prefix: "/preset",
|
|
@@ -76579,7 +76673,7 @@ const router$a = new Router$1({
|
|
|
76579
76673
|
*/
|
|
76580
76674
|
router$a.get("/streamLogs", sse({
|
|
76581
76675
|
maxClients: 5000,
|
|
76582
|
-
pingInterval:
|
|
76676
|
+
pingInterval: 60 * 60 * 1000,
|
|
76583
76677
|
}), async (ctx) => {
|
|
76584
76678
|
const logFilePath = exports.config.logPath;
|
|
76585
76679
|
// 初始化logSize为文件当前大小
|
|
@@ -78181,7 +78275,7 @@ async function parseVideo({ url, }) {
|
|
|
78181
78275
|
}
|
|
78182
78276
|
}
|
|
78183
78277
|
async function downloadVideo(options) {
|
|
78184
|
-
|
|
78278
|
+
let filepath = path$7.join(options.savePath, options.filename);
|
|
78185
78279
|
if (options.platform === "douyu") {
|
|
78186
78280
|
if (!options?.extra?.decodeData) {
|
|
78187
78281
|
throw new Error("decodeData is required for douyu download");
|
|
@@ -78241,6 +78335,7 @@ async function downloadVideo(options) {
|
|
|
78241
78335
|
if (!options?.extra?.bvid) {
|
|
78242
78336
|
throw new Error("bvid is required for bilibili download");
|
|
78243
78337
|
}
|
|
78338
|
+
filepath = index.replaceExtName(filepath, ".mp4");
|
|
78244
78339
|
await index.biliApi.download({
|
|
78245
78340
|
bvid: options.extra.bvid,
|
|
78246
78341
|
cid: Number(options.id),
|
|
@@ -78709,7 +78804,7 @@ async function uploadTest(params) {
|
|
|
78709
78804
|
const tempDir = index.getTempPath();
|
|
78710
78805
|
// 在临时文件新建一个文件,内容为"biliLive-tools"
|
|
78711
78806
|
const tempFilePath = path$7.join(tempDir, "biliLive-tools-upload-test.txt");
|
|
78712
|
-
await index.fs.writeFile(tempFilePath,
|
|
78807
|
+
await index.fs.writeFile(tempFilePath, `biliLive-tools-${index.uuid()}`);
|
|
78713
78808
|
return new Promise(async (resolve, reject) => {
|
|
78714
78809
|
const task = await addSyncTask({
|
|
78715
78810
|
input: tempFilePath,
|
|
@@ -79218,9 +79313,23 @@ class FileRefManager {
|
|
|
79218
79313
|
*/
|
|
79219
79314
|
class ConfigManager {
|
|
79220
79315
|
appConfig;
|
|
79316
|
+
static APP_CONFIG_CACHE_TTL = 30 * 1000;
|
|
79317
|
+
appConfigCache;
|
|
79221
79318
|
constructor(appConfig) {
|
|
79222
79319
|
this.appConfig = appConfig;
|
|
79223
79320
|
}
|
|
79321
|
+
getAppConfigAll() {
|
|
79322
|
+
const now = Date.now();
|
|
79323
|
+
if (this.appConfigCache && this.appConfigCache.expiresAt > now) {
|
|
79324
|
+
return this.appConfigCache.value;
|
|
79325
|
+
}
|
|
79326
|
+
const value = this.appConfig.getAll();
|
|
79327
|
+
this.appConfigCache = {
|
|
79328
|
+
value,
|
|
79329
|
+
expiresAt: now + ConfigManager.APP_CONFIG_CACHE_TTL,
|
|
79330
|
+
};
|
|
79331
|
+
return value;
|
|
79332
|
+
}
|
|
79224
79333
|
/**
|
|
79225
79334
|
* 判断房间是否开启
|
|
79226
79335
|
*/
|
|
@@ -79245,7 +79354,7 @@ class ConfigManager {
|
|
|
79245
79354
|
* @returns 房间配置对象
|
|
79246
79355
|
*/
|
|
79247
79356
|
getConfig(roomId) {
|
|
79248
|
-
const appConfigAll = this.
|
|
79357
|
+
const appConfigAll = this.getAppConfigAll();
|
|
79249
79358
|
const roomSetting = appConfigAll.webhook?.rooms?.[roomId];
|
|
79250
79359
|
const danmu = this.getRoomSetting("danmu", roomSetting) ?? false;
|
|
79251
79360
|
const mergePart = this.getRoomSetting("autoPartMerge", roomSetting) ?? false;
|
|
@@ -79271,9 +79380,7 @@ class ConfigManager {
|
|
|
79271
79380
|
];
|
|
79272
79381
|
const syncId = this.getRoomSetting("syncId", roomSetting);
|
|
79273
79382
|
const afterConvertAction = this.getRoomSetting("afterConvertAction", roomSetting) ?? [];
|
|
79274
|
-
|
|
79275
|
-
const removeSourceAferrConvert2Mp4Before = this.getRoomSetting("removeSourceAferrConvert2Mp4", roomSetting);
|
|
79276
|
-
const removeSourceAferrConvert2Mp4 = afterConvertAction.includes("removeAfterConvert2Mp4") || !!removeSourceAferrConvert2Mp4Before;
|
|
79383
|
+
const removeSourceAferrConvert2Mp4 = afterConvertAction.includes("removeAfterConvert2Mp4");
|
|
79277
79384
|
const afterConvertRemoveVideoRaw = afterConvertAction.includes("removeVideo");
|
|
79278
79385
|
const afterConvertRemoveXmlRaw = afterConvertAction.includes("removeXml");
|
|
79279
79386
|
const afterConvertRemoveFlvRaw = afterConvertAction.includes("removeAfterFlvRepair");
|
|
@@ -79284,6 +79391,7 @@ class ConfigManager {
|
|
|
79284
79391
|
"23:59:59",
|
|
79285
79392
|
];
|
|
79286
79393
|
const uploadNoDanmu = this.getRoomSetting("uploadNoDanmu", roomSetting) ?? false;
|
|
79394
|
+
const uploadToSameMedia = this.getRoomSetting("uploadToSameMedia", roomSetting) ?? false;
|
|
79287
79395
|
const noDanmuVideoPreset = this.getRoomSetting("noDanmuVideoPreset", roomSetting) || "default";
|
|
79288
79396
|
// 如果没有开启断播续传,那么不需要合并part
|
|
79289
79397
|
if (!mergePart)
|
|
@@ -79333,6 +79441,7 @@ class ConfigManager {
|
|
|
79333
79441
|
limitUploadTime,
|
|
79334
79442
|
uploadHandleTime,
|
|
79335
79443
|
uploadNoDanmu,
|
|
79444
|
+
uploadToSameMedia,
|
|
79336
79445
|
noDanmuVideoPreset,
|
|
79337
79446
|
videoHandleTime: limitVideoConvertTime ? videoHandleTime : undefined,
|
|
79338
79447
|
partTitleTemplate: this.getRoomSetting("partTitleTemplate", roomSetting) || "{{filename}}",
|
|
@@ -79353,7 +79462,7 @@ class ConfigManager {
|
|
|
79353
79462
|
* @returns 配置值
|
|
79354
79463
|
*/
|
|
79355
79464
|
getRoomSetting(key, roomSetting) {
|
|
79356
|
-
const appConfigAll = this.
|
|
79465
|
+
const appConfigAll = this.getAppConfigAll();
|
|
79357
79466
|
if (roomSetting) {
|
|
79358
79467
|
if (roomSetting.noGlobal?.includes(key)) {
|
|
79359
79468
|
return roomSetting[key];
|
|
@@ -79373,7 +79482,7 @@ class ConfigManager {
|
|
|
79373
79482
|
const { syncId } = this.getConfig(roomId);
|
|
79374
79483
|
if (!syncId)
|
|
79375
79484
|
return null;
|
|
79376
|
-
const appConfig = this.
|
|
79485
|
+
const appConfig = this.getAppConfigAll();
|
|
79377
79486
|
const syncConfig = appConfig.sync?.syncConfigs?.find((cfg) => cfg.id === syncId);
|
|
79378
79487
|
if (!syncConfig)
|
|
79379
79488
|
return null;
|
|
@@ -80149,6 +80258,7 @@ class EventBufferManager extends EventEmitter$3.EventEmitter {
|
|
|
80149
80258
|
}
|
|
80150
80259
|
}
|
|
80151
80260
|
|
|
80261
|
+
const SAME_MEDIA_UPLOAD_ORDER = ["handled", "raw"];
|
|
80152
80262
|
class WebhookHandler {
|
|
80153
80263
|
liveManager = new LiveManager();
|
|
80154
80264
|
ffmpegPreset;
|
|
@@ -80860,11 +80970,58 @@ class WebhookHandler {
|
|
|
80860
80970
|
* 通用上传任务处理逻辑
|
|
80861
80971
|
* @private
|
|
80862
80972
|
*/
|
|
80863
|
-
|
|
80973
|
+
getRuntimePart(part) {
|
|
80974
|
+
return part;
|
|
80975
|
+
}
|
|
80976
|
+
setPartCid(part, type, cid) {
|
|
80977
|
+
if (!cid)
|
|
80978
|
+
return;
|
|
80979
|
+
const runtimePart = this.getRuntimePart(part);
|
|
80980
|
+
if (type === "handled") {
|
|
80981
|
+
runtimePart.handledCid = cid;
|
|
80982
|
+
}
|
|
80983
|
+
else {
|
|
80984
|
+
runtimePart.rawCid = cid;
|
|
80985
|
+
}
|
|
80986
|
+
}
|
|
80987
|
+
getPartCid(part, type) {
|
|
80988
|
+
const runtimePart = this.getRuntimePart(part);
|
|
80989
|
+
return type === "handled" ? runtimePart.handledCid : runtimePart.rawCid;
|
|
80990
|
+
}
|
|
80991
|
+
toPathArray(items) {
|
|
80992
|
+
return items.map((item) => ({
|
|
80993
|
+
path: item.path,
|
|
80994
|
+
title: item.title,
|
|
80995
|
+
}));
|
|
80996
|
+
}
|
|
80997
|
+
createUploadItems(filePaths, type) {
|
|
80998
|
+
return filePaths.map((item) => ({
|
|
80999
|
+
...item,
|
|
81000
|
+
type,
|
|
81001
|
+
}));
|
|
81002
|
+
}
|
|
81003
|
+
writeUploadResultToParts(uploadedItems, data) {
|
|
81004
|
+
const itemQueue = new Map();
|
|
81005
|
+
for (const item of uploadedItems) {
|
|
81006
|
+
const queue = itemQueue.get(item.path) ?? [];
|
|
81007
|
+
queue.push(item);
|
|
81008
|
+
itemQueue.set(item.path, queue);
|
|
81009
|
+
}
|
|
81010
|
+
for (const result of data) {
|
|
81011
|
+
const queue = itemQueue.get(result.filePath);
|
|
81012
|
+
const item = queue?.shift();
|
|
81013
|
+
if (!item)
|
|
81014
|
+
continue;
|
|
81015
|
+
this.setPartCid(item.part, item.type, result.cid);
|
|
81016
|
+
}
|
|
81017
|
+
}
|
|
81018
|
+
async handleUploadTask(task, uploadedItems) {
|
|
80864
81019
|
return new Promise((resolve, reject) => {
|
|
80865
|
-
task.on("task-end", async () => {
|
|
81020
|
+
task.on("task-end", async (payload) => {
|
|
81021
|
+
const data = payload?.data ?? [];
|
|
81022
|
+
this.writeUploadResultToParts(uploadedItems, data);
|
|
80866
81023
|
// 释放所有文件的引用
|
|
80867
|
-
for (const { path } of
|
|
81024
|
+
for (const { path } of uploadedItems) {
|
|
80868
81025
|
await this.fileRefManager.releaseRef(path);
|
|
80869
81026
|
}
|
|
80870
81027
|
resolve(task.output);
|
|
@@ -80893,25 +81050,31 @@ class WebhookHandler {
|
|
|
80893
81050
|
}
|
|
80894
81051
|
};
|
|
80895
81052
|
}
|
|
80896
|
-
addUploadTask = async (uid,
|
|
81053
|
+
addUploadTask = async (uid, uploadedItems, options, limitedUploadTime, afterUploadDeletAction) => {
|
|
81054
|
+
const pathArray = this.toPathArray(uploadedItems);
|
|
80897
81055
|
const checkCallback = this.setupDeleteAfterCheckLock(pathArray, afterUploadDeletAction);
|
|
81056
|
+
// console.log("upload", pathArray);
|
|
80898
81057
|
const task = await index.biliApi.addMedia(pathArray, options, uid, {
|
|
80899
81058
|
limitedUploadTime,
|
|
80900
81059
|
afterUploadDeletAction: "none",
|
|
80901
81060
|
forceCheck: afterUploadDeletAction === "deleteAfterCheck",
|
|
80902
81061
|
checkCallback,
|
|
80903
81062
|
});
|
|
80904
|
-
return this.handleUploadTask(task,
|
|
81063
|
+
return this.handleUploadTask(task, uploadedItems);
|
|
80905
81064
|
};
|
|
80906
|
-
addEditMediaTask = async (uid, aid,
|
|
81065
|
+
addEditMediaTask = async (uid, aid, uploadedItems, uploadPreset, limitedUploadTime, afterUploadDeletAction, sortParams) => {
|
|
81066
|
+
const pathArray = this.toPathArray(uploadedItems);
|
|
80907
81067
|
const checkCallback = this.setupDeleteAfterCheckLock(pathArray, afterUploadDeletAction);
|
|
81068
|
+
// console.log("sortParams111111111", sortParams, pathArray);
|
|
81069
|
+
// 参数sortParams: array<{filePath:string;cid?:number}>,表示按照 filePath 对历史分P和当前上传文件统一排序
|
|
80908
81070
|
const task = await index.biliApi.editMedia(aid, pathArray, uploadPreset, uid, {
|
|
80909
81071
|
limitedUploadTime,
|
|
80910
81072
|
afterUploadDeletAction: "none",
|
|
80911
81073
|
forceCheck: afterUploadDeletAction === "deleteAfterCheck",
|
|
80912
81074
|
checkCallback,
|
|
81075
|
+
sortParams,
|
|
80913
81076
|
});
|
|
80914
|
-
return this.handleUploadTask(task,
|
|
81077
|
+
return this.handleUploadTask(task, uploadedItems);
|
|
80915
81078
|
};
|
|
80916
81079
|
/**
|
|
80917
81080
|
* 构建上传文件列表
|
|
@@ -80945,6 +81108,110 @@ class WebhookHandler {
|
|
|
80945
81108
|
}
|
|
80946
81109
|
return { filePaths, cover };
|
|
80947
81110
|
}
|
|
81111
|
+
isSameMediaUploadEnabled(config) {
|
|
81112
|
+
return config.uploadNoDanmu && config.uploadToSameMedia;
|
|
81113
|
+
}
|
|
81114
|
+
updateUploadStatusForItems(filePaths, status) {
|
|
81115
|
+
for (const item of filePaths) {
|
|
81116
|
+
item.part.updateUploadStatus(status, item.type === "raw");
|
|
81117
|
+
}
|
|
81118
|
+
}
|
|
81119
|
+
getSameMediaUploadCandidate(part, type, config) {
|
|
81120
|
+
if (type === "handled") {
|
|
81121
|
+
return {
|
|
81122
|
+
type,
|
|
81123
|
+
path: part.filePath,
|
|
81124
|
+
status: part.uploadStatus,
|
|
81125
|
+
canUpload: part.canUpload("handled"),
|
|
81126
|
+
enabled: true,
|
|
81127
|
+
};
|
|
81128
|
+
}
|
|
81129
|
+
return {
|
|
81130
|
+
type,
|
|
81131
|
+
path: part.rawFilePath,
|
|
81132
|
+
status: part.rawUploadStatus,
|
|
81133
|
+
canUpload: part.canUpload("raw"),
|
|
81134
|
+
enabled: config.uploadNoDanmu,
|
|
81135
|
+
};
|
|
81136
|
+
}
|
|
81137
|
+
buildSameMediaSortParams(live, config) {
|
|
81138
|
+
const sortParams = [];
|
|
81139
|
+
for (const type of SAME_MEDIA_UPLOAD_ORDER) {
|
|
81140
|
+
for (const part of live.parts) {
|
|
81141
|
+
const item = this.getSameMediaUploadCandidate(part, type, config);
|
|
81142
|
+
if (item.enabled === false || item.status === "error") {
|
|
81143
|
+
continue;
|
|
81144
|
+
}
|
|
81145
|
+
const cid = this.getPartCid(part, item.type);
|
|
81146
|
+
sortParams.push({
|
|
81147
|
+
filePath: item.path,
|
|
81148
|
+
cid,
|
|
81149
|
+
});
|
|
81150
|
+
if (item.status !== "uploaded" && !item.canUpload) {
|
|
81151
|
+
return sortParams;
|
|
81152
|
+
}
|
|
81153
|
+
}
|
|
81154
|
+
}
|
|
81155
|
+
return sortParams;
|
|
81156
|
+
}
|
|
81157
|
+
getUploadedItemCountForSameMedia(live, config) {
|
|
81158
|
+
let uploadedCount = 0;
|
|
81159
|
+
for (const part of live.parts) {
|
|
81160
|
+
if (part.uploadStatus === "uploaded") {
|
|
81161
|
+
uploadedCount++;
|
|
81162
|
+
}
|
|
81163
|
+
if (config.uploadNoDanmu && part.rawUploadStatus === "uploaded") {
|
|
81164
|
+
uploadedCount++;
|
|
81165
|
+
}
|
|
81166
|
+
}
|
|
81167
|
+
return uploadedCount;
|
|
81168
|
+
}
|
|
81169
|
+
buildSameMediaUploadFileList(live, config) {
|
|
81170
|
+
let cover;
|
|
81171
|
+
const filePaths = [];
|
|
81172
|
+
let currentIndex = this.getUploadedItemCountForSameMedia(live, config) + 1;
|
|
81173
|
+
for (const type of SAME_MEDIA_UPLOAD_ORDER) {
|
|
81174
|
+
for (const part of live.parts) {
|
|
81175
|
+
const item = this.getSameMediaUploadCandidate(part, type, config);
|
|
81176
|
+
if (item.enabled === false)
|
|
81177
|
+
continue;
|
|
81178
|
+
if (item.status === "uploaded" || item.status === "error")
|
|
81179
|
+
continue;
|
|
81180
|
+
if (!item.canUpload)
|
|
81181
|
+
continue;
|
|
81182
|
+
const filename = path$7.parse(item.path).name;
|
|
81183
|
+
const baseTitle = index.formatPartTitle({
|
|
81184
|
+
title: part.title,
|
|
81185
|
+
username: live.username,
|
|
81186
|
+
roomId: live.roomId,
|
|
81187
|
+
time: part?.startTime
|
|
81188
|
+
? new Date(part.startTime).toISOString()
|
|
81189
|
+
: new Date().toISOString(),
|
|
81190
|
+
filename,
|
|
81191
|
+
index: currentIndex,
|
|
81192
|
+
}, config.partTitleTemplate ?? "{{filename}}");
|
|
81193
|
+
filePaths.push({
|
|
81194
|
+
part,
|
|
81195
|
+
path: item.path,
|
|
81196
|
+
title: baseTitle,
|
|
81197
|
+
type: item.type,
|
|
81198
|
+
});
|
|
81199
|
+
if (!cover) {
|
|
81200
|
+
cover = part.cover;
|
|
81201
|
+
}
|
|
81202
|
+
currentIndex++;
|
|
81203
|
+
}
|
|
81204
|
+
}
|
|
81205
|
+
return { filePaths, cover };
|
|
81206
|
+
}
|
|
81207
|
+
validateCombinedUploadConfig(filePaths, config) {
|
|
81208
|
+
if (!config.uid) {
|
|
81209
|
+
this.updateUploadStatusForItems(filePaths, "error");
|
|
81210
|
+
index.logObj.error("无须上传,uid未配置");
|
|
81211
|
+
return false;
|
|
81212
|
+
}
|
|
81213
|
+
return true;
|
|
81214
|
+
}
|
|
80948
81215
|
/**
|
|
80949
81216
|
* 验证上传配置
|
|
80950
81217
|
* @private
|
|
@@ -80990,6 +81257,9 @@ class WebhookHandler {
|
|
|
80990
81257
|
}
|
|
80991
81258
|
return uploadPreset;
|
|
80992
81259
|
}
|
|
81260
|
+
async prepareSharedUploadPreset(config, live, cover) {
|
|
81261
|
+
return this.prepareUploadPreset("handled", config, live, cover);
|
|
81262
|
+
}
|
|
80993
81263
|
/**
|
|
80994
81264
|
* 格式化上传视频标题
|
|
80995
81265
|
* @private
|
|
@@ -81031,11 +81301,9 @@ class WebhookHandler {
|
|
|
81031
81301
|
*/
|
|
81032
81302
|
async performContinueUpload(live, aid, filePaths, type, config, uploadPreset, limitedUploadTime) {
|
|
81033
81303
|
index.logObj.info("续传", filePaths);
|
|
81304
|
+
const uploadedItems = this.createUploadItems(filePaths, type);
|
|
81034
81305
|
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);
|
|
81306
|
+
await this.addEditMediaTask(config.uid, aid, uploadedItems, uploadPreset, limitedUploadTime, config.afterUploadDeletAction);
|
|
81039
81307
|
live.batchUpdateUploadStatus(filePaths.map((item) => item.part), "uploaded", type);
|
|
81040
81308
|
}
|
|
81041
81309
|
/**
|
|
@@ -81044,17 +81312,61 @@ class WebhookHandler {
|
|
|
81044
81312
|
*/
|
|
81045
81313
|
async performNewUpload(live, filePaths, type, config, uploadPreset, limitedUploadTime) {
|
|
81046
81314
|
const aidField = type === "handled" ? "aid" : "rawAid";
|
|
81315
|
+
const uploadedItems = this.createUploadItems(filePaths, type);
|
|
81047
81316
|
live.batchUpdateUploadStatus(filePaths.map((item) => item.part), "uploading", type);
|
|
81048
81317
|
// 格式化标题
|
|
81049
81318
|
const videoTitle = this.formatUploadTitle(live, filePaths[0].part, type, uploadPreset, config);
|
|
81050
81319
|
uploadPreset.title = videoTitle;
|
|
81051
|
-
const aid = (await this.addUploadTask(config.uid,
|
|
81052
|
-
path: item.path,
|
|
81053
|
-
title: item.title,
|
|
81054
|
-
})), uploadPreset, limitedUploadTime, config.afterUploadDeletAction));
|
|
81320
|
+
const aid = (await this.addUploadTask(config.uid, uploadedItems, uploadPreset, limitedUploadTime, config.afterUploadDeletAction));
|
|
81055
81321
|
live[aidField] = Number(aid);
|
|
81056
81322
|
live.batchUpdateUploadStatus(filePaths.map((item) => item.part), "uploaded", type);
|
|
81057
81323
|
}
|
|
81324
|
+
async performContinueUploadForSameMedia(live, aid, filePaths, config, uploadPreset, limitedUploadTime) {
|
|
81325
|
+
// log.info("同稿件续传", filePaths);
|
|
81326
|
+
const sortParams = this.buildSameMediaSortParams(live, config);
|
|
81327
|
+
live.aid = aid;
|
|
81328
|
+
this.updateUploadStatusForItems(filePaths, "uploading");
|
|
81329
|
+
await this.addEditMediaTask(config.uid, aid, filePaths, uploadPreset, limitedUploadTime, config.afterUploadDeletAction, sortParams);
|
|
81330
|
+
this.updateUploadStatusForItems(filePaths, "uploaded");
|
|
81331
|
+
}
|
|
81332
|
+
async performNewUploadForSameMedia(live, filePaths, config, uploadPreset, limitedUploadTime) {
|
|
81333
|
+
this.updateUploadStatusForItems(filePaths, "uploading");
|
|
81334
|
+
const videoTitle = this.formatUploadTitle(live, filePaths[0].part, "handled", uploadPreset, config);
|
|
81335
|
+
uploadPreset.title = videoTitle;
|
|
81336
|
+
const aid = (await this.addUploadTask(config.uid, filePaths, uploadPreset, limitedUploadTime, config.afterUploadDeletAction));
|
|
81337
|
+
live.aid = Number(aid);
|
|
81338
|
+
this.updateUploadStatusForItems(filePaths, "uploaded");
|
|
81339
|
+
}
|
|
81340
|
+
async uploadVideoToSameMedia(live, config) {
|
|
81341
|
+
if (live.hasUploadingParts("handled") || live.hasUploadingParts("raw")) {
|
|
81342
|
+
return;
|
|
81343
|
+
}
|
|
81344
|
+
const { filePaths, cover } = this.buildSameMediaUploadFileList(live, config);
|
|
81345
|
+
// console.log("同稿件上传候选列表", filePaths);
|
|
81346
|
+
if (filePaths.length === 0) {
|
|
81347
|
+
return;
|
|
81348
|
+
}
|
|
81349
|
+
if (!this.validateCombinedUploadConfig(filePaths, config)) {
|
|
81350
|
+
return;
|
|
81351
|
+
}
|
|
81352
|
+
const uploadPreset = await this.prepareSharedUploadPreset(config, live, cover);
|
|
81353
|
+
const limitedUploadTime = config.limitUploadTime
|
|
81354
|
+
? config.uploadHandleTime
|
|
81355
|
+
: [];
|
|
81356
|
+
const sharedAid = live.aid ?? live.rawAid;
|
|
81357
|
+
try {
|
|
81358
|
+
if (sharedAid) {
|
|
81359
|
+
await this.performContinueUploadForSameMedia(live, sharedAid, filePaths, config, uploadPreset, limitedUploadTime);
|
|
81360
|
+
}
|
|
81361
|
+
else {
|
|
81362
|
+
await this.performNewUploadForSameMedia(live, filePaths, config, uploadPreset, limitedUploadTime);
|
|
81363
|
+
}
|
|
81364
|
+
}
|
|
81365
|
+
catch (error) {
|
|
81366
|
+
index.logObj.error(error);
|
|
81367
|
+
this.updateUploadStatusForItems(filePaths, "error");
|
|
81368
|
+
}
|
|
81369
|
+
}
|
|
81058
81370
|
/**
|
|
81059
81371
|
* 上传单个类型的视频(弹幕版或原始版)
|
|
81060
81372
|
* @private
|
|
@@ -81100,9 +81412,14 @@ class WebhookHandler {
|
|
|
81100
81412
|
/**
|
|
81101
81413
|
* 处理直播上传
|
|
81102
81414
|
* @param live 直播数据
|
|
81103
|
-
* @param type 上传类型:handled-弹幕版,raw
|
|
81415
|
+
* @param type 上传类型:handled-弹幕版,raw-原始版
|
|
81104
81416
|
*/
|
|
81105
81417
|
handleLive = async (live, type) => {
|
|
81418
|
+
const config = this.configManager.getConfig(live.roomId);
|
|
81419
|
+
if (this.isSameMediaUploadEnabled(config)) {
|
|
81420
|
+
await this.uploadVideoToSameMedia(live, config);
|
|
81421
|
+
return;
|
|
81422
|
+
}
|
|
81106
81423
|
if (type) {
|
|
81107
81424
|
if (type === "handled") {
|
|
81108
81425
|
await this.uploadVideoByType(live, "handled");
|
|
@@ -81156,7 +81473,7 @@ exports.handler = void 0;
|
|
|
81156
81473
|
exports.appConfig = void 0;
|
|
81157
81474
|
exports.container = void 0;
|
|
81158
81475
|
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-
|
|
81476
|
+
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-BeK_zfM-.cjs', document.baseURI).href))));
|
|
81160
81477
|
const authMiddleware = (passKey) => {
|
|
81161
81478
|
return async (ctx, next) => {
|
|
81162
81479
|
const authHeader = ctx.headers["authorization"] || ctx.request.query.auth;
|