@dan-uni/dan-any 0.9.8 → 1.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.
- package/dist/index.js +255 -242
- package/dist/index.min.js +260 -247
- package/dist/index.umd.min.js +306 -283
- package/dist/src/index.d.ts +18 -8
- package/dist/src/proto/gen/danuni_pb.d.ts +2 -2
- package/package.json +5 -5
- package/src/ass-gen/ass/dialogue.ts +4 -4
- package/src/index.ts +182 -132
- package/src/proto/gen/bili/dm_pb.ts +1 -1
- package/src/proto/gen/danuni_pb.ts +4 -4
- package/src/proto/src/danuni.proto +1 -1
- package/src/utils/dm-gen.ts +16 -19
package/dist/src/index.d.ts
CHANGED
|
@@ -116,17 +116,18 @@ export interface DM_JSON_DDPlay {
|
|
|
116
116
|
m: string;
|
|
117
117
|
}[];
|
|
118
118
|
}
|
|
119
|
-
export type DM_format = 'danuni.json' | 'danuni.pb.bin' | 'bili.xml' | 'bili.pb.bin' | 'bili.cmd.pb.bin' | 'dplayer.json' | 'artplayer.json' | 'ddplay.json' | 'common.ass';
|
|
119
|
+
export type DM_format = 'danuni.json' | 'danuni.pb.bin' | 'bili.xml' | 'bili.pb.bin' | 'bili.cmd.pb.bin' | 'bili.up.json' | 'dplayer.json' | 'artplayer.json' | 'ddplay.json' | 'common.ass';
|
|
120
120
|
type shareItems = Partial<Pick<UniDMTools.UniDMObj, 'SOID' | 'senderID' | 'platform' | 'SOID' | 'pool' | 'mode' | 'color'>>;
|
|
121
121
|
type statItems = Partial<Pick<UniDMTools.UniDMObj, 'SOID' | 'mode' | 'fontsize' | 'color' | 'senderID' | 'content' | 'weight' | 'pool' | 'platform'>>;
|
|
122
|
-
|
|
123
|
-
val: statItems[keyof statItems];
|
|
124
|
-
count: number;
|
|
125
|
-
}
|
|
122
|
+
type Stats<T extends keyof statItems> = Map<statItems[T], number>;
|
|
126
123
|
type UniPoolPipe = (that: UniPool) => Promise<UniPool>;
|
|
127
124
|
type UniPoolPipeSync = (that: UniPool) => UniPool;
|
|
128
125
|
export interface Options {
|
|
129
126
|
dedupe?: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* @description
|
|
129
|
+
* 当为`false`时,关闭DMID生成; 当为正整数时,表示生成DMID的截取位数; 或可传入一个DMID生成器实例
|
|
130
|
+
*/
|
|
130
131
|
dmid?: boolean | number | UniIDTools.DMIDGenerator;
|
|
131
132
|
}
|
|
132
133
|
export declare class UniPool {
|
|
@@ -146,10 +147,19 @@ export declare class UniPool {
|
|
|
146
147
|
});
|
|
147
148
|
pipe(fn: UniPoolPipe): Promise<UniPool>;
|
|
148
149
|
pipeSync(fn: UniPoolPipeSync): UniPool;
|
|
150
|
+
/**
|
|
151
|
+
* @deprecated 使用 `getShared` 代替
|
|
152
|
+
*/
|
|
149
153
|
get shared(): shareItems;
|
|
150
|
-
getShared(key:
|
|
151
|
-
getStat(key:
|
|
152
|
-
getMost(key:
|
|
154
|
+
getShared<K extends keyof shareItems>(key: K): shareItems[K];
|
|
155
|
+
getStat<K extends keyof statItems>(key: K): Stats<K>;
|
|
156
|
+
getMost<K extends keyof statItems>(key: K): {
|
|
157
|
+
val: Partial<Pick<UniDMTools.UniDMObj, "SOID" | "mode" | "fontsize" | "color" | "senderID" | "content" | "weight" | "pool" | "platform">>[K] | undefined;
|
|
158
|
+
count: number;
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* @deprecated 使用 `getMost` 代替
|
|
162
|
+
*/
|
|
153
163
|
get most(): {
|
|
154
164
|
mode: UniDMTools.Modes;
|
|
155
165
|
fontsize: number;
|
|
@@ -76,9 +76,9 @@ export type Danmaku = Message<"danuni.danmaku.v1.Danmaku"> & {
|
|
|
76
76
|
*/
|
|
77
77
|
attr: string[];
|
|
78
78
|
/**
|
|
79
|
-
* @generated from field: string platform = 13;
|
|
79
|
+
* @generated from field: optional string platform = 13;
|
|
80
80
|
*/
|
|
81
|
-
platform
|
|
81
|
+
platform?: string;
|
|
82
82
|
/**
|
|
83
83
|
* @generated from field: optional string extra = 14;
|
|
84
84
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dan-uni/dan-any",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "A danmaku transformer lib, supporting danmaku from different platforms.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
"buf": "buf generate"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@bufbuild/protobuf": "^2.
|
|
35
|
+
"@bufbuild/protobuf": "^2.10.1",
|
|
36
36
|
"base16384": "^1.0.0",
|
|
37
37
|
"class-transformer": "^0.5.1",
|
|
38
38
|
"class-validator": "^0.14.2",
|
|
39
|
-
"fast-xml-parser": "^5.3.
|
|
39
|
+
"fast-xml-parser": "^5.3.2",
|
|
40
40
|
"fs-extra": "^11.3.2",
|
|
41
41
|
"hh-mm-ss": "^1.2.0",
|
|
42
42
|
"json-bigint": "^1.0.0",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"reflect-metadata": "^0.2.2"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@bufbuild/buf": "^1.
|
|
48
|
-
"@bufbuild/protoc-gen-es": "^2.
|
|
47
|
+
"@bufbuild/buf": "^1.60.0",
|
|
48
|
+
"@bufbuild/protoc-gen-es": "^2.10.1",
|
|
49
49
|
"@types/fs-extra": "^11.0.4",
|
|
50
50
|
"@types/hh-mm-ss": "^1.2.3",
|
|
51
51
|
"@types/json-bigint": "^1.0.4",
|
|
@@ -34,11 +34,11 @@ const scrollCommand = ({
|
|
|
34
34
|
start: number
|
|
35
35
|
end: number
|
|
36
36
|
top: number
|
|
37
|
-
}) =>
|
|
37
|
+
}) => String.raw`\move(${start},${top},${end},${top})`
|
|
38
38
|
const fixCommand = ({ top, left }: { top: number; left: number }) =>
|
|
39
|
-
|
|
40
|
-
const colorCommand = (color: RGB) =>
|
|
41
|
-
const borderColorCommand = (color: RGB) =>
|
|
39
|
+
String.raw`\an8\pos(${left},${top})`
|
|
40
|
+
const colorCommand = (color: RGB) => String.raw`\c${formatColor(color)}`
|
|
41
|
+
const borderColorCommand = (color: RGB) => String.raw`\3c${formatColor(color)}`
|
|
42
42
|
|
|
43
43
|
export const dialogue = (
|
|
44
44
|
danmaku: {
|
package/src/index.ts
CHANGED
|
@@ -157,6 +157,7 @@ export type DM_format =
|
|
|
157
157
|
| 'bili.xml'
|
|
158
158
|
| 'bili.pb.bin'
|
|
159
159
|
| 'bili.cmd.pb.bin'
|
|
160
|
+
| 'bili.up.json'
|
|
160
161
|
| 'dplayer.json'
|
|
161
162
|
| 'artplayer.json'
|
|
162
163
|
| 'ddplay.json'
|
|
@@ -182,16 +183,17 @@ type statItems = Partial<
|
|
|
182
183
|
| 'platform'
|
|
183
184
|
>
|
|
184
185
|
>
|
|
185
|
-
|
|
186
|
-
val: statItems[keyof statItems]
|
|
187
|
-
count: number
|
|
188
|
-
}
|
|
186
|
+
type Stats<T extends keyof statItems> = Map<statItems[T], number>
|
|
189
187
|
|
|
190
188
|
type UniPoolPipe = (that: UniPool) => Promise<UniPool>
|
|
191
189
|
type UniPoolPipeSync = (that: UniPool) => UniPool
|
|
192
190
|
|
|
193
191
|
export interface Options {
|
|
194
192
|
dedupe?: boolean
|
|
193
|
+
/**
|
|
194
|
+
* @description
|
|
195
|
+
* 当为`false`时,关闭DMID生成; 当为正整数时,表示生成DMID的截取位数; 或可传入一个DMID生成器实例
|
|
196
|
+
*/
|
|
195
197
|
dmid?: boolean | number | UniIDTools.DMIDGenerator
|
|
196
198
|
}
|
|
197
199
|
|
|
@@ -215,51 +217,109 @@ export class UniPool {
|
|
|
215
217
|
pipeSync(fn: UniPoolPipeSync): UniPool {
|
|
216
218
|
return fn(this)
|
|
217
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* @deprecated 使用 `getShared` 代替
|
|
222
|
+
*/
|
|
218
223
|
get shared(): shareItems {
|
|
219
|
-
|
|
220
|
-
|
|
224
|
+
if (this.dans.length === 0) return {}
|
|
225
|
+
const keys: (keyof shareItems)[] = [
|
|
226
|
+
'SOID',
|
|
227
|
+
'senderID',
|
|
228
|
+
'platform',
|
|
229
|
+
'pool',
|
|
230
|
+
'mode',
|
|
231
|
+
'color',
|
|
232
|
+
]
|
|
233
|
+
const result: shareItems = {} as shareItems
|
|
234
|
+
for (const key of keys) {
|
|
235
|
+
const sharedVal = this.getShared(key)
|
|
236
|
+
if (sharedVal !== undefined) {
|
|
237
|
+
result[key] = sharedVal as any
|
|
238
|
+
}
|
|
221
239
|
}
|
|
222
|
-
return
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
240
|
+
return result
|
|
241
|
+
}
|
|
242
|
+
getShared<K extends keyof shareItems>(key: K): shareItems[K] {
|
|
243
|
+
if (this.dans.length === 0) return undefined
|
|
244
|
+
const firstVal = this.dans[0][key]
|
|
245
|
+
for (let i = 1; i < this.dans.length; i++) {
|
|
246
|
+
if (this.dans[i][key] !== firstVal) {
|
|
247
|
+
return undefined
|
|
248
|
+
}
|
|
229
249
|
}
|
|
250
|
+
return firstVal
|
|
230
251
|
}
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
|
|
252
|
+
getStat<K extends keyof statItems>(key: K): Stats<K> {
|
|
253
|
+
const statMap = new Map<statItems[K], number>()
|
|
254
|
+
for (const dan of this.dans) {
|
|
255
|
+
const val = dan[key]
|
|
256
|
+
statMap.set(val, (statMap.get(val) || 0) + 1)
|
|
234
257
|
}
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
258
|
+
return statMap
|
|
259
|
+
}
|
|
260
|
+
getMost<K extends keyof statItems>(key: K) {
|
|
261
|
+
const stats = this.getStat(key)
|
|
262
|
+
if (stats.size === 0) return { val: undefined, count: 0 }
|
|
263
|
+
let mostVal: statItems[K] | undefined
|
|
264
|
+
let maxCount = 0
|
|
265
|
+
for (const [val, count] of stats.entries()) {
|
|
266
|
+
if (count > maxCount) {
|
|
267
|
+
maxCount = count
|
|
268
|
+
mostVal = val
|
|
245
269
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return stats
|
|
249
|
-
}
|
|
250
|
-
getMost(key: keyof statItems) {
|
|
251
|
-
return this.getStat(key).toSorted((a, b) => b.count - a.count)[0]
|
|
270
|
+
}
|
|
271
|
+
return { val: mostVal, count: maxCount }
|
|
252
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* @deprecated 使用 `getMost` 代替
|
|
275
|
+
*/
|
|
253
276
|
get most() {
|
|
277
|
+
const keys: (keyof statItems)[] = [
|
|
278
|
+
'mode',
|
|
279
|
+
'fontsize',
|
|
280
|
+
'color',
|
|
281
|
+
'senderID',
|
|
282
|
+
'content',
|
|
283
|
+
'weight',
|
|
284
|
+
'pool',
|
|
285
|
+
'platform',
|
|
286
|
+
]
|
|
287
|
+
const statMaps = new Map<
|
|
288
|
+
keyof statItems,
|
|
289
|
+
Map<statItems[keyof statItems], number>
|
|
290
|
+
>()
|
|
291
|
+
for (const dan of this.dans) {
|
|
292
|
+
for (const key of keys) {
|
|
293
|
+
if (!statMaps.has(key)) {
|
|
294
|
+
statMaps.set(key, new Map())
|
|
295
|
+
}
|
|
296
|
+
const statMap = statMaps.get(key)!
|
|
297
|
+
const val = dan[key]
|
|
298
|
+
statMap.set(val, (statMap.get(val) || 0) + 1)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
const result: Record<string, any> = {}
|
|
302
|
+
for (const key of keys) {
|
|
303
|
+
const statMap = statMaps.get(key)!
|
|
304
|
+
let mostVal: statItems[keyof statItems] | undefined
|
|
305
|
+
let maxCount = 0
|
|
306
|
+
for (const [val, count] of statMap.entries()) {
|
|
307
|
+
if (count > maxCount) {
|
|
308
|
+
maxCount = count
|
|
309
|
+
mostVal = val
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
result[key] = mostVal
|
|
313
|
+
}
|
|
254
314
|
return {
|
|
255
|
-
mode:
|
|
256
|
-
fontsize:
|
|
257
|
-
color:
|
|
258
|
-
senderID:
|
|
259
|
-
content:
|
|
260
|
-
weight:
|
|
261
|
-
pool:
|
|
262
|
-
platform:
|
|
315
|
+
mode: result.mode as UniDMTools.Modes,
|
|
316
|
+
fontsize: result.fontsize as number,
|
|
317
|
+
color: result.color as number,
|
|
318
|
+
senderID: result.senderID as string,
|
|
319
|
+
content: result.content as string,
|
|
320
|
+
weight: result.weight as number,
|
|
321
|
+
pool: result.pool as UniDMTools.Pools,
|
|
322
|
+
platform: result.platform as string | undefined,
|
|
263
323
|
}
|
|
264
324
|
}
|
|
265
325
|
static create(options?: Options) {
|
|
@@ -285,7 +345,7 @@ export class UniPool {
|
|
|
285
345
|
* 按共通属性拆分弹幕库
|
|
286
346
|
*/
|
|
287
347
|
split(key: keyof shareItems) {
|
|
288
|
-
if (this.
|
|
348
|
+
if (this.getShared(key)) return [this]
|
|
289
349
|
const set = new Set(this.dans.map((d) => d[key]))
|
|
290
350
|
return [...set].map((v) => {
|
|
291
351
|
return new UniPool(
|
|
@@ -299,6 +359,7 @@ export class UniPool {
|
|
|
299
359
|
* 基于DMID的基本去重功能,用于解决该class下dans为array而非Set的问题
|
|
300
360
|
*/
|
|
301
361
|
private dedupe() {
|
|
362
|
+
// 这里基本上没有性能瓶颈(大文件测试与AI优化下无明显区别)
|
|
302
363
|
if (this.options.dmid !== false) {
|
|
303
364
|
const map = new Map()
|
|
304
365
|
this.dans.forEach((d) => map.set(d.DMID || d.toDMID(), d))
|
|
@@ -311,104 +372,77 @@ export class UniPool {
|
|
|
311
372
|
* @param lifetime 查重时间区段,单位秒 (默认为 0,表示不查重)
|
|
312
373
|
*/
|
|
313
374
|
merge(lifetime = 0) {
|
|
314
|
-
if (!this.
|
|
375
|
+
if (!this.getShared('SOID')) {
|
|
315
376
|
console.error(
|
|
316
377
|
"本功能仅支持同弹幕库内使用,可先 .split('SOID') 在分别使用",
|
|
317
378
|
)
|
|
318
379
|
return this
|
|
319
380
|
}
|
|
320
381
|
if (lifetime <= 0) return this
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
352
|
-
danmaku.extraStr = JSON.stringify(extra)
|
|
353
|
-
cache[key] = danmaku
|
|
354
|
-
mergeObj[key] = extra.danuni.merge
|
|
355
|
-
return [result, cache, mergeObj]
|
|
356
|
-
} else {
|
|
357
|
-
mergeObj[key] = {
|
|
358
|
-
count: 1,
|
|
359
|
-
duration: 0,
|
|
360
|
-
senders: [danmaku.senderID],
|
|
361
|
-
taolu_count: 1,
|
|
362
|
-
taolu_senders: [danmaku.senderID],
|
|
363
|
-
}
|
|
364
|
-
cache[key] = danmaku
|
|
365
|
-
// 初始化merge信息,包含第一个sender
|
|
366
|
-
const extra = danmaku.extra
|
|
367
|
-
extra.danuni = extra.danuni || {}
|
|
368
|
-
extra.danuni.merge = mergeObj[key]
|
|
369
|
-
danmaku.extraStr = JSON.stringify(extra)
|
|
370
|
-
result.push(danmaku)
|
|
371
|
-
return [result, cache, mergeObj]
|
|
382
|
+
const result: UniDM[] = []
|
|
383
|
+
const cache: Record<string, UniDM> = {}
|
|
384
|
+
const mergeObj: Record<string, UniDMTools.ExtraDanUniMerge> = {}
|
|
385
|
+
// 第一遍:合并弹幕
|
|
386
|
+
for (const danmaku of this.dans) {
|
|
387
|
+
const key = `${danmaku.content}|${danmaku.mode}|${danmaku.pool}|${danmaku.platform}`
|
|
388
|
+
const cached = cache[key]
|
|
389
|
+
|
|
390
|
+
if (
|
|
391
|
+
cached &&
|
|
392
|
+
danmaku.progress - cached.progress <= lifetime &&
|
|
393
|
+
danmaku.isSameAs(cached, { skipDanuniMerge: true })
|
|
394
|
+
) {
|
|
395
|
+
// 更新已存在的弹幕
|
|
396
|
+
mergeObj[key].senders.push(danmaku.senderID)
|
|
397
|
+
mergeObj[key].count = mergeObj[key].senders.length
|
|
398
|
+
mergeObj[key].taolu_count = mergeObj[key].count
|
|
399
|
+
mergeObj[key].taolu_senders = mergeObj[key].senders
|
|
400
|
+
mergeObj[key].duration = Number.parseFloat(
|
|
401
|
+
(danmaku.progress - cached.progress).toFixed(3),
|
|
402
|
+
)
|
|
403
|
+
cache[key] = danmaku
|
|
404
|
+
} else {
|
|
405
|
+
// 新弹幕
|
|
406
|
+
mergeObj[key] = {
|
|
407
|
+
count: 1,
|
|
408
|
+
duration: 0,
|
|
409
|
+
senders: [danmaku.senderID],
|
|
410
|
+
taolu_count: 1,
|
|
411
|
+
taolu_senders: [danmaku.senderID],
|
|
372
412
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
const key =
|
|
380
|
-
.map((k) => danmaku[k as keyof UniDM])
|
|
381
|
-
.join('|')
|
|
382
|
-
const extra = result[i].extra
|
|
413
|
+
cache[key] = danmaku
|
|
414
|
+
result.push(danmaku)
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// 第二遍:更新 extraStr
|
|
418
|
+
for (const danmaku of result) {
|
|
419
|
+
const key = `${danmaku.content}|${danmaku.mode}|${danmaku.pool}|${danmaku.platform}`
|
|
383
420
|
const mergeData = mergeObj[key]
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
421
|
+
const extra = danmaku.extra
|
|
422
|
+
if (mergeData.count > 1) {
|
|
423
|
+
// 多个发送者:设置为机器人并添加保护标记
|
|
424
|
+
danmaku.senderID = 'merge[bot]@dan-any'
|
|
425
|
+
if (!danmaku.attr) {
|
|
426
|
+
danmaku.attr = [UniDMTools.DMAttr.Protect]
|
|
427
|
+
} else if (!danmaku.attr.includes(UniDMTools.DMAttr.Protect)) {
|
|
428
|
+
danmaku.attr.push(UniDMTools.DMAttr.Protect)
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
extra.danuni = extra.danuni || {}
|
|
432
|
+
extra.danuni.merge = mergeData
|
|
433
|
+
danmaku.extraStr = JSON.stringify(extra)
|
|
434
|
+
} else {
|
|
435
|
+
// 单个发送者:清理 merge 字段
|
|
436
|
+
if (extra.danuni?.merge) {
|
|
437
|
+
delete extra.danuni.merge
|
|
438
|
+
if (Object.keys(extra.danuni).length === 0) {
|
|
439
|
+
delete extra.danuni
|
|
399
440
|
}
|
|
400
|
-
result[i].extraStr =
|
|
401
|
-
Object.keys(updatedExtra).length > 0
|
|
402
|
-
? JSON.stringify(updatedExtra)
|
|
403
|
-
: undefined
|
|
404
|
-
} else {
|
|
405
|
-
result[i].senderID = 'merge[bot]@dan-any'
|
|
406
|
-
result[i].attr
|
|
407
|
-
? result[i].attr.push(UniDMTools.DMAttr.Protect)
|
|
408
|
-
: (result[i].attr = [UniDMTools.DMAttr.Protect])
|
|
409
441
|
}
|
|
442
|
+
danmaku.extraStr =
|
|
443
|
+
Object.keys(extra).length > 0 ? JSON.stringify(extra) : undefined
|
|
410
444
|
}
|
|
411
|
-
}
|
|
445
|
+
}
|
|
412
446
|
return new UniPool(result, this.options, this.info)
|
|
413
447
|
}
|
|
414
448
|
minify() {
|
|
@@ -427,7 +461,8 @@ export class UniPool {
|
|
|
427
461
|
const parseJSON = (
|
|
428
462
|
json: DM_JSON_Artplayer &
|
|
429
463
|
DM_JSON_DDPlay &
|
|
430
|
-
DM_JSON_Dplayer &
|
|
464
|
+
DM_JSON_Dplayer &
|
|
465
|
+
DM_JSON_BiliUp & { danuni?: DanUniConvertTip },
|
|
431
466
|
): { pool: UniPool; fmt: DM_format } | undefined => {
|
|
432
467
|
try {
|
|
433
468
|
if (Array.isArray(json) && json.every((d) => d.SOID)) {
|
|
@@ -445,6 +480,7 @@ export class UniPool {
|
|
|
445
480
|
} else if (
|
|
446
481
|
json.count &&
|
|
447
482
|
json.comments &&
|
|
483
|
+
Array.isArray(json.comments) &&
|
|
448
484
|
json.comments.every((d) => d.m)
|
|
449
485
|
) {
|
|
450
486
|
return {
|
|
@@ -452,8 +488,9 @@ export class UniPool {
|
|
|
452
488
|
fmt: 'ddplay.json',
|
|
453
489
|
}
|
|
454
490
|
} else if (
|
|
455
|
-
json
|
|
491
|
+
json.code == 0 &&
|
|
456
492
|
json.data &&
|
|
493
|
+
Array.isArray(json.data) &&
|
|
457
494
|
json.data.every((d) => Array.isArray(d))
|
|
458
495
|
) {
|
|
459
496
|
return {
|
|
@@ -465,6 +502,19 @@ export class UniPool {
|
|
|
465
502
|
),
|
|
466
503
|
fmt: 'dplayer.json',
|
|
467
504
|
}
|
|
505
|
+
} else if (
|
|
506
|
+
json.code == 0 &&
|
|
507
|
+
json.message == '0' &&
|
|
508
|
+
json.data &&
|
|
509
|
+
json.data.page &&
|
|
510
|
+
json.data.result &&
|
|
511
|
+
Array.isArray(json.data.result) &&
|
|
512
|
+
json.data.result.every((d) => d.id && d.oid)
|
|
513
|
+
) {
|
|
514
|
+
return {
|
|
515
|
+
pool: this.fromBiliUp(json, options),
|
|
516
|
+
fmt: 'bili.up.json',
|
|
517
|
+
}
|
|
468
518
|
}
|
|
469
519
|
} catch {}
|
|
470
520
|
}
|
|
@@ -678,7 +728,7 @@ export class UniPool {
|
|
|
678
728
|
state: 0,
|
|
679
729
|
real_name: 0,
|
|
680
730
|
source: 'k-v',
|
|
681
|
-
danuni: { ...DanUniConvertTipTemplate, data: this.
|
|
731
|
+
danuni: { ...DanUniConvertTipTemplate, data: this.getShared('SOID') },
|
|
682
732
|
d: this.dans.map((dan) => dan.toBiliXML(options)),
|
|
683
733
|
},
|
|
684
734
|
})
|
|
@@ -880,7 +930,7 @@ export class UniPool {
|
|
|
880
930
|
toASS(canvasCtx: CanvasCtx, options?: AssGenOptions): string {
|
|
881
931
|
const defaultOptions: AssGenOptions = { substyle: {} }
|
|
882
932
|
const finalOptions = options ?? defaultOptions
|
|
883
|
-
const fn = this.
|
|
933
|
+
const fn = this.getShared('SOID')
|
|
884
934
|
return generateASS(
|
|
885
935
|
this,
|
|
886
936
|
{ filename: fn, title: fn, ...finalOptions },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @generated by protoc-gen-es v2.
|
|
1
|
+
// @generated by protoc-gen-es v2.10.1 with parameter "target=ts"
|
|
2
2
|
// @generated from file danuni.proto (package danuni.danmaku.v1, syntax proto3)
|
|
3
3
|
/* eslint-disable */
|
|
4
4
|
|
|
@@ -12,7 +12,7 @@ import type { Message } from "@bufbuild/protobuf";
|
|
|
12
12
|
* Describes the file danuni.proto.
|
|
13
13
|
*/
|
|
14
14
|
export const file_danuni: GenFile = /*@__PURE__*/
|
|
15
|
-
fileDesc("
|
|
15
|
+
fileDesc("CgxkYW51bmkucHJvdG8SEWRhbnVuaS5kYW5tYWt1LnYxIjIKCmxpc3REYW5SZXESCgoCSUQYASABKAkSEAoDc2VnGAIgASgFSACIAQFCBgoEX3NlZyLUAgoHRGFubWFrdRIMCgRTT0lEGAEgASgJEgwKBERNSUQYAiABKAkSEAoIcHJvZ3Jlc3MYAyABKAUSJQoEbW9kZRgEIAEoDjIXLmRhbnVuaS5kYW5tYWt1LnYxLk1vZGUSEAoIZm9udHNpemUYBSABKAUSDQoFY29sb3IYBiABKAUSEAoIc2VuZGVySUQYByABKAkSDwoHY29udGVudBgIIAEoCRIpCgVjdGltZRgJIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGd2VpZ2h0GAogASgFEiUKBHBvb2wYCyABKA4yFy5kYW51bmkuZGFubWFrdS52MS5Qb29sEgwKBGF0dHIYDCADKAkSFQoIcGxhdGZvcm0YDSABKAlIAIgBARISCgVleHRyYRgOIAEoCUgBiAEBQgsKCV9wbGF0Zm9ybUIICgZfZXh0cmEiPAoMRGFubWFrdVJlcGx5EiwKCGRhbm1ha3VzGAEgAygLMhouZGFudW5pLmRhbm1ha3UudjEuRGFubWFrdSo9CgRNb2RlEgoKBk5vcm1hbBAAEgoKBkJvdHRvbRABEgcKA1RvcBACEgsKB1JldmVyc2UQAxIHCgNFeHQQBCopCgRQb29sEgcKA0RlZhAAEgcKA1N1YhABEgcKA0FkdhACEgYKAkl4EAMyXQoORGFubWFrdVNlcnZpY2USSwoHbGlzdERhbhIdLmRhbnVuaS5kYW5tYWt1LnYxLmxpc3REYW5SZXEaHy5kYW51bmkuZGFubWFrdS52MS5EYW5tYWt1UmVwbHkiAFAAYgZwcm90bzM", [file_google_protobuf_timestamp]);
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @generated from message danuni.danmaku.v1.listDanReq
|
|
@@ -101,9 +101,9 @@ export type Danmaku = Message<"danuni.danmaku.v1.Danmaku"> & {
|
|
|
101
101
|
attr: string[];
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
|
-
* @generated from field: string platform = 13;
|
|
104
|
+
* @generated from field: optional string platform = 13;
|
|
105
105
|
*/
|
|
106
|
-
platform
|
|
106
|
+
platform?: string;
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
109
|
* @generated from field: optional string extra = 14;
|
package/src/utils/dm-gen.ts
CHANGED
|
@@ -562,6 +562,8 @@ export class UniDM {
|
|
|
562
562
|
}
|
|
563
563
|
@Expose()
|
|
564
564
|
isSameAs(dan: UniDM, options?: { skipDanuniMerge?: boolean }): boolean {
|
|
565
|
+
// 引用相同直接返回
|
|
566
|
+
if (this === dan) return true
|
|
565
567
|
// 不支持比较高级弹幕
|
|
566
568
|
if (this.mode === Modes.Ext || dan.mode === Modes.Ext) return false
|
|
567
569
|
// 合并过视为不同,防止存在合并完成弹幕后再次合并造成计数错误
|
|
@@ -586,25 +588,20 @@ export class UniDM {
|
|
|
586
588
|
@Expose()
|
|
587
589
|
minify() {
|
|
588
590
|
type UObj = Partial<UniDMObj> & Pick<UniDMObj, 'SOID'>
|
|
589
|
-
const def
|
|
590
|
-
const
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
if (shouldKeep(key, value)) {
|
|
604
|
-
if (key === 'SOID') continue
|
|
605
|
-
Reflect.set(result, key, value)
|
|
606
|
-
}
|
|
607
|
-
}
|
|
591
|
+
const def = new UniDM()
|
|
592
|
+
const result: UObj = { SOID: this.SOID }
|
|
593
|
+
if (this.progress !== def.progress) result.progress = this.progress
|
|
594
|
+
if (this.mode !== def.mode) result.mode = this.mode
|
|
595
|
+
if (this.fontsize !== def.fontsize) result.fontsize = this.fontsize
|
|
596
|
+
if (this.color !== def.color) result.color = this.color
|
|
597
|
+
if (this.senderID !== def.senderID) result.senderID = this.senderID
|
|
598
|
+
if (this.content !== def.content) result.content = this.content
|
|
599
|
+
if (this.weight !== def.weight) result.weight = this.weight
|
|
600
|
+
if (this.pool !== def.pool) result.pool = this.pool
|
|
601
|
+
if (this.attr.length > 0) result.attr = this.attr
|
|
602
|
+
if (this.platform !== undefined) result.platform = this.platform
|
|
603
|
+
if (this.extraStr && this.extraStr !== '{}') result.extraStr = this.extraStr
|
|
604
|
+
if (this.DMID !== undefined) result.DMID = this.DMID
|
|
608
605
|
return result
|
|
609
606
|
}
|
|
610
607
|
@Expose()
|