bililive-cli 3.22.2 → 4.0.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.
@@ -16,7 +16,7 @@ var os$5 = require('node:os');
16
16
  var path$z = require('node:path');
17
17
  var process$2 = require('node:process');
18
18
  var require$$3$1 = require('node:util');
19
- var EventEmitter$k = require('node:events');
19
+ var EventEmitter$l = require('node:events');
20
20
  var fs$F = require('node:fs');
21
21
  var require$$0$b = require('node:stream');
22
22
  var Database = require('better-sqlite3');
@@ -11626,7 +11626,7 @@ async function writeFileAsync(filePath, data, options = DEFAULT_WRITE_OPTIONS) {
11626
11626
  }
11627
11627
  else if (data instanceof require$$0$b.Readable) {
11628
11628
  const writeStream = fs$F.createWriteStream(tempPath, { fd, autoClose: false });
11629
- const finishPromise = EventEmitter$k.once(writeStream, 'finish');
11629
+ const finishPromise = EventEmitter$l.once(writeStream, 'finish');
11630
11630
  data.pipe(writeStream);
11631
11631
  await finishPromise;
11632
11632
  }
@@ -11811,6 +11811,7 @@ const APP_DEFAULT_CONFIG = {
11811
11811
  uploadPresetId: undefined,
11812
11812
  blacklist: "",
11813
11813
  danmu: false,
11814
+ burnWithoutDanmu: false,
11814
11815
  rooms: {},
11815
11816
  ffmpegPreset: undefined,
11816
11817
  danmuPreset: undefined,
@@ -12131,6 +12132,7 @@ const APP_DEFAULT_CONFIG = {
12131
12132
  recorderType: "bililive",
12132
12133
  useServerTimestamp: false,
12133
12134
  recordRetryImmediately: true,
12135
+ saveDanmaStats2DB: false,
12134
12136
  bilibili: {
12135
12137
  uid: undefined,
12136
12138
  quality: 10000,
@@ -12613,6 +12615,7 @@ const defaultRecordConfig = {
12613
12615
  disableProvideCommentsWhenRecording: false,
12614
12616
  saveGiftDanma: false,
12615
12617
  saveSCDanma: true,
12618
+ saveDanmaStats2DB: false,
12616
12619
  streamPriorities: [],
12617
12620
  sourcePriorities: [],
12618
12621
  disableAutoCheck: false,
@@ -12971,6 +12974,7 @@ class FFmpegPreset extends CommonPreset {
12971
12974
 
12972
12975
  const DEFAULT_BILIUP_CONFIG = {
12973
12976
  title: "",
12977
+ seasonTitleTemplate: "{{mediaTitle}}",
12974
12978
  desc: "",
12975
12979
  dolby: 0,
12976
12980
  hires: 0,
@@ -48717,11 +48721,11 @@ function levelToStyle(level) {
48717
48721
  return map[level] || map.default;
48718
48722
  }
48719
48723
 
48720
- const EventEmitter$j = require$$0$8;
48724
+ const EventEmitter$k = require$$0$8;
48721
48725
  const fs$b = require$$0$6;
48722
48726
  const os$2 = require$$1$2;
48723
48727
 
48724
- let File$3 = class File extends EventEmitter$j {
48728
+ let File$3 = class File extends EventEmitter$k {
48725
48729
  asyncWriteQueue = [];
48726
48730
  bytesWritten = 0;
48727
48731
  hasActiveAsyncWriting = false;
@@ -48900,13 +48904,13 @@ let NullFile$1 = class NullFile extends File$2 {
48900
48904
 
48901
48905
  var NullFile_1 = NullFile$1;
48902
48906
 
48903
- const EventEmitter$i = require$$0$8;
48907
+ const EventEmitter$j = require$$0$8;
48904
48908
  const fs$a = require$$0$6;
48905
48909
  const path$9 = require$$0$7;
48906
48910
  const File$1 = File_1;
48907
48911
  const NullFile = NullFile_1;
48908
48912
 
48909
- let FileRegistry$1 = class FileRegistry extends EventEmitter$i {
48913
+ let FileRegistry$1 = class FileRegistry extends EventEmitter$j {
48910
48914
  store = {};
48911
48915
 
48912
48916
  constructor() {
@@ -49384,6 +49388,12 @@ const BaseLiveHistory = z.object({
49384
49388
  danma_num: z.number().optional(),
49385
49389
  // 互动人数
49386
49390
  interact_num: z.number().optional(),
49391
+ // 弹幕统计 JSON,
49392
+ // {danmaTimeline: {
49393
+ // interval: 5,
49394
+ // data: [2, 1],
49395
+ // }}
49396
+ danma_stats_json: z.string().optional(),
49387
49397
  // 直播id
49388
49398
  live_id: z.string().optional(),
49389
49399
  // 文件快速哈希值
@@ -49416,7 +49426,8 @@ class RecordHistoryModel extends BaseModel {
49416
49426
  video_filename TEXT, -- 视频文件名,不含后缀
49417
49427
  video_duration REAL, -- 视频持续时长,浮点数,秒
49418
49428
  danma_num INTEGER, -- 弹幕数量
49419
- interact_num INTEGER, -- 互动人数
49429
+ interact_num INTEGER, -- 互动人数
49430
+ danma_stats_json TEXT, -- 弹幕统计JSON
49420
49431
  quick_hash TEXT, -- 文件快速哈希值
49421
49432
  FOREIGN KEY (streamer_id) REFERENCES streamer(id) -- 外键约束
49422
49433
  ) STRICT;
@@ -49486,6 +49497,8 @@ class RecordHistoryModel extends BaseModel {
49486
49497
  // @ts-ignore
49487
49498
  const hasInteractNumColumn = columns.some((col) => col.name === "interact_num");
49488
49499
  // @ts-ignore
49500
+ const hasDanmaStatsJsonColumn = columns.some((col) => col.name === "danma_stats_json");
49501
+ // @ts-ignore
49489
49502
  const hasLiveIdColumn = columns.some((col) => col.name === "live_id");
49490
49503
  // @ts-ignore
49491
49504
  const hasQuickHashColumn = columns.some((col) => col.name === "quick_hash");
@@ -49506,6 +49519,11 @@ class RecordHistoryModel extends BaseModel {
49506
49519
  this.db.prepare(`ALTER TABLE ${this.tableName} ADD COLUMN interact_num INTEGER`).run();
49507
49520
  logObj.info(`已为${this.tableName}表添加interactNum列`);
49508
49521
  }
49522
+ if (!hasDanmaStatsJsonColumn) {
49523
+ // 添加danma_stats_json列
49524
+ this.db.prepare(`ALTER TABLE ${this.tableName} ADD COLUMN danma_stats_json TEXT`).run();
49525
+ logObj.info(`已为${this.tableName}表添加danma_stats_json列`);
49526
+ }
49509
49527
  if (!hasLiveIdColumn) {
49510
49528
  // 添加live_id列
49511
49529
  this.db.prepare(`ALTER TABLE ${this.tableName} ADD COLUMN live_id TEXT`).run();
@@ -54951,7 +54969,7 @@ async function trash(paths, options) {
54951
54969
  } else if (process$2.platform === 'win32') {
54952
54970
  module = await Promise.resolve().then(function () { return require('./windows-C30k1cv-.cjs'); });
54953
54971
  } else {
54954
- module = await Promise.resolve().then(function () { return require('./linux-Cy2IwLL8.cjs'); });
54972
+ module = await Promise.resolve().then(function () { return require('./linux-dGf0gycY.cjs'); });
54955
54973
  }
54956
54974
 
54957
54975
  return module.default(paths);
@@ -60200,13 +60218,13 @@ class Config extends TypedEmitter {
60200
60218
  const oldData = cloneDeep(this.data);
60201
60219
  set(this.data, key, value);
60202
60220
  this.save();
60203
- this.emit("update", this.data, oldData);
60221
+ this.emit("update", this.data, oldData, key);
60204
60222
  }
60205
60223
  setAll(data) {
60206
60224
  const oldData = this.read();
60207
60225
  this.data = data;
60208
60226
  this.save();
60209
- this.emit("update", this.data, oldData);
60227
+ this.emit("update", this.data, oldData, null);
60210
60228
  }
60211
60229
  get(key) {
60212
60230
  this.read();
@@ -60276,7 +60294,10 @@ class AppConfig extends Config {
60276
60294
  const initData = defaultsDeep(data, APP_DEFAULT_CONFIG);
60277
60295
  super.init(filepath, initData);
60278
60296
  }
60279
- get(key) {
60297
+ get(key, withCache = false) {
60298
+ if (withCache) {
60299
+ return get$1(this.data, key);
60300
+ }
60280
60301
  return super.get(key);
60281
60302
  }
60282
60303
  // 使用lodash的get方法,保留type
@@ -61592,6 +61613,7 @@ function formatTitle(options, template) {
61592
61613
  time: new Date(options.time),
61593
61614
  roomId: options.roomId,
61594
61615
  filename: options.filename,
61616
+ mediaTitle: options.mediaTitle,
61595
61617
  };
61596
61618
  renderText = ejs.render(template, renderOptions);
61597
61619
  }
@@ -61610,10 +61632,22 @@ function formatTitle(options, template) {
61610
61632
  .replaceAll("{{mm}}", minutes)
61611
61633
  .replaceAll("{{ss}}", seconds)
61612
61634
  .replaceAll("{{filename}}", options.filename)
61635
+ .replaceAll("{{mediaTitle}}", () => options.mediaTitle ?? "{{mediaTitle}}")
61613
61636
  .trim()
61614
61637
  .slice(0, 80);
61615
61638
  return title;
61616
61639
  }
61640
+ /** 合集中稿件的标题,mediaTitle 为最终的视频标题 */
61641
+ function formatSeasonTitle(options, template = "{{mediaTitle}}") {
61642
+ return (formatTitle({
61643
+ title: "",
61644
+ username: "",
61645
+ roomId: "",
61646
+ filename: "",
61647
+ time: "",
61648
+ ...options,
61649
+ }, template.trim() || "{{mediaTitle}}") || options.mediaTitle);
61650
+ }
61617
61651
  /**
61618
61652
  * 简介格式化,支持{{title}},{{user}},{{now}}等占位符
61619
61653
  * 直播标题:{{title}}<br/>
@@ -63142,7 +63176,7 @@ class Live extends BaseRequest {
63142
63176
  }
63143
63177
  }
63144
63178
 
63145
- var eventemitter3 = {exports: {}};
63179
+ var eventemitter3$1 = {exports: {}};
63146
63180
 
63147
63181
  (function (module) {
63148
63182
 
@@ -63480,10 +63514,10 @@ var eventemitter3 = {exports: {}};
63480
63514
  {
63481
63515
  module.exports = EventEmitter;
63482
63516
  }
63483
- } (eventemitter3));
63517
+ } (eventemitter3$1));
63484
63518
 
63485
- var eventemitter3Exports = eventemitter3.exports;
63486
- var EventEmitter$h = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
63519
+ var eventemitter3Exports$1 = eventemitter3$1.exports;
63520
+ var EventEmitter$i = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports$1);
63487
63521
 
63488
63522
  let TimeoutError$2 = class TimeoutError extends Error {
63489
63523
  constructor(message) {
@@ -63669,7 +63703,7 @@ class PriorityQueue {
63669
63703
  /**
63670
63704
  Promise queue with concurrency control.
63671
63705
  */
63672
- class PQueue extends EventEmitter$h {
63706
+ class PQueue extends EventEmitter$i {
63673
63707
  #carryoverConcurrencyCount;
63674
63708
  #isIntervalIgnored;
63675
63709
  #intervalCount = 0;
@@ -65905,7 +65939,7 @@ class Platform extends BaseRequest {
65905
65939
  }
65906
65940
  });
65907
65941
  const queue = new PQueue({ concurrency: 1 });
65908
- const emitter = new EventEmitter$k();
65942
+ const emitter = new EventEmitter$l();
65909
65943
  const uploadTasks = [];
65910
65944
  for (let i = 0; i < mediaOptions.length; i++) {
65911
65945
  const uploader = new WebVideoUploader(mediaOptions[i], this.auth, {
@@ -67596,7 +67630,7 @@ class Video extends BaseRequest {
67596
67630
  * @param mediaOptions.audioQuality 音质,默认使用最高音质,30216:64k,30232:128k,30280:192k,30250:杜比全景声,30251:Hi-Res无损
67597
67631
  */
67598
67632
  async dashDownload(options, mediaOptions = {}, autoStart = true) {
67599
- const emitter = new EventEmitter$k();
67633
+ const emitter = new EventEmitter$l();
67600
67634
  if (options.disableVideo && options.disableAudio) {
67601
67635
  throw new Error("不能同时禁止视频和音频");
67602
67636
  }
@@ -67790,7 +67824,7 @@ class Video extends BaseRequest {
67790
67824
  async mp4Download(options, mediaOptions = {
67791
67825
  qn: 64,
67792
67826
  }, autoStart = true) {
67793
- const emitter = new EventEmitter$k();
67827
+ const emitter = new EventEmitter$l();
67794
67828
  const media = await this.playurl({
67795
67829
  bvid: options.bvid,
67796
67830
  aid: options.aid,
@@ -86961,7 +86995,7 @@ let MailMessage$1 = class MailMessage {
86961
86995
 
86962
86996
  var mailMessage = MailMessage$1;
86963
86997
 
86964
- const EventEmitter$g = require$$0$8;
86998
+ const EventEmitter$h = require$$0$8;
86965
86999
  const shared$9 = sharedExports;
86966
87000
  const mimeTypes = mimeTypes_1;
86967
87001
  const MailComposer = mailComposer;
@@ -86981,7 +87015,7 @@ const crypto$7 = require$$1$6;
86981
87015
  * @constructor
86982
87016
  * @param {Object} transporter Transport object instance to pass the mails to
86983
87017
  */
86984
- class Mail extends EventEmitter$g {
87018
+ class Mail extends EventEmitter$h {
86985
87019
  constructor(transporter, options, defaults) {
86986
87020
  super();
86987
87021
 
@@ -87497,7 +87531,7 @@ let DataStream$1 = class DataStream extends Transform$1 {
87497
87531
  var dataStream = DataStream$1;
87498
87532
 
87499
87533
  const packageInfo = require$$9;
87500
- const EventEmitter$f = require$$0$8.EventEmitter;
87534
+ const EventEmitter$g = require$$0$8.EventEmitter;
87501
87535
  const net$8 = require$$4;
87502
87536
  const tls$9 = require$$4$2;
87503
87537
  const os = require$$1$2;
@@ -87539,7 +87573,7 @@ const DNS_TIMEOUT = 30 * 1000; // how much to wait for resolveHostname
87539
87573
  * @namespace SMTP Client module
87540
87574
  * @param {Object} [options] Option properties
87541
87575
  */
87542
- let SMTPConnection$3 = class SMTPConnection extends EventEmitter$f {
87576
+ let SMTPConnection$3 = class SMTPConnection extends EventEmitter$g {
87543
87577
  constructor(options) {
87544
87578
  super(options);
87545
87579
 
@@ -89707,7 +89741,7 @@ var xoauth2 = XOAuth2$2;
89707
89741
  const SMTPConnection$2 = smtpConnection;
89708
89742
  const assign = sharedExports.assign;
89709
89743
  const XOAuth2$1 = xoauth2;
89710
- const EventEmitter$e = require$$0$8;
89744
+ const EventEmitter$f = require$$0$8;
89711
89745
 
89712
89746
  /**
89713
89747
  * Creates an element for the pool
@@ -89715,7 +89749,7 @@ const EventEmitter$e = require$$0$8;
89715
89749
  * @constructor
89716
89750
  * @param {Object} options SMTPPool instance
89717
89751
  */
89718
- let PoolResource$1 = class PoolResource extends EventEmitter$e {
89752
+ let PoolResource$1 = class PoolResource extends EventEmitter$f {
89719
89753
  constructor(pool) {
89720
89754
  super();
89721
89755
 
@@ -90410,7 +90444,7 @@ var wellKnown$2 = function (key) {
90410
90444
  return normalized[key] || false;
90411
90445
  };
90412
90446
 
90413
- const EventEmitter$d = require$$0$8;
90447
+ const EventEmitter$e = require$$0$8;
90414
90448
  const PoolResource = poolResource;
90415
90449
  const SMTPConnection$1 = smtpConnection;
90416
90450
  const wellKnown$1 = wellKnown$2;
@@ -90423,7 +90457,7 @@ const packageData$6 = require$$9;
90423
90457
  * @constructor
90424
90458
  * @param {Object} options SMTP Connection options
90425
90459
  */
90426
- let SMTPPool$1 = class SMTPPool extends EventEmitter$d {
90460
+ let SMTPPool$1 = class SMTPPool extends EventEmitter$e {
90427
90461
  constructor(options) {
90428
90462
  super();
90429
90463
 
@@ -91057,7 +91091,7 @@ let SMTPPool$1 = class SMTPPool extends EventEmitter$d {
91057
91091
  // expose to the world
91058
91092
  var smtpPool = SMTPPool$1;
91059
91093
 
91060
- const EventEmitter$c = require$$0$8;
91094
+ const EventEmitter$d = require$$0$8;
91061
91095
  const SMTPConnection = smtpConnection;
91062
91096
  const wellKnown = wellKnown$2;
91063
91097
  const shared$5 = sharedExports;
@@ -91070,7 +91104,7 @@ const packageData$5 = require$$9;
91070
91104
  * @constructor
91071
91105
  * @param {Object} options Connection options
91072
91106
  */
91073
- let SMTPTransport$1 = class SMTPTransport extends EventEmitter$c {
91107
+ let SMTPTransport$1 = class SMTPTransport extends EventEmitter$d {
91074
91108
  constructor(options) {
91075
91109
  super();
91076
91110
 
@@ -91896,7 +91930,7 @@ let JSONTransport$1 = class JSONTransport {
91896
91930
 
91897
91931
  var jsonTransport = JSONTransport$1;
91898
91932
 
91899
- const EventEmitter$b = require$$0$8;
91933
+ const EventEmitter$c = require$$0$8;
91900
91934
  const packageData$1 = require$$9;
91901
91935
  const shared$1 = sharedExports;
91902
91936
  const LeWindows = leWindows;
@@ -91912,7 +91946,7 @@ const LeWindows = leWindows;
91912
91946
  * @constructor
91913
91947
  * @param {Object} optional config parameter
91914
91948
  */
91915
- let SESTransport$1 = class SESTransport extends EventEmitter$b {
91949
+ let SESTransport$1 = class SESTransport extends EventEmitter$c {
91916
91950
  constructor(options) {
91917
91951
  super();
91918
91952
  options = options || {};
@@ -179412,7 +179446,7 @@ function requireRecipes () {
179412
179446
 
179413
179447
  /*jshint node:true*/
179414
179448
  var util$F = require$$1$1;
179415
- var EventEmitter$a = require$$0$8.EventEmitter;
179449
+ var EventEmitter$b = require$$0$8.EventEmitter;
179416
179450
 
179417
179451
  var utils$4 = utilsExports;
179418
179452
 
@@ -179442,7 +179476,7 @@ function FfmpegCommand(input, options) {
179442
179476
  return new FfmpegCommand(input, options);
179443
179477
  }
179444
179478
 
179445
- EventEmitter$a.call(this);
179479
+ EventEmitter$b.call(this);
179446
179480
 
179447
179481
  if (typeof input === 'object' && !('readable' in input)) {
179448
179482
  // Options object passed directly
@@ -179485,7 +179519,7 @@ function FfmpegCommand(input, options) {
179485
179519
  error: function() {}
179486
179520
  };
179487
179521
  }
179488
- util$F.inherits(FfmpegCommand, EventEmitter$a);
179522
+ util$F.inherits(FfmpegCommand, EventEmitter$b);
179489
179523
  var fluentFfmpeg$1 = FfmpegCommand;
179490
179524
 
179491
179525
 
@@ -187500,6 +187534,20 @@ const createXmlEvents = (items, sourceType) => {
187500
187534
  }
187501
187535
  return result;
187502
187536
  };
187537
+ const parseXmlMetadata = async (jObj, files) => {
187538
+ const parsedMeta = await parseMeta(files);
187539
+ return {
187540
+ user_name: parsedMeta.username,
187541
+ room_id: parsedMeta.roomId,
187542
+ room_title: parsedMeta.title,
187543
+ video_start_time: parsedMeta.startTimestamp === null ? null : parsedMeta.startTimestamp * 1000,
187544
+ platform: parsedMeta.platform,
187545
+ BililiveRecorderVersion: jObj.i?.BililiveRecorder?.["@_version"] ??
187546
+ jObj.i?.BililiveRecorder?.version ??
187547
+ jObj.i?.BililiveRecorderVersion ??
187548
+ jObj.i?.metadata?.BililiveRecorderVersion,
187549
+ };
187550
+ };
187503
187551
  /**
187504
187552
  * 生成经过自定义处理后的xml文件
187505
187553
  * @param input
@@ -187509,6 +187557,7 @@ const createXmlEvents = (items, sourceType) => {
187509
187557
  */
187510
187558
  const genProcessedXml = async (input, output, filterFunction) => {
187511
187559
  const { jObj, danmuku, sc, guard, gift } = await parseXmlFile(input, true);
187560
+ const metadata = await parseXmlMetadata(jObj, { danmaFilePath: input });
187512
187561
  const events = [
187513
187562
  ...createXmlEvents(danmuku, "danmu"),
187514
187563
  ...createXmlEvents(sc, "sc"),
@@ -187516,7 +187565,7 @@ const genProcessedXml = async (input, output, filterFunction) => {
187516
187565
  ...createXmlEvents(gift, "gift"),
187517
187566
  ];
187518
187567
  const processedBuckets = processXmlItems(events, filterFunction);
187519
- const xmlData = generateMergedXmlContent(processedBuckets.danmu, processedBuckets.gift, processedBuckets.sc, processedBuckets.guard, jObj.i?.metadata || {});
187568
+ const xmlData = generateMergedXmlContent(processedBuckets.danmu, processedBuckets.gift, processedBuckets.sc, processedBuckets.guard, metadata);
187520
187569
  await fs$m.writeFile(output, xmlData);
187521
187570
  return output;
187522
187571
  };
@@ -187708,25 +187757,35 @@ function processDanmuOffset(items, videoDuration, startOffset, isP = false) {
187708
187757
  return newItem;
187709
187758
  });
187710
187759
  }
187760
+ // 与录制文件一致的内嵌 XSL 样式,按原始 XML 写入,避免被转义。
187761
+ const RECORDER_XML_STYLE = `<z:stylesheet version="1.0" id="s" xml:id="s" xmlns:z="http://www.w3.org/1999/XSL/Transform"><z:output method="html"/><z:template match="/"><html><meta name="viewport" content="width=device-width"/><title>弹幕文件 <z:value-of select="/i/metadata/user_name/text()"/></title><style>body{margin:0}h1,h2,p,table{margin-left:5px}table{border-spacing:0}td,th{border:1px solid grey;padding:1px 5px}th{position:sticky;top:0;background:#4098de}tr:hover{background:#d9f4ff}div{overflow:auto;max-height:80vh;max-width:100vw;width:fit-content}</style><h1>弹幕XML文件</h1><p>本文件不支持在 IE 浏览器里预览,请使用 Chrome Firefox Edge 等浏览器。</p><p>文件用法参考文档 <a href="https://rec.danmuji.org/user/danmaku/">https://rec.danmuji.org/user/danmaku/</a></p><table><tr><td>房间号</td><td><z:value-of select="/i/metadata/room_id/text()"/></td></tr><tr><td>主播名</td><td><z:value-of select="/i/metadata/user_name/text()"/></td></tr><tr><td><a href="#d">弹幕</a></td><td>共<z:value-of select="count(/i/d)"/>条记录</td></tr><tr><td><a href="#guard">上船</a></td><td>共<z:value-of select="count(/i/guard)"/>条记录</td></tr><tr><td><a href="#sc">SC</a></td><td>共<z:value-of select="count(/i/sc)"/>条记录</td></tr><tr><td><a href="#gift">礼物</a></td><td>共<z:value-of select="count(/i/gift)"/>条记录</td></tr></table><h2 id="d">弹幕</h2><div id="dm"><table><tr><th>用户名</th><th>出现时间</th><th>用户ID</th><th>弹幕</th><th>参数</th></tr><z:for-each select="/i/d"><tr><td><z:value-of select="@user"/></td><td></td><td></td><td><z:value-of select="."/></td><td><z:value-of select="@p"/></td></tr></z:for-each></table></div><script>Array.from(document.querySelectorAll('#dm tr')).slice(1).map(t=>t.querySelectorAll('td')).forEach(t=>{let p=t[4].textContent.split(','),a=p[0];t[1].textContent=\`\u0024{(Math.floor(a/60/60)+'').padStart(2,0)}:\u0024{(Math.floor(a/60%60)+'').padStart(2,0)}:\u0024{(a%60).toFixed(3).padStart(6,0)}\`;t[2].innerHTML=\`&lt;a target=_blank rel="nofollow noreferrer" "&gt;\u0024{p[6]}&lt;/a&gt;\`})</script><h2 id="guard">舰长购买</h2><div><table><tr><th>用户名</th><th>用户ID</th><th>舰长等级</th><th>购买数量</th><th>出现时间</th></tr><z:for-each select="/i/guard"><tr><td><z:value-of select="@user"/></td><td><a rel="nofollow noreferrer"><z:attribute name="href"><z:text></z:text><z:value-of select="@uid" /></z:attribute><z:value-of select="@uid"/></a></td><td><z:value-of select="@level"/></td><td><z:value-of select="@count"/></td><td><z:value-of select="@ts"/></td></tr></z:for-each></table></div><h2 id="sc">SuperChat 醒目留言</h2><div><table><tr><th>用户名</th><th>用户ID</th><th>内容</th><th>显示时长</th><th>价格</th><th>出现时间</th></tr><z:for-each select="/i/sc"><tr><td><z:value-of select="@user"/></td><td><a rel="nofollow noreferrer"><z:attribute name="href"><z:text></z:text><z:value-of select="@uid" /></z:attribute><z:value-of select="@uid"/></a></td><td><z:value-of select="."/></td><td><z:value-of select="@time"/></td><td><z:value-of select="@price"/></td><td><z:value-of select="@ts"/></td></tr></z:for-each></table></div><h2 id="gift">礼物</h2><div><table><tr><th>用户名</th><th>用户ID</th><th>礼物名</th><th>礼物数量</th><th>出现时间</th></tr><z:for-each select="/i/gift"><tr><td><z:value-of select="@user"/></td><td><span rel="nofollow noreferrer"><z:attribute name="href"></z:attribute><z:value-of select="@uid"/></span></td><td><z:value-of select="@giftname"/></td><td><z:value-of select="@giftcount"/></td><td><z:value-of select="@ts"/></td></tr></z:for-each></table></div></html></z:template></z:stylesheet>`;
187711
187762
  /**
187712
187763
  * 生成合并后的XML内容(纯函数)
187713
187764
  */
187714
187765
  function generateMergedXmlContent(mergedDanmuku, mergedGift, mergedSc, mergedGuard, metadata = null) {
187766
+ const styleTag = metadata?.BililiveRecorderVersion
187767
+ ? "BililiveRecorderXmlStyle"
187768
+ : "RecorderXmlStyle";
187715
187769
  const builder = new Builder({
187716
187770
  ignoreAttributes: false,
187717
187771
  attributeNamePrefix: "@_",
187718
187772
  format: true,
187773
+ stopNodes: [`i.${styleTag}`],
187719
187774
  });
187775
+ const BililiveRecorderVersion = metadata?.BililiveRecorderVersion || undefined;
187776
+ delete metadata?.BililiveRecorderVersion;
187720
187777
  const xmlContent = builder.build({
187721
187778
  i: {
187722
187779
  metadata,
187780
+ BililiveRecorderVersion: BililiveRecorderVersion,
187781
+ [styleTag]: RECORDER_XML_STYLE,
187723
187782
  d: mergedDanmuku,
187724
187783
  gift: mergedGift,
187725
187784
  sc: mergedSc,
187726
187785
  guard: mergedGuard,
187727
187786
  },
187728
187787
  });
187729
- return `<?xml version="1.0" encoding="utf-8"?>\n${xmlContent}`;
187788
+ return `<?xml version="1.0" encoding="utf-8"?>\n<?xml-stylesheet type="text/xsl" href="#s"?>\n${xmlContent}`;
187730
187789
  }
187731
187790
  /**
187732
187791
  * 根据视频合并xml弹幕
@@ -187761,11 +187820,15 @@ const mergeXml = async (inputFiles, options = {}) => {
187761
187820
  }
187762
187821
  // 解析XML文件
187763
187822
  const { jObj, danmuku, sc, guard, gift } = await parseXmlFile(file.danmakuPath, true);
187823
+ const metadata = await parseXmlMetadata(jObj, {
187824
+ videoFilePath: file.videoPath,
187825
+ danmaFilePath: file.danmakuPath,
187826
+ });
187764
187827
  videoData.push({
187765
187828
  path: file.danmakuPath,
187766
187829
  videoDuration: duration,
187767
187830
  startOffset: cumulativeDuration,
187768
- meta: jObj.i?.metadata || {},
187831
+ meta: metadata,
187769
187832
  danmuku: danmuku || [],
187770
187833
  sc: sc || [],
187771
187834
  guard: guard || [],
@@ -187778,7 +187841,6 @@ const mergeXml = async (inputFiles, options = {}) => {
187778
187841
  const mergedSc = [];
187779
187842
  const mergedGuard = [];
187780
187843
  const mergedGift = [];
187781
- // TODO: 测试录播姬的,可能存在问题,比如礼物某些解析
187782
187844
  const metadata = options.saveMeta ? videoData[0]?.meta : null;
187783
187845
  for (const data of videoData) {
187784
187846
  // 处理各类型弹幕并添加到对应数组
@@ -188156,8 +188218,8 @@ const matchUser = (str) => {
188156
188218
  const bililiveRecorderVideoRegex = /主播名: (.+)/;
188157
188219
  const oneLiveRecVideoRegex = /user_name: (.+)/;
188158
188220
  const regexes = [
188159
- bililiveRecorderRegex,
188160
188221
  blrecRegex,
188222
+ bililiveRecorderRegex,
188161
188223
  bililiveRecorderVideoRegex,
188162
188224
  oneLiveRecVideoRegex,
188163
188225
  ];
@@ -188175,8 +188237,8 @@ const matchUser = (str) => {
188175
188237
  */
188176
188238
  const matchPlatform = (str) => {
188177
188239
  // 录播姬参数
188178
- if (str.includes("mikufans录播姬")) {
188179
- return "bilibili";
188240
+ if (str.includes("<BililiveRecorderRecordInfo")) {
188241
+ return "Bilibili";
188180
188242
  }
188181
188243
  // biliLive-tools
188182
188244
  const match = str.match(/<platform>(.+?)<\/platform>/);
@@ -188855,7 +188917,7 @@ const burn = async (files, output, options) => {
188855
188917
  throw new Error("视频编码不能为copy");
188856
188918
  }
188857
188919
  const { videoFilePath, subtitleFilePath } = files;
188858
- let assFilePath = subtitleFilePath;
188920
+ let assFilePath = options.ignoreDanmu ? undefined : subtitleFilePath;
188859
188921
  let hotProgressInput = undefined;
188860
188922
  let startTimestamp = 0;
188861
188923
  let timestampFont = undefined;
@@ -188868,30 +188930,32 @@ const burn = async (files, output, options) => {
188868
188930
  const duration = videoMeta.format.duration;
188869
188931
  // 弹幕转换
188870
188932
  if (subtitleFilePath.endsWith(".xml")) {
188871
- if (await isEmptyDanmu(subtitleFilePath)) {
188872
- throw new Error("弹幕文件为空,无需压制");
188873
- }
188874
- const name = uuid$4();
188875
- const danmaOptions = options.danmaOptions;
188876
- // 开启跟随视频分辨率
188877
- if (danmaOptions.resolutionResponsive && width && height) {
188878
- danmaOptions.resolution[0] = width;
188879
- danmaOptions.resolution[1] = height;
188880
- }
188881
- const task = await convertXml2Ass({
188882
- input: subtitleFilePath,
188883
- output: name,
188884
- }, options.danmaOptions, {
188885
- saveRadio: 2,
188886
- savePath: getTempPath(),
188887
- removeOrigin: removeOrigin,
188888
- });
188889
- logObj.debug("convertXml2Ass task start", task.taskId);
188890
- await promiseTask(task);
188891
- logObj.debug("convertXml2Ass task end", task.taskId);
188892
- assFilePath = task.output;
188933
+ if (!options.ignoreDanmu) {
188934
+ if (await isEmptyDanmu(subtitleFilePath)) {
188935
+ throw new Error("弹幕文件为空,无需压制");
188936
+ }
188937
+ const name = uuid$4();
188938
+ const danmaOptions = options.danmaOptions;
188939
+ // 开启跟随视频分辨率
188940
+ if (danmaOptions.resolutionResponsive && width && height) {
188941
+ danmaOptions.resolution[0] = width;
188942
+ danmaOptions.resolution[1] = height;
188943
+ }
188944
+ const task = await convertXml2Ass({
188945
+ input: subtitleFilePath,
188946
+ output: name,
188947
+ }, options.danmaOptions, {
188948
+ saveRadio: 2,
188949
+ savePath: getTempPath(),
188950
+ removeOrigin: removeOrigin,
188951
+ });
188952
+ logObj.debug("convertXml2Ass task start", task.taskId);
188953
+ await promiseTask(task);
188954
+ logObj.debug("convertXml2Ass task end", task.taskId);
188955
+ assFilePath = task.output;
188956
+ }
188893
188957
  if (options.ffmpegOptions.addTimestamp) {
188894
- startTimestamp = await readXmlTimestamp(files.subtitleFilePath);
188958
+ startTimestamp = await readXmlTimestamp(subtitleFilePath);
188895
188959
  logObj.debug("readXmlTimestamp end", startTimestamp);
188896
188960
  }
188897
188961
  if (options.ffmpegOptions.timestampFollowDanmu) {
@@ -188899,9 +188963,9 @@ const burn = async (files, output, options) => {
188899
188963
  }
188900
188964
  }
188901
188965
  // 高能进度条转换
188902
- if (hasHotProgress) {
188966
+ if (hasHotProgress && !options.ignoreDanmu) {
188903
188967
  const hotProgressOptions = options.hotProgressOptions;
188904
- const task = await genHotProgress(files.subtitleFilePath, {
188968
+ const task = await genHotProgress(subtitleFilePath, {
188905
188969
  ...hotProgressOptions,
188906
188970
  width,
188907
188971
  duration,
@@ -189432,21 +189496,39 @@ async function preFormatOptions(options, filePath) {
189432
189496
  const needParseForSource = options.copyright === 2 && !options.source;
189433
189497
  const needParseForPartTitle = hasTemplateVariable(options.partTitleTemplate);
189434
189498
  const needParseForDesc = hasTemplateVariable(options.desc);
189435
- if (!needParseForTitle && !needParseForSource && !needParseForPartTitle && !needParseForDesc) {
189499
+ const needParseForSeasonTitle = !!options.seasonId &&
189500
+ hasTemplateVariable(options.seasonTitleTemplate) &&
189501
+ options.seasonTitleTemplate?.trim() !== "{{mediaTitle}}";
189502
+ const resultOptions = { ...options };
189503
+ const formatSeasonOptions = (context) => {
189504
+ if (options.seasonId) {
189505
+ resultOptions.seasonTitleTemplate = formatSeasonTitle({
189506
+ filename: path$z.parse(normalizedFiles[0].path).name,
189507
+ ...context,
189508
+ mediaTitle: resultOptions.title,
189509
+ }, options.seasonTitleTemplate);
189510
+ }
189511
+ };
189512
+ if (!needParseForTitle &&
189513
+ !needParseForSource &&
189514
+ !needParseForPartTitle &&
189515
+ !needParseForDesc &&
189516
+ !needParseForSeasonTitle) {
189517
+ formatSeasonOptions();
189436
189518
  // 不需要解析,直接返回
189437
189519
  return {
189438
- options,
189520
+ options: resultOptions,
189439
189521
  videos: normalizedFiles.map((item) => ({
189440
189522
  path: item.path,
189441
189523
  title: item.title,
189442
189524
  })),
189443
189525
  };
189444
189526
  }
189445
- const resultOptions = { ...options };
189446
- if (needParseForTitle || needParseForDesc || needParseForSource) {
189527
+ let firstFormatContext = null;
189528
+ if (needParseForTitle || needParseForDesc || needParseForSource || needParseForSeasonTitle) {
189447
189529
  const firstFile = normalizedFiles[0];
189448
189530
  const firstMeta = await resolveUploadFileMeta(firstFile, "解析视频文件信息失败");
189449
- const firstFormatContext = getUploadFormatContext(firstMeta, firstFile.path);
189531
+ firstFormatContext = getUploadFormatContext(firstMeta, firstFile.path);
189450
189532
  // 格式化主标题
189451
189533
  if (needParseForTitle && firstFormatContext) {
189452
189534
  resultOptions.title = formatTitle(firstFormatContext, options.title);
@@ -189472,6 +189554,7 @@ async function preFormatOptions(options, filePath) {
189472
189554
  }
189473
189555
  }
189474
189556
  }
189557
+ formatSeasonOptions(firstFormatContext);
189475
189558
  // 格式化分P标题
189476
189559
  const videos = [];
189477
189560
  if (needParseForPartTitle) {
@@ -189526,13 +189609,16 @@ async function addMedia(filePath, options, uid, extraOptions) {
189526
189609
  sectionId = (await client.platform.getSeasonDetail(formattedOptions.seasonId))
189527
189610
  .sections.sections[0].id;
189528
189611
  }
189612
+ if (!sectionId) {
189613
+ throw new Error("无法获取合集分区ID");
189614
+ }
189529
189615
  client.platform.addMedia2Season({
189530
189616
  sectionId: sectionId,
189531
189617
  episodes: [
189532
189618
  {
189533
189619
  aid: data.aid,
189534
189620
  cid: cid,
189535
- title: formattedOptions.title,
189621
+ title: formattedOptions.seasonTitleTemplate || formattedOptions.title,
189536
189622
  },
189537
189623
  ],
189538
189624
  });
@@ -191878,7 +191964,7 @@ const handleRestartTask = (taskId) => {
191878
191964
 
191879
191965
  let ntsuspend;
191880
191966
  function getNtSuspend() {
191881
- ntsuspend ??= node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-Bqpkb00O.cjs', document.baseURI).href)))("ntsuspend");
191967
+ ntsuspend ??= node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-CWkwaDmT.cjs', document.baseURI).href)))("ntsuspend");
191882
191968
  return ntsuspend;
191883
191969
  }
191884
191970
  class DanmuTask extends AbstractTask {
@@ -192635,7 +192721,7 @@ class BiliEditVideoTask extends BiliVideoTask {
192635
192721
  class BiliDownloadVideoTask extends AbstractTask {
192636
192722
  command;
192637
192723
  type = TaskType.biliDownload;
192638
- emitter = new EventEmitter$k();
192724
+ emitter = new EventEmitter$l();
192639
192725
  constructor(command, options, callback) {
192640
192726
  super();
192641
192727
  this.command = command;
@@ -194638,6 +194724,7 @@ async function getBiliStatusInfoByRoomIds(RoomIds) {
194638
194724
  */
194639
194725
  const METADATA_PLACEHOLDER = "<!--METADATA_PLACEHOLDER-->";
194640
194726
  const XML_FILE_HEADER = `<?xml version="1.0" encoding="utf-8"?>\n<?xml-stylesheet type="text/xsl" href="#s"?>\n<i>\n${METADATA_PLACEHOLDER}\n<RecorderXmlStyle><z:stylesheet version="1.0" id="s" xml:id="s" xmlns:z="http://www.w3.org/1999/XSL/Transform"><z:output method="html"/><z:template match="/"><html><meta name="viewport" content="width=device-width"/><title>弹幕文件 <z:value-of select="/i/metadata/user_name/text()"/></title><style>body{margin:0}h1,h2,p,table{margin-left:5px}table{border-spacing:0}td,th{border:1px solid grey;padding:1px 5px}th{position:sticky;top:0;background:#4098de}tr:hover{background:#d9f4ff}div{overflow:auto;max-height:80vh;max-width:100vw;width:fit-content}</style><h1>弹幕XML文件</h1><p>本文件不支持在 IE 浏览器里预览,请使用 Chrome Firefox Edge 等浏览器。</p><p>文件用法参考文档 <a href="https://rec.danmuji.org/user/danmaku/">https://rec.danmuji.org/user/danmaku/</a></p><table><tr><td>房间号</td><td><z:value-of select="/i/metadata/room_id/text()"/></td></tr><tr><td>主播名</td><td><z:value-of select="/i/metadata/user_name/text()"/></td></tr><tr><td><a href="#d">弹幕</a></td><td>共<z:value-of select="count(/i/d)"/>条记录</td></tr><tr><td><a href="#guard">上船</a></td><td>共<z:value-of select="count(/i/guard)"/>条记录</td></tr><tr><td><a href="#sc">SC</a></td><td>共<z:value-of select="count(/i/sc)"/>条记录</td></tr><tr><td><a href="#gift">礼物</a></td><td>共<z:value-of select="count(/i/gift)"/>条记录</td></tr></table><h2 id="d">弹幕</h2><div id="dm"><table><tr><th>用户名</th><th>出现时间</th><th>用户ID</th><th>弹幕</th><th>参数</th></tr><z:for-each select="/i/d"><tr><td><z:value-of select="@user"/></td><td></td><td></td><td><z:value-of select="."/></td><td><z:value-of select="@p"/></td></tr></z:for-each></table></div><script>Array.from(document.querySelectorAll('#dm tr')).slice(1).map(t=>t.querySelectorAll('td')).forEach(t=>{let p=t[4].textContent.split(','),a=p[0];t[1].textContent=\`\u0024{(Math.floor(a/60/60)+'').padStart(2,0)}:\u0024{(Math.floor(a/60%60)+'').padStart(2,0)}:\u0024{(a%60).toFixed(3).padStart(6,0)}\`;t[2].innerHTML=\`&lt;a target=_blank rel="nofollow noreferrer" "&gt;\u0024{p[6]}&lt;/a&gt;\`})</script><h2 id="guard">舰长购买</h2><div><table><tr><th>用户名</th><th>用户ID</th><th>舰长等级</th><th>购买数量</th><th>出现时间</th></tr><z:for-each select="/i/guard"><tr><td><z:value-of select="@user"/></td><td><a rel="nofollow noreferrer"><z:attribute name="href"><z:text></z:text><z:value-of select="@uid" /></z:attribute><z:value-of select="@uid"/></a></td><td><z:value-of select="@level"/></td><td><z:value-of select="@count"/></td><td><z:value-of select="@ts"/></td></tr></z:for-each></table></div><h2 id="sc">SuperChat 醒目留言</h2><div><table><tr><th>用户名</th><th>用户ID</th><th>内容</th><th>显示时长</th><th>价格</th><th>出现时间</th></tr><z:for-each select="/i/sc"><tr><td><z:value-of select="@user"/></td><td><a rel="nofollow noreferrer"><z:attribute name="href"><z:text></z:text><z:value-of select="@uid" /></z:attribute><z:value-of select="@uid"/></a></td><td><z:value-of select="."/></td><td><z:value-of select="@time"/></td><td><z:value-of select="@price"/></td><td><z:value-of select="@ts"/></td></tr></z:for-each></table></div><h2 id="gift">礼物</h2><div><table><tr><th>用户名</th><th>用户ID</th><th>礼物名</th><th>礼物数量</th><th>出现时间</th></tr><z:for-each select="/i/gift"><tr><td><z:value-of select="@user"/></td><td><span rel="nofollow noreferrer"><z:attribute name="href"></z:attribute><z:value-of select="@uid"/></span></td><td><z:value-of select="@giftname"/></td><td><z:value-of select="@giftcount"/></td><td><z:value-of select="@ts"/></td></tr></z:for-each></table></div></html></z:template></z:stylesheet></RecorderXmlStyle>\n`;
194727
+ const DANMA_STATS_INTERVAL = 10;
194641
194728
  function createRecordExtraDataController(savePath) {
194642
194729
  const data = {
194643
194730
  header: XML_FILE_HEADER,
@@ -194651,13 +194738,42 @@ function createRecordExtraDataController(savePath) {
194651
194738
  let danmaNum = 0;
194652
194739
  let scNum = 0;
194653
194740
  let guardNum = 0;
194741
+ let maxDanmaBucketStart = -1;
194654
194742
  const interactedUsers = new Set();
194743
+ const danmaBucketCountMap = new Map();
194744
+ const getDanmaStats = () => {
194745
+ if (maxDanmaBucketStart < 0) {
194746
+ return {
194747
+ danmaTimeline: {
194748
+ interval: DANMA_STATS_INTERVAL,
194749
+ data: [],
194750
+ },
194751
+ };
194752
+ }
194753
+ const stats = [];
194754
+ for (let start = 0; start <= maxDanmaBucketStart; start += DANMA_STATS_INTERVAL) {
194755
+ stats.push(danmaBucketCountMap.get(start) ?? 0);
194756
+ }
194757
+ return {
194758
+ danmaTimeline: {
194759
+ interval: DANMA_STATS_INTERVAL,
194760
+ data: stats,
194761
+ },
194762
+ };
194763
+ };
194655
194764
  const getStats = () => ({
194656
194765
  danmaNum,
194657
194766
  uniqMember: interactedUsers.size,
194658
194767
  scNum,
194659
194768
  guardNum,
194769
+ danmaStats: getDanmaStats(),
194660
194770
  });
194771
+ const trackDanmaBucket = (message) => {
194772
+ const progressInSeconds = Math.max((message.timestamp - data.meta.recordStartTimestamp) / 1000, 0);
194773
+ const bucketStart = Math.floor(progressInSeconds / DANMA_STATS_INTERVAL) * DANMA_STATS_INTERVAL;
194774
+ danmaBucketCountMap.set(bucketStart, (danmaBucketCountMap.get(bucketStart) ?? 0) + 1);
194775
+ maxDanmaBucketStart = Math.max(maxDanmaBucketStart, bucketStart);
194776
+ };
194661
194777
  const trackInteractedUser = (message) => {
194662
194778
  const userName = message.sender?.name?.trim();
194663
194779
  if (!userName)
@@ -194699,6 +194815,7 @@ function createRecordExtraDataController(savePath) {
194699
194815
  return;
194700
194816
  if (message.type === "comment") {
194701
194817
  danmaNum += 1;
194818
+ trackDanmaBucket(message);
194702
194819
  }
194703
194820
  else if (message.type === "super_chat") {
194704
194821
  scNum += 1;
@@ -194869,7 +194986,7 @@ function generateMetadataXml(metadata) {
194869
194986
  });
194870
194987
  }
194871
194988
 
194872
- class Segment extends EventEmitter$k {
194989
+ class Segment extends EventEmitter$l {
194873
194990
  extraDataController = null;
194874
194991
  init = true;
194875
194992
  getSavePath;
@@ -194988,7 +195105,7 @@ class Segment extends EventEmitter$k {
194988
195105
  return `${this.outputVideoFilePath}.${this.videoExt}`;
194989
195106
  }
194990
195107
  }
194991
- class StreamManager extends EventEmitter$k {
195108
+ class StreamManager extends EventEmitter$l {
194992
195109
  segment = null;
194993
195110
  extraDataController = null;
194994
195111
  recordSavePath;
@@ -195660,7 +195777,7 @@ function genSavePathFromRule(manager, recorder, extData) {
195660
195777
  return formatTemplate(savePathRule, params);
195661
195778
  }
195662
195779
 
195663
- class MesioCommand extends EventEmitter$k {
195780
+ class MesioCommand extends EventEmitter$l {
195664
195781
  _input = "";
195665
195782
  _output = "";
195666
195783
  _inputOptions = [];
@@ -195742,7 +195859,7 @@ class MesioCommand extends EventEmitter$k {
195742
195859
  const createMesioBuilder = () => {
195743
195860
  return new MesioCommand();
195744
195861
  };
195745
- class mesioDownloader extends EventEmitter$k {
195862
+ class mesioDownloader extends EventEmitter$l {
195746
195863
  onEnd;
195747
195864
  onUpdateLiveInfo;
195748
195865
  type = "mesio";
@@ -195884,7 +196001,7 @@ class mesioDownloader extends EventEmitter$k {
195884
196001
  }
195885
196002
 
195886
196003
  // Bililive command builder class similar to ffmpeg
195887
- class BililiveRecorderCommand extends EventEmitter$k {
196004
+ class BililiveRecorderCommand extends EventEmitter$l {
195888
196005
  _input = "";
195889
196006
  _output = "";
195890
196007
  _inputOptions = [];
@@ -195975,7 +196092,7 @@ class BililiveRecorderCommand extends EventEmitter$k {
195975
196092
  const createBililiveBuilder = () => {
195976
196093
  return new BililiveRecorderCommand();
195977
196094
  };
195978
- class BililiveDownloader extends EventEmitter$k {
196095
+ class BililiveDownloader extends EventEmitter$l {
195979
196096
  onEnd;
195980
196097
  onUpdateLiveInfo;
195981
196098
  type = "bililive";
@@ -196191,7 +196308,7 @@ function createDownloader(type, opts, onEnd, onUpdateLiveInfo) {
196191
196308
  return createBaseDownloader(recorderType, { ...opts, formatName: sourceFormatName }, onEnd, onUpdateLiveInfo);
196192
196309
  }
196193
196310
 
196194
- class FFmpegDownloader extends EventEmitter$k {
196311
+ class FFmpegDownloader extends EventEmitter$l {
196195
196312
  onEnd;
196196
196313
  onUpdateLiveInfo;
196197
196314
  type = "ffmpeg";
@@ -197751,7 +197868,7 @@ const { IncomingMessage: IncomingMessage$3 } = http$f;
197751
197868
  const stream$3 = require$$0$b;
197752
197869
  const net$7 = require$$1$7;
197753
197870
  const { stringify } = require$$5;
197754
- const { EventEmitter: EE, addAbortListener: addAbortListenerNative } = EventEmitter$k;
197871
+ const { EventEmitter: EE, addAbortListener: addAbortListenerNative } = EventEmitter$l;
197755
197872
  const timers$1 = timers$2;
197756
197873
  const { InvalidArgumentError: InvalidArgumentError$y, ConnectTimeoutError: ConnectTimeoutError$2 } = errors$1;
197757
197874
  const { headerNameLowerCasedRecord: headerNameLowerCasedRecord$1 } = constants$g;
@@ -199556,9 +199673,9 @@ function processHeader (request, key, val) {
199556
199673
 
199557
199674
  var request$3 = Request$3;
199558
199675
 
199559
- const EventEmitter$9 = EventEmitter$k;
199676
+ const EventEmitter$a = EventEmitter$l;
199560
199677
 
199561
- let Dispatcher$4 = class Dispatcher extends EventEmitter$9 {
199678
+ let Dispatcher$4 = class Dispatcher extends EventEmitter$a {
199562
199679
  dispatch () {
199563
199680
  throw new Error('not implemented')
199564
199681
  }
@@ -210951,7 +211068,7 @@ var socks5Utils = {
210951
211068
  createReplyError
210952
211069
  };
210953
211070
 
210954
- const { EventEmitter: EventEmitter$8 } = EventEmitter$k;
211071
+ const { EventEmitter: EventEmitter$9 } = EventEmitter$l;
210955
211072
  const { Buffer: Buffer$8 } = require$$0$h;
210956
211073
  const { InvalidArgumentError: InvalidArgumentError$m, Socks5ProxyError } = errors$1;
210957
211074
  const { debuglog: debuglog$1 } = require$$3$1;
@@ -211014,7 +211131,7 @@ const STATES$1 = {
211014
211131
  * SOCKS5 client implementation
211015
211132
  * Handles SOCKS5 protocol negotiation and connection establishment
211016
211133
  */
211017
- let Socks5Client$1 = class Socks5Client extends EventEmitter$8 {
211134
+ let Socks5Client$1 = class Socks5Client extends EventEmitter$9 {
211018
211135
  constructor (socket, options = {}) {
211019
211136
  super();
211020
211137
 
@@ -212621,7 +212738,7 @@ var api = {};
212621
212738
  var apiRequest = {exports: {}};
212622
212739
 
212623
212740
  const assert$h = require$$0$g;
212624
- const { addAbortListener: addAbortListener$1 } = EventEmitter$k;
212741
+ const { addAbortListener: addAbortListener$1 } = EventEmitter$l;
212625
212742
  const { Readable: Readable$4 } = require$$0$b;
212626
212743
  const { RequestAbortedError: RequestAbortedError$5, NotSupportedError, InvalidArgumentError: InvalidArgumentError$i, AbortError: AbortError$2 } = errors$1;
212627
212744
  const util$t = util$E;
@@ -219635,7 +219752,7 @@ function isValidDate$1 (date) {
219635
219752
  var cacheHandler = CacheHandler$1;
219636
219753
 
219637
219754
  const { Writable: Writable$4 } = require$$0$b;
219638
- const { EventEmitter: EventEmitter$7 } = EventEmitter$k;
219755
+ const { EventEmitter: EventEmitter$8 } = EventEmitter$l;
219639
219756
  const { assertCacheKey: assertCacheKey$1, assertCacheValue: assertCacheValue$1 } = cache$3;
219640
219757
 
219641
219758
  /**
@@ -219649,7 +219766,7 @@ const { assertCacheKey: assertCacheKey$1, assertCacheValue: assertCacheValue$1 }
219649
219766
  * @implements {CacheStore}
219650
219767
  * @extends {EventEmitter}
219651
219768
  */
219652
- let MemoryCacheStore$1 = class MemoryCacheStore extends EventEmitter$7 {
219769
+ let MemoryCacheStore$1 = class MemoryCacheStore extends EventEmitter$8 {
219653
219770
  #maxCount = 1024
219654
219771
  #maxSize = 104857600 // 100MB
219655
219772
  #maxEntrySize = 5242880 // 5MB
@@ -223225,7 +223342,7 @@ function requireRequest () {
223225
223342
  const { URLSerializer } = requireDataUrl();
223226
223343
  const { kConstruct } = requireSymbols();
223227
223344
  const assert = require$$0$g;
223228
- const { getMaxListeners, setMaxListeners, defaultMaxListeners } = EventEmitter$k;
223345
+ const { getMaxListeners, setMaxListeners, defaultMaxListeners } = EventEmitter$l;
223229
223346
 
223230
223347
  const kAbortController = Symbol('abortController');
223231
223348
 
@@ -224721,7 +224838,7 @@ function requireFetch () {
224721
224838
  requestBodyHeader,
224722
224839
  subresourceSet
224723
224840
  } = requireConstants$2();
224724
- const EE = EventEmitter$k;
224841
+ const EE = EventEmitter$l;
224725
224842
  const { Readable, pipeline, finished, isErrored, isReadable } = require$$0$b;
224726
224843
  const { addAbortListener, bufferToLowerCasedHeaderName } = util$E;
224727
224844
  const { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = requireDataUrl();
@@ -231872,7 +231989,7 @@ function requireWebsocketstream () {
231872
231989
  if (hasRequiredWebsocketstream) return websocketstream;
231873
231990
  hasRequiredWebsocketstream = 1;
231874
231991
 
231875
- const { addAbortListener } = EventEmitter$k;
231992
+ const { addAbortListener } = EventEmitter$l;
231876
231993
  const { environmentSettingsObject, readableStreamClose } = requireUtil$5();
231877
231994
  const { states, opcodes, sentCloseFrameState } = requireConstants();
231878
231995
  const { webidl } = requireWebidl();
@@ -242115,7 +242232,7 @@ var extension$4 = { format: format$4, parse: parse$6 };
242115
242232
 
242116
242233
  /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex|Readable$", "caughtErrors": "none" }] */
242117
242234
 
242118
- const EventEmitter$6 = require$$0$8;
242235
+ const EventEmitter$7 = require$$0$8;
242119
242236
  const https$7 = require$$1$5;
242120
242237
  const http$8 = require$$1$4;
242121
242238
  const net$3 = require$$4;
@@ -242155,7 +242272,7 @@ const subprotocolRegex$1 = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
242155
242272
  *
242156
242273
  * @extends EventEmitter
242157
242274
  */
242158
- let WebSocket$6 = class WebSocket extends EventEmitter$6 {
242275
+ let WebSocket$6 = class WebSocket extends EventEmitter$7 {
242159
242276
  /**
242160
242277
  * Create a new `WebSocket`.
242161
242278
  *
@@ -246770,16 +246887,16 @@ function fe$1(e, t, i, s, a, r) {
246770
246887
  return pe$1(((n = pe$1(pe$1(t, e), pe$1(s, r))) << (o = a)) | (n >>> (32 - o)), i);
246771
246888
  var n, o;
246772
246889
  }
246773
- function _e$1(e, t, i, s, a, r, n) {
246890
+ function _e(e, t, i, s, a, r, n) {
246774
246891
  return fe$1((t & i) | (~t & s), e, t, a, r, n);
246775
246892
  }
246776
246893
  function me$1(e, t, i, s, a, r, n) {
246777
246894
  return fe$1((t & s) | (i & ~s), e, t, a, r, n);
246778
246895
  }
246779
- function ye$1(e, t, i, s, a, r, n) {
246896
+ function ye(e, t, i, s, a, r, n) {
246780
246897
  return fe$1(t ^ i ^ s, e, t, a, r, n);
246781
246898
  }
246782
- function ve$1(e, t, i, s, a, r, n) {
246899
+ function ve(e, t, i, s, a, r, n) {
246783
246900
  return fe$1(i ^ (t | ~s), e, t, a, r, n);
246784
246901
  }
246785
246902
  function ge$1(e, t) {
@@ -246791,22 +246908,22 @@ function ge$1(e, t) {
246791
246908
  (a = h),
246792
246909
  (r = u),
246793
246910
  (n = l),
246794
- (o = _e$1(o, h, u, l, e[i], 7, -680876936)),
246795
- (l = _e$1(l, o, h, u, e[i + 1], 12, -389564586)),
246796
- (u = _e$1(u, l, o, h, e[i + 2], 17, 606105819)),
246797
- (h = _e$1(h, u, l, o, e[i + 3], 22, -1044525330)),
246798
- (o = _e$1(o, h, u, l, e[i + 4], 7, -176418897)),
246799
- (l = _e$1(l, o, h, u, e[i + 5], 12, 1200080426)),
246800
- (u = _e$1(u, l, o, h, e[i + 6], 17, -1473231341)),
246801
- (h = _e$1(h, u, l, o, e[i + 7], 22, -45705983)),
246802
- (o = _e$1(o, h, u, l, e[i + 8], 7, 1770035416)),
246803
- (l = _e$1(l, o, h, u, e[i + 9], 12, -1958414417)),
246804
- (u = _e$1(u, l, o, h, e[i + 10], 17, -42063)),
246805
- (h = _e$1(h, u, l, o, e[i + 11], 22, -1990404162)),
246806
- (o = _e$1(o, h, u, l, e[i + 12], 7, 1804603682)),
246807
- (l = _e$1(l, o, h, u, e[i + 13], 12, -40341101)),
246808
- (u = _e$1(u, l, o, h, e[i + 14], 17, -1502002290)),
246809
- (o = me$1(o, (h = _e$1(h, u, l, o, e[i + 15], 22, 1236535329)), u, l, e[i + 1], 5, -165796510)),
246911
+ (o = _e(o, h, u, l, e[i], 7, -680876936)),
246912
+ (l = _e(l, o, h, u, e[i + 1], 12, -389564586)),
246913
+ (u = _e(u, l, o, h, e[i + 2], 17, 606105819)),
246914
+ (h = _e(h, u, l, o, e[i + 3], 22, -1044525330)),
246915
+ (o = _e(o, h, u, l, e[i + 4], 7, -176418897)),
246916
+ (l = _e(l, o, h, u, e[i + 5], 12, 1200080426)),
246917
+ (u = _e(u, l, o, h, e[i + 6], 17, -1473231341)),
246918
+ (h = _e(h, u, l, o, e[i + 7], 22, -45705983)),
246919
+ (o = _e(o, h, u, l, e[i + 8], 7, 1770035416)),
246920
+ (l = _e(l, o, h, u, e[i + 9], 12, -1958414417)),
246921
+ (u = _e(u, l, o, h, e[i + 10], 17, -42063)),
246922
+ (h = _e(h, u, l, o, e[i + 11], 22, -1990404162)),
246923
+ (o = _e(o, h, u, l, e[i + 12], 7, 1804603682)),
246924
+ (l = _e(l, o, h, u, e[i + 13], 12, -40341101)),
246925
+ (u = _e(u, l, o, h, e[i + 14], 17, -1502002290)),
246926
+ (o = me$1(o, (h = _e(h, u, l, o, e[i + 15], 22, 1236535329)), u, l, e[i + 1], 5, -165796510)),
246810
246927
  (l = me$1(l, o, h, u, e[i + 6], 9, -1069501632)),
246811
246928
  (u = me$1(u, l, o, h, e[i + 11], 14, 643717713)),
246812
246929
  (h = me$1(h, u, l, o, e[i], 20, -373897302)),
@@ -246821,37 +246938,37 @@ function ge$1(e, t) {
246821
246938
  (o = me$1(o, h, u, l, e[i + 13], 5, -1444681467)),
246822
246939
  (l = me$1(l, o, h, u, e[i + 2], 9, -51403784)),
246823
246940
  (u = me$1(u, l, o, h, e[i + 7], 14, 1735328473)),
246824
- (o = ye$1(o, (h = me$1(h, u, l, o, e[i + 12], 20, -1926607734)), u, l, e[i + 5], 4, -378558)),
246825
- (l = ye$1(l, o, h, u, e[i + 8], 11, -2022574463)),
246826
- (u = ye$1(u, l, o, h, e[i + 11], 16, 1839030562)),
246827
- (h = ye$1(h, u, l, o, e[i + 14], 23, -35309556)),
246828
- (o = ye$1(o, h, u, l, e[i + 1], 4, -1530992060)),
246829
- (l = ye$1(l, o, h, u, e[i + 4], 11, 1272893353)),
246830
- (u = ye$1(u, l, o, h, e[i + 7], 16, -155497632)),
246831
- (h = ye$1(h, u, l, o, e[i + 10], 23, -1094730640)),
246832
- (o = ye$1(o, h, u, l, e[i + 13], 4, 681279174)),
246833
- (l = ye$1(l, o, h, u, e[i], 11, -358537222)),
246834
- (u = ye$1(u, l, o, h, e[i + 3], 16, -722521979)),
246835
- (h = ye$1(h, u, l, o, e[i + 6], 23, 76029189)),
246836
- (o = ye$1(o, h, u, l, e[i + 9], 4, -640364487)),
246837
- (l = ye$1(l, o, h, u, e[i + 12], 11, -421815835)),
246838
- (u = ye$1(u, l, o, h, e[i + 15], 16, 530742520)),
246839
- (o = ve$1(o, (h = ye$1(h, u, l, o, e[i + 2], 23, -995338651)), u, l, e[i], 6, -198630844)),
246840
- (l = ve$1(l, o, h, u, e[i + 7], 10, 1126891415)),
246841
- (u = ve$1(u, l, o, h, e[i + 14], 15, -1416354905)),
246842
- (h = ve$1(h, u, l, o, e[i + 5], 21, -57434055)),
246843
- (o = ve$1(o, h, u, l, e[i + 12], 6, 1700485571)),
246844
- (l = ve$1(l, o, h, u, e[i + 3], 10, -1894986606)),
246845
- (u = ve$1(u, l, o, h, e[i + 10], 15, -1051523)),
246846
- (h = ve$1(h, u, l, o, e[i + 1], 21, -2054922799)),
246847
- (o = ve$1(o, h, u, l, e[i + 8], 6, 1873313359)),
246848
- (l = ve$1(l, o, h, u, e[i + 15], 10, -30611744)),
246849
- (u = ve$1(u, l, o, h, e[i + 6], 15, -1560198380)),
246850
- (h = ve$1(h, u, l, o, e[i + 13], 21, 1309151649)),
246851
- (o = ve$1(o, h, u, l, e[i + 4], 6, -145523070)),
246852
- (l = ve$1(l, o, h, u, e[i + 11], 10, -1120210379)),
246853
- (u = ve$1(u, l, o, h, e[i + 2], 15, 718787259)),
246854
- (h = ve$1(h, u, l, o, e[i + 9], 21, -343485551)),
246941
+ (o = ye(o, (h = me$1(h, u, l, o, e[i + 12], 20, -1926607734)), u, l, e[i + 5], 4, -378558)),
246942
+ (l = ye(l, o, h, u, e[i + 8], 11, -2022574463)),
246943
+ (u = ye(u, l, o, h, e[i + 11], 16, 1839030562)),
246944
+ (h = ye(h, u, l, o, e[i + 14], 23, -35309556)),
246945
+ (o = ye(o, h, u, l, e[i + 1], 4, -1530992060)),
246946
+ (l = ye(l, o, h, u, e[i + 4], 11, 1272893353)),
246947
+ (u = ye(u, l, o, h, e[i + 7], 16, -155497632)),
246948
+ (h = ye(h, u, l, o, e[i + 10], 23, -1094730640)),
246949
+ (o = ye(o, h, u, l, e[i + 13], 4, 681279174)),
246950
+ (l = ye(l, o, h, u, e[i], 11, -358537222)),
246951
+ (u = ye(u, l, o, h, e[i + 3], 16, -722521979)),
246952
+ (h = ye(h, u, l, o, e[i + 6], 23, 76029189)),
246953
+ (o = ye(o, h, u, l, e[i + 9], 4, -640364487)),
246954
+ (l = ye(l, o, h, u, e[i + 12], 11, -421815835)),
246955
+ (u = ye(u, l, o, h, e[i + 15], 16, 530742520)),
246956
+ (o = ve(o, (h = ye(h, u, l, o, e[i + 2], 23, -995338651)), u, l, e[i], 6, -198630844)),
246957
+ (l = ve(l, o, h, u, e[i + 7], 10, 1126891415)),
246958
+ (u = ve(u, l, o, h, e[i + 14], 15, -1416354905)),
246959
+ (h = ve(h, u, l, o, e[i + 5], 21, -57434055)),
246960
+ (o = ve(o, h, u, l, e[i + 12], 6, 1700485571)),
246961
+ (l = ve(l, o, h, u, e[i + 3], 10, -1894986606)),
246962
+ (u = ve(u, l, o, h, e[i + 10], 15, -1051523)),
246963
+ (h = ve(h, u, l, o, e[i + 1], 21, -2054922799)),
246964
+ (o = ve(o, h, u, l, e[i + 8], 6, 1873313359)),
246965
+ (l = ve(l, o, h, u, e[i + 15], 10, -30611744)),
246966
+ (u = ve(u, l, o, h, e[i + 6], 15, -1560198380)),
246967
+ (h = ve(h, u, l, o, e[i + 13], 21, 1309151649)),
246968
+ (o = ve(o, h, u, l, e[i + 4], 6, -145523070)),
246969
+ (l = ve(l, o, h, u, e[i + 11], 10, -1120210379)),
246970
+ (u = ve(u, l, o, h, e[i + 2], 15, 718787259)),
246971
+ (h = ve(h, u, l, o, e[i + 9], 21, -343485551)),
246855
246972
  (o = pe$1(o, s)),
246856
246973
  (h = pe$1(h, a)),
246857
246974
  (u = pe$1(u, r)),
@@ -252287,7 +252404,7 @@ function viewToBuffer (view) {
252287
252404
  return buf;
252288
252405
  }
252289
252406
 
252290
- const EventEmitter$5 = require$$0$8;
252407
+ const EventEmitter$6 = require$$0$8;
252291
252408
  const crypto$2 = require$$1$6;
252292
252409
  const https$6 = require$$1$5;
252293
252410
  const http$7 = require$$1$4;
@@ -252309,7 +252426,7 @@ const closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection
252309
252426
  *
252310
252427
  * @extends EventEmitter
252311
252428
  */
252312
- let WebSocket$5 = class WebSocket extends EventEmitter$5 {
252429
+ let WebSocket$5 = class WebSocket extends EventEmitter$6 {
252313
252430
  /**
252314
252431
  * Create a new `WebSocket`.
252315
252432
  *
@@ -252992,7 +253109,7 @@ function initAsClient$1 (address, protocols, options) {
252992
253109
  }
252993
253110
 
252994
253111
  const safeBuffer = safeBufferExports;
252995
- const EventEmitter$4 = require$$0$8;
253112
+ const EventEmitter$5 = require$$0$8;
252996
253113
  const crypto$1 = require$$1$6;
252997
253114
  const http$6 = require$$1$4;
252998
253115
  const url = require$$0$9;
@@ -253009,7 +253126,7 @@ const Buffer$2 = safeBuffer.Buffer;
253009
253126
  *
253010
253127
  * @extends EventEmitter
253011
253128
  */
253012
- class WebSocketServer extends EventEmitter$4 {
253129
+ class WebSocketServer extends EventEmitter$5 {
253013
253130
  /**
253014
253131
  * Create a `WebSocketServer` instance.
253015
253132
  *
@@ -265762,7 +265879,7 @@ var base64$3 = {};
265762
265879
  };
265763
265880
  } (base64$3));
265764
265881
 
265765
- var eventemitter$1 = EventEmitter$3;
265882
+ var eventemitter$1 = EventEmitter$4;
265766
265883
 
265767
265884
  /**
265768
265885
  * Constructs a new event emitter instance.
@@ -265770,7 +265887,7 @@ var eventemitter$1 = EventEmitter$3;
265770
265887
  * @memberof util
265771
265888
  * @constructor
265772
265889
  */
265773
- function EventEmitter$3() {
265890
+ function EventEmitter$4() {
265774
265891
 
265775
265892
  /**
265776
265893
  * Registered listeners.
@@ -265795,7 +265912,7 @@ function EventEmitter$3() {
265795
265912
  * @param {*} [ctx] Listener context
265796
265913
  * @returns {this} `this`
265797
265914
  */
265798
- EventEmitter$3.prototype.on = function on(evt, fn, ctx) {
265915
+ EventEmitter$4.prototype.on = function on(evt, fn, ctx) {
265799
265916
  (this._listeners[evt] || (this._listeners[evt] = [])).push({
265800
265917
  fn : fn,
265801
265918
  ctx : ctx || this
@@ -265809,7 +265926,7 @@ EventEmitter$3.prototype.on = function on(evt, fn, ctx) {
265809
265926
  * @param {EventEmitterListener} [fn] Listener to remove. Removes all listeners of `evt` if omitted.
265810
265927
  * @returns {this} `this`
265811
265928
  */
265812
- EventEmitter$3.prototype.off = function off(evt, fn) {
265929
+ EventEmitter$4.prototype.off = function off(evt, fn) {
265813
265930
  if (evt === undefined)
265814
265931
  this._listeners = {};
265815
265932
  else {
@@ -265833,7 +265950,7 @@ EventEmitter$3.prototype.off = function off(evt, fn) {
265833
265950
  * @param {...*} args Arguments
265834
265951
  * @returns {this} `this`
265835
265952
  */
265836
- EventEmitter$3.prototype.emit = function emit(evt) {
265953
+ EventEmitter$4.prototype.emit = function emit(evt) {
265837
265954
  var listeners = this._listeners[evt];
265838
265955
  if (listeners) {
265839
265956
  var args = [],
@@ -278540,6 +278657,349 @@ var listenAll = (instance, roomId, handler) => {
278540
278657
  }
278541
278658
  };
278542
278659
 
278660
+ var eventemitter3 = {exports: {}};
278661
+
278662
+ (function (module) {
278663
+
278664
+ var has = Object.prototype.hasOwnProperty
278665
+ , prefix = '~';
278666
+
278667
+ /**
278668
+ * Constructor to create a storage for our `EE` objects.
278669
+ * An `Events` instance is a plain object whose properties are event names.
278670
+ *
278671
+ * @constructor
278672
+ * @private
278673
+ */
278674
+ function Events() {}
278675
+
278676
+ //
278677
+ // We try to not inherit from `Object.prototype`. In some engines creating an
278678
+ // instance in this way is faster than calling `Object.create(null)` directly.
278679
+ // If `Object.create(null)` is not supported we prefix the event names with a
278680
+ // character to make sure that the built-in object properties are not
278681
+ // overridden or used as an attack vector.
278682
+ //
278683
+ if (Object.create) {
278684
+ Events.prototype = Object.create(null);
278685
+
278686
+ //
278687
+ // This hack is needed because the `__proto__` property is still inherited in
278688
+ // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
278689
+ //
278690
+ if (!new Events().__proto__) prefix = false;
278691
+ }
278692
+
278693
+ /**
278694
+ * Representation of a single event listener.
278695
+ *
278696
+ * @param {Function} fn The listener function.
278697
+ * @param {*} context The context to invoke the listener with.
278698
+ * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
278699
+ * @constructor
278700
+ * @private
278701
+ */
278702
+ function EE(fn, context, once) {
278703
+ this.fn = fn;
278704
+ this.context = context;
278705
+ this.once = once || false;
278706
+ }
278707
+
278708
+ /**
278709
+ * Add a listener for a given event.
278710
+ *
278711
+ * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
278712
+ * @param {(String|Symbol)} event The event name.
278713
+ * @param {Function} fn The listener function.
278714
+ * @param {*} context The context to invoke the listener with.
278715
+ * @param {Boolean} once Specify if the listener is a one-time listener.
278716
+ * @returns {EventEmitter}
278717
+ * @private
278718
+ */
278719
+ function addListener(emitter, event, fn, context, once) {
278720
+ if (typeof fn !== 'function') {
278721
+ throw new TypeError('The listener must be a function');
278722
+ }
278723
+
278724
+ var listener = new EE(fn, context || emitter, once)
278725
+ , evt = prefix ? prefix + event : event;
278726
+
278727
+ if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
278728
+ else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
278729
+ else emitter._events[evt] = [emitter._events[evt], listener];
278730
+
278731
+ return emitter;
278732
+ }
278733
+
278734
+ /**
278735
+ * Clear event by name.
278736
+ *
278737
+ * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
278738
+ * @param {(String|Symbol)} evt The Event name.
278739
+ * @private
278740
+ */
278741
+ function clearEvent(emitter, evt) {
278742
+ if (--emitter._eventsCount === 0) emitter._events = new Events();
278743
+ else delete emitter._events[evt];
278744
+ }
278745
+
278746
+ /**
278747
+ * Minimal `EventEmitter` interface that is molded against the Node.js
278748
+ * `EventEmitter` interface.
278749
+ *
278750
+ * @constructor
278751
+ * @public
278752
+ */
278753
+ function EventEmitter() {
278754
+ this._events = new Events();
278755
+ this._eventsCount = 0;
278756
+ }
278757
+
278758
+ /**
278759
+ * Return an array listing the events for which the emitter has registered
278760
+ * listeners.
278761
+ *
278762
+ * @returns {Array}
278763
+ * @public
278764
+ */
278765
+ EventEmitter.prototype.eventNames = function eventNames() {
278766
+ var names = []
278767
+ , events
278768
+ , name;
278769
+
278770
+ if (this._eventsCount === 0) return names;
278771
+
278772
+ for (name in (events = this._events)) {
278773
+ if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
278774
+ }
278775
+
278776
+ if (Object.getOwnPropertySymbols) {
278777
+ return names.concat(Object.getOwnPropertySymbols(events));
278778
+ }
278779
+
278780
+ return names;
278781
+ };
278782
+
278783
+ /**
278784
+ * Return the listeners registered for a given event.
278785
+ *
278786
+ * @param {(String|Symbol)} event The event name.
278787
+ * @returns {Array} The registered listeners.
278788
+ * @public
278789
+ */
278790
+ EventEmitter.prototype.listeners = function listeners(event) {
278791
+ var evt = prefix ? prefix + event : event
278792
+ , handlers = this._events[evt];
278793
+
278794
+ if (!handlers) return [];
278795
+ if (handlers.fn) return [handlers.fn];
278796
+
278797
+ for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
278798
+ ee[i] = handlers[i].fn;
278799
+ }
278800
+
278801
+ return ee;
278802
+ };
278803
+
278804
+ /**
278805
+ * Return the number of listeners listening to a given event.
278806
+ *
278807
+ * @param {(String|Symbol)} event The event name.
278808
+ * @returns {Number} The number of listeners.
278809
+ * @public
278810
+ */
278811
+ EventEmitter.prototype.listenerCount = function listenerCount(event) {
278812
+ var evt = prefix ? prefix + event : event
278813
+ , listeners = this._events[evt];
278814
+
278815
+ if (!listeners) return 0;
278816
+ if (listeners.fn) return 1;
278817
+ return listeners.length;
278818
+ };
278819
+
278820
+ /**
278821
+ * Calls each of the listeners registered for a given event.
278822
+ *
278823
+ * @param {(String|Symbol)} event The event name.
278824
+ * @returns {Boolean} `true` if the event had listeners, else `false`.
278825
+ * @public
278826
+ */
278827
+ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
278828
+ var evt = prefix ? prefix + event : event;
278829
+
278830
+ if (!this._events[evt]) return false;
278831
+
278832
+ var listeners = this._events[evt]
278833
+ , len = arguments.length
278834
+ , args
278835
+ , i;
278836
+
278837
+ if (listeners.fn) {
278838
+ if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
278839
+
278840
+ switch (len) {
278841
+ case 1: return listeners.fn.call(listeners.context), true;
278842
+ case 2: return listeners.fn.call(listeners.context, a1), true;
278843
+ case 3: return listeners.fn.call(listeners.context, a1, a2), true;
278844
+ case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
278845
+ case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
278846
+ case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
278847
+ }
278848
+
278849
+ for (i = 1, args = new Array(len -1); i < len; i++) {
278850
+ args[i - 1] = arguments[i];
278851
+ }
278852
+
278853
+ listeners.fn.apply(listeners.context, args);
278854
+ } else {
278855
+ var length = listeners.length
278856
+ , j;
278857
+
278858
+ for (i = 0; i < length; i++) {
278859
+ if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
278860
+
278861
+ switch (len) {
278862
+ case 1: listeners[i].fn.call(listeners[i].context); break;
278863
+ case 2: listeners[i].fn.call(listeners[i].context, a1); break;
278864
+ case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
278865
+ case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
278866
+ default:
278867
+ if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
278868
+ args[j - 1] = arguments[j];
278869
+ }
278870
+
278871
+ listeners[i].fn.apply(listeners[i].context, args);
278872
+ }
278873
+ }
278874
+ }
278875
+
278876
+ return true;
278877
+ };
278878
+
278879
+ /**
278880
+ * Add a listener for a given event.
278881
+ *
278882
+ * @param {(String|Symbol)} event The event name.
278883
+ * @param {Function} fn The listener function.
278884
+ * @param {*} [context=this] The context to invoke the listener with.
278885
+ * @returns {EventEmitter} `this`.
278886
+ * @public
278887
+ */
278888
+ EventEmitter.prototype.on = function on(event, fn, context) {
278889
+ return addListener(this, event, fn, context, false);
278890
+ };
278891
+
278892
+ /**
278893
+ * Add a one-time listener for a given event.
278894
+ *
278895
+ * @param {(String|Symbol)} event The event name.
278896
+ * @param {Function} fn The listener function.
278897
+ * @param {*} [context=this] The context to invoke the listener with.
278898
+ * @returns {EventEmitter} `this`.
278899
+ * @public
278900
+ */
278901
+ EventEmitter.prototype.once = function once(event, fn, context) {
278902
+ return addListener(this, event, fn, context, true);
278903
+ };
278904
+
278905
+ /**
278906
+ * Remove the listeners of a given event.
278907
+ *
278908
+ * @param {(String|Symbol)} event The event name.
278909
+ * @param {Function} fn Only remove the listeners that match this function.
278910
+ * @param {*} context Only remove the listeners that have this context.
278911
+ * @param {Boolean} once Only remove one-time listeners.
278912
+ * @returns {EventEmitter} `this`.
278913
+ * @public
278914
+ */
278915
+ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
278916
+ var evt = prefix ? prefix + event : event;
278917
+
278918
+ if (!this._events[evt]) return this;
278919
+ if (!fn) {
278920
+ clearEvent(this, evt);
278921
+ return this;
278922
+ }
278923
+
278924
+ var listeners = this._events[evt];
278925
+
278926
+ if (listeners.fn) {
278927
+ if (
278928
+ listeners.fn === fn &&
278929
+ (!once || listeners.once) &&
278930
+ (!context || listeners.context === context)
278931
+ ) {
278932
+ clearEvent(this, evt);
278933
+ }
278934
+ } else {
278935
+ for (var i = 0, events = [], length = listeners.length; i < length; i++) {
278936
+ if (
278937
+ listeners[i].fn !== fn ||
278938
+ (once && !listeners[i].once) ||
278939
+ (context && listeners[i].context !== context)
278940
+ ) {
278941
+ events.push(listeners[i]);
278942
+ }
278943
+ }
278944
+
278945
+ //
278946
+ // Reset the array, or remove it completely if we have no more listeners.
278947
+ //
278948
+ if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
278949
+ else clearEvent(this, evt);
278950
+ }
278951
+
278952
+ return this;
278953
+ };
278954
+
278955
+ /**
278956
+ * Remove all listeners, or those of the specified event.
278957
+ *
278958
+ * @param {(String|Symbol)} [event] The event name.
278959
+ * @returns {EventEmitter} `this`.
278960
+ * @public
278961
+ */
278962
+ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
278963
+ var evt;
278964
+
278965
+ if (event) {
278966
+ evt = prefix ? prefix + event : event;
278967
+ if (this._events[evt]) clearEvent(this, evt);
278968
+ } else {
278969
+ this._events = new Events();
278970
+ this._eventsCount = 0;
278971
+ }
278972
+
278973
+ return this;
278974
+ };
278975
+
278976
+ //
278977
+ // Alias methods names because people roll like that.
278978
+ //
278979
+ EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
278980
+ EventEmitter.prototype.addListener = EventEmitter.prototype.on;
278981
+
278982
+ //
278983
+ // Expose the prefix.
278984
+ //
278985
+ EventEmitter.prefixed = prefix;
278986
+
278987
+ //
278988
+ // Allow `EventEmitter` to be imported as module namespace.
278989
+ //
278990
+ EventEmitter.EventEmitter = EventEmitter;
278991
+
278992
+ //
278993
+ // Expose the module.
278994
+ //
278995
+ {
278996
+ module.exports = EventEmitter;
278997
+ }
278998
+ } (eventemitter3));
278999
+
279000
+ var eventemitter3Exports = eventemitter3.exports;
279001
+ var EventEmitter$3 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
279002
+
278543
279003
  var bufferUtil$1 = {exports: {}};
278544
279004
 
278545
279005
  const BINARY_TYPES$2 = ['nodebuffer', 'arraybuffer', 'fragments'];
@@ -282679,11 +283139,11 @@ function socketOnError() {
282679
283139
 
282680
283140
  var WebSocket$2 = /*@__PURE__*/getDefaultExportFromCjs(websocket);
282681
283141
 
282682
- let c$1=function(e){return e[e.HEARTBEAT=2]=`HEARTBEAT`,e[e.HEARTBEAT_REPLY=3]=`HEARTBEAT_REPLY`,e[e.MESSAGE=5]=`MESSAGE`,e[e.USER_AUTHENTICATION=7]=`USER_AUTHENTICATION`,e[e.CONNECT_SUCCESS=8]=`CONNECT_SUCCESS`,e[e.Unknown=-1]=`Unknown`,e}({}),l=function(e){return e[e.NORMAL=0]=`NORMAL`,e[e.NUMBER=1]=`NUMBER`,e[e.ZLIB=2]=`ZLIB`,e[e.BROTLI=3]=`BROTLI`,e}({});const ee=16,u$1=0,d=4,f=6,p=8,m=12,h$2=4,g=2,_$1=new TextDecoder(`utf-8`),te=new TextEncoder,v=function(e,t,n){let r=0;for(let i=n-1;i>=0;i--)r+=256**(n-i-1)*e[t+i];return r},ne=function(e,t,n,r){let i=0;for(;i<n;)e[t+i]=r/256**(n-i-1),i++;};function y(e,t){return e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3]}var b=class{_buffer;constructor(e){this._buffer=e;}get buffer(){return this._buffer}get length(){return this._buffer.length}write(e,t,n){ne(this.buffer,e,t,n);}},re=class{_buffer;constructor(e){this._buffer=e;}get buffer(){return this._buffer}get length(){return this._buffer.length}read(e,t){return v(this._buffer,e,t)}};function ie(e){let t=e.reduce((e,t)=>e+t.length,0),n=new Uint8Array(t),r=0;for(let t of e)n.set(t,r),r+=t.length;return n}function ae(e){let t=[],n;for(let r=0;r<e.length;r+=n)n=v(e,r,h$2),t.push(e.slice(r,r+n));return t}var x=class extends re{readOperation(){return this.read(p,h$2)}readHeaderLength(){return this.read(d,g)}readVersion(){return this.read(f,g)}readSequence(){return this.read(m,h$2)}readPacketLength(){return this.read(u$1,h$2)}toJSON(){return {op:this.readOperation(),ver:this.readVersion(),sequence:this.readSequence(),packetLength:this.readPacketLength(),headerLength:this.readHeaderLength()}}};async function S(e,t){let n=ae(e),r=n.map(e=>{let t=new x(e.slice(0,16)).toJSON(),n=e.slice(16);return {header:t,body:n}}),i=r.map(async e=>{let{header:n,body:r}=e,i;if(n.ver===l.NORMAL&&(i=JSON.parse(_$1.decode(r))),n.ver===l.NUMBER&&(n.op===c$1.HEARTBEAT_REPLY&&(i=v(r,0,4)),n.op===c$1.CONNECT_SUCCESS))try{i=JSON.parse(_$1.decode(r));}catch{}return n.ver===l.ZLIB&&(i=await S(await t.inflateAsync(r),t)),n.ver===l.BROTLI&&(i=await S(await t.brotliDecompressAsync(r),t)),{meta:n,data:i}}),a=await Promise.all(i);return a.flatMap(e=>e.meta.ver===l.ZLIB||e.meta.ver===l.BROTLI?e.data:e)}function C(e,t={}){typeof t!=`string`&&(t=JSON.stringify(t));let n=new b(new Uint8Array(ee));n.write(d,g,16),n.write(f,g,l.NUMBER),n.write(p,h$2,e),n.write(m,h$2,1);let r=new b(new Uint8Array(te.encode(t)));return n.write(u$1,h$2,n.length+r.length),ie([n.buffer,r.buffer])}function oe(e,t){return S(e,t)}function w(e,t,n){return new Promise((r,i)=>{if(e.once(t,e=>{r(e);}),n);})}function E(e){return e[Math.floor(Math.random()*e.length)]}function D(e,t){let n=Number(e);if(Number.isNaN(n)){throw Error(`roomId must be Number`)}return n}function ce(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!=null))}function O(e,t,n){return new Promise((r,i)=>{let a=0,o=async()=>{try{let t=await e();r(t);}catch(e){++a<t?setTimeout(o,n):i(e);}};o();})}var k=class extends EventEmitter$h{on(e,t){return super.on(e,t)}once(e,t){return super.once(e,t)}addListener(e,t){return this.on(e,t)}off(e,t){return super.off(e,t)}emit(e,...t){return super.emit(e,...t)}removeListener(e,t){return this.off(e,t)}removeAllListeners(e){return super.removeAllListeners(e)}listenerCount(e){return e?super.listenerCount(e):super.eventNames().length}};let A=function(e){return e.DEFAULT=`zj-cn-live-comet.chat.bilibili.com`,e}({});const j=`__message__`,M$1=`__open__`,N=`__error__`,P=`__close__`;function F(){}const I=A.DEFAULT,L=2243;var U=class extends k{online=0;closed=!0;roomId=0;close_func_called=!1;socket;timeout;HEARTBEAT_TIME;RECONNECT_TIME;zlib;live=!1;skipMessage=[];constructor(e){super(),this.options=e,this.HEARTBEAT_TIME=e.heartbeatTime??30*1e3,this.RECONNECT_TIME=e.reconnectTime??5*1e3,this.socket=e.socket,this.zlib=e.zlib,this.bindEvent();}onlyListener(e){for(let t of Array.isArray(e)?e:[e])this.skipMessage.includes(t)||this.skipMessage.push(t);}clearOnlyListener(e){for(let t of Array.isArray(e)?e:[e])this.skipMessage.includes(t)&&this.skipMessage.splice(this.skipMessage.findIndex(e=>t===e),1);}rawSend(e){`write`in this.socket?this.socket.write(e):this.socket.send(e);}bindEvent(){this.on(M$1,()=>{if(this.closed=!1,this.emit(`open`),this.options.authBody)this.rawSend(this.options.authBody);else {let e={uid:this.options.uid,roomid:this.roomId,protover:this.options.protover,platform:this.options.platform,type:this.options.type,key:this.options.key,buvid:this.options.buvid};this.send(c$1.USER_AUTHENTICATION,ce(e));}}),this.on(j,async e=>{this.options.raw&&this.emit(`message`,e);let t=await oe(e,this.zlib).catch(e=>(e instanceof Error&&this.emit(`deserialize:error`,e),[]));for(let e of t){if(e.meta.op===c$1.MESSAGE){let t=e.data?.cmd||e.data?.msg&&e.data?.msg?.cmd;if(this.skipMessage.length>0&&this.skipMessage.includes(t))continue;this.options.stub&&this.emit(`msg`,e),t.includes(`DANMU_MSG`)?this.emit(`DANMU_MSG`,e):this.emit(t,e);continue}if(e.meta.op===c$1.HEARTBEAT_REPLY){this.online=e.data,clearTimeout(this.timeout),this.timeout=setTimeout(()=>this.heartbeat(),this.HEARTBEAT_TIME),this.emit(`heartbeat`,this.online);continue}e.meta.op===c$1.CONNECT_SUCCESS&&(typeof e.data==`object`&&e.data?.code!==0&&console.warn(`连接失败: `,e.data),this.emit(`live`),this.live=!0,this.send(c$1.HEARTBEAT));}}),this.on(N,e=>{this.emit(`error`,e);}),this.on(P,e=>{if(this.emit(`close`,e),this.options.keepalive&&!this.close_func_called){this.emit(`reconnect`,!0);let e=setTimeout(()=>{clearTimeout(e),this.closed=!0,this.online=0,this.live=!1,clearTimeout(this.timeout),this.socket.reconnect();},this.RECONNECT_TIME);}else this.closed=!0,this.online=0,this.live=!1,this.close_func_called=!1,clearTimeout(this.timeout);});}send(e,t={}){this.rawSend(C(e,t));}async runWhenConnected(...e){this.live||await w(this,`live`);for(let t of e)t();}heartbeat(){this.send(c$1.HEARTBEAT);}async getOnline(){return this.live||await w(this,`live`),new Promise(e=>{this.once(`heartbeat`,t=>{e(typeof t==`number`?t:t.data);}),this.heartbeat();})}close(){return this.live?(this.close_func_called=!0,clearTimeout(this.timeout),`end`in this.socket?this.socket.end():this.socket.close(),!0):!1}reconnect(){this.closed=!0,this.online=0,this.live=!1,clearTimeout(this.timeout),this.close_func_called=!1,this.emit(`reconnect`,!1),this.socket.reconnect();}};function W$1(e,t){return (n,r)=>{n?t(n):e(r);}}function le(e,t){return new Promise((n,i)=>{zlib$5.brotliDecompress(e,t??{},W$1(n,i));})}function ue(e,t){return new Promise((n,r)=>{zlib$5.inflate(e,t??{},W$1(n,r));})}const de=ue,fe=le,G$2={inflateAsync:de,brotliDecompressAsync:fe},K={raw:!1,stub:!0,ssl:!0,keepalive:!0,reconnectTime:5*1e3,heartbeatTime:30*1e3,platform:`web`,protover:3,type:2};function pe(e){return new Promise((t,n)=>{let r=new urlLib.URL(e.url),i=e.method||`GET`,o={hostname:r.hostname,path:r.pathname+r.search,method:i,headers:{"User-Agent":`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36`,...e.headers},timeout:e.timeout||1e4},c=https$c.request(o,e=>{let n=``;e.on(`data`,e=>{n+=e;}),e.on(`end`,()=>{let r;try{r=JSON.parse(n);}catch{r=n;}let i={};Object.entries(e.headers).forEach(([e,t])=>{e&&t&&(i[e]=Array.isArray(t)?t.join(`, `):t);}),t({data:r,status:e.statusCode||0,headers:i});});});if(c.on(`error`,e=>{n(e);}),c.on(`timeout`,()=>{c.destroy(),n(Error(`请求超时: ${e.url}`));}),e.data&&i!==`GET`){let t=typeof e.data==`string`?e.data:JSON.stringify(e.data);c.write(t);}c.end();})}const me=[46,47,18,2,53,8,23,32,15,50,10,31,58,3,45,35,27,43,5,49,33,9,42,19,29,28,14,39,12,38,41,13,37,48,7,16,24,55,40,61,26,17,0,1,60,51,30,4,22,25,54,21,56,59,6,63,57,62,11,36,20,34,44,52];function he(e){let t=``;return me.forEach(n=>{t+=e[n];}),t.slice(0,32)}function ge(e){let t=crypto$d.createHash(`md5`);return t.update(e),t.digest(`hex`)}function _e(e,t,n){let r=he(t+n),i=Math.round(Date.now()/1e3),a=/[!'()*]/g,o=[];Object.assign(e,{wts:i}),Object.keys(e).sort().forEach(t=>{o.push(`${encodeURIComponent(t)}=${encodeURIComponent(e[t].toString().replace(a,``))}`);});let s=o.join(`&`),c=ge(s+r);return `${s}&w_rid=${c}`}async function ve(){let e=await pe({url:`https://api.bilibili.com/x/web-interface/nav`,method:`GET`}),t=e.data,n=t.data.wbi_img.img_url,r=t.data.wbi_img.sub_url;return {img_key:n.slice(n.lastIndexOf(`/`)+1,n.lastIndexOf(`.`)),sub_key:r.slice(r.lastIndexOf(`/`)+1,r.lastIndexOf(`.`))}}async function q(e){let t=await ve();return _e(e,t.img_key,t.sub_key)}const J=new TextDecoder,Y=new Map,X=new Map;let Z;function Q(e,t){return new Promise((n,r)=>{https$c.get(`https://api.live.bilibili.com/room/v1/Room/mobileRoomInit?id=${e}`,{headers:t},e=>{let t=new Uint8Array;e.on(`data`,e=>{t=new Uint8Array([...t,...e]);}),e.once(`end`,()=>{n(JSON.parse(J.decode(t)));});}).on(`error`,e=>r(e));})}function ye(e,t){return new Promise((n,r)=>{https$c.get(`https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?${e}`,{headers:t},e=>{let t=new Uint8Array;e.on(`data`,e=>{t=new Uint8Array([...t,...e]);}),e.once(`end`,()=>{n(JSON.parse(J.decode(t)));});}).on(`error`,e=>r(e));})}function be(e){return new Promise((t,n)=>{https$c.get(`https://api.bilibili.com/x/frontend/finger/spi`,{headers:e},e=>{let n=new Uint8Array;e.on(`data`,e=>{n=new Uint8Array([...n,...e]);}),e.once(`end`,()=>{t(JSON.parse(J.decode(n)));});}).on(`error`,e=>n(e));})}async function $(e,t){let n,r;if(Y.has(e))n=Y.get(e);else {let r=await O(()=>Q(e,t.headers),2,200);Y.set(e,r),n=r;}if(X.has(n.data.room_id))r=X.get(n.data.room_id);else {let e={id:n.data.room_id,type:0,wts:Math.floor(Date.now()/1e3)},i=await q(e),a=await O(()=>ye(i,t.headers),2,200);X.set(n.data.room_id,a),r=a;}if(!Z){let e=await O(()=>be(t.headers),2,200);Z=e.data.b_3;}return [n,r,Z]}var xe=class extends U{buffer=new Uint8Array;i=0;tcpSocket;constructor(e,t=K){let n=Object.assign({},K,t),r={...n,socket:{type:`tcp`,write:e=>{this.tcpSocket.write(e);},reconnect:F,end:()=>{this.tcpSocket.end();}},zlib:G$2,room:e};super(r),this.init(r);}async getSocketUrl(e){let t;try{let[n,r,i]=await $(e,this.options);this.options.key||(this.options.key=r.data.token),this.options.buvid||(this.options.buvid=i),t=E(r.data.host_list);}catch(e){console.error(e);}return {host:t?.host,port:t?.port}}async init(t){let n=D(t.room),r=t.url?t.url:await this.getSocketUrl(n),i=Y.get(n)?.data?.room_id||n;this.options.room=i,this.roomId=i;let a=typeof r==`string`?require$$1$7.connect(r):require$$1$7.connect(r.port??L,r.host??I);this.options.socket.reconnect=()=>{this.tcpSocket?.end(),this.tcpSocket=null;let t=typeof r==`string`?require$$1$7.connect(r):require$$1$7.connect(r.port??L,r.host??I);this.tcpSocket=t,this._bindEvent(t);},this.tcpSocket=a,this._bindEvent(a);}_bindEvent(e){e.on(`ready`,()=>this.emit(M$1)),e.on(`close`,e=>this.emit(P,e)),e.on(`error`,e=>this.emit(N,e)),e.on(`data`,e=>{this.buffer=new Uint8Array([...this.buffer,...e]),this.splitBuffer();});}splitBuffer(){for(;this.buffer.length>=4&&y(this.buffer,0)<=this.buffer.length;){let e=y(this.buffer,0),t=this.buffer.subarray(0,e);this.buffer=this.buffer.subarray(e),this.i++,this.i>5&&(this.i=0,this.buffer=new Uint8Array(this.buffer)),this.emit(j,t);}}};
283142
+ (function(e){return e[e.HEARTBEAT=2]=`HEARTBEAT`,e[e.HEARTBEAT_REPLY=3]=`HEARTBEAT_REPLY`,e[e.MESSAGE=5]=`MESSAGE`,e[e.USER_AUTHENTICATION=7]=`USER_AUTHENTICATION`,e[e.CONNECT_SUCCESS=8]=`CONNECT_SUCCESS`,e[e.Unknown=-1]=`Unknown`,e})({});(function(e){return e[e.NORMAL=0]=`NORMAL`,e[e.NUMBER=1]=`NUMBER`,e[e.ZLIB=2]=`ZLIB`,e[e.BROTLI=3]=`BROTLI`,e})({});const c$1=new TextDecoder(`utf-8`),ee=new TextEncoder;function l(e,t,n){let r=0;for(let i=n-1;i>=0;i--)r+=256**(n-i-1)*e[t+i];return r}function te(e,t,n,r){let i=0;for(;i<n;)e[t+i]=r/256**(n-i-1),i++;}function u$1(e,t){return e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3]}var d=class{constructor(e){this._buffer=e;}get buffer(){return this._buffer}get length(){return this._buffer.length}write(e,t,n){te(this.buffer,e,t,n);}},f=class{constructor(e){this._buffer=e;}get buffer(){return this._buffer}get length(){return this._buffer.length}read(e,t){return l(this._buffer,e,t)}};function ne(e){let t=e.reduce((e,t)=>e+t.length,0),n=new Uint8Array(t),r=0;for(let t of e)n.set(t,r),r+=t.length;return n}function re(e){let t=[],n;for(let r=0;r<e.length;r+=n)n=l(e,r,4),t.push(e.slice(r,r+n));return t}var ie=class extends f{readOperation(){return this.read(8,4)}readHeaderLength(){return this.read(4,2)}readVersion(){return this.read(6,2)}readSequence(){return this.read(12,4)}readPacketLength(){return this.read(0,4)}toJSON(){return {op:this.readOperation(),ver:this.readVersion(),sequence:this.readSequence(),packetLength:this.readPacketLength(),headerLength:this.readHeaderLength()}}};async function p(e,t){let n=re(e).map(e=>({header:new ie(e.slice(0,16)).toJSON(),body:e.slice(16)})).map(async e=>{let{header:n,body:r}=e,i;if(n.ver===0&&(i=JSON.parse(c$1.decode(r))),n.ver===1&&(n.op===3&&(i=l(r,0,4)),n.op===8))try{i=JSON.parse(c$1.decode(r));}catch{}return n.ver===2&&(i=await p(await t.inflateAsync(r),t)),n.ver===3&&(i=await p(await t.brotliDecompressAsync(r),t)),{meta:n,data:i}});return (await Promise.all(n)).flatMap(e=>e.meta.ver===2||e.meta.ver===3?e.data:e)}function m(e,t={}){typeof t!=`string`&&(t=JSON.stringify(t));let n=new d(new Uint8Array(16));n.write(4,2,16),n.write(6,2,1),n.write(8,4,e),n.write(12,4,1);let r=new d(new Uint8Array(ee.encode(t)));return n.write(0,4,n.length+r.length),ne([n.buffer,r.buffer])}function ae(e,t){return p(e,t)}var h$2=class h extends EventEmitter$3{on(e,t){return super.on(e,t)}once(e,t){return super.once(e,t)}addListener(e,t){return this.on(e,t)}off(e,t){return super.off(e,t)}emit(e,...t){return super.emit(e,...t)}removeListener(e,t){return this.off(e,t)}removeAllListeners(e){return super.removeAllListeners(e)}listenerCount(e){return e?super.listenerCount(e):super.eventNames().length}};const g=new TextDecoder;function _$1(e){let t=atob(e);return Uint8Array.from(t,e=>e.charCodeAt(0))}function v(e,t){let n=0,r=1;for(;t<e.length;){let i=e[t++];if(n+=(i&127)*r,!(i&128))return [n,t];r*=128;}throw Error(`Invalid protobuf varint`)}function y(e){let t=[],n=0;for(;n<e.length;){let r;[r,n]=v(e,n);let i=Math.floor(r/8),a=r&7;if(i===0)throw Error(`Invalid protobuf field number`);if(a===0){let r;[r,n]=v(e,n),t.push({number:i,wireType:a,value:r});}else if(a===1){if(n+8>e.length)throw Error(`Invalid protobuf fixed64 field`);n+=8;}else if(a===2){let r;[r,n]=v(e,n);let o=n+r;if(o>e.length)throw Error(`Invalid protobuf length-delimited field`);t.push({number:i,wireType:a,value:e.subarray(n,o)}),n=o;}else if(a===5){if(n+4>e.length)throw Error(`Invalid protobuf fixed32 field`);n+=4;}else throw Error(`Unsupported protobuf wire type: ${a}`)}return t}function b(e,t){let n=e.find(e=>e.number===t&&e.wireType===0)?.value;return typeof n==`number`?n:0}function x(e,t){let n=e.find(e=>e.number===t&&e.wireType===2)?.value;return n instanceof Uint8Array?n:void 0}function S(e,t){let n=x(e,t);return n?g.decode(n):``}function C(e){let t=e?y(e):[];return {target_id:b(t,1),anchor_roomid:b(t,4),medal_level:b(t,5),medal_name:S(t,6)}}function w(e){let t=e?y(e):[];return {original_gift_name:S(t,3),original_gift_price:b(t,6)}}function oe(e){let t=y(e),n=x(t,35);return {gift_id:b(t,1),gift_name:S(t,2),num:b(t,3),gift_type:b(t,4),price:b(t,5),total_coin:b(t,7),coin_type:S(t,8),tid:S(t,9),timestamp:b(t,10),rnd:S(t,12),action:S(t,18),gift_img_basic:n?S(y(n),1):``}}function T(e){let t=y(_$1(e));return {uid:b(t,1),uname:S(t,2),face:S(t,3),guard_level:b(t,5),medal_info:C(x(t,8)),blind_gift:w(x(t,9)),gift_list:t.filter(e=>e.number===10&&e.wireType===2&&e.value instanceof Uint8Array).map(e=>oe(e.value))}}function E(e){let t=T(e);return t.gift_list.map(e=>({...e,uid:t.uid,uname:t.uname,face:t.face,guard_level:t.guard_level,medal_level:t.medal_info.medal_level,medal_name:t.medal_info.medal_name,medal_room_id:t.medal_info.anchor_roomid,medal_ruid:t.medal_info.target_id,blind_gift_name:t.blind_gift.original_gift_name,blind_price:t.blind_gift.original_gift_price}))}function D(e,t,n){return new Promise((r,i)=>{if(e.once(t,e=>{r(e);}),n);})}function A(e){return e[Math.floor(Math.random()*e.length)]}function j(e,t){let n=Number(e);if(Number.isNaN(n)){throw Error(`roomId must be Number`)}return n}function se(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!=null))}function M$1(e,t,n){return new Promise((r,i)=>{let a=0,o=async()=>{try{r(await e());}catch(e){++a<t?setTimeout(o,n):i(e);}};o();})}(function(e){return e.DEFAULT=`zj-cn-live-comet.chat.bilibili.com`,e})({});const N=`__message__`,P=`__open__`,F=`__error__`,I=`__close__`;function L(){}var V=class extends h$2{constructor(e){super(),this.options=e,this.online=0,this.closed=!0,this.roomId=0,this.manualClose=!1,this.live=!1,this.skipMessage=[],this.HEARTBEAT_TIME=e.heartbeatTime??30*1e3,this.RECONNECT_TIME=e.reconnectTime??5*1e3,this.socket=e.socket,this.zlib=e.zlib,this.bindEvent();}onlyListener(e){for(let t of Array.isArray(e)?e:[e])this.skipMessage.includes(t)||this.skipMessage.push(t);}clearOnlyListener(e){for(let t of Array.isArray(e)?e:[e])this.skipMessage.includes(t)&&this.skipMessage.splice(this.skipMessage.findIndex(e=>t===e),1);}rawSend(e){`write`in this.socket?this.socket.write(e):this.socket.send(e);}clearTimers(){clearTimeout(this.timeout),clearTimeout(this.reconnectTimer);}resetConnectionState(){this.closed=!0,this.online=0,this.live=!1;}bindEvent(){this.on(P,()=>{if(this.closed=!1,this.emit(`open`),this.options.authBody)this.rawSend(this.options.authBody);else {let e={uid:this.options.uid,roomid:this.roomId,protover:this.options.protover,platform:this.options.platform,type:this.options.type,key:this.options.key,buvid:this.options.buvid};this.send(7,se(e));}}),this.on(N,async e=>{this.options.raw&&this.emit(`message`,e);let t=await ae(e,this.zlib).catch(e=>(e instanceof Error&&this.emit(`deserialize:error`,e),[]));for(let e of t){if(e.meta.op===5){let t=e.data?.cmd||e.data?.msg&&e.data?.msg?.cmd;if(this.skipMessage.length>0&&this.skipMessage.includes(t))continue;if(this.options.stub&&this.emit(`msg`,e),t===`SEND_GIFT_V2`)try{let{pb:t,...n}=e.data.data;for(let r of E(t))this.emit(`SEND_GIFT_V2`,{...e,data:{...e.data,data:{...n,...r}}});}catch(e){e instanceof Error&&this.emit(`deserialize:error`,e);}else t.includes(`DANMU_MSG`)?this.emit(`DANMU_MSG`,e):this.emit(t,e);continue}if(e.meta.op===3){this.online=e.data,clearTimeout(this.timeout),this.timeout=setTimeout(()=>this.heartbeat(),this.HEARTBEAT_TIME),this.emit(`heartbeat`,this.online);continue}e.meta.op===8&&(typeof e.data==`object`&&e.data?.code!==0&&console.warn(`连接失败: `,e.data),this.emit(`live`),this.live=!0,this.send(2));}}),this.on(F,e=>{this.emit(`error`,e);}),this.on(I,e=>{this.emit(`close`,e),this.options.keepalive&&!this.manualClose?(this.emit(`reconnect`,!0),clearTimeout(this.reconnectTimer),this.reconnectTimer=setTimeout(()=>{clearTimeout(this.reconnectTimer),this.resetConnectionState(),this.clearTimers(),this.socket.reconnect();},this.RECONNECT_TIME)):(this.resetConnectionState(),this.clearTimers(),this.manualClose=!1);});}send(e,t={}){this.rawSend(m(e,t));}async runWhenConnected(...e){this.live||await D(this,`live`);for(let t of e)t();}heartbeat(){this.send(2);}async getOnline(){return this.live||await D(this,`live`),new Promise(e=>{this.once(`heartbeat`,t=>{e(typeof t==`number`?t:t.data);}),this.heartbeat();})}close(){return this.manualClose=!0,this.clearTimers(),this.live?(`end`in this.socket?this.socket.end():this.socket.close(),!0):!1}reconnect(){this.resetConnectionState(),this.clearTimers(),this.manualClose=!1,this.emit(`reconnect`,!1),this.socket.reconnect();}};const H={raw:!1,stub:!0,ssl:!0,keepalive:!0,reconnectTime:5*1e3,heartbeatTime:30*1e3,platform:`web`,protover:3,type:2},U=[46,47,18,2,53,8,23,32,15,50,10,31,58,3,45,35,27,43,5,49,33,9,42,19,29,28,14,39,12,38,41,13,37,48,7,16,24,55,40,61,26,17,0,1,60,51,30,4,22,25,54,21,56,59,6,63,57,62,11,36,20,34,44,52];function W$1(e){let t=``;return U.forEach(n=>{t+=e[n];}),t.slice(0,32)}function le(e){let t=crypto$d.createHash(`md5`);return t.update(e),t.digest(`hex`)}function ue(e,t,n){let r=W$1(t+n),i=Math.round(Date.now()/1e3),a=/[!'()*]/g,o=[];Object.assign(e,{wts:i}),Object.keys(e).sort().forEach(t=>{o.push(`${encodeURIComponent(t)}=${encodeURIComponent(e[t].toString().replace(a,``))}`);});let s=o.join(`&`);return `${s}&w_rid=${le(s+r)}`}async function de(e){let t=await pe();return ue(e,t.img_key,t.sub_key)}const G$2=new Map,K=new Map;let q;function J(e,t={}){return fetch(e,{headers:{"User-Agent":`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36`,...t.headers},...t})}async function Y(e,t){let n=await J(`https://api.live.bilibili.com/room/v1/Room/mobileRoomInit?id=${e}`,{headers:t});if(!n.ok)throw Error(`Failed to get long room id: ${n.statusText}`);return await n.json()}async function fe(e,t){let n=await J(`https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?${e}`,{headers:t});if(!n.ok)throw Error(`Failed to get danmu conf: ${n.statusText}`);let r=await n.json();if(r.code!==0)throw Error(`Failed to get danmu conf: ${r.code} ${r.message}`);return r}async function X(e){let t=await J(`https://api.bilibili.com/x/frontend/finger/spi`,{headers:e});if(!t.ok)throw Error(`Failed to get buvid conf: ${t.statusText}`);return await t.json()}async function Z(e,t){let n,r;if(G$2.has(e))n=G$2.get(e);else {let r=await M$1(()=>Y(e,t.headers),2,200);G$2.set(e,r),n=r;}let i=K.get(n.data.room_id);if(i&&i.expiresAt>Date.now())r=i.info;else {K.delete(n.data.room_id);let e=await de({id:n.data.room_id,type:0,wts:Math.floor(Date.now()/1e3)}),i=await M$1(()=>fe(e,t.headers),2,200);K.set(n.data.room_id,{info:i,expiresAt:Date.now()+2592e5}),r=i;}return q||=(await M$1(()=>X(t.headers),2,200)).data.b_3,[n,r,q]}async function pe(){let e=await J(`https://api.bilibili.com/x/web-interface/nav`);if(!e.ok)throw Error(`Failed to get wbi keys: ${e.statusText}`);let t=await e.json(),n=t.data.wbi_img.img_url,r=t.data.wbi_img.sub_url;return {img_key:n.slice(n.lastIndexOf(`/`)+1,n.lastIndexOf(`.`)),sub_key:r.slice(r.lastIndexOf(`/`)+1,r.lastIndexOf(`.`))}}function Q(e,t){return (n,r)=>{n?t(n):e(r);}}function me(e,t){return new Promise((n,r)=>{zlib$5.brotliDecompress(e,t??{},Q(n,r));})}function he(e,t){return new Promise((n,r)=>{zlib$5.inflate(e,t??{},Q(n,r));})}const $={inflateAsync:he,brotliDecompressAsync:me};var ge=class extends V{constructor(e,t=H){let n={...Object.assign({},H,t),socket:{type:`tcp`,write:e=>{this.tcpSocket.write(e);},reconnect:L,end:()=>{this.tcpSocket.end();}},zlib:$,room:e};super(n),this.buffer=new Uint8Array,this.i=0,this.init(n);}async getSocketUrl(e){let t;try{let[n,r,i]=await Z(e,this.options);this.options.key||(this.options.key=r.data.token),this.options.buvid||(this.options.buvid=i),t=A(r.data.host_list);}catch(e){console.error(e);}return {host:t?.host,port:t?.port}}async init(e){let n=j(e.room),r=e.url?e.url:await this.getSocketUrl(n),i=G$2.get(n)?.data?.room_id||n;this.options.room=i,this.roomId=i;let a=typeof r==`string`?require$$1$7.connect(r):require$$1$7.connect(r.port??2243,r.host??`zj-cn-live-comet.chat.bilibili.com`);this.options.socket.reconnect=()=>{this.tcpSocket?.end(),this.tcpSocket=null;let e=typeof r==`string`?require$$1$7.connect(r):require$$1$7.connect(r.port??2243,r.host??`zj-cn-live-comet.chat.bilibili.com`);this.tcpSocket=e,this._bindEvent(e);},this.tcpSocket=a,this._bindEvent(a);}_bindEvent(e){e.on(`ready`,()=>this.emit(P)),e.on(`close`,e=>this.emit(I,e)),e.on(`error`,e=>this.emit(F,e)),e.on(`data`,e=>{this.buffer=new Uint8Array([...this.buffer,...e]),this.splitBuffer();});}splitBuffer(){for(;this.buffer.length>=4&&u$1(this.buffer,0)<=this.buffer.length;){let e=u$1(this.buffer,0),t=this.buffer.subarray(0,e);this.buffer=this.buffer.subarray(e),this.i++,this.i>5&&(this.i=0,this.buffer=new Uint8Array(this.buffer)),this.emit(N,t);}}};
282683
283143
 
282684
283144
  // src/index.ts
282685
283145
  var startListen = (roomId, handler, options) => {
282686
- const live = new xe(roomId, options?.ws);
283146
+ const live = new ge(roomId, options?.ws);
282687
283147
  listenAll(live, roomId, handler);
282688
283148
  const listenerInstance = {
282689
283149
  live,
@@ -282744,7 +283204,7 @@ async function getBuvidConfWithRetry(maxRetries = 3, retryDelay = 1000) {
282744
283204
  // 这里不应该到达,但为了类型安全
282745
283205
  throw lastError;
282746
283206
  }
282747
- class DanmaClient extends EventEmitter$k.EventEmitter {
283207
+ class DanmaClient extends EventEmitter$l.EventEmitter {
282748
283208
  client = null;
282749
283209
  roomId;
282750
283210
  auth;
@@ -365615,7 +366075,7 @@ class CacheableRequest {
365615
366075
  key.toLowerCase(),
365616
366076
  value,
365617
366077
  ]));
365618
- const ee = new EventEmitter$k();
366078
+ const ee = new EventEmitter$l();
365619
366079
  const normalizedUrlString = normalizeUrl(urlLib.format(url), {
365620
366080
  stripWWW: false,
365621
366081
  removeTrailingSlash: false,
@@ -366069,7 +366529,7 @@ const timer = (request) => {
366069
366529
  };
366070
366530
  request.timings = timings;
366071
366531
  const handleError = (origin) => {
366072
- origin.once(EventEmitter$k.errorMonitor, () => {
366532
+ origin.once(EventEmitter$l.errorMonitor, () => {
366073
366533
  timings.error = Date.now();
366074
366534
  timings.phases.total = timings.error - timings.start;
366075
366535
  });
@@ -372389,7 +372849,7 @@ let Request$1 = class Request extends require$$0$b.Duplex {
372389
372849
  abort();
372390
372850
  }
372391
372851
  else {
372392
- this._abortListenerDisposer = EventEmitter$k.addAbortListener(signal, abort);
372852
+ this._abortListenerDisposer = EventEmitter$l.addAbortListener(signal, abort);
372393
372853
  }
372394
372854
  }
372395
372855
  _shouldIncrementallyDecodeBody() {
@@ -373834,7 +374294,7 @@ const proxiedRequestEvents = [
373834
374294
  function asPromise(firstRequest) {
373835
374295
  let globalRequest;
373836
374296
  let globalResponse;
373837
- const emitter = new EventEmitter$k.EventEmitter();
374297
+ const emitter = new EventEmitter$l.EventEmitter();
373838
374298
  let promiseSettled = false;
373839
374299
  const promise = new Promise((resolve, reject) => {
373840
374300
  const makeRequest = (retryCount, defaultOptions) => {
@@ -380464,7 +380924,7 @@ function __decorate(decorators, target, key, desc) {
380464
380924
  }
380465
380925
  //#endregion
380466
380926
  //#region src/lib/client/index.ts
380467
- var TikTokLiveConnection = class extends EventEmitter$k.EventEmitter {
380927
+ var TikTokLiveConnection = class extends EventEmitter$l.EventEmitter {
380468
380928
  options;
380469
380929
  _webClient;
380470
380930
  _wsClientInstance = null;
@@ -380965,7 +381425,7 @@ function getTimestamp(value) {
380965
381425
  return Date.now();
380966
381426
  return timestamp < 1_000_000_000_000 ? timestamp * 1000 : timestamp;
380967
381427
  }
380968
- class TikTokDanmaClient extends EventEmitter$k.EventEmitter {
381428
+ class TikTokDanmaClient extends EventEmitter$l.EventEmitter {
380969
381429
  uniqueId;
380970
381430
  connection = null;
380971
381431
  connectionFactory;
@@ -381552,7 +382012,29 @@ class RecorderConfig {
381552
382012
  const setting = this.appConfig.get("recorders");
381553
382013
  return setting.find((setting) => setting.id === id);
381554
382014
  }
381555
- get(id) {
382015
+ getAuth(providerId, uid, authCache) {
382016
+ const key = `${providerId}:${uid}`;
382017
+ if (authCache.has(key))
382018
+ return authCache.get(key);
382019
+ let auth;
382020
+ try {
382021
+ if (providerId === "Bilibili") {
382022
+ auth = Object.entries(getCookie$2(uid))
382023
+ .map(([key, value]) => `${key}=${value}`)
382024
+ .join("; ");
382025
+ }
382026
+ else {
382027
+ auth = readDouyuUser(uid)?.loginCookies.main;
382028
+ }
382029
+ }
382030
+ catch (error) {
382031
+ console.error(error);
382032
+ }
382033
+ authCache.set(key, auth);
382034
+ return auth;
382035
+ }
382036
+ get(id, opts = {}) {
382037
+ const { authCache = new Map() } = opts;
381556
382038
  const getValue = (key) => {
381557
382039
  if ((setting?.noGlobalFollowFields ?? []).includes(key)) {
381558
382040
  return setting?.[key];
@@ -381703,40 +382185,18 @@ class RecorderConfig {
381703
382185
  }
381704
382186
  }
381705
382187
  };
381706
- const settings = this.appConfig.get("recorders");
381707
- const globalConfig = this.appConfig.get("recorder");
382188
+ const settings = this.appConfig.get("recorders", true);
382189
+ const globalConfig = this.appConfig.get("recorder", true);
381708
382190
  const setting = settings.find((setting) => setting.id === id);
381709
382191
  if (!setting)
381710
382192
  return null;
381711
382193
  // 授权处理
381712
382194
  let uid = undefined;
381713
382195
  let auth;
381714
- if (setting.providerId === "Bilibili") {
381715
- uid = getValue("uid");
381716
- if (uid) {
381717
- try {
381718
- const cookies = getCookie$2(Number(uid));
381719
- auth = Object.entries(cookies)
381720
- .map(([key, value]) => {
381721
- return `${key}=${value}`;
381722
- })
381723
- .join("; ");
381724
- }
381725
- catch (error) {
381726
- console.error(error);
381727
- }
381728
- }
381729
- }
381730
- else if (setting.providerId === "DouYu") {
382196
+ if (setting.providerId === "Bilibili" || setting.providerId === "DouYu") {
381731
382197
  uid = getValue("uid");
381732
382198
  if (uid) {
381733
- try {
381734
- auth = readDouyuUser(Number(uid))?.loginCookies.main;
381735
- // console.log("pp", readDouyuUser(Number(uid)));
381736
- }
381737
- catch (error) {
381738
- console.error(error);
381739
- }
382199
+ auth = this.getAuth(setting.providerId, Number(uid), authCache);
381740
382200
  }
381741
382201
  }
381742
382202
  else if (setting.providerId === "DouYin") {
@@ -381795,6 +382255,7 @@ class RecorderConfig {
381795
382255
  disableProvideCommentsWhenRecording: disableProvideCommentsWhenRecording,
381796
382256
  saveGiftDanma: getValue("saveGiftDanma") ?? false,
381797
382257
  saveSCDanma: getValue("saveSCDanma") ?? true,
382258
+ saveDanmaStats2DB: getValue("saveDanmaStats2DB") ?? false,
381798
382259
  saveCover: getValue("saveCover") ?? false,
381799
382260
  convert2Mp4: getValue("convert2Mp4") ?? false,
381800
382261
  segment: getValue("segment") ?? 90,
@@ -381820,9 +382281,16 @@ class RecorderConfig {
381820
382281
  }
381821
382282
  list() {
381822
382283
  const recorders = this.appConfig.get("recorders");
382284
+ const authCache = new Map();
382285
+ for (const uid of Object.keys(this.appConfig.get("bilibiliUser", true) || {})) {
382286
+ this.getAuth("Bilibili", Number(uid), authCache);
382287
+ }
382288
+ for (const uid of Object.keys(this.appConfig.get("douyuUser", true) || {})) {
382289
+ this.getAuth("DouYu", Number(uid), authCache);
382290
+ }
381823
382291
  return recorders
381824
382292
  .map((recorder) => {
381825
- return this.get(recorder.id);
382293
+ return this.get(recorder.id, { authCache });
381826
382294
  })
381827
382295
  .filter((recorder) => recorder != null);
381828
382296
  }
@@ -382259,13 +382727,14 @@ async function createRecorderManager(appConfig) {
382259
382727
  video_filename: videoFilename,
382260
382728
  quick_hash: quickHash,
382261
382729
  });
382262
- if (stats) {
382730
+ if (data?.saveDanmaStats2DB && stats) {
382263
382731
  recordHistory.upadteLive({
382264
382732
  video_file: filename,
382265
382733
  live_id: liveId,
382266
382734
  }, {
382267
382735
  danma_num: stats.danmaNum,
382268
382736
  interact_num: stats.uniqMember,
382737
+ danma_stats_json: JSON.stringify(stats.danmaStats),
382269
382738
  });
382270
382739
  }
382271
382740
  else if (xmlFile && (await fs$m.pathExists(xmlFile))) {
@@ -382413,7 +382882,10 @@ async function createRecorderManager(appConfig) {
382413
382882
  });
382414
382883
  }
382415
382884
  });
382416
- appConfig.on("update", () => {
382885
+ appConfig.on("update", (_newVal, _oldVal, key) => {
382886
+ // @ts-ignore
382887
+ if (["tool", "recorders"].includes(key))
382888
+ return;
382417
382889
  const { ffmpegPath, mesioPath, bililiveRecorderPath } = getBinPath();
382418
382890
  setFFMPEGPath(ffmpegPath);
382419
382891
  setMesioPath(mesioPath);
@@ -382452,8 +382924,8 @@ async function createRecorderManager(appConfig) {
382452
382924
  manager,
382453
382925
  config: recorderConfig,
382454
382926
  addRecorder: async (recorder) => {
382455
- const recorders = recorderConfig.list();
382456
- if (recorders.findIndex((item) => item.channelId === recorder.channelId && item.providerId === recorder.providerId) !== -1) {
382927
+ const recorders = appConfig.get("recorders");
382928
+ if (recorders.some((item) => item.channelId === recorder.channelId && item.providerId === recorder.providerId)) {
382457
382929
  return null;
382458
382930
  }
382459
382931
  recorderConfig.add(recorder);
@@ -382511,8 +382983,10 @@ const init = async (config) => {
382511
382983
  });
382512
382984
  const logLevel = appConfig.get("logLevel");
382513
382985
  initLogger(config.logPath, logLevel);
382514
- appConfig.on("update", (data) => {
382515
- setLogLevel(data.logLevel);
382986
+ appConfig.on("update", (newData, oldData) => {
382987
+ if (newData.logLevel !== oldData.logLevel) {
382988
+ setLogLevel(newData.logLevel);
382989
+ }
382516
382990
  });
382517
382991
  initDB(config.userDataPath);
382518
382992
  container.register({
@@ -382668,6 +383142,7 @@ exports.extension = extension$4;
382668
383142
  exports.fetch = fetch$2;
382669
383143
  exports.formatDesc = formatDesc;
382670
383144
  exports.formatPartTitle = formatPartTitle;
383145
+ exports.formatSeasonTitle = formatSeasonTitle;
382671
383146
  exports.formatTitle = formatTitle;
382672
383147
  exports.fs = fs$m;
382673
383148
  exports.functionBind = functionBind;