@dan-uni/dan-any 1.1.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/browser/157.min.js +20 -4
  2. package/dist/browser/17.min.js +13289 -0
  3. package/dist/browser/898.min.js +10 -0
  4. package/dist/browser/index.min.js +1 -13248
  5. package/dist/browser/plugins/bili-dedupe.min.js +1 -1
  6. package/dist/browser/plugins/index.min.js +1 -0
  7. package/dist/browser/plugins/stats.min.js +1 -0
  8. package/dist/browser/src/index.d.ts +4 -4
  9. package/dist/browser/src/plugins/bili-dedupe/index.d.ts +3 -5
  10. package/dist/browser/src/plugins/index.d.ts +2 -2
  11. package/dist/browser/src/plugins/stats/getLatestDan.d.ts +6 -0
  12. package/dist/browser/src/plugins/stats/index.d.ts +1 -0
  13. package/dist/browser/src/plugins/stats/index.test.d.ts +1 -0
  14. package/dist/node/157.js +20 -4
  15. package/dist/node/17.js +1864 -0
  16. package/dist/node/898.js +10 -0
  17. package/dist/node/index.js +1 -1823
  18. package/dist/node/plugins/bili-dedupe.js +1 -1
  19. package/dist/node/plugins/index.js +1 -0
  20. package/dist/node/plugins/stats.js +1 -0
  21. package/dist/node/src/index.d.ts +4 -4
  22. package/dist/node/src/plugins/bili-dedupe/index.d.ts +3 -5
  23. package/dist/node/src/plugins/index.d.ts +2 -2
  24. package/dist/node/src/plugins/stats/getLatestDan.d.ts +6 -0
  25. package/dist/node/src/plugins/stats/index.d.ts +1 -0
  26. package/dist/node/src/plugins/stats/index.test.d.ts +1 -0
  27. package/dist/umd/index.umd.min.js +65 -62
  28. package/dist/umd/plugins/bili-dedupe.umd.min.js +24997 -48
  29. package/dist/umd/plugins/bili-dedupe.umd.min.js.LICENSE.txt +34 -0
  30. package/dist/umd/plugins/index.umd.min.js +24971 -21
  31. package/dist/umd/plugins/index.umd.min.js.LICENSE.txt +34 -0
  32. package/dist/umd/plugins/stats.umd.min.js +39 -0
  33. package/dist/umd/src/index.d.ts +4 -4
  34. package/dist/umd/src/plugins/bili-dedupe/index.d.ts +3 -5
  35. package/dist/umd/src/plugins/index.d.ts +2 -2
  36. package/dist/umd/src/plugins/stats/getLatestDan.d.ts +6 -0
  37. package/dist/umd/src/plugins/stats/index.d.ts +1 -0
  38. package/dist/umd/src/plugins/stats/index.test.d.ts +1 -0
  39. package/package.json +1 -1
  40. package/rslib.config.ts +1 -0
  41. package/src/index.ts +8 -4
  42. package/src/plugins/bili-dedupe/index.test.ts +5 -2
  43. package/src/plugins/bili-dedupe/index.ts +13 -3
  44. package/src/plugins/index.ts +2 -3
  45. package/src/plugins/stats/getLatestDan.ts +13 -0
  46. package/src/plugins/stats/index.test.ts +39 -0
  47. package/src/plugins/stats/index.ts +1 -0
  48. package/dist/browser/42.min.js +0 -45
  49. package/dist/node/42.js +0 -45
  50. /package/dist/browser/{index.min.js.LICENSE.txt → 17.min.js.LICENSE.txt} +0 -0
@@ -0,0 +1,1864 @@
1
+ import { __webpack_require__ } from "./rslib-runtime.js";
2
+ import "reflect-metadata/lite";
3
+ import { IsDate, IsEmail, IsEnum, IsInt, IsNotEmpty, IsNumber, IsOptional, IsString, Max, Min, isEmail, isJSON, isObject, isString, validateOrReject } from "class-validator";
4
+ import { XMLBuilder, XMLParser } from "fast-xml-parser";
5
+ import json_bigint from "json-bigint";
6
+ import { create, fromBinary, toBinary } from "@bufbuild/protobuf";
7
+ import { file_google_protobuf_timestamp, timestampDate, timestampFromDate, timestampNow } from "@bufbuild/protobuf/wkt";
8
+ import { Expose, plainToInstance } from "class-transformer";
9
+ import hh_mm_ss from "hh-mm-ss";
10
+ import jssha from "jssha";
11
+ import { brotliCompressSync, brotliDecompressSync, gunzipSync, gzipSync } from "node:zlib";
12
+ import { decode, encode as external_base16384_encode } from "base16384";
13
+ import { fileDesc, messageDesc as codegenv2_messageDesc } from "@bufbuild/protobuf/codegenv2";
14
+ var dm_gen_namespaceObject = {};
15
+ __webpack_require__.r(dm_gen_namespaceObject);
16
+ __webpack_require__.d(dm_gen_namespaceObject, {
17
+ DMAttr: ()=>dm_gen_DMAttr,
18
+ ExtraDanUniChapterAction: ()=>dm_gen_ExtraDanUniChapterAction,
19
+ ExtraDanUniChapterType: ()=>dm_gen_ExtraDanUniChapterType,
20
+ Modes: ()=>dm_gen_Modes,
21
+ Pools: ()=>dm_gen_Pools,
22
+ UniDM: ()=>UniDM
23
+ });
24
+ var id_gen_namespaceObject = {};
25
+ __webpack_require__.r(id_gen_namespaceObject);
26
+ __webpack_require__.d(id_gen_namespaceObject, {
27
+ UniID: ()=>id_gen_UniID,
28
+ createDMID: ()=>createDMID
29
+ });
30
+ var platform_namespaceObject = {};
31
+ __webpack_require__.r(platform_namespaceObject);
32
+ __webpack_require__.d(platform_namespaceObject, {
33
+ PlatformDanmakuOnlySource: ()=>platform_PlatformDanmakuOnlySource,
34
+ PlatformDanmakuOnlySources: ()=>PlatformDanmakuOnlySources,
35
+ PlatformDanmakuSources: ()=>PlatformDanmakuSources,
36
+ PlatformInfoSource: ()=>platform_PlatformInfoSource,
37
+ PlatformInfoSources: ()=>PlatformInfoSources,
38
+ PlatformSources: ()=>PlatformSources,
39
+ PlatformVideoSource: ()=>platform_PlatformVideoSource,
40
+ PlatformVideoSources: ()=>PlatformVideoSources
41
+ });
42
+ var package_namespaceObject = JSON.parse('{"UU":"@dan-uni/dan-any","rE":"1.2.2","TB":"https://github.com/ani-uni/danuni/tree/master/packages/dan-any#readme"}');
43
+ const color_pad = (s)=>s.length < 2 ? `0${s}` : s;
44
+ const decimalToHex = (n)=>color_pad(n.toString(16));
45
+ const isDarkColor = ({ r, g, b })=>0.299 * r + 0.587 * g + 0.114 * b < 0x30;
46
+ const WHITE = {
47
+ r: 255,
48
+ g: 255,
49
+ b: 255
50
+ };
51
+ const BLACK = {
52
+ r: 0,
53
+ g: 0,
54
+ b: 0
55
+ };
56
+ const hexColorToRGB = (hex)=>{
57
+ if (0 === hex.indexOf('#')) hex = hex.slice(1);
58
+ const [r, g, b] = 3 === hex.length ? hex.split('').map((c)=>c + c) : hex.match(/../g) || [];
59
+ return {
60
+ r: Number.parseInt(r, 16),
61
+ g: Number.parseInt(g, 16),
62
+ b: Number.parseInt(b, 16)
63
+ };
64
+ };
65
+ const formatColor = ({ r, g, b }, opacity)=>{
66
+ const color = [
67
+ b,
68
+ g,
69
+ r
70
+ ];
71
+ if (void 0 !== opacity) {
72
+ const alpha = Math.round((1 - opacity) * 255);
73
+ color.unshift(alpha);
74
+ }
75
+ return `&H${color.map(decimalToHex).join('').toUpperCase()}`;
76
+ };
77
+ const getDecoratingColor = (color)=>isDarkColor(color) ? WHITE : BLACK;
78
+ const isWhite = (color)=>255 === color.r && 255 === color.g && 255 === color.b;
79
+ var platform_PlatformInfoSource = /*#__PURE__*/ function(PlatformInfoSource) {
80
+ PlatformInfoSource["Bangumi"] = "bgm";
81
+ PlatformInfoSource["TMDB"] = "tmdb";
82
+ return PlatformInfoSource;
83
+ }({});
84
+ const PlatformInfoSources = Object.values(platform_PlatformInfoSource);
85
+ var platform_PlatformVideoSource = /*#__PURE__*/ function(PlatformVideoSource) {
86
+ PlatformVideoSource["Acfun"] = "acfun";
87
+ PlatformVideoSource["Baha"] = "baha";
88
+ PlatformVideoSource["Bilibili"] = "bili";
89
+ PlatformVideoSource["BilibiliGlobal"] = "bglobal";
90
+ PlatformVideoSource["Iqiyi"] = "iqiyi";
91
+ PlatformVideoSource["Tencent"] = "tencent";
92
+ PlatformVideoSource["Youku"] = "youku";
93
+ return PlatformVideoSource;
94
+ }({});
95
+ const PlatformVideoSources = Object.values(platform_PlatformVideoSource);
96
+ var platform_PlatformDanmakuOnlySource = /*#__PURE__*/ function(PlatformDanmakuOnlySource) {
97
+ PlatformDanmakuOnlySource["DanDanPlay"] = "ddplay";
98
+ PlatformDanmakuOnlySource["TuCao"] = "tucao";
99
+ return PlatformDanmakuOnlySource;
100
+ }({});
101
+ const PlatformDanmakuOnlySources = Object.values(platform_PlatformDanmakuOnlySource);
102
+ const PlatformDanmakuSources = [
103
+ ...PlatformVideoSources,
104
+ ...PlatformDanmakuOnlySources
105
+ ];
106
+ const PlatformSources = [
107
+ ...PlatformInfoSources,
108
+ ...PlatformDanmakuSources
109
+ ];
110
+ class id_gen_UniID {
111
+ constructor(id, domain){
112
+ this.id = id;
113
+ this.domain = domain;
114
+ }
115
+ static fromString(str) {
116
+ const [id, domain] = str.split('@');
117
+ return new id_gen_UniID(id, domain);
118
+ }
119
+ toString() {
120
+ return `${this.id}@${this.domain}`;
121
+ }
122
+ static fromNull(domain) {
123
+ return new id_gen_UniID('runtime' === domain ? 'runtime' : 'anonymous', domain || 'danuni');
124
+ }
125
+ static fromBili({ cid, mid, midHash }) {
126
+ if (cid) return new id_gen_UniID(cid.toString(), platform_PlatformVideoSource.Bilibili);
127
+ if (mid) return new id_gen_UniID(mid.toString(), platform_PlatformVideoSource.Bilibili);
128
+ if (midHash) return new id_gen_UniID(midHash, platform_PlatformVideoSource.Bilibili);
129
+ return this.fromNull(platform_PlatformVideoSource.Bilibili);
130
+ }
131
+ static fromUnknown(id, domain) {
132
+ if (id) return new id_gen_UniID(id, domain);
133
+ return this.fromNull(domain);
134
+ }
135
+ }
136
+ function createDMID(dan, slice = 8) {
137
+ return new jssha('SHA3-256', 'TEXT').update(`${dan.content}|${dan.mode}|${dan.pool}|${dan.platform}|${dan.extraStr}|${dan.senderID}|${UniDM.transCtime(dan.ctime).toISOString()}`).getHash('HEX').slice(0, slice);
138
+ }
139
+ function _ts_decorate(decorators, target, key, desc) {
140
+ var c = arguments.length, r = c < 3 ? target : null === desc ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
141
+ if ("object" == typeof Reflect && "function" == typeof Reflect.decorate) r = Reflect.decorate(decorators, target, key, desc);
142
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
143
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
144
+ }
145
+ function _ts_metadata(k, v) {
146
+ if ("object" == typeof Reflect && "function" == typeof Reflect.metadata) return Reflect.metadata(k, v);
147
+ }
148
+ const dm_gen_JSON = json_bigint({
149
+ useNativeBigInt: true
150
+ });
151
+ function cleanEmptyObjects(obj) {
152
+ if (null === obj || 'object' != typeof obj) return obj;
153
+ if (Array.isArray(obj)) return obj;
154
+ const cleaned = {};
155
+ for (const [key, value] of Object.entries(obj)){
156
+ const cleanedValue = cleanEmptyObjects(value);
157
+ if (void 0 !== cleanedValue && ('object' != typeof cleanedValue || 0 !== Object.keys(cleanedValue).length)) cleaned[key] = cleanedValue;
158
+ }
159
+ return Object.keys(cleaned).length > 0 ? cleaned : {};
160
+ }
161
+ class SetBin {
162
+ constructor(bin){
163
+ this.bin = bin;
164
+ }
165
+ set1(bit) {
166
+ this.bin |= 1 << bit;
167
+ }
168
+ set0(bit) {
169
+ this.bin &= ~(1 << bit);
170
+ }
171
+ }
172
+ const toBits = (number)=>{
173
+ const bits = [];
174
+ do {
175
+ bits.unshift(!!(1 & number));
176
+ number >>= 1;
177
+ }while (number);
178
+ return bits.toReversed();
179
+ };
180
+ var dm_gen_DMAttr = /*#__PURE__*/ function(DMAttr) {
181
+ DMAttr["Protect"] = "Protect";
182
+ DMAttr["FromLive"] = "FromLive";
183
+ DMAttr["HighLike"] = "HighLike";
184
+ DMAttr["Compatible"] = "Compatible";
185
+ DMAttr["Reported"] = "Reported";
186
+ DMAttr["Unchecked"] = "Unchecked";
187
+ DMAttr["HasEvent"] = "HasEvent";
188
+ DMAttr["Hide"] = "Hide";
189
+ return DMAttr;
190
+ }({});
191
+ const DMAttrUtils = {
192
+ fromBin (bin = 0, format) {
193
+ const array = toBits(bin);
194
+ const attr = [];
195
+ if ('bili' === format) {
196
+ if (array[0]) attr.push("Protect");
197
+ if (array[1]) attr.push("FromLive");
198
+ if (array[2]) attr.push("HighLike");
199
+ }
200
+ return attr;
201
+ },
202
+ toBin (attr = [], format) {
203
+ const bin = new SetBin(0);
204
+ if ('bili' === format) {
205
+ if (attr.includes("Protect")) bin.set1(0);
206
+ if (attr.includes("FromLive")) bin.set1(1);
207
+ if (attr.includes("HighLike")) bin.set1(2);
208
+ }
209
+ return bin.bin;
210
+ }
211
+ };
212
+ var dm_gen_ExtraDanUniChapterType = /*#__PURE__*/ function(ExtraDanUniChapterType) {
213
+ ExtraDanUniChapterType["Chapter"] = "ch";
214
+ ExtraDanUniChapterType["Review"] = "rev";
215
+ ExtraDanUniChapterType["OP"] = "op";
216
+ ExtraDanUniChapterType["Intermission"] = "int";
217
+ ExtraDanUniChapterType["ED"] = "ed";
218
+ ExtraDanUniChapterType["Preview"] = "prvw";
219
+ ExtraDanUniChapterType["Cut"] = "cut";
220
+ ExtraDanUniChapterType["Duplicate"] = "dup";
221
+ ExtraDanUniChapterType["AdBiz"] = "biz";
222
+ ExtraDanUniChapterType["AdUnpaid"] = "promo";
223
+ return ExtraDanUniChapterType;
224
+ }({});
225
+ const ExtraDanUniChapterTypeDict = {
226
+ chs: {
227
+ ch: '其它片段',
228
+ rev: '回顾',
229
+ op: '片头',
230
+ int: '中场',
231
+ ed: '片尾',
232
+ prvw: '预告',
233
+ cut: '删减',
234
+ dup: '补档',
235
+ biz: '商业广告',
236
+ promo: '推广'
237
+ }
238
+ };
239
+ var dm_gen_ExtraDanUniChapterAction = /*#__PURE__*/ function(ExtraDanUniChapterAction) {
240
+ ExtraDanUniChapterAction[ExtraDanUniChapterAction["Disabled"] = -1] = "Disabled";
241
+ ExtraDanUniChapterAction[ExtraDanUniChapterAction["ShowOverlay"] = 0] = "ShowOverlay";
242
+ ExtraDanUniChapterAction[ExtraDanUniChapterAction["ManualSkip"] = 1] = "ManualSkip";
243
+ ExtraDanUniChapterAction[ExtraDanUniChapterAction["AutoSkip"] = 2] = "AutoSkip";
244
+ return ExtraDanUniChapterAction;
245
+ }({});
246
+ var dm_gen_Modes = /*#__PURE__*/ function(Modes) {
247
+ Modes[Modes["Normal"] = 0] = "Normal";
248
+ Modes[Modes["Bottom"] = 1] = "Bottom";
249
+ Modes[Modes["Top"] = 2] = "Top";
250
+ Modes[Modes["Reverse"] = 3] = "Reverse";
251
+ Modes[Modes["Ext"] = 4] = "Ext";
252
+ return Modes;
253
+ }({});
254
+ var dm_gen_Pools = /*#__PURE__*/ function(Pools) {
255
+ Pools[Pools["Def"] = 0] = "Def";
256
+ Pools[Pools["Sub"] = 1] = "Sub";
257
+ Pools[Pools["Adv"] = 2] = "Adv";
258
+ Pools[Pools["Ix"] = 3] = "Ix";
259
+ return Pools;
260
+ }({});
261
+ class UniDM {
262
+ init(options) {
263
+ this.options = options || this.options;
264
+ const def = new UniDM();
265
+ if (void 0 === this.options.dmid || true === this.options.dmid) this.options.dmid = createDMID;
266
+ this.content = String(this.content);
267
+ this.ctime = UniDM.transCtime(this.ctime);
268
+ if (!this.SOID) this.SOID = def.SOID;
269
+ if (!this.progress) this.progress = def.progress;
270
+ if (!this.mode) this.mode = def.mode;
271
+ if (!this.fontsize) this.fontsize = def.mode;
272
+ if (!this.color) this.color = def.color;
273
+ if (!this.senderID) this.senderID = def.senderID;
274
+ if (!this.content) this.content = def.content;
275
+ if (!this.ctime) this.ctime = def.ctime;
276
+ if (!this.weight) this.weight = def.weight;
277
+ if (!this.pool) this.pool = def.pool;
278
+ if (!this.attr) this.attr = def.attr;
279
+ if (!this.DMID && false !== this.options.dmid) this.DMID = this.toDMID();
280
+ this.progress = Number.parseFloat(this.progress.toFixed(3));
281
+ if (this.extraStr) this.extraStr = dm_gen_JSON.stringify(cleanEmptyObjects(dm_gen_JSON.parse(this.extraStr)));
282
+ if ('{}' === this.extraStr) this.extraStr = void 0;
283
+ else if (4 !== this.mode) {
284
+ const checkExtraBili = (obj)=>obj ? [
285
+ 'adv',
286
+ 'bas',
287
+ 'code',
288
+ 'command'
289
+ ].some((k)=>obj[k]) : false;
290
+ if (this.extra.artplayer || this.extra.danuni?.chapter || checkExtraBili(this.extra.bili)) this.mode = 4;
291
+ }
292
+ return this;
293
+ }
294
+ async validate() {
295
+ return validateOrReject(this);
296
+ }
297
+ static create(pjson, options) {
298
+ return pjson ? plainToInstance(UniDM, pjson.extra ? {
299
+ ...pjson,
300
+ extraStr: pjson.extra ? dm_gen_JSON.stringify(pjson.extra) : pjson.extraStr
301
+ } : pjson, {
302
+ excludeExtraneousValues: true
303
+ }).init(options) : new UniDM();
304
+ }
305
+ get extra() {
306
+ const extra = dm_gen_JSON.parse(this.extraStr || '{}');
307
+ return extra;
308
+ }
309
+ get isFrom3rdPlatform() {
310
+ if (this.platform && PlatformDanmakuSources.includes(this.platform)) return true;
311
+ return false;
312
+ }
313
+ toDMID() {
314
+ if (false === this.options.dmid) return;
315
+ if (true === this.options.dmid) return createDMID(this);
316
+ if ('number' == typeof this.options.dmid) return createDMID(this, this.options.dmid);
317
+ return this.options.dmid(this);
318
+ }
319
+ isSameAs(dan, options) {
320
+ if (this === dan) return true;
321
+ if (4 === this.mode || 4 === dan.mode) return false;
322
+ if (!options?.skipDanuniMerge && (this.extra.danuni?.merge || dan.extra.danuni?.merge)) return false;
323
+ if (this.extra.bili?.dmid && dan.extra.bili?.dmid) {
324
+ if (this.extra.bili.dmid && !dan.extra.bili.dmid || !this.extra.bili.dmid && dan.extra.bili.dmid) return false;
325
+ if (this.extra.bili.dmid === dan.extra.bili.dmid) return true;
326
+ return false;
327
+ }
328
+ if (this.extra.artplayer && !dan.extra.artplayer || !this.extra.artplayer && dan.extra.artplayer) return false;
329
+ if (this.extra.artplayer && dan.extra.artplayer && (this.extra.artplayer.border !== dan.extra.artplayer.border || dm_gen_JSON.stringify(this.extra.artplayer.style) !== dm_gen_JSON.stringify(dan.extra.artplayer.style))) return false;
330
+ const isSame = (k)=>this[k] === dan[k];
331
+ const checks = [
332
+ 'SOID',
333
+ 'content',
334
+ 'mode',
335
+ 'pool',
336
+ 'platform'
337
+ ].every((k)=>isSame(k));
338
+ return checks;
339
+ }
340
+ minify() {
341
+ const def = new UniDM();
342
+ const result = {
343
+ SOID: this.SOID
344
+ };
345
+ if (this.progress !== def.progress) result.progress = this.progress;
346
+ if (this.mode !== def.mode) result.mode = this.mode;
347
+ if (this.fontsize !== def.fontsize) result.fontsize = this.fontsize;
348
+ if (this.color !== def.color) result.color = this.color;
349
+ if (this.senderID !== def.senderID) result.senderID = this.senderID;
350
+ if (this.content !== def.content) result.content = this.content;
351
+ if (this.weight !== def.weight) result.weight = this.weight;
352
+ if (this.pool !== def.pool) result.pool = this.pool;
353
+ if (this.attr.length > 0) result.attr = this.attr;
354
+ if (void 0 !== this.platform) result.platform = this.platform;
355
+ if (this.extraStr && '{}' !== this.extraStr) result.extraStr = this.extraStr;
356
+ if (void 0 !== this.DMID) result.DMID = this.DMID;
357
+ return result;
358
+ }
359
+ downgradeAdvcancedDan({ include, exclude, cleanExtra = false } = {}) {
360
+ if (!this.extra) return this;
361
+ {
362
+ if (!include) include = [];
363
+ if (!exclude) exclude = [];
364
+ const check = (k)=>include?.includes(k) || !exclude?.includes(k);
365
+ const clone = UniDM.create(this);
366
+ clone.mode = 2;
367
+ if (check('danuni') && clone.extra.danuni) {
368
+ const danuni = clone.extra.danuni;
369
+ if (danuni.merge) {
370
+ const merge = danuni.merge;
371
+ clone.content = `${this.content} x${merge.count}`;
372
+ } else if (danuni.chapter) {
373
+ const chapter = danuni.chapter;
374
+ if ("cut" === chapter.type) clone.content = `[提示]${clone.platform}源${ExtraDanUniChapterTypeDict.chs[chapter.type]}了${chapter.duration}秒`;
375
+ else if ("dup" === chapter.type) clone.content = `[提示(${ExtraDanUniChapterTypeDict.chs[chapter.type]})]${clone.platform}源-${chapter.duration}秒`;
376
+ else clone.content = `[空降(${ExtraDanUniChapterTypeDict.chs[chapter.type]})]${hh_mm_ss.fromS(clone.progress + chapter.duration)}`;
377
+ }
378
+ } else if (check('bili') && clone.extra.bili) {
379
+ const bili = clone.extra.bili;
380
+ if (7 === bili.mode && bili.adv) clone.content = `[B站高级弹幕]${dm_gen_JSON.parse(bili.adv)[4] || ''}`;
381
+ else if (bili.command) {
382
+ const command = bili.command;
383
+ clone.content = `[B站指令弹幕]${command.content}`;
384
+ clone.fontsize = 36;
385
+ }
386
+ }
387
+ clone.senderID = 'compat[bot]@dan-any';
388
+ clone.attr.push("Compatible");
389
+ if (cleanExtra) clone.extraStr = void 0;
390
+ return clone;
391
+ }
392
+ }
393
+ static transCtime(oriCtime, tsUnit) {
394
+ function isMsTs(ts) {
395
+ if ('ms' === tsUnit) return true;
396
+ if ('s' === tsUnit) return false;
397
+ return ts < 100000000;
398
+ }
399
+ if ('number' == typeof oriCtime || 'bigint' == typeof oriCtime) if (isMsTs(oriCtime)) return new Date(Number(oriCtime));
400
+ else return new Date(1000 * Number(oriCtime));
401
+ if ('string' != typeof oriCtime) return oriCtime;
402
+ if (/^\d+n$/.test(oriCtime)) return new Date(Number(oriCtime.slice(0, -1)));
403
+ return new Date(oriCtime);
404
+ }
405
+ static transMode(oriMode, fmt) {
406
+ let mode = 0;
407
+ switch(fmt){
408
+ case 'bili':
409
+ switch(oriMode){
410
+ case 4:
411
+ mode = 1;
412
+ break;
413
+ case 5:
414
+ mode = 2;
415
+ break;
416
+ case 6:
417
+ mode = 3;
418
+ break;
419
+ case 7:
420
+ mode = 4;
421
+ break;
422
+ case 8:
423
+ mode = 4;
424
+ break;
425
+ case 9:
426
+ mode = 4;
427
+ break;
428
+ }
429
+ break;
430
+ case 'dplayer':
431
+ if (1 === oriMode) mode = 2;
432
+ else if (2 === oriMode) mode = 1;
433
+ break;
434
+ case 'artplayer':
435
+ if (1 === oriMode) mode = 2;
436
+ else if (2 === oriMode) mode = 1;
437
+ break;
438
+ case 'ddplay':
439
+ mode = this.transMode(oriMode, 'bili');
440
+ break;
441
+ default:
442
+ mode = 0;
443
+ break;
444
+ }
445
+ return mode;
446
+ }
447
+ static parseBiliSingle(p, c) {
448
+ const p_arr = p.split(',');
449
+ return {
450
+ content: c,
451
+ progress: Number.parseFloat(p_arr[0]),
452
+ mode: Number.parseInt(p_arr[1]),
453
+ fontsize: Number.parseInt(p_arr[2]),
454
+ color: Number.parseInt(p_arr[3]),
455
+ ctime: BigInt(p_arr[4]),
456
+ pool: Number.parseInt(p_arr[5]),
457
+ midHash: p_arr[6],
458
+ id: BigInt(p_arr[7]),
459
+ weight: Number.parseInt(p_arr[8])
460
+ };
461
+ }
462
+ static fromBili(args, cid, options, recSOID) {
463
+ if (args.oid && !cid) cid = args.oid;
464
+ const SOID = recSOID || `def_${platform_PlatformVideoSource.Bilibili}+${id_gen_UniID.fromBili({
465
+ cid
466
+ })}`;
467
+ const senderID = isEmail(args.midHash, {
468
+ require_tld: false
469
+ }) ? args.midHash : id_gen_UniID.fromBili({
470
+ midHash: args.midHash
471
+ });
472
+ let mode = 0;
473
+ const pool = args.pool;
474
+ const extra = {
475
+ bili: {
476
+ mode: args.mode,
477
+ pool: args.pool,
478
+ dmid: args.id,
479
+ attr: args.attr,
480
+ mid: args.mid
481
+ }
482
+ };
483
+ switch(args.mode){
484
+ case 4:
485
+ mode = 1;
486
+ break;
487
+ case 5:
488
+ mode = 2;
489
+ break;
490
+ case 6:
491
+ mode = 3;
492
+ break;
493
+ case 7:
494
+ mode = 4;
495
+ extra.bili.adv = args.content;
496
+ break;
497
+ case 8:
498
+ mode = 4;
499
+ extra.bili.code = args.content;
500
+ break;
501
+ case 9:
502
+ mode = 4;
503
+ extra.bili.bas = args.content;
504
+ break;
505
+ default:
506
+ mode = 0;
507
+ break;
508
+ }
509
+ return this.create({
510
+ ...args,
511
+ SOID,
512
+ mode,
513
+ senderID: senderID.toString(),
514
+ ctime: this.transCtime(args.ctime, 's'),
515
+ weight: args.weight || (3 === pool ? 1 : 0),
516
+ pool,
517
+ attr: DMAttrUtils.fromBin(args.attr, platform_PlatformVideoSource.Bilibili),
518
+ platform: platform_PlatformVideoSource.Bilibili,
519
+ extra
520
+ }, options);
521
+ }
522
+ toBiliXML(options) {
523
+ if (options?.skipBiliCommand && this.extra.bili?.command) return null;
524
+ const recMode = (mode, extra)=>{
525
+ switch(mode){
526
+ case 0:
527
+ return 1;
528
+ case 1:
529
+ return 4;
530
+ case 2:
531
+ return 5;
532
+ case 3:
533
+ return 6;
534
+ case 4:
535
+ if (!extra) return 1;
536
+ if (extra.adv) return 7;
537
+ if (extra.code) return 8;
538
+ else if (extra.bas) return 9;
539
+ else return 1;
540
+ default:
541
+ return 1;
542
+ }
543
+ };
544
+ const rMode = this.extra.bili?.mode || recMode(this.mode, this.extra?.bili);
545
+ let content;
546
+ switch(rMode){
547
+ case 7:
548
+ content = this.extra?.bili?.adv;
549
+ break;
550
+ case 8:
551
+ content = this.extra?.bili?.code;
552
+ break;
553
+ case 9:
554
+ content = this.extra?.bili?.bas;
555
+ break;
556
+ default:
557
+ content = this.content;
558
+ break;
559
+ }
560
+ return {
561
+ '#text': content ?? this.content,
562
+ '@_p': [
563
+ this.progress,
564
+ rMode,
565
+ this.fontsize,
566
+ this.color,
567
+ this.ctime.getTime() / 1000,
568
+ this.extra.bili?.pool || this.pool,
569
+ options?.avoidSenderIDWithAt ? this.senderID.replaceAll(`@${platform_PlatformVideoSource.Bilibili}`, '') : this.senderID,
570
+ this.extra.bili?.dmid || this.DMID || this.toDMID(),
571
+ this.weight
572
+ ].join(',')
573
+ };
574
+ }
575
+ static fromBiliCommand(args, cid, options) {
576
+ if (args.oid && !cid) cid = args.oid;
577
+ const SOID = `def_${platform_PlatformVideoSource.Bilibili}+${id_gen_UniID.fromBili({
578
+ cid
579
+ })}`;
580
+ const senderID = id_gen_UniID.fromBili({
581
+ mid: args.mid
582
+ });
583
+ return this.create({
584
+ ...args,
585
+ SOID,
586
+ mode: 4,
587
+ senderID: senderID.toString(),
588
+ ctime: new Date(`${args.ctime} GMT+0800`),
589
+ weight: 10,
590
+ pool: 2,
591
+ attr: [
592
+ "Protect"
593
+ ],
594
+ platform: platform_PlatformVideoSource.Bilibili,
595
+ extra: {
596
+ bili: {
597
+ command: args
598
+ }
599
+ }
600
+ }, options);
601
+ }
602
+ static fromDplayer(args, playerID, domain, options) {
603
+ const SOID = id_gen_UniID.fromUnknown(playerID, domain);
604
+ const senderID = id_gen_UniID.fromUnknown(args.midHash, domain);
605
+ return this.create({
606
+ ...args,
607
+ SOID: SOID.toString(),
608
+ mode: this.transMode(args.mode, 'dplayer'),
609
+ senderID: senderID.toString(),
610
+ platform: domain
611
+ }, options);
612
+ }
613
+ toDplayer() {
614
+ let mode = 0;
615
+ if (2 === this.mode) mode = 1;
616
+ else if (1 === this.mode) mode = 2;
617
+ return {
618
+ mode,
619
+ progress: this.progress,
620
+ color: this.color,
621
+ midHash: this.senderID,
622
+ content: this.content
623
+ };
624
+ }
625
+ static fromArtplayer(args, playerID, domain, options) {
626
+ const SOID = id_gen_UniID.fromUnknown(playerID, domain);
627
+ const senderID = id_gen_UniID.fromUnknown('', domain);
628
+ let extra = args.border ? {
629
+ artplayer: {
630
+ border: args.border,
631
+ style: {}
632
+ }
633
+ } : void 0;
634
+ if (args.style) extra = extra ? {
635
+ ...extra,
636
+ artplayer: {
637
+ ...extra.artplayer,
638
+ style: args.style
639
+ }
640
+ } : {
641
+ artplayer: {
642
+ style: args.style
643
+ }
644
+ };
645
+ return this.create({
646
+ ...args,
647
+ SOID: SOID.toString(),
648
+ mode: this.transMode(args.mode, 'artplayer'),
649
+ senderID: senderID.toString(),
650
+ platform: domain,
651
+ extra
652
+ }, options);
653
+ }
654
+ toArtplayer() {
655
+ let mode = 0;
656
+ if (2 === this.mode) mode = 1;
657
+ else if (1 === this.mode) mode = 2;
658
+ return {
659
+ progress: this.progress,
660
+ mode,
661
+ color: this.color,
662
+ content: this.content,
663
+ style: this.extra.artplayer?.style
664
+ };
665
+ }
666
+ static fromDDplay(args, episodeId, domain = platform_PlatformDanmakuOnlySource.DanDanPlay, options) {
667
+ const SOID = id_gen_UniID.fromUnknown(`def_${platform_PlatformDanmakuOnlySource.DanDanPlay}+${episodeId}`, domain);
668
+ return this.create({
669
+ ...args,
670
+ SOID: SOID.toString(),
671
+ mode: this.transMode(args.mode, 'ddplay'),
672
+ senderID: args.uid,
673
+ content: args.m,
674
+ platform: domain,
675
+ DMID: args.cid.toString()
676
+ }, options);
677
+ }
678
+ toDDplay() {
679
+ let mode = 1;
680
+ if (2 === this.mode) mode = 5;
681
+ else if (1 === this.mode) mode = 4;
682
+ return {
683
+ progress: this.progress,
684
+ mode,
685
+ color: this.color,
686
+ uid: this.senderID,
687
+ m: this.content,
688
+ cid: this.DMID ? BigInt(`0x${Buffer.from(this.DMID).toString('hex')}`) : 0n
689
+ };
690
+ }
691
+ constructor(){
692
+ this.SOID = id_gen_UniID.fromNull().toString();
693
+ this.progress = 0;
694
+ this.mode = 0;
695
+ this.fontsize = 25;
696
+ this.color = 16777215;
697
+ this.senderID = id_gen_UniID.fromNull().toString();
698
+ this.content = '';
699
+ this.ctime = new Date();
700
+ this.weight = 0;
701
+ this.pool = 0;
702
+ this.attr = [];
703
+ this.options = {
704
+ dmid: createDMID
705
+ };
706
+ }
707
+ }
708
+ _ts_decorate([
709
+ IsEmail({
710
+ require_tld: false
711
+ }),
712
+ IsString(),
713
+ IsNotEmpty(),
714
+ Expose(),
715
+ _ts_metadata("design:type", String)
716
+ ], UniDM.prototype, "SOID", void 0);
717
+ _ts_decorate([
718
+ Min(0),
719
+ IsNumber(),
720
+ IsNotEmpty(),
721
+ Expose(),
722
+ _ts_metadata("design:type", Number)
723
+ ], UniDM.prototype, "progress", void 0);
724
+ _ts_decorate([
725
+ IsEnum(dm_gen_Modes),
726
+ IsNotEmpty(),
727
+ Expose(),
728
+ _ts_metadata("design:type", Number)
729
+ ], UniDM.prototype, "mode", void 0);
730
+ _ts_decorate([
731
+ Max(64),
732
+ Min(12),
733
+ IsNumber(),
734
+ IsNotEmpty(),
735
+ Expose(),
736
+ _ts_metadata("design:type", Number)
737
+ ], UniDM.prototype, "fontsize", void 0);
738
+ _ts_decorate([
739
+ IsNumber(),
740
+ IsNotEmpty(),
741
+ Expose(),
742
+ _ts_metadata("design:type", Number)
743
+ ], UniDM.prototype, "color", void 0);
744
+ _ts_decorate([
745
+ IsEmail({
746
+ require_tld: false
747
+ }),
748
+ IsString(),
749
+ IsNotEmpty(),
750
+ Expose(),
751
+ _ts_metadata("design:type", String)
752
+ ], UniDM.prototype, "senderID", void 0);
753
+ _ts_decorate([
754
+ IsString(),
755
+ IsNotEmpty(),
756
+ Expose(),
757
+ _ts_metadata("design:type", String)
758
+ ], UniDM.prototype, "content", void 0);
759
+ _ts_decorate([
760
+ IsDate(),
761
+ IsNotEmpty(),
762
+ Expose(),
763
+ _ts_metadata("design:type", "u" < typeof Date ? Object : Date)
764
+ ], UniDM.prototype, "ctime", void 0);
765
+ _ts_decorate([
766
+ Max(11),
767
+ Min(0),
768
+ IsInt(),
769
+ IsNotEmpty(),
770
+ Expose(),
771
+ _ts_metadata("design:type", Number)
772
+ ], UniDM.prototype, "weight", void 0);
773
+ _ts_decorate([
774
+ IsEnum(dm_gen_Pools),
775
+ IsNotEmpty(),
776
+ Expose(),
777
+ _ts_metadata("design:type", Number)
778
+ ], UniDM.prototype, "pool", void 0);
779
+ _ts_decorate([
780
+ IsEnum(dm_gen_DMAttr, {
781
+ each: true
782
+ }),
783
+ IsNotEmpty(),
784
+ Expose(),
785
+ _ts_metadata("design:type", Array)
786
+ ], UniDM.prototype, "attr", void 0);
787
+ _ts_decorate([
788
+ IsString(),
789
+ IsOptional(),
790
+ Expose(),
791
+ _ts_metadata("design:type", Object)
792
+ ], UniDM.prototype, "platform", void 0);
793
+ _ts_decorate([
794
+ IsString(),
795
+ IsOptional(),
796
+ Expose(),
797
+ _ts_metadata("design:type", String)
798
+ ], UniDM.prototype, "extraStr", void 0);
799
+ _ts_decorate([
800
+ IsString(),
801
+ IsOptional(),
802
+ Expose(),
803
+ _ts_metadata("design:type", String)
804
+ ], UniDM.prototype, "DMID", void 0);
805
+ _ts_decorate([
806
+ Expose(),
807
+ _ts_metadata("design:type", Function),
808
+ _ts_metadata("design:paramtypes", [
809
+ "u" < typeof Options ? Object : Options
810
+ ]),
811
+ _ts_metadata("design:returntype", void 0)
812
+ ], UniDM.prototype, "init", null);
813
+ _ts_decorate([
814
+ Expose(),
815
+ _ts_metadata("design:type", Function),
816
+ _ts_metadata("design:paramtypes", []),
817
+ _ts_metadata("design:returntype", Promise)
818
+ ], UniDM.prototype, "validate", null);
819
+ _ts_decorate([
820
+ Expose(),
821
+ _ts_metadata("design:type", "u" < typeof Extra ? Object : Extra),
822
+ _ts_metadata("design:paramtypes", [])
823
+ ], UniDM.prototype, "extra", null);
824
+ _ts_decorate([
825
+ Expose(),
826
+ _ts_metadata("design:type", void 0),
827
+ _ts_metadata("design:paramtypes", [])
828
+ ], UniDM.prototype, "isFrom3rdPlatform", null);
829
+ _ts_decorate([
830
+ Expose(),
831
+ _ts_metadata("design:type", Function),
832
+ _ts_metadata("design:paramtypes", []),
833
+ _ts_metadata("design:returntype", void 0)
834
+ ], UniDM.prototype, "toDMID", null);
835
+ _ts_decorate([
836
+ Expose(),
837
+ _ts_metadata("design:type", Function),
838
+ _ts_metadata("design:paramtypes", [
839
+ Object,
840
+ Object
841
+ ]),
842
+ _ts_metadata("design:returntype", Boolean)
843
+ ], UniDM.prototype, "isSameAs", null);
844
+ _ts_decorate([
845
+ Expose(),
846
+ _ts_metadata("design:type", Function),
847
+ _ts_metadata("design:paramtypes", []),
848
+ _ts_metadata("design:returntype", void 0)
849
+ ], UniDM.prototype, "minify", null);
850
+ _ts_decorate([
851
+ Expose(),
852
+ _ts_metadata("design:type", Function),
853
+ _ts_metadata("design:paramtypes", [
854
+ Object
855
+ ]),
856
+ _ts_metadata("design:returntype", void 0)
857
+ ], UniDM.prototype, "downgradeAdvcancedDan", null);
858
+ _ts_decorate([
859
+ Expose(),
860
+ _ts_metadata("design:type", Function),
861
+ _ts_metadata("design:paramtypes", [
862
+ Object
863
+ ]),
864
+ _ts_metadata("design:returntype", void 0)
865
+ ], UniDM.prototype, "toBiliXML", null);
866
+ _ts_decorate([
867
+ Expose(),
868
+ _ts_metadata("design:type", Function),
869
+ _ts_metadata("design:paramtypes", []),
870
+ _ts_metadata("design:returntype", "u" < typeof DMDplayer ? Object : DMDplayer)
871
+ ], UniDM.prototype, "toDplayer", null);
872
+ _ts_decorate([
873
+ Expose(),
874
+ _ts_metadata("design:type", Function),
875
+ _ts_metadata("design:paramtypes", []),
876
+ _ts_metadata("design:returntype", "u" < typeof DMArtplayer ? Object : DMArtplayer)
877
+ ], UniDM.prototype, "toArtplayer", null);
878
+ _ts_decorate([
879
+ Expose(),
880
+ _ts_metadata("design:type", Function),
881
+ _ts_metadata("design:paramtypes", []),
882
+ _ts_metadata("design:returntype", "u" < typeof DMDDplay ? Object : DMDDplay)
883
+ ], UniDM.prototype, "toDDplay", null);
884
+ const DanmakuType = {
885
+ SCROLL: 1,
886
+ BOTTOM: 2,
887
+ TOP: 3
888
+ };
889
+ const FontSize = {
890
+ SMALL: 0,
891
+ NORMAL: 1,
892
+ LARGE: 2
893
+ };
894
+ function decimalToRGB888(decimal) {
895
+ const r = decimal >> 16 & 0xff;
896
+ const g = decimal >> 8 & 0xff;
897
+ const b = 0xff & decimal;
898
+ return {
899
+ r,
900
+ g,
901
+ b
902
+ };
903
+ }
904
+ function UniPool2DanmakuLists(UP) {
905
+ const dans = UP.dans;
906
+ let type = DanmakuType.SCROLL;
907
+ return dans.map((d)=>{
908
+ if (d.mode === dm_gen_Modes.Bottom) type = DanmakuType.BOTTOM;
909
+ else if (d.mode === dm_gen_Modes.Top) type = DanmakuType.TOP;
910
+ return {
911
+ time: d.progress,
912
+ type,
913
+ fontSizeType: d.fontsize,
914
+ content: d.content,
915
+ color: decimalToRGB888(d.color),
916
+ extra: d
917
+ };
918
+ });
919
+ }
920
+ function DanmakuList2UniPool(d, options) {
921
+ return new UniPool(d.map((d)=>UniDM.create(d.extra)), options);
922
+ }
923
+ const lang_assign = (source, ...targets)=>{
924
+ for (const target of targets)for (const key of Object.keys(target))source[key] = target[key];
925
+ return source;
926
+ };
927
+ const arrayOfLength = (length, defaultValue)=>{
928
+ const array = new Array(length);
929
+ for(let i = 0; i < length; i++)array[i] = defaultValue;
930
+ return array;
931
+ };
932
+ const computeScrollInTime = (rectWidth, screenWidth, scrollTime)=>{
933
+ const speed = (screenWidth + rectWidth) / scrollTime;
934
+ return rectWidth / speed;
935
+ };
936
+ const computeScrollOverTime = (rectWidth, screenWidth, scrollTime)=>{
937
+ const speed = (screenWidth + rectWidth) / scrollTime;
938
+ return screenWidth / speed;
939
+ };
940
+ const splitGrids = ({ fontSize, padding, playResY, bottomSpace })=>{
941
+ const defaultFontSize = fontSize[FontSize.NORMAL];
942
+ const paddingTop = padding[0];
943
+ const paddingBottom = padding[2];
944
+ const linesCount = Math.floor((playResY - bottomSpace) / (defaultFontSize + paddingTop + paddingBottom));
945
+ return {
946
+ 1: arrayOfLength(linesCount, {
947
+ start: 0,
948
+ end: 0,
949
+ width: 0
950
+ }),
951
+ 3: arrayOfLength(linesCount, 0),
952
+ 2: arrayOfLength(linesCount, 0)
953
+ };
954
+ };
955
+ const measureTextWidthConstructor = (canvasContext)=>{
956
+ const supportTextMeasure = !!canvasContext.measureText('中');
957
+ if (supportTextMeasure) return (fontName, fontSize, bold, text)=>{
958
+ canvasContext.font = `${bold ? 'bold' : 'normal'} ${fontSize}px ${fontName}`;
959
+ const textWidth = canvasContext.measureText(text).width;
960
+ return Math.round(textWidth);
961
+ };
962
+ console.warn('[Warn] node-canvas is installed without text measure support, layout may not be correct');
963
+ return (_fontName, fontSize, _bold, text)=>text.length * fontSize;
964
+ };
965
+ const resolveAvailableFixGrid = (grids, time)=>{
966
+ for (const [i, grid] of grids.entries())if (grid <= time) return i;
967
+ return -1;
968
+ };
969
+ const resolveAvailableScrollGrid = (grids, rectWidth, screenWidth, time, duration)=>{
970
+ for (const [i, previous] of grids.entries()){
971
+ const previousInTime = previous.start + computeScrollInTime(previous.width, screenWidth, duration);
972
+ const currentOverTime = time + computeScrollOverTime(rectWidth, screenWidth, duration);
973
+ if (time >= previousInTime && currentOverTime >= previous.end) return i;
974
+ }
975
+ return -1;
976
+ };
977
+ const initializeLayout = (config, canvasCtx)=>{
978
+ const { playResX, playResY, fontName, fontSize, bold, padding, scrollTime, fixTime, bottomSpace } = config;
979
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = padding;
980
+ const defaultFontSize = fontSize[FontSize.NORMAL];
981
+ const grids = splitGrids(config);
982
+ const gridHeight = defaultFontSize + paddingTop + paddingBottom;
983
+ return (danmaku)=>{
984
+ const targetGrids = grids[danmaku.type];
985
+ const danmakuFontSize = fontSize[danmaku.fontSizeType];
986
+ const rectWidth = measureTextWidthConstructor(canvasCtx)(fontName, danmakuFontSize, bold, danmaku.content) + paddingLeft + paddingRight;
987
+ const verticalOffset = paddingTop + Math.round((defaultFontSize - danmakuFontSize) / 2);
988
+ if (danmaku.type === DanmakuType.SCROLL) {
989
+ const scrollGrids = targetGrids;
990
+ const gridNumber = resolveAvailableScrollGrid(scrollGrids, rectWidth, playResX, danmaku.time, scrollTime);
991
+ if (gridNumber < 0) return null;
992
+ targetGrids[gridNumber] = {
993
+ width: rectWidth,
994
+ start: danmaku.time,
995
+ end: danmaku.time + scrollTime
996
+ };
997
+ const top = gridNumber * gridHeight + verticalOffset;
998
+ const start = playResX + paddingLeft;
999
+ const end = -rectWidth;
1000
+ return {
1001
+ ...danmaku,
1002
+ top,
1003
+ start,
1004
+ end
1005
+ };
1006
+ }
1007
+ {
1008
+ const gridNumber = resolveAvailableFixGrid(targetGrids, danmaku.time);
1009
+ if (gridNumber < 0) return null;
1010
+ if (danmaku.type === DanmakuType.TOP) {
1011
+ targetGrids[gridNumber] = danmaku.time + fixTime;
1012
+ const top = gridNumber * gridHeight + verticalOffset;
1013
+ const left = Math.round(playResX / 2);
1014
+ return {
1015
+ ...danmaku,
1016
+ top,
1017
+ left
1018
+ };
1019
+ }
1020
+ targetGrids[gridNumber] = danmaku.time + fixTime;
1021
+ const top = playResY - bottomSpace - gridHeight * gridNumber - gridHeight + verticalOffset;
1022
+ const left = Math.round(playResX / 2);
1023
+ return {
1024
+ ...danmaku,
1025
+ top,
1026
+ left
1027
+ };
1028
+ }
1029
+ };
1030
+ };
1031
+ const layoutDanmaku = (inputList, config, canvasCtx)=>{
1032
+ const list = [
1033
+ ...UniPool2DanmakuLists(inputList)
1034
+ ].toSorted((x, y)=>x.time - y.time);
1035
+ const layout = initializeLayout(config, canvasCtx);
1036
+ return DanmakuList2UniPool(list.map(layout).filter((danmaku)=>!!danmaku));
1037
+ };
1038
+ const formatTime = (seconds)=>{
1039
+ const div = (i, j)=>Math.floor(i / j);
1040
+ const pad = (n)=>n < 10 ? `0${n}` : String(n);
1041
+ const integer = Math.floor(seconds);
1042
+ const hour = div(integer, 3600);
1043
+ const minute = div(integer, 60) % 60;
1044
+ const second = integer % 60;
1045
+ const minorSecond = Math.floor((seconds - integer) * 100);
1046
+ return `${hour}:${pad(minute)}:${pad(second)}.${minorSecond}`;
1047
+ };
1048
+ const encode = (text)=>text.toString().replaceAll('{', '{').replaceAll('}', '}').replaceAll(/\r|\n/g, '');
1049
+ const scrollCommand = ({ start, end, top })=>String.raw`\move(${start},${top},${end},${top})`;
1050
+ const fixCommand = ({ top, left })=>String.raw`\an8\pos(${left},${top})`;
1051
+ const colorCommand = (color)=>String.raw`\c${formatColor(color)}`;
1052
+ const borderColorCommand = (color)=>String.raw`\3c${formatColor(color)}`;
1053
+ const dialogue = (danmaku, config)=>{
1054
+ const { fontSizeType, content, time } = danmaku;
1055
+ const { scrollTime, fixTime } = config;
1056
+ const commands = [
1057
+ danmaku.type === DanmakuType.SCROLL ? scrollCommand({
1058
+ start: danmaku.start,
1059
+ end: danmaku.end,
1060
+ top: danmaku.top
1061
+ }) : fixCommand({
1062
+ top: danmaku.top,
1063
+ left: danmaku.left
1064
+ }),
1065
+ isWhite(danmaku.color) ? '' : colorCommand(danmaku.color),
1066
+ isWhite(danmaku.color) ? '' : borderColorCommand(getDecoratingColor(danmaku.color))
1067
+ ];
1068
+ const fields = [
1069
+ 0,
1070
+ formatTime(time),
1071
+ formatTime(time + (danmaku.type === DanmakuType.SCROLL ? scrollTime : fixTime)),
1072
+ `F${fontSizeType}`,
1073
+ '',
1074
+ '0000',
1075
+ '0000',
1076
+ '0000',
1077
+ '',
1078
+ `{${commands.join('')}}${encode(content)}`
1079
+ ];
1080
+ return `Dialogue: ${fields.join(',')}`;
1081
+ };
1082
+ const calculateDanmakuPosition = (danmaku, config)=>{
1083
+ const { playResX, playResY, scrollTime, fixTime } = config;
1084
+ switch(danmaku.type){
1085
+ case DanmakuType.SCROLL:
1086
+ {
1087
+ const start = playResX;
1088
+ const end = -playResX / 10;
1089
+ const top = danmaku.fontSizeType * playResY / 20;
1090
+ return {
1091
+ ...danmaku,
1092
+ start,
1093
+ end,
1094
+ top,
1095
+ left: 0,
1096
+ duration: scrollTime
1097
+ };
1098
+ }
1099
+ case DanmakuType.TOP:
1100
+ case DanmakuType.BOTTOM:
1101
+ {
1102
+ const left = playResX / 2;
1103
+ const top = danmaku.type === DanmakuType.TOP ? danmaku.fontSizeType * playResY / 20 : playResY - config.bottomSpace - danmaku.fontSizeType * playResY / 20;
1104
+ return {
1105
+ ...danmaku,
1106
+ start: 0,
1107
+ end: 0,
1108
+ top,
1109
+ left,
1110
+ duration: fixTime
1111
+ };
1112
+ }
1113
+ default:
1114
+ throw new Error(`Unknown danmaku type: ${danmaku.type}`);
1115
+ }
1116
+ };
1117
+ const event_event = (list, config)=>{
1118
+ const content = [
1119
+ '[Events]',
1120
+ 'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text',
1121
+ ...list.map((danmaku)=>{
1122
+ const positionedDanmaku = calculateDanmakuPosition(danmaku, config);
1123
+ return dialogue(positionedDanmaku, config);
1124
+ })
1125
+ ];
1126
+ return content.join('\n');
1127
+ };
1128
+ const info_info = ({ playResX, playResY }, { filename, title })=>{
1129
+ const content = [
1130
+ '[Script Info]',
1131
+ `Title: ${title}`,
1132
+ `Original Script: 根据 ${filename} 的弹幕信息,由 ${package_namespaceObject.TB} 生成`,
1133
+ 'ScriptType: v4.00+',
1134
+ 'Collisions: Reverse',
1135
+ `PlayResX: ${playResX}`,
1136
+ `PlayResY: ${playResY}`,
1137
+ 'Timer: 100.0000'
1138
+ ];
1139
+ return content.join('\n');
1140
+ };
1141
+ const compressTypes = new Set([
1142
+ 'brotli',
1143
+ 'gzip'
1144
+ ]);
1145
+ const baseTypes = new Set([
1146
+ 'base64',
1147
+ 'base18384'
1148
+ ]);
1149
+ function fromUint16Array(array) {
1150
+ let result = '';
1151
+ for (const element of array)result += String.fromCodePoint(element);
1152
+ return result;
1153
+ }
1154
+ function raw_raw(list, config, context, compressType = 'brotli', baseType = 'base18384') {
1155
+ const raw1 = {
1156
+ list,
1157
+ config,
1158
+ context
1159
+ };
1160
+ const rawText = JSON.stringify(raw1);
1161
+ let compress;
1162
+ compress = 'brotli' === compressType ? brotliCompressSync(rawText) : gzipSync(rawText);
1163
+ return `;RawCompressType: ${compressType}\n;RawBaseType: ${baseType}\n;Raw: ${'base64' === baseType ? compress.toString('base64') : fromUint16Array(external_base16384_encode(compress))}`;
1164
+ }
1165
+ function deRaw(ass) {
1166
+ const arr = ass.split('\n');
1167
+ const lineCompressType = arr.find((line)=>line.startsWith(';RawCompressType:'));
1168
+ const lineBaseType = arr.find((line)=>line.startsWith(';RawBaseType:'));
1169
+ const lineRaw = arr.find((line)=>line.startsWith(';Raw:'));
1170
+ if (!lineCompressType || !lineBaseType || !lineRaw) return;
1171
+ {
1172
+ let compressType = lineCompressType.replace(';RawCompressType: ', '').trim();
1173
+ let baseType = lineBaseType.replace(';RawBaseType: ', '').trim();
1174
+ if (!compressTypes.has(compressType)) compressType = 'gzip';
1175
+ if (!baseTypes.has(baseType)) baseType = 'base64';
1176
+ const text = lineRaw.replace(';Raw: ', '').trim();
1177
+ const buffer = 'base64' === baseType ? Buffer.from(text, 'base64') : Buffer.from(decode(Buffer.from(text, 'utf8').toString('utf8')));
1178
+ let decompress;
1179
+ decompress = 'brotli' === compressType ? brotliDecompressSync(buffer) : gunzipSync(buffer);
1180
+ try {
1181
+ return JSON.parse(decompress.toString('utf8'));
1182
+ } catch {
1183
+ return;
1184
+ }
1185
+ }
1186
+ }
1187
+ const style = ({ fontName, fontSize, color: configColor, outlineColor, backColor, bold, outline, shadow, opacity })=>{
1188
+ const fields = [
1189
+ 'Name',
1190
+ 'Fontname',
1191
+ 'Fontsize',
1192
+ 'PrimaryColour',
1193
+ 'SecondaryColour',
1194
+ 'OutlineColour',
1195
+ 'BackColour',
1196
+ 'Bold',
1197
+ 'Italic',
1198
+ 'Underline',
1199
+ 'StrikeOut',
1200
+ 'ScaleX',
1201
+ 'ScaleY',
1202
+ 'Spacing',
1203
+ 'Angle',
1204
+ 'BorderStyle',
1205
+ 'Outline',
1206
+ 'Shadow',
1207
+ 'Alignment',
1208
+ 'MarginL',
1209
+ 'MarginR',
1210
+ 'MarginV',
1211
+ 'Encoding'
1212
+ ];
1213
+ const primaryColorValue = formatColor(hexColorToRGB(configColor), opacity);
1214
+ const secondaryColor = getDecoratingColor(hexColorToRGB(configColor));
1215
+ const outlineColorValue = formatColor(outlineColor ? hexColorToRGB(outlineColor) : secondaryColor, opacity);
1216
+ const backColorValue = formatColor(backColor ? hexColorToRGB(backColor) : secondaryColor, opacity);
1217
+ const colorStyle = `${primaryColorValue},${primaryColorValue},${outlineColorValue},${backColorValue}`;
1218
+ const boldValue = bold ? '1' : '0';
1219
+ const fontStyle = `${boldValue},0,0,0,100,100,0,0,1,${outline},${shadow},7,0,0,0,0`;
1220
+ const fontDeclaration = (size, i)=>`Style: F${i},${fontName},${size},${colorStyle},${fontStyle}`;
1221
+ const content = [
1222
+ '[V4+ Styles]',
1223
+ `Format: ${fields.join(',')}`,
1224
+ ...fontSize.map(fontDeclaration)
1225
+ ];
1226
+ return content.join('\n');
1227
+ };
1228
+ const default_context = {
1229
+ filename: 'unknown',
1230
+ title: 'unknown'
1231
+ };
1232
+ const create_ass = (list, rawList, config, context = default_context, rawConfig)=>{
1233
+ const Elist = UniPool2DanmakuLists(list);
1234
+ const ErawList = UniPool2DanmakuLists(rawList);
1235
+ const content = [
1236
+ info_info(config, context),
1237
+ style(config),
1238
+ event_event(Elist, config)
1239
+ ];
1240
+ if (config.includeRaw) content.push(raw_raw(ErawList, config, context, rawConfig?.compressType, rawConfig?.baseType));
1241
+ return `${content.join('\n\n')}\n`;
1242
+ };
1243
+ const getConfig = (overrides = {})=>{
1244
+ const defaults = {
1245
+ fontSize: [
1246
+ 25,
1247
+ 25,
1248
+ 36
1249
+ ],
1250
+ fontName: 'SimHei',
1251
+ color: '#ffffff',
1252
+ outlineColor: void 0,
1253
+ backColor: void 0,
1254
+ outline: 2,
1255
+ shadow: 0,
1256
+ bold: false,
1257
+ padding: [
1258
+ 2,
1259
+ 2,
1260
+ 2,
1261
+ 2
1262
+ ],
1263
+ playResX: 1920,
1264
+ playResY: 1080,
1265
+ scrollTime: 8,
1266
+ fixTime: 4,
1267
+ opacity: 0.6,
1268
+ bottomSpace: 60,
1269
+ includeRaw: true,
1270
+ mergeIn: -1
1271
+ };
1272
+ const config = lang_assign(defaults, overrides);
1273
+ config.color = formatColor(hexColorToRGB(config.color));
1274
+ config.outlineColor = config.outlineColor && formatColor(hexColorToRGB(config.outlineColor));
1275
+ config.backColor = config.backColor && formatColor(hexColorToRGB(config.backColor));
1276
+ return config;
1277
+ };
1278
+ function generateASS(danmaku, options, canvasCtx) {
1279
+ const config = getConfig(options.substyle);
1280
+ const mergedList = danmaku.merge(config.mergeIn);
1281
+ const layoutList = layoutDanmaku(mergedList, config, canvasCtx);
1282
+ const content = create_ass(layoutList, danmaku, config, {
1283
+ filename: options?.filename || 'unknown',
1284
+ title: options?.title || 'unknown'
1285
+ }, options.raw);
1286
+ return content;
1287
+ }
1288
+ function parseAssRawField(ass, options) {
1289
+ const raw = deRaw(ass);
1290
+ if (raw) return DanmakuList2UniPool(raw.list, options);
1291
+ return UniPool.create();
1292
+ }
1293
+ const file_bili_dm = /*@__PURE__*/ fileDesc("Cg1iaWxpL2RtLnByb3RvEiBiaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MSJkCgZBdmF0YXISCgoCaWQYASABKAkSCwoDdXJsGAIgASgJEkEKC2F2YXRhcl90eXBlGAMgASgOMiwuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuQXZhdGFyVHlwZSIjCgZCdWJibGUSDAoEdGV4dBgBIAEoCRILCgN1cmwYAiABKAkixgEKCEJ1YmJsZVYyEgwKBHRleHQYASABKAkSCwoDdXJsGAIgASgJEkEKC2J1YmJsZV90eXBlGAMgASgOMiwuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuQnViYmxlVHlwZRIVCg1leHBvc3VyZV9vbmNlGAQgASgIEkUKDWV4cG9zdXJlX3R5cGUYBSABKA4yLi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5FeHBvc3VyZVR5cGUiWwoGQnV0dG9uEgwKBHRleHQYASABKAkSQwoGYWN0aW9uGAIgASgOMjMuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuVG9hc3RGdW5jdGlvblR5cGUiWAoOQnV6endvcmRDb25maWcSRgoIa2V5d29yZHMYASADKAsyNC5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5CdXp6d29yZFNob3dDb25maWcieAoSQnV6endvcmRTaG93Q29uZmlnEgwKBG5hbWUYASABKAkSDgoGc2NoZW1hGAIgASgJEg4KBnNvdXJjZRgDIAEoBRIKCgJpZBgEIAEoAxITCgtidXp6d29yZF9pZBgFIAEoAxITCgtzY2hlbWFfdHlwZRgGIAEoBSJ7CghDaGVja0JveBIMCgR0ZXh0GAEgASgJEjwKBHR5cGUYAiABKA4yLi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5DaGVja2JveFR5cGUSFQoNZGVmYXVsdF92YWx1ZRgDIAEoCBIMCgRzaG93GAQgASgIIm8KCkNoZWNrQm94VjISDAoEdGV4dBgBIAEoCRI8CgR0eXBlGAIgASgOMi4uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuQ2hlY2tib3hUeXBlEhUKDWRlZmF1bHRfdmFsdWUYAyABKAgiggIKC0NsaWNrQnV0dG9uEhUKDXBvcnRyYWl0X3RleHQYASADKAkSFgoObGFuZHNjYXBlX3RleHQYAiADKAkSGwoTcG9ydHJhaXRfdGV4dF9mb2N1cxgDIAMoCRIcChRsYW5kc2NhcGVfdGV4dF9mb2N1cxgEIAMoCRJBCgtyZW5kZXJfdHlwZRgFIAEoDjIsLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlJlbmRlclR5cGUSDAoEc2hvdxgGIAEoCBI4CgZidWJibGUYByABKAsyKC5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5CdWJibGUiswIKDUNsaWNrQnV0dG9uVjISFQoNcG9ydHJhaXRfdGV4dBgBIAMoCRIWCg5sYW5kc2NhcGVfdGV4dBgCIAMoCRIbChNwb3J0cmFpdF90ZXh0X2ZvY3VzGAMgAygJEhwKFGxhbmRzY2FwZV90ZXh0X2ZvY3VzGAQgAygJEkEKC3JlbmRlcl90eXBlGAUgASgOMiwuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUmVuZGVyVHlwZRIXCg90ZXh0X2lucHV0X3Bvc3QYBiABKAgSFQoNZXhwb3N1cmVfb25jZRgHIAEoCBJFCg1leHBvc3VyZV90eXBlGAggASgOMi4uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRXhwb3N1cmVUeXBlIksKB0NvbW1hbmQSQAoLY29tbWFuZF9kbXMYASADKAsyKy5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5Db21tYW5kRG0i5gEKCUNvbW1hbmREbRIKCgJpZBgBIAEoAxILCgNvaWQYAiABKAMSCwoDbWlkGAMgASgDEg8KB2NvbW1hbmQYBCABKAkSDwoHY29udGVudBgFIAEoCRIQCghwcm9ncmVzcxgGIAEoBRINCgVjdGltZRgHIAEoCRINCgVtdGltZRgIIAEoCRINCgVleHRyYRgJIAEoCRINCgVpZFN0chgKIAEoCRIMCgR0eXBlGAsgASgFEhMKC2F1dG9fY3JlYXRlGAwgASgIEhIKCmNvdW50X2Rvd24YDSABKAUSDAoEYXR0chgOIAEoBSJQCg1EYW5tYWt1QUlGbGFnEj8KCGRtX2ZsYWdzGAEgAygLMi0uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRGFubWFrdUZsYWciiwMKC0Rhbm1ha3VFbGVtEgoKAmlkGAEgASgDEhAKCHByb2dyZXNzGAIgASgFEgwKBG1vZGUYAyABKAUSEAoIZm9udHNpemUYBCABKAUSPwoFY29sb3IYBSABKA4yMC5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EbUNvbG9yZnVsVHlwZRIQCghtaWRfaGFzaBgGIAEoCRIPCgdjb250ZW50GAcgASgJEg0KBWN0aW1lGAggASgDEg4KBndlaWdodBgJIAEoBRIOCgZhY3Rpb24YCiABKAkSDAoEcG9vbBgLIAEoBRIOCgZpZF9zdHIYDCABKAkSDAoEYXR0chgNIAEoBRIRCglhbmltYXRpb24YFiABKAkSDQoFZXh0cmEYFyABKAkSQgoIY29sb3JmdWwYGCABKA4yMC5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EbUNvbG9yZnVsVHlwZRIMCgR0eXBlGBkgASgFEgsKA29pZBgaIAEoAyIpCgtEYW5tYWt1RmxhZxIMCgRkbWlkGAEgASgDEgwKBGZsYWcYAiABKAUiSwoRRGFubWFrdUZsYWdDb25maWcSEAoIcmVjX2ZsYWcYASABKAUSEAoIcmVjX3RleHQYAiABKAkSEgoKcmVjX3N3aXRjaBgDIAEoBSKLBwoYRGFubXVEZWZhdWx0UGxheWVyQ29uZmlnEikKIXBsYXllcl9kYW5tYWt1X3VzZV9kZWZhdWx0X2NvbmZpZxgBIAEoCBIsCiRwbGF5ZXJfZGFubWFrdV9haV9yZWNvbW1lbmRlZF9zd2l0Y2gYBCABKAgSKwojcGxheWVyX2Rhbm1ha3VfYWlfcmVjb21tZW5kZWRfbGV2ZWwYBSABKAUSHwoXcGxheWVyX2Rhbm1ha3VfYmxvY2t0b3AYBiABKAgSIgoacGxheWVyX2Rhbm1ha3VfYmxvY2tzY3JvbGwYByABKAgSIgoacGxheWVyX2Rhbm1ha3VfYmxvY2tib3R0b20YCCABKAgSJAoccGxheWVyX2Rhbm1ha3VfYmxvY2tjb2xvcmZ1bBgJIAEoCBIiChpwbGF5ZXJfZGFubWFrdV9ibG9ja3JlcGVhdBgKIAEoCBIjChtwbGF5ZXJfZGFubWFrdV9ibG9ja3NwZWNpYWwYCyABKAgSHgoWcGxheWVyX2Rhbm1ha3Vfb3BhY2l0eRgMIAEoAhIkChxwbGF5ZXJfZGFubWFrdV9zY2FsaW5nZmFjdG9yGA0gASgCEh0KFXBsYXllcl9kYW5tYWt1X2RvbWFpbhgOIAEoAhIcChRwbGF5ZXJfZGFubWFrdV9zcGVlZBgPIAEoBRIkChxpbmxpbmVfcGxheWVyX2Rhbm1ha3Vfc3dpdGNoGBAgASgIEikKIXBsYXllcl9kYW5tYWt1X3Nlbmlvcl9tb2RlX3N3aXRjaBgRIAEoBRIuCiZwbGF5ZXJfZGFubWFrdV9haV9yZWNvbW1lbmRlZF9sZXZlbF92MhgSIAEoBRKYAQoqcGxheWVyX2Rhbm1ha3VfYWlfcmVjb21tZW5kZWRfbGV2ZWxfdjJfbWFwGBMgAygLMmQuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRGFubXVEZWZhdWx0UGxheWVyQ29uZmlnLlBsYXllckRhbm1ha3VBaVJlY29tbWVuZGVkTGV2ZWxWMk1hcEVudHJ5EiUKHXBsYXllcl9kYW5tYWt1X2VuYWJsZV9oZXJkX2RtGBQgASgIGksKKVBsYXllckRhbm1ha3VBaVJlY29tbWVuZGVkTGV2ZWxWMk1hcEVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEi7AkKEURhbm11UGxheWVyQ29uZmlnEh0KFXBsYXllcl9kYW5tYWt1X3N3aXRjaBgBIAEoCBIiChpwbGF5ZXJfZGFubWFrdV9zd2l0Y2hfc2F2ZRgCIAEoCBIpCiFwbGF5ZXJfZGFubWFrdV91c2VfZGVmYXVsdF9jb25maWcYAyABKAgSLAokcGxheWVyX2Rhbm1ha3VfYWlfcmVjb21tZW5kZWRfc3dpdGNoGAQgASgIEisKI3BsYXllcl9kYW5tYWt1X2FpX3JlY29tbWVuZGVkX2xldmVsGAUgASgFEh8KF3BsYXllcl9kYW5tYWt1X2Jsb2NrdG9wGAYgASgIEiIKGnBsYXllcl9kYW5tYWt1X2Jsb2Nrc2Nyb2xsGAcgASgIEiIKGnBsYXllcl9kYW5tYWt1X2Jsb2NrYm90dG9tGAggASgIEiQKHHBsYXllcl9kYW5tYWt1X2Jsb2NrY29sb3JmdWwYCSABKAgSIgoacGxheWVyX2Rhbm1ha3VfYmxvY2tyZXBlYXQYCiABKAgSIwobcGxheWVyX2Rhbm1ha3VfYmxvY2tzcGVjaWFsGAsgASgIEh4KFnBsYXllcl9kYW5tYWt1X29wYWNpdHkYDCABKAISJAoccGxheWVyX2Rhbm1ha3Vfc2NhbGluZ2ZhY3RvchgNIAEoAhIdChVwbGF5ZXJfZGFubWFrdV9kb21haW4YDiABKAISHAoUcGxheWVyX2Rhbm1ha3Vfc3BlZWQYDyABKAUSJgoecGxheWVyX2Rhbm1ha3VfZW5hYmxlYmxvY2tsaXN0GBAgASgIEiQKHGlubGluZV9wbGF5ZXJfZGFubWFrdV9zd2l0Y2gYESABKAgSJAocaW5saW5lX3BsYXllcl9kYW5tYWt1X2NvbmZpZxgSIAEoBRImCh5wbGF5ZXJfZGFubWFrdV9pb3Nfc3dpdGNoX3NhdmUYEyABKAUSKQohcGxheWVyX2Rhbm1ha3Vfc2VuaW9yX21vZGVfc3dpdGNoGBQgASgFEi4KJnBsYXllcl9kYW5tYWt1X2FpX3JlY29tbWVuZGVkX2xldmVsX3YyGBUgASgFEpEBCipwbGF5ZXJfZGFubWFrdV9haV9yZWNvbW1lbmRlZF9sZXZlbF92Ml9tYXAYFiADKAsyXS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EYW5tdVBsYXllckNvbmZpZy5QbGF5ZXJEYW5tYWt1QWlSZWNvbW1lbmRlZExldmVsVjJNYXBFbnRyeRIlCh1wbGF5ZXJfZGFubWFrdV9lbmFibGVfaGVyZF9kbRgXIAEoCBImCh5wbGF5ZXJfZGFubWFrdV9ibG9ja3RvcF9ib3R0b20YGCABKAgSIAoYcGxheWVyX2Rhbm1ha3VfZG9tYWluX3YyGBkgASgFEh4KFnBsYXllcl9kYW5tYWt1X2RlbnNpdHkYGiABKAUSJQodcGxheWVyX2Rhbm1ha3Vfc3VidGl0bGVfcHJvb2YYGyABKAgSIwobcGxheWVyX2Rhbm1ha3VfcGVvcGxlX3Byb29mGBwgASgIGksKKVBsYXllckRhbm1ha3VBaVJlY29tbWVuZGVkTGV2ZWxWMk1hcEVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEiMAoWRGFubXVQbGF5ZXJDb25maWdQYW5lbBIWCg5zZWxlY3Rpb25fdGV4dBgBIAEoCSJLChhEYW5tdVBsYXllckR5bmFtaWNDb25maWcSEAoIcHJvZ3Jlc3MYASABKAUSHQoVcGxheWVyX2Rhbm1ha3VfZG9tYWluGA4gASgCIpADChVEYW5tdVBsYXllclZpZXdDb25maWcSYQodZGFubXVrdV9kZWZhdWx0X3BsYXllcl9jb25maWcYASABKAsyOi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EYW5tdURlZmF1bHRQbGF5ZXJDb25maWcSUgoVZGFubXVrdV9wbGF5ZXJfY29uZmlnGAIgASgLMjMuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRGFubXVQbGF5ZXJDb25maWcSYQodZGFubXVrdV9wbGF5ZXJfZHluYW1pY19jb25maWcYAyADKAsyOi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EYW5tdVBsYXllckR5bmFtaWNDb25maWcSXQobZGFubXVrdV9wbGF5ZXJfY29uZmlnX3BhbmVsGAQgASgLMjguYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRGFubXVQbGF5ZXJDb25maWdQYW5lbCKZBQoURGFubXVXZWJQbGF5ZXJDb25maWcSEQoJZG1fc3dpdGNoGAEgASgIEhEKCWFpX3N3aXRjaBgCIAEoCBIQCghhaV9sZXZlbBgDIAEoBRIQCghibG9ja3RvcBgEIAEoCBITCgtibG9ja3Njcm9sbBgFIAEoCBITCgtibG9ja2JvdHRvbRgGIAEoCBISCgpibG9ja2NvbG9yGAcgASgIEhQKDGJsb2Nrc3BlY2lhbBgIIAEoCBIUCgxwcmV2ZW50c2hhZGUYCSABKAgSDQoFZG1hc2sYCiABKAgSDwoHb3BhY2l0eRgLIAEoAhIOCgZkbWFyZWEYDCABKAUSEQoJc3BlZWRwbHVzGA0gASgCEhAKCGZvbnRzaXplGA4gASgCEhIKCnNjcmVlbnN5bmMYDyABKAgSEQoJc3BlZWRzeW5jGBAgASgIEhIKCmZvbnRmYW1pbHkYESABKAkSDAoEYm9sZBgSIAEoCBISCgpmb250Ym9yZGVyGBMgASgFEhEKCWRyYXdfdHlwZRgUIAEoCRIaChJzZW5pb3JfbW9kZV9zd2l0Y2gYFSABKAUSEwoLYWlfbGV2ZWxfdjIYFiABKAUSYQoPYWlfbGV2ZWxfdjJfbWFwGBcgAygLMkguYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRGFubXVXZWJQbGF5ZXJDb25maWcuQWlMZXZlbFYyTWFwRW50cnkSFwoPYmxvY2t0b3BfYm90dG9tGBggASgIEhIKCmRtX2FyZWFfdjIYGSABKAUSEgoKZG1fZGVuc2l0eRgaIAEoBRozChFBaUxldmVsVjJNYXBFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBIlkKCkRtQ29sb3JmdWwSPgoEdHlwZRgBIAEoDjIwLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRtQ29sb3JmdWxUeXBlEgsKA3NyYxgCIAEoCSJQCg9EbUV4cG9SZXBvcnRSZXESEgoKc2Vzc2lvbl9pZBgBIAEoCRILCgNvaWQYAiABKAMSDQoFZG1pZHMYAyABKAwSDQoFc3BtaWQYBCABKAkiEQoPRG1FeHBvUmVwb3J0UmVzIm0KCkRtSGVyZFZpZXcSGwoTZGlzcGxheV9oZXJkX2RtX251bRgBIAEoBRJCCghoZXJkX2RtcxgCIAMoCzIwLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlZpZXdIZXJkRG1FbGVtIpYCCgpEbU1hc2tXYWxsEg0KBXN0YXJ0GAEgASgDEgsKA2VuZBgCIAEoAxIPCgdjb250ZW50GAMgASgJEk0KDGNvbnRlbnRfdHlwZRgEIAEoDjI3LmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRtTWFza1dhbGxDb250ZW50VHlwZRJFCghiaXpfdHlwZRgFIAEoDjIzLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRtTWFza1dhbGxCaXpUeXBlEkUKCGNvbnRlbnRzGAYgAygLMjMuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRG1NYXNrV2FsbENvbnRlbnQiawoRRG1NYXNrV2FsbENvbnRlbnQSRQoEdHlwZRgBIAEoDjI3LmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRtTWFza1dhbGxDb250ZW50VHlwZRIPCgdjb250ZW50GAIgASgJIs0QChFEbVBsYXllckNvbmZpZ1JlcRIKCgJ0cxgBIAEoAxJFCgZzd2l0Y2gYAiABKAsyNS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5QbGF5ZXJEYW5tYWt1U3dpdGNoEk4KC3N3aXRjaF9zYXZlGAMgASgLMjkuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdVN3aXRjaFNhdmUSWwoSdXNlX2RlZmF1bHRfY29uZmlnGAQgASgLMj8uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdVVzZURlZmF1bHRDb25maWcSYQoVYWlfcmVjb21tZW5kZWRfc3dpdGNoGAUgASgLMkIuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdUFpUmVjb21tZW5kZWRTd2l0Y2gSXwoUYWlfcmVjb21tZW5kZWRfbGV2ZWwYBiABKAsyQS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5QbGF5ZXJEYW5tYWt1QWlSZWNvbW1lbmRlZExldmVsEkkKCGJsb2NrdG9wGAcgASgLMjcuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdUJsb2NrdG9wEk8KC2Jsb2Nrc2Nyb2xsGAggASgLMjouYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdUJsb2Nrc2Nyb2xsEk8KC2Jsb2NrYm90dG9tGAkgASgLMjouYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdUJsb2NrYm90dG9tElMKDWJsb2NrY29sb3JmdWwYCiABKAsyPC5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5QbGF5ZXJEYW5tYWt1QmxvY2tjb2xvcmZ1bBJPCgtibG9ja3JlcGVhdBgLIAEoCzI6LmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBsYXllckRhbm1ha3VCbG9ja3JlcGVhdBJRCgxibG9ja3NwZWNpYWwYDCABKAsyOy5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5QbGF5ZXJEYW5tYWt1QmxvY2tzcGVjaWFsEkcKB29wYWNpdHkYDSABKAsyNi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5QbGF5ZXJEYW5tYWt1T3BhY2l0eRJTCg1zY2FsaW5nZmFjdG9yGA4gASgLMjwuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdVNjYWxpbmdmYWN0b3ISRQoGZG9tYWluGA8gASgLMjUuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdURvbWFpbhJDCgVzcGVlZBgQIAEoCzI0LmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBsYXllckRhbm1ha3VTcGVlZBJXCg9lbmFibGVibG9ja2xpc3QYESABKAsyPi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5QbGF5ZXJEYW5tYWt1RW5hYmxlYmxvY2tsaXN0El4KGWlubGluZVBsYXllckRhbm1ha3VTd2l0Y2gYEiABKAsyOy5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5JbmxpbmVQbGF5ZXJEYW5tYWt1U3dpdGNoElsKEnNlbmlvcl9tb2RlX3N3aXRjaBgTIAEoCzI/LmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBsYXllckRhbm1ha3VTZW5pb3JNb2RlU3dpdGNoEmQKF2FpX3JlY29tbWVuZGVkX2xldmVsX3YyGBQgASgLMkMuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdUFpUmVjb21tZW5kZWRMZXZlbFYyElMKDmVuYWJsZV9oZXJkX2RtGBUgASgLMjsuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdUVuYWJsZUhlcmREbRJWCg9ibG9ja3RvcF9ib3R0b20YFiABKAsyPS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5QbGF5ZXJEYW5tYWt1QmxvY2t0b3BCb3R0b20SSgoJZG9tYWluX3YyGBcgASgLMjcuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUGxheWVyRGFubWFrdURvbWFpblYyEkcKB2RlbnNpdHkYGCABKAsyNi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5QbGF5ZXJEYW5tYWt1RGVuc2l0eRJUCg5zdWJ0aXRsZV9wcm9vZhgZIAEoCzI8LmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBsYXllckRhbm1ha3VTdWJ0aXRsZVByb29mElAKDHBlb3BsZV9wcm9vZhgaIAEoCzI6LmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBsYXllckRhbm1ha3VQZW9wbGVQcm9vZiIvCgtEbVNlZ0NvbmZpZxIRCglwYWdlX3NpemUYASABKAMSDQoFdG90YWwYAiABKAMikQIKEERtU2VnTW9iaWxlUmVwbHkSPAoFZWxlbXMYASADKAsyLS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EYW5tYWt1RWxlbRINCgVzdGF0ZRgCIAEoBRJACgdhaV9mbGFnGAMgASgLMi8uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRGFubWFrdUFJRmxhZxIVCg1zZWdtZW50X3J1bGVzGAQgAygDEkIKDGNvbG9yZnVsX3NyYxgFIAMoCzIsLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRtQ29sb3JmdWwSEwoLY29udGV4dF9zcmMYBiABKAkiygEKDkRtU2VnTW9iaWxlUmVxEgsKA3BpZBgBIAEoAxILCgNvaWQYAiABKAMSDAoEdHlwZRgDIAEoBRIVCg1zZWdtZW50X2luZGV4GAQgASgDEhYKDnRlZW5hZ2Vyc19tb2RlGAUgASgFEgoKAnBzGAYgASgDEgoKAnBlGAcgASgDEhEKCXB1bGxfbW9kZRgIIAEoBRISCgpmcm9tX3NjZW5lGAkgASgFEg0KBXNwbWlkGAogASgJEhMKC2NvbnRleHRfZXh0GAsgASgJIlwKDURtU2VnT3R0UmVwbHkSPAoFZWxlbXMYASADKAsyLS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EYW5tYWt1RWxlbRINCgVzdGF0ZRgCIAEoBSJMCgtEbVNlZ090dFJlcRILCgNwaWQYASABKAMSCwoDb2lkGAIgASgDEgwKBHR5cGUYAyABKAUSFQoNc2VnbWVudF9pbmRleBgEIAEoAyJdCg1EbVNlZ1NES1JlcGx5Eg4KBmNsb3NlZBgBIAEoCBI8CgVlbGVtcxgCIAMoCzItLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRhbm1ha3VFbGVtIkwKC0RtU2VnU0RLUmVxEgsKA3BpZBgBIAEoAxILCgNvaWQYAiABKAMSDAoEdHlwZRgDIAEoBRIVCg1zZWdtZW50X2luZGV4GAQgASgDIncKCURtU3ViVmlldxIMCgR0eXBlGAEgASgFEgsKA29pZBgCIAEoAxILCgNwaWQYAyABKAMSQgoLcG9zdF9wYW5lbDIYBCADKAsyLS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5Qb3N0UGFuZWxWMiKhCQoLRG1WaWV3UmVwbHkSDgoGY2xvc2VkGAEgASgIEjkKBG1hc2sYAiABKAsyKy5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5WaWRlb01hc2sSQQoIc3VidGl0bGUYAyABKAsyLy5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5WaWRlb1N1YnRpdGxlEhMKC3NwZWNpYWxfZG1zGAQgAygJEkQKB2FpX2ZsYWcYBSABKAsyMy5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EYW5tYWt1RmxhZ0NvbmZpZxJOCg1wbGF5ZXJfY29uZmlnGAYgASgLMjcuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRGFubXVQbGF5ZXJWaWV3Q29uZmlnEhYKDnNlbmRfYm94X3N0eWxlGAcgASgFEg0KBWFsbG93GAggASgIEhEKCWNoZWNrX2JveBgJIAEoCBIaChJjaGVja19ib3hfc2hvd19tc2cYCiABKAkSGAoQdGV4dF9wbGFjZWhvbGRlchgLIAEoCRIZChFpbnB1dF9wbGFjZWhvbGRlchgMIAEoCRIdChVyZXBvcnRfZmlsdGVyX2NvbnRlbnQYDSADKAkSQQoLZXhwb19yZXBvcnQYDiABKAsyLC5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5FeHBvUmVwb3J0EkkKD2J1enp3b3JkX2NvbmZpZxgPIAEoCzIwLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkJ1enp3b3JkQ29uZmlnEkIKC2V4cHJlc3Npb25zGBAgAygLMi0uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRXhwcmVzc2lvbnMSPwoKcG9zdF9wYW5lbBgRIAMoCzIrLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBvc3RQYW5lbBIVCg1hY3Rpdml0eV9tZXRhGBIgAygJEkIKC3Bvc3RfcGFuZWwyGBMgAygLMi0uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUG9zdFBhbmVsVjISQgoMZG1fbWFza193YWxsGBQgAygLMiwuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRG1NYXNrV2FsbBI9CgdkbV9oZXJkGBUgASgLMiwuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRG1IZXJkVmlldxI6Cgdjb21tYW5kGBYgASgLMikuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuQ29tbWFuZBIKCgJrdhgXIAEoCRI+CglzdWJfdmlld3MYGCADKAsyKy5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EbVN1YlZpZXcSNgoDcW9lGBkgASgLMikuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUW9lSW5mbyJtCglEbVZpZXdSZXESCwoDcGlkGAEgASgDEgsKA29pZBgCIAEoAxIMCgR0eXBlGAMgASgFEg0KBXNwbWlkGAQgASgJEhQKDGlzX2hhcmRfYm9vdBgFIAEoBRITCgtjb250ZXh0X2V4dBgGIAEoCSKBBgoORG1XZWJWaWV3UmVwbHkSDQoFc3RhdGUYASABKAUSDAoEdGV4dBgCIAEoCRIRCgl0ZXh0X3NpZGUYAyABKAkSPQoGZG1fc2dlGAQgASgLMi0uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRG1TZWdDb25maWcSQQoEZmxhZxgFIAEoCzIzLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRhbm1ha3VGbGFnQ29uZmlnEhMKC3NwZWNpYWxfZG1zGAYgAygJEhEKCWNoZWNrX2JveBgHIAEoCBINCgVjb3VudBgIIAEoAxJACgtjb21tYW5kX2RtcxgJIAMoCzIrLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkNvbW1hbmREbRJNCg1wbGF5ZXJfY29uZmlnGAogASgLMjYuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRGFubXVXZWJQbGF5ZXJDb25maWcSHQoVcmVwb3J0X2ZpbHRlcl9jb250ZW50GAsgAygJEkIKC2V4cHJlc3Npb25zGAwgAygLMi0uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRXhwcmVzc2lvbnMSPwoKcG9zdF9wYW5lbBgNIAMoCzIrLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBvc3RQYW5lbBIVCg1hY3Rpdml0eV9tZXRhGA4gAygJEkIKC3Bvc3RfcGFuZWwyGA8gAygLMi0uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUG9zdFBhbmVsVjISPgoJc3ViX3ZpZXdzGBAgAygLMisuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRG1TdWJWaWV3EjYKA3FvZRgRIAEoCzIpLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlFvZUluZm8iKgoKRXhwb1JlcG9ydBIcChRzaG91bGRfcmVwb3J0X2F0X2VuZBgBIAEoCCJkCgpFeHByZXNzaW9uEg8KB2tleXdvcmQYASADKAkSCwoDdXJsGAIgASgJEjgKBnBlcmlvZBgDIAMoCzIoLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBlcmlvZCJJCgtFeHByZXNzaW9ucxI6CgRkYXRhGAEgAygLMiwuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRXhwcmVzc2lvbiIqChlJbmxpbmVQbGF5ZXJEYW5tYWt1U3dpdGNoEg0KBXZhbHVlGAEgASgIIicKBUxhYmVsEg0KBXRpdGxlGAEgASgJEg8KB2NvbnRlbnQYAiADKAkihwEKB0xhYmVsVjISDQoFdGl0bGUYASABKAkSDwoHY29udGVudBgCIAMoCRIVCg1leHBvc3VyZV9vbmNlGAMgASgIEkUKDWV4cG9zdXJlX3R5cGUYBCABKA4yLi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5FeHBvc3VyZVR5cGUiJAoGUGVyaW9kEg0KBXN0YXJ0GAEgASgDEgsKA2VuZBgCIAEoAyIwCh9QbGF5ZXJEYW5tYWt1QWlSZWNvbW1lbmRlZExldmVsEg0KBXZhbHVlGAEgASgFIjIKIVBsYXllckRhbm1ha3VBaVJlY29tbWVuZGVkTGV2ZWxWMhINCgV2YWx1ZRgBIAEoBSIxCiBQbGF5ZXJEYW5tYWt1QWlSZWNvbW1lbmRlZFN3aXRjaBINCgV2YWx1ZRgBIAEoCCIpChhQbGF5ZXJEYW5tYWt1QmxvY2tib3R0b20SDQoFdmFsdWUYASABKAgiKwoaUGxheWVyRGFubWFrdUJsb2NrY29sb3JmdWwSDQoFdmFsdWUYASABKAgiKQoYUGxheWVyRGFubWFrdUJsb2NrcmVwZWF0Eg0KBXZhbHVlGAEgASgIIikKGFBsYXllckRhbm1ha3VCbG9ja3Njcm9sbBINCgV2YWx1ZRgBIAEoCCIqChlQbGF5ZXJEYW5tYWt1QmxvY2tzcGVjaWFsEg0KBXZhbHVlGAEgASgIIiYKFVBsYXllckRhbm1ha3VCbG9ja3RvcBINCgV2YWx1ZRgBIAEoCCIsChtQbGF5ZXJEYW5tYWt1QmxvY2t0b3BCb3R0b20SDQoFdmFsdWUYASABKAgiJQoUUGxheWVyRGFubWFrdURlbnNpdHkSDQoFdmFsdWUYASABKAUiJAoTUGxheWVyRGFubWFrdURvbWFpbhINCgV2YWx1ZRgBIAEoAiImChVQbGF5ZXJEYW5tYWt1RG9tYWluVjISDQoFdmFsdWUYASABKAUiKgoZUGxheWVyRGFubWFrdUVuYWJsZUhlcmREbRINCgV2YWx1ZRgBIAEoCCItChxQbGF5ZXJEYW5tYWt1RW5hYmxlYmxvY2tsaXN0Eg0KBXZhbHVlGAEgASgIIiUKFFBsYXllckRhbm1ha3VPcGFjaXR5Eg0KBXZhbHVlGAEgASgCIikKGFBsYXllckRhbm1ha3VQZW9wbGVQcm9vZhINCgV2YWx1ZRgBIAEoCCIrChpQbGF5ZXJEYW5tYWt1U2NhbGluZ2ZhY3RvchINCgV2YWx1ZRgBIAEoAiIuCh1QbGF5ZXJEYW5tYWt1U2VuaW9yTW9kZVN3aXRjaBINCgV2YWx1ZRgBIAEoBSIjChJQbGF5ZXJEYW5tYWt1U3BlZWQSDQoFdmFsdWUYASABKAUiKwoaUGxheWVyRGFubWFrdVN1YnRpdGxlUHJvb2YSDQoFdmFsdWUYASABKAgiOAoTUGxheWVyRGFubWFrdVN3aXRjaBINCgV2YWx1ZRgBIAEoCBISCgpjYW5faWdub3JlGAIgASgIIigKF1BsYXllckRhbm1ha3VTd2l0Y2hTYXZlEg0KBXZhbHVlGAEgASgIIi4KHVBsYXllckRhbm1ha3VVc2VEZWZhdWx0Q29uZmlnEg0KBXZhbHVlGAEgASgIIowDCglQb3N0UGFuZWwSDQoFc3RhcnQYASABKAMSCwoDZW5kGAIgASgDEhAKCHByaW9yaXR5GAMgASgDEg4KBmJpel9pZBgEIAEoAxJECghiaXpfdHlwZRgFIAEoDjIyLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBvc3RQYW5lbEJpelR5cGUSQwoMY2xpY2tfYnV0dG9uGAYgASgLMi0uYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuQ2xpY2tCdXR0b24SPwoKdGV4dF9pbnB1dBgHIAEoCzIrLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlRleHRJbnB1dBI9CgljaGVja19ib3gYCCABKAsyKi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5DaGVja0JveBI2CgV0b2FzdBgJIAEoCzInLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlRvYXN0Iq0ECgtQb3N0UGFuZWxWMhINCgVzdGFydBgBIAEoAxILCgNlbmQYAiABKAMSRAoIYml6X3R5cGUYAyABKA4yMi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5Qb3N0UGFuZWxCaXpUeXBlEkUKDGNsaWNrX2J1dHRvbhgEIAEoCzIvLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkNsaWNrQnV0dG9uVjISQQoKdGV4dF9pbnB1dBgFIAEoCzItLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlRleHRJbnB1dFYyEj8KCWNoZWNrX2JveBgGIAEoCzIsLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkNoZWNrQm94VjISOAoFdG9hc3QYByABKAsyKS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5Ub2FzdFYyEjoKBmJ1YmJsZRgIIAEoCzIqLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkJ1YmJsZVYyEjgKBWxhYmVsGAkgASgLMikuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuTGFiZWxWMhJBCgtwb3N0X3N0YXR1cxgKIAEoDjIsLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlBvc3RTdGF0dXMiFwoHUW9lSW5mbxIMCgRpbmZvGAEgASgJIikKCFJlc3BvbnNlEgwKBGNvZGUYASABKAUSDwoHbWVzc2FnZRgCIAEoCSL5AgoMU3VidGl0bGVJdGVtEgoKAmlkGAEgASgDEg4KBmlkX3N0chgCIAEoCRILCgNsYW4YAyABKAkSDwoHbGFuX2RvYxgEIAEoCRIUCgxzdWJ0aXRsZV91cmwYBSABKAkSOgoGYXV0aG9yGAYgASgLMiouYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuVXNlckluZm8SPAoEdHlwZRgHIAEoDjIuLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlN1YnRpdGxlVHlwZRIVCg1sYW5fZG9jX2JyaWVmGAggASgJEkEKB2FpX3R5cGUYCSABKA4yMC5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5TdWJ0aXRsZUFpVHlwZRJFCglhaV9zdGF0dXMYCiABKA4yMi5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5TdWJ0aXRsZUFpU3RhdHVzIugCCglUZXh0SW5wdXQSHAoUcG9ydHJhaXRfcGxhY2Vob2xkZXIYASADKAkSHQoVbGFuZHNjYXBlX3BsYWNlaG9sZGVyGAIgAygJEkEKC3JlbmRlcl90eXBlGAMgASgOMiwuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUmVuZGVyVHlwZRIYChBwbGFjZWhvbGRlcl9wb3N0GAQgASgIEgwKBHNob3cYBSABKAgSOAoGYXZhdGFyGAYgAygLMiguYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuQXZhdGFyEkEKC3Bvc3Rfc3RhdHVzGAcgASgOMiwuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUG9zdFN0YXR1cxI2CgVsYWJlbBgIIAEoCzInLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkxhYmVsIvsBCgtUZXh0SW5wdXRWMhIcChRwb3J0cmFpdF9wbGFjZWhvbGRlchgBIAMoCRIdChVsYW5kc2NhcGVfcGxhY2Vob2xkZXIYAiADKAkSQQoLcmVuZGVyX3R5cGUYAyABKA4yLC5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5SZW5kZXJUeXBlEhgKEHBsYWNlaG9sZGVyX3Bvc3QYBCABKAgSOAoGYXZhdGFyGAUgAygLMiguYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuQXZhdGFyEhgKEHRleHRfaW5wdXRfbGltaXQYBiABKAUibwoFVG9hc3QSDAoEdGV4dBgBIAEoCRIQCghkdXJhdGlvbhgCIAEoBRIMCgRzaG93GAMgASgIEjgKBmJ1dHRvbhgEIAEoCzIoLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkJ1dHRvbiJiCg1Ub2FzdEJ1dHRvblYyEgwKBHRleHQYASABKAkSQwoGYWN0aW9uGAIgASgOMjMuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuVG9hc3RGdW5jdGlvblR5cGUicwoHVG9hc3RWMhIMCgR0ZXh0GAEgASgJEhAKCGR1cmF0aW9uGAIgASgFEkgKD3RvYXN0X2J1dHRvbl92MhgDIAEoCzIvLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlRvYXN0QnV0dG9uVjIiXAoIVXNlckluZm8SCwoDbWlkGAEgASgDEgwKBG5hbWUYAiABKAkSCwoDc2V4GAMgASgJEgwKBGZhY2UYBCABKAkSDAoEc2lnbhgFIAEoCRIMCgRyYW5rGAYgASgFIlMKCVZpZGVvTWFzaxILCgNjaWQYASABKAMSDAoEcGxhdBgCIAEoBRILCgNmcHMYAyABKAUSDAoEdGltZRgEIAEoAxIQCghtYXNrX3VybBgFIAEoCSJwCg1WaWRlb1N1YnRpdGxlEgsKA2xhbhgBIAEoCRIPCgdsYW5fZG9jGAIgASgJEkEKCXN1YnRpdGxlcxgDIAMoCzIuLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLlN1YnRpdGxlSXRlbSKSAQoOVmlld0hlcmREbUVsZW0SEAoIaGVyZF9tc2cYASABKAkSFgoOaGVyZF9zdGFydF9jbnQYAiABKAUSFAoMaGVyZF9lbmRfY250GAMgASgFEhIKCnJlZ2V4X3J1bGUYBCABKAkSFgoOc3RhcnRfcHJvZ3Jlc3MYBSABKAUSFAoMZW5kX3Byb2dyZXNzGAYgASgFKjMKCkF2YXRhclR5cGUSEgoOQXZhdGFyVHlwZU5vbmUQABIRCg1BdmF0YXJUeXBlTkZUEAEqWQoKQnViYmxlVHlwZRISCg5CdWJibGVUeXBlTm9uZRAAEhkKFUJ1YmJsZVR5cGVDbGlja0J1dHRvbhABEhwKGEJ1YmJsZVR5cGVEbVNldHRpbmdQYW5lbBACKlgKDENoZWNrYm94VHlwZRIUChBDaGVja2JveFR5cGVOb25lEAASGQoVQ2hlY2tib3hUeXBlRW5jb3VyYWdlEAESFwoTQ2hlY2tib3hUeXBlQ29sb3JETRACKjUKDkRtQ29sb3JmdWxUeXBlEgwKCE5vbmVUeXBlEAASFQoPVmlwR3JhZHVhbENvbG9yEOHUAypgChFEbU1hc2tXYWxsQml6VHlwZRILCgdVbmtub3duEAASBwoDT0dWEAESCgoGQml6UGljEAISCAoETXV0ZRADEgoKBlJlY29yZBAEEgkKBUNsb3VkEAUSCAoEQUlHQxAGKnYKFURtTWFza1dhbGxDb250ZW50VHlwZRIgChxEbU1hc2tXYWxsQ29udGVudFR5cGVVbmtub3duEAASHQoZRG1NYXNrV2FsbENvbnRlbnRUeXBlVGV4dBABEhwKGERtTWFza1dhbGxDb250ZW50VHlwZVBpYxACKjwKDEV4cG9zdXJlVHlwZRIUChBFeHBvc3VyZVR5cGVOb25lEAASFgoSRXhwb3N1cmVUeXBlRE1TZW5kEAEqgwIKEFBvc3RQYW5lbEJpelR5cGUSGAoUUG9zdFBhbmVsQml6VHlwZU5vbmUQABIdChlQb3N0UGFuZWxCaXpUeXBlRW5jb3VyYWdlEAESGwoXUG9zdFBhbmVsQml6VHlwZUNvbG9yRE0QAhIZChVQb3N0UGFuZWxCaXpUeXBlTkZURE0QAxIdChlQb3N0UGFuZWxCaXpUeXBlRnJhZ0Nsb3NlEAQSHQoZUG9zdFBhbmVsQml6VHlwZVJlY29tbWVuZBAFEhwKGFBvc3RQYW5lbEJpelR5cGVQbG90TGVhaxAGEiIKHlBvc3RQYW5lbEJpelR5cGVBbnRpSGFyYXNzbWVudBAHKjgKClBvc3RTdGF0dXMSFAoQUG9zdFN0YXR1c05vcm1hbBAAEhQKEFBvc3RTdGF0dXNDbG9zZWQQASpOCgpSZW5kZXJUeXBlEhIKDlJlbmRlclR5cGVOb25lEAASFAoQUmVuZGVyVHlwZVNpbmdsZRABEhYKElJlbmRlclR5cGVSb3RhdGlvbhACKjYKEFN1YnRpdGxlQWlTdGF0dXMSCAoETm9uZRAAEgwKCEV4cG9zdXJlEAESCgoGQXNzaXN0EAIqKwoOU3VidGl0bGVBaVR5cGUSCgoGTm9ybWFsEAASDQoJVHJhbnNsYXRlEAEqHgoMU3VidGl0bGVUeXBlEgYKAkNDEAASBgoCQUkQASpOChFUb2FzdEZ1bmN0aW9uVHlwZRIZChVUb2FzdEZ1bmN0aW9uVHlwZU5vbmUQABIeChpUb2FzdEZ1bmN0aW9uVHlwZVBvc3RQYW5lbBABMqAFCgJETRJzCgtEbVNlZ01vYmlsZRIwLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRtU2VnTW9iaWxlUmVxGjIuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRG1TZWdNb2JpbGVSZXBseRJkCgZEbVZpZXcSKy5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EbVZpZXdSZXEaLS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EbVZpZXdSZXBseRJxCg5EbVBsYXllckNvbmZpZxIzLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRtUGxheWVyQ29uZmlnUmVxGiouYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuUmVzcG9uc2USagoIRG1TZWdPdHQSLS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EbVNlZ090dFJlcRovLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRtU2VnT3R0UmVwbHkSagoIRG1TZWdTREsSLS5iaWxpYmlsaS5jb21tdW5pdHkuc2VydmljZS5kbS52MS5EbVNlZ1NES1JlcRovLmJpbGliaWxpLmNvbW11bml0eS5zZXJ2aWNlLmRtLnYxLkRtU2VnU0RLUmVwbHkSdAoMRG1FeHBvUmVwb3J0EjEuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRG1FeHBvUmVwb3J0UmVxGjEuYmlsaWJpbGkuY29tbXVuaXR5LnNlcnZpY2UuZG0udjEuRG1FeHBvUmVwb3J0UmVzYgZwcm90bzM");
1294
+ const DmSegMobileReplySchema = /*@__PURE__*/ codegenv2_messageDesc(file_bili_dm, 30);
1295
+ const DmWebViewReplySchema = /*@__PURE__*/ codegenv2_messageDesc(file_bili_dm, 39);
1296
+ const file_danuni = /*@__PURE__*/ fileDesc("CgxkYW51bmkucHJvdG8SEWRhbnVuaS5kYW5tYWt1LnYxIjIKCmxpc3REYW5SZXESCgoCSUQYASABKAkSEAoDc2VnGAIgASgFSACIAQFCBgoEX3NlZyLUAgoHRGFubWFrdRIMCgRTT0lEGAEgASgJEgwKBERNSUQYAiABKAkSEAoIcHJvZ3Jlc3MYAyABKAUSJQoEbW9kZRgEIAEoDjIXLmRhbnVuaS5kYW5tYWt1LnYxLk1vZGUSEAoIZm9udHNpemUYBSABKAUSDQoFY29sb3IYBiABKAUSEAoIc2VuZGVySUQYByABKAkSDwoHY29udGVudBgIIAEoCRIpCgVjdGltZRgJIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGd2VpZ2h0GAogASgFEiUKBHBvb2wYCyABKA4yFy5kYW51bmkuZGFubWFrdS52MS5Qb29sEgwKBGF0dHIYDCADKAkSFQoIcGxhdGZvcm0YDSABKAlIAIgBARISCgVleHRyYRgOIAEoCUgBiAEBQgsKCV9wbGF0Zm9ybUIICgZfZXh0cmEiPAoMRGFubWFrdVJlcGx5EiwKCGRhbm1ha3VzGAEgAygLMhouZGFudW5pLmRhbm1ha3UudjEuRGFubWFrdSo9CgRNb2RlEgoKBk5vcm1hbBAAEgoKBkJvdHRvbRABEgcKA1RvcBACEgsKB1JldmVyc2UQAxIHCgNFeHQQBCopCgRQb29sEgcKA0RlZhAAEgcKA1N1YhABEgcKA0FkdhACEgYKAkl4EAMyXQoORGFubWFrdVNlcnZpY2USSwoHbGlzdERhbhIdLmRhbnVuaS5kYW5tYWt1LnYxLmxpc3REYW5SZXEaHy5kYW51bmkuZGFubWFrdS52MS5EYW5tYWt1UmVwbHkiAFAAYgZwcm90bzM", [
1297
+ file_google_protobuf_timestamp
1298
+ ]);
1299
+ const DanmakuReplySchema = /*@__PURE__*/ codegenv2_messageDesc(file_danuni, 2);
1300
+ const src_JSON = json_bigint({
1301
+ useNativeBigInt: true
1302
+ });
1303
+ const DanUniConvertTipTemplate = {
1304
+ meassage: 'Converted by DanUni!',
1305
+ version: `JS/TS ${package_namespaceObject.UU} (v${package_namespaceObject.rE})`
1306
+ };
1307
+ class UniPool {
1308
+ constructor(dans, options = {}, info = {
1309
+ fromConverted: false
1310
+ }){
1311
+ this.dans = dans;
1312
+ this.options = options;
1313
+ this.info = info;
1314
+ if (false !== options.dedupe) options.dedupe = true;
1315
+ if (this.options.dedupe) this.dedupe();
1316
+ }
1317
+ async pipe(fn) {
1318
+ return fn(this);
1319
+ }
1320
+ pipeSync(fn) {
1321
+ return fn(this);
1322
+ }
1323
+ get shared() {
1324
+ if (0 === this.dans.length) return {};
1325
+ const keys = [
1326
+ 'SOID',
1327
+ 'senderID',
1328
+ 'platform',
1329
+ 'pool',
1330
+ 'mode',
1331
+ 'color'
1332
+ ];
1333
+ const result = {};
1334
+ for (const key of keys){
1335
+ const sharedVal = this.getShared(key);
1336
+ if (void 0 !== sharedVal) result[key] = sharedVal;
1337
+ }
1338
+ return result;
1339
+ }
1340
+ getShared(key) {
1341
+ if (0 === this.dans.length) return;
1342
+ const firstVal = this.dans[0][key];
1343
+ for(let i = 1; i < this.dans.length; i++)if (this.dans[i][key] !== firstVal) return;
1344
+ return firstVal;
1345
+ }
1346
+ getStat(key) {
1347
+ const statMap = new Map();
1348
+ for (const dan of this.dans){
1349
+ const val = dan[key];
1350
+ statMap.set(val, (statMap.get(val) || 0) + 1);
1351
+ }
1352
+ return statMap;
1353
+ }
1354
+ getMost(key) {
1355
+ const stats = this.getStat(key);
1356
+ if (0 === stats.size) return {
1357
+ val: void 0,
1358
+ count: 0
1359
+ };
1360
+ let mostVal;
1361
+ let maxCount = 0;
1362
+ for (const [val, count] of stats.entries())if (count > maxCount) {
1363
+ maxCount = count;
1364
+ mostVal = val;
1365
+ }
1366
+ return {
1367
+ val: mostVal,
1368
+ count: maxCount
1369
+ };
1370
+ }
1371
+ get most() {
1372
+ const keys = [
1373
+ 'mode',
1374
+ 'fontsize',
1375
+ 'color',
1376
+ 'senderID',
1377
+ 'content',
1378
+ 'weight',
1379
+ 'pool',
1380
+ 'platform'
1381
+ ];
1382
+ const statMaps = new Map();
1383
+ for (const dan of this.dans)for (const key of keys){
1384
+ if (!statMaps.has(key)) statMaps.set(key, new Map());
1385
+ const statMap = statMaps.get(key);
1386
+ const val = dan[key];
1387
+ statMap.set(val, (statMap.get(val) || 0) + 1);
1388
+ }
1389
+ const result = {};
1390
+ for (const key of keys){
1391
+ const statMap = statMaps.get(key);
1392
+ let mostVal;
1393
+ let maxCount = 0;
1394
+ for (const [val, count] of statMap.entries())if (count > maxCount) {
1395
+ maxCount = count;
1396
+ mostVal = val;
1397
+ }
1398
+ result[key] = mostVal;
1399
+ }
1400
+ return {
1401
+ mode: result.mode,
1402
+ fontsize: result.fontsize,
1403
+ color: result.color,
1404
+ senderID: result.senderID,
1405
+ content: result.content,
1406
+ weight: result.weight,
1407
+ pool: result.pool,
1408
+ platform: result.platform
1409
+ };
1410
+ }
1411
+ static create(options) {
1412
+ return new UniPool([], options);
1413
+ }
1414
+ assign(dans) {
1415
+ if (dans instanceof UniPool) return new UniPool([
1416
+ ...this.dans,
1417
+ ...dans.dans
1418
+ ], {
1419
+ ...this.options,
1420
+ ...dans.options
1421
+ }, {
1422
+ ...this.info,
1423
+ ...dans.info
1424
+ });
1425
+ if (dans instanceof UniDM) return new UniPool([
1426
+ ...this.dans,
1427
+ dans
1428
+ ], this.options, this.info);
1429
+ if (Array.isArray(dans) && dans.every((d)=>d instanceof UniDM)) return new UniPool([
1430
+ ...this.dans,
1431
+ ...dans
1432
+ ], this.options, this.info);
1433
+ return this;
1434
+ }
1435
+ split(key) {
1436
+ if (this.getShared(key)) return [
1437
+ this
1438
+ ];
1439
+ const set = new Set(this.dans.map((d)=>d[key]));
1440
+ return [
1441
+ ...set
1442
+ ].map((v)=>new UniPool(this.dans.filter((d)=>d[key] === v), {
1443
+ ...this.options,
1444
+ dedupe: false
1445
+ }, this.info));
1446
+ }
1447
+ dedupe() {
1448
+ if (false !== this.options.dmid) {
1449
+ const map = new Map();
1450
+ this.dans.forEach((d)=>map.set(d.DMID || d.toDMID(), d));
1451
+ this.dans = [
1452
+ ...map.values()
1453
+ ];
1454
+ }
1455
+ this.options.dedupe = false;
1456
+ }
1457
+ merge(lifetime = 0) {
1458
+ if (!this.getShared('SOID')) {
1459
+ console.error("本功能仅支持同弹幕库内使用,可先 .split('SOID') 在分别使用");
1460
+ return this;
1461
+ }
1462
+ if (lifetime <= 0) return this;
1463
+ const result = [];
1464
+ const cache = {};
1465
+ const mergeObj = {};
1466
+ for (const danmaku of this.dans){
1467
+ const key = `${danmaku.content}|${danmaku.mode}|${danmaku.pool}|${danmaku.platform}`;
1468
+ const cached = cache[key];
1469
+ if (cached && danmaku.progress - cached.progress <= lifetime && danmaku.isSameAs(cached, {
1470
+ skipDanuniMerge: true
1471
+ })) {
1472
+ mergeObj[key].senders.push(danmaku.senderID);
1473
+ mergeObj[key].count = mergeObj[key].senders.length;
1474
+ mergeObj[key].taolu_count = mergeObj[key].count;
1475
+ mergeObj[key].taolu_senders = mergeObj[key].senders;
1476
+ mergeObj[key].duration = Number.parseFloat((danmaku.progress - cached.progress).toFixed(3));
1477
+ cache[key] = danmaku;
1478
+ } else {
1479
+ mergeObj[key] = {
1480
+ count: 1,
1481
+ duration: 0,
1482
+ senders: [
1483
+ danmaku.senderID
1484
+ ],
1485
+ taolu_count: 1,
1486
+ taolu_senders: [
1487
+ danmaku.senderID
1488
+ ]
1489
+ };
1490
+ cache[key] = danmaku;
1491
+ result.push(danmaku);
1492
+ }
1493
+ }
1494
+ for (const danmaku of result){
1495
+ const key = `${danmaku.content}|${danmaku.mode}|${danmaku.pool}|${danmaku.platform}`;
1496
+ const mergeData = mergeObj[key];
1497
+ const extra = danmaku.extra;
1498
+ if (mergeData.count > 1) {
1499
+ danmaku.senderID = 'merge[bot]@dan-any';
1500
+ if (danmaku.attr) {
1501
+ if (!danmaku.attr.includes(dm_gen_DMAttr.Protect)) danmaku.attr.push(dm_gen_DMAttr.Protect);
1502
+ } else danmaku.attr = [
1503
+ dm_gen_DMAttr.Protect
1504
+ ];
1505
+ extra.danuni = extra.danuni || {};
1506
+ extra.danuni.merge = mergeData;
1507
+ danmaku.extraStr = src_JSON.stringify(extra);
1508
+ } else {
1509
+ if (extra.danuni?.merge) {
1510
+ delete extra.danuni.merge;
1511
+ if (0 === Object.keys(extra.danuni).length) delete extra.danuni;
1512
+ }
1513
+ danmaku.extraStr = Object.keys(extra).length > 0 ? src_JSON.stringify(extra) : void 0;
1514
+ }
1515
+ }
1516
+ return new UniPool(result, this.options, this.info);
1517
+ }
1518
+ minify() {
1519
+ return this.dans.map((d)=>d.minify());
1520
+ }
1521
+ static import(file, options, mod) {
1522
+ if (!mod) mod = [
1523
+ 'json',
1524
+ 'str',
1525
+ 'bin'
1526
+ ];
1527
+ const err = '无法识别该文件,请手动指定格式!';
1528
+ const parseJSON = (json)=>{
1529
+ try {
1530
+ if (Array.isArray(json) && json.every((d)=>d.SOID)) return {
1531
+ pool: new UniPool(json, options),
1532
+ fmt: 'danuni.json'
1533
+ };
1534
+ if (json.danmuku && json.danmuku.every((d)=>d.text)) return {
1535
+ pool: this.fromArtplayer(json, json.danuni?.data ?? '', void 0, options),
1536
+ fmt: 'artplayer.json'
1537
+ };
1538
+ if (json.count && json.comments && Array.isArray(json.comments) && json.comments.every((d)=>d.m)) return {
1539
+ pool: this.fromDDPlay(json, json.danuni?.data ?? '', options),
1540
+ fmt: 'ddplay.json'
1541
+ };
1542
+ else if (0 == json.code && json.data && Array.isArray(json.data) && json.data.every((d)=>Array.isArray(d))) return {
1543
+ pool: this.fromDplayer(json, json.danuni?.data ?? '', void 0, options),
1544
+ fmt: 'dplayer.json'
1545
+ };
1546
+ else if (0 == json.code && '0' == json.message && json.data && json.data.page && json.data.result && Array.isArray(json.data.result) && json.data.result.every((d)=>d.id && d.oid)) return {
1547
+ pool: this.fromBiliUp(json, options),
1548
+ fmt: 'bili.up.json'
1549
+ };
1550
+ } catch {}
1551
+ };
1552
+ const parseStr = (file)=>{
1553
+ if (mod.includes('json')) try {
1554
+ if (isJSON(file)) {
1555
+ const json = src_JSON.parse(file);
1556
+ return parseJSON(json);
1557
+ }
1558
+ } catch {}
1559
+ if (mod.includes('str')) {
1560
+ try {
1561
+ const xmlParser = new XMLParser({
1562
+ ignoreAttributes: false
1563
+ });
1564
+ const xml = xmlParser.parse(file);
1565
+ if (xml?.i?.d) return {
1566
+ pool: this.fromBiliXML(file, options),
1567
+ fmt: 'bili.xml'
1568
+ };
1569
+ } catch {}
1570
+ try {
1571
+ return {
1572
+ pool: this.fromASS(file, options),
1573
+ fmt: 'common.ass'
1574
+ };
1575
+ } catch {}
1576
+ }
1577
+ };
1578
+ let errmesg;
1579
+ if (isObject(file)) {
1580
+ if (file instanceof ArrayBuffer || file instanceof Uint8Array) {
1581
+ if (mod.includes('bin')) {
1582
+ try {
1583
+ return {
1584
+ pool: this.fromPb(file),
1585
+ fmt: 'danuni.pb.bin'
1586
+ };
1587
+ } catch {}
1588
+ try {
1589
+ return {
1590
+ pool: this.fromBiliGrpc(file),
1591
+ fmt: 'bili.pb.bin'
1592
+ };
1593
+ } catch {}
1594
+ try {
1595
+ return {
1596
+ pool: this.fromBiliCommandGrpc(file),
1597
+ fmt: 'bili.cmd.pb.bin'
1598
+ };
1599
+ } catch {}
1600
+ }
1601
+ try {
1602
+ const fileStr = new TextDecoder().decode(file);
1603
+ const prStr = parseStr(fileStr);
1604
+ if (prStr) return prStr;
1605
+ errmesg = `${err}(定位: bin->string)`;
1606
+ } catch {}
1607
+ } else if (mod.includes('json')) {
1608
+ const prJSON = parseJSON(file);
1609
+ if (!prJSON) throw new Error(`${err}(定位: json)`);
1610
+ return prJSON;
1611
+ }
1612
+ } else if (isString(file)) {
1613
+ const prStr = parseStr(file);
1614
+ if (!prStr) throw new Error(`${err}(定位: string)`);
1615
+ return prStr;
1616
+ }
1617
+ throw new Error(errmesg ?? err);
1618
+ }
1619
+ convert2(format, continue_on_error = false) {
1620
+ switch(format){
1621
+ case 'danuni.json':
1622
+ return this.dans;
1623
+ case 'danuni.pb.bin':
1624
+ return this.toPb();
1625
+ case 'bili.xml':
1626
+ return this.toBiliXML();
1627
+ case 'dplayer.json':
1628
+ return this.toDplayer();
1629
+ case 'artplayer.json':
1630
+ return this.toArtplayer();
1631
+ case 'ddplay.json':
1632
+ return this.toDDplay();
1633
+ default:
1634
+ {
1635
+ const message = '(err) Unknown format or unsupported now!';
1636
+ if (continue_on_error) return message;
1637
+ throw new Error(message);
1638
+ }
1639
+ }
1640
+ }
1641
+ static fromPb(bin, options) {
1642
+ const data = fromBinary(DanmakuReplySchema, new Uint8Array(bin));
1643
+ return new UniPool(data.danmakus.map((d)=>UniDM.create({
1644
+ ...d,
1645
+ progress: d.progress / 1000,
1646
+ mode: d.mode,
1647
+ ctime: timestampDate(d.ctime || timestampNow()),
1648
+ pool: d.pool,
1649
+ attr: d.attr,
1650
+ extra: void 0,
1651
+ extraStr: d.extra
1652
+ }, options)), options);
1653
+ }
1654
+ toPb() {
1655
+ return toBinary(DanmakuReplySchema, create(DanmakuReplySchema, {
1656
+ danmakus: this.dans.map((d)=>({
1657
+ SOID: d.SOID,
1658
+ DMID: d.DMID,
1659
+ progress: Math.round(1000 * d.progress),
1660
+ mode: d.mode,
1661
+ fontsize: d.fontsize,
1662
+ color: d.color,
1663
+ senderID: d.senderID,
1664
+ content: d.content,
1665
+ ctime: timestampFromDate(d.ctime),
1666
+ weight: d.weight,
1667
+ pool: d.pool,
1668
+ attr: d.attr,
1669
+ platform: d.platform,
1670
+ extra: d.extraStr
1671
+ }))
1672
+ }));
1673
+ }
1674
+ static fromBiliXML(xml, options) {
1675
+ const parser = new XMLParser({
1676
+ ignoreAttributes: false
1677
+ });
1678
+ const oriData = parser.parse(xml);
1679
+ const dans = oriData.i.d;
1680
+ const fromConverted = !!oriData.i.danuni;
1681
+ const cid = BigInt(oriData.i.chatid);
1682
+ return new UniPool(dans.map((d)=>UniDM.fromBili(UniDM.parseBiliSingle(d['@_p'], d['#text']), cid, options, fromConverted ? oriData.i.danuni?.data : void 0)).filter((d)=>null !== d), options, {
1683
+ fromConverted
1684
+ });
1685
+ }
1686
+ toBiliXML(options) {
1687
+ const genCID = (id)=>{
1688
+ const UniID = id_gen_UniID.fromString(id);
1689
+ if (UniID.domain === platform_PlatformVideoSource.Bilibili) {
1690
+ const cid = UniID.id.replaceAll(`def_${platform_PlatformVideoSource.Bilibili}+`, '');
1691
+ if (cid) return cid;
1692
+ }
1693
+ return !options?.cid || id;
1694
+ };
1695
+ if (options?.avoidSenderIDWithAt) {
1696
+ const ok = this.dans.every((d)=>d.senderID.endsWith(`@${platform_PlatformVideoSource.Bilibili}`));
1697
+ if (!ok) throw new Error('存在其他来源的senderID,请关闭该功能再试!');
1698
+ }
1699
+ const builder = new XMLBuilder({
1700
+ ignoreAttributes: false
1701
+ });
1702
+ return builder.build({
1703
+ '?xml': {
1704
+ '@_version': '1.0',
1705
+ '@_encoding': 'UTF-8'
1706
+ },
1707
+ i: {
1708
+ chatserver: 'chat.bilibili.com',
1709
+ chatid: genCID(this.dans[0].SOID),
1710
+ mission: 0,
1711
+ maxlimit: this.dans.length,
1712
+ state: 0,
1713
+ real_name: 0,
1714
+ source: 'k-v',
1715
+ danuni: {
1716
+ ...DanUniConvertTipTemplate,
1717
+ data: this.getShared('SOID')
1718
+ },
1719
+ d: this.dans.map((dan)=>dan.toBiliXML(options))
1720
+ }
1721
+ });
1722
+ }
1723
+ static fromBiliGrpc(bin, options) {
1724
+ const data = fromBinary(DmSegMobileReplySchema, new Uint8Array(bin));
1725
+ const json = data.elems;
1726
+ return new UniPool(json.map((d)=>UniDM.fromBili({
1727
+ ...d,
1728
+ progress: d.progress / 1000
1729
+ }, d.oid, options)), options);
1730
+ }
1731
+ static fromBiliCommandGrpc(bin, options) {
1732
+ const data = fromBinary(DmWebViewReplySchema, new Uint8Array(bin));
1733
+ const json = data.commandDms;
1734
+ return new UniPool(json.map((d)=>UniDM.fromBiliCommand(d, d.oid, options)), options);
1735
+ }
1736
+ static fromBiliUp(json, options) {
1737
+ return new UniPool(json.data.result.map((d)=>{
1738
+ const attrBin = d.attrs ? d.attrs.split(',').map(Number).reduce((bin, bitPosition)=>bin | 1 << bitPosition - 1, 0) : 0;
1739
+ return UniDM.fromBili({
1740
+ id: BigInt(d.id_str || d.id),
1741
+ progress: d.progress / 1000,
1742
+ mode: d.mode,
1743
+ fontsize: d.fontsize,
1744
+ color: Number.parseInt(d.color, 16),
1745
+ mid: d.mid,
1746
+ midHash: d.mid_hash,
1747
+ content: d.msg,
1748
+ ctime: BigInt(d.ctime),
1749
+ pool: d.pool,
1750
+ attr: attrBin,
1751
+ oid: BigInt(d.oid)
1752
+ }, BigInt(d.oid), options);
1753
+ }), options);
1754
+ }
1755
+ static fromDplayer(json, playerID, domain = 'other', options) {
1756
+ return new UniPool(json.data.map((d)=>UniDM.fromDplayer({
1757
+ content: d[4],
1758
+ progress: d[0],
1759
+ mode: d[1],
1760
+ color: d[2],
1761
+ midHash: d[3]
1762
+ }, playerID, domain, options)), options, {
1763
+ fromConverted: !!json.danuni
1764
+ });
1765
+ }
1766
+ toDplayer() {
1767
+ return {
1768
+ code: 0,
1769
+ danuni: {
1770
+ ...DanUniConvertTipTemplate,
1771
+ data: this.dans[0].SOID.split('@')[0]
1772
+ },
1773
+ data: this.dans.map((dan)=>{
1774
+ const d = dan.toDplayer();
1775
+ return [
1776
+ d.progress,
1777
+ d.mode,
1778
+ d.color,
1779
+ d.midHash,
1780
+ d.content
1781
+ ];
1782
+ })
1783
+ };
1784
+ }
1785
+ static fromArtplayer(json, playerID, domain = 'other', options) {
1786
+ return new UniPool(json.danmuku.map((d)=>UniDM.fromArtplayer({
1787
+ content: d.text,
1788
+ progress: d.time || 0,
1789
+ mode: d.mode || 0,
1790
+ color: Number((d.color || 'FFFFFF').replace('#', '0x')),
1791
+ style: d.style
1792
+ }, playerID, domain, options)), options, {
1793
+ fromConverted: !!json.danuni
1794
+ });
1795
+ }
1796
+ toArtplayer() {
1797
+ return {
1798
+ danuni: {
1799
+ ...DanUniConvertTipTemplate,
1800
+ data: this.dans[0].SOID.split('@')[0]
1801
+ },
1802
+ danmuku: this.dans.map((dan)=>{
1803
+ const d = dan.toArtplayer();
1804
+ return {
1805
+ text: d.content,
1806
+ time: d.progress,
1807
+ mode: d.mode,
1808
+ color: `#${d.color.toString(16).toUpperCase() || 'FFFFFF'}`,
1809
+ border: d.border,
1810
+ style: d.style
1811
+ };
1812
+ })
1813
+ };
1814
+ }
1815
+ static fromDDPlay(json, episodeId, options) {
1816
+ return new UniPool(json.comments.map((d)=>{
1817
+ const p_arr = d.p.split(',');
1818
+ return UniDM.fromDDplay({
1819
+ cid: d.cid,
1820
+ color: Number.parseInt(p_arr[2]),
1821
+ m: d.m,
1822
+ mode: Number.parseInt(p_arr[1]),
1823
+ progress: Number.parseFloat(p_arr[0]),
1824
+ uid: p_arr[3]
1825
+ }, episodeId, void 0, options);
1826
+ }), options, {
1827
+ fromConverted: !!json.danuni
1828
+ });
1829
+ }
1830
+ toDDplay() {
1831
+ const episodeId = this.dans[0].SOID.split('@')[0].replaceAll(`def_${platform_PlatformDanmakuOnlySource.DanDanPlay}+`, '');
1832
+ return {
1833
+ danuni: {
1834
+ ...DanUniConvertTipTemplate,
1835
+ data: episodeId
1836
+ },
1837
+ count: this.dans.length,
1838
+ comments: this.dans.map((dan)=>{
1839
+ const d = dan.toDDplay();
1840
+ return {
1841
+ cid: d.cid,
1842
+ p: `${d.progress},${d.mode},${d.color},${d.uid}`,
1843
+ m: d.m
1844
+ };
1845
+ })
1846
+ };
1847
+ }
1848
+ static fromASS(ass, options) {
1849
+ return parseAssRawField(ass, options);
1850
+ }
1851
+ toASS(canvasCtx, options) {
1852
+ const defaultOptions = {
1853
+ substyle: {}
1854
+ };
1855
+ const finalOptions = options ?? defaultOptions;
1856
+ const fn = this.getShared('SOID');
1857
+ return generateASS(this, {
1858
+ filename: fn,
1859
+ title: fn,
1860
+ ...finalOptions
1861
+ }, canvasCtx);
1862
+ }
1863
+ }
1864
+ export { UniDM, UniPool, dm_gen_namespaceObject as UniDMTools, id_gen_namespaceObject as UniIDTools, platform_PlatformVideoSource, platform_namespaceObject as platform };