@dan-uni/dan-any 0.2.4 → 0.4.7
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/README.md +9 -2
- package/dist/index.js +1158 -410
- package/dist/index.umd.min.js +4880 -4357
- package/dist/index.umd.min.js.LICENSE.txt +3 -1
- package/dist/src/ass-gen/ass/create.d.ts +2 -1
- package/dist/src/ass-gen/ass/raw.d.ts +6 -2
- package/dist/src/ass-gen/index.d.ts +2 -0
- package/dist/src/index.d.ts +72 -14
- package/dist/src/proto/gen/bili/dm_pb.d.ts +1 -1
- package/dist/src/proto/gen/danuni_pb.d.ts +35 -8
- package/dist/src/utils/dm-gen.d.ts +32 -46
- package/dist/src/utils/id-gen.d.ts +8 -32
- package/dist/src/utils/platform.d.ts +24 -0
- package/package.json +12 -9
- package/src/ass-gen/__tests__/898651903.xml.ass +1 -1
- package/src/ass-gen/ass/create.ts +12 -2
- package/src/ass-gen/ass/raw.ts +14 -5
- package/src/ass-gen/index.ts +12 -4
- package/src/ass-gen/util/danconvert.ts +2 -2
- package/src/index.ts +175 -42
- package/src/proto/gen/bili/dm_pb.ts +3 -3
- package/src/proto/gen/danuni_pb.ts +46 -14
- package/src/proto/src/danuni.proto +11 -3
- package/src/utils/dm-gen.test.ts +62 -2
- package/src/utils/dm-gen.ts +118 -62
- package/src/utils/id-gen.ts +15 -62
- package/src/utils/platform.ts +38 -0
- package/tsconfig.json +12 -16
package/src/utils/dm-gen.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import TimeFormat from 'hh-mm-ss'
|
|
1
2
|
import type { DM_JSON_BiliCommandGrpc } from '..'
|
|
2
|
-
import type {
|
|
3
|
+
import type { PlatformDanmakuSource } from './platform'
|
|
3
4
|
|
|
4
|
-
import { createDMID,
|
|
5
|
+
import { createDMID, UniID as ID } from './id-gen'
|
|
6
|
+
import {
|
|
7
|
+
PlatformDanmakuOnlySource,
|
|
8
|
+
PlatformDanmakuSources,
|
|
9
|
+
PlatformVideoSource,
|
|
10
|
+
} from './platform'
|
|
5
11
|
|
|
6
12
|
const BigIntSerializer = (k: string, v: any) =>
|
|
7
13
|
typeof v === 'bigint' ? v.toString() : v
|
|
@@ -18,10 +24,8 @@ function cleanEmptyObjects(obj: object): object {
|
|
|
18
24
|
const cleanedValue = cleanEmptyObjects(value)
|
|
19
25
|
if (
|
|
20
26
|
cleanedValue !== undefined &&
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Object.keys(cleanedValue).length === 0
|
|
24
|
-
)
|
|
27
|
+
(typeof cleanedValue !== 'object' ||
|
|
28
|
+
Object.keys(cleanedValue).length !== 0)
|
|
25
29
|
) {
|
|
26
30
|
cleaned[key] = cleanedValue
|
|
27
31
|
}
|
|
@@ -55,10 +59,13 @@ export type DMAttr =
|
|
|
55
59
|
| 'Protect'
|
|
56
60
|
| 'FromLive'
|
|
57
61
|
| 'HighLike'
|
|
58
|
-
| 'Compatible'
|
|
59
|
-
| 'Reported'
|
|
62
|
+
| 'Compatible' // 由dan-any进行过兼容处理的弹幕,可能丢失部分信息
|
|
63
|
+
| 'Reported' // 在DanUni上被多人举报过的弹幕
|
|
64
|
+
| 'Unchecked' // 在DanUni上未被审核过的弹幕
|
|
65
|
+
| 'HasEvent' // 该弹幕当前在DanUni上存在事件(如点赞/举报等)
|
|
66
|
+
| 'Hide' // 由于其它原因需要隐藏的弹幕(建议在server端不返回该类弹幕)
|
|
60
67
|
const DMAttrUtils = {
|
|
61
|
-
fromBin(bin: number = 0, format?:
|
|
68
|
+
fromBin(bin: number = 0, format?: PlatformDanmakuSource) {
|
|
62
69
|
const array = toBits(bin),
|
|
63
70
|
attr: DMAttr[] = []
|
|
64
71
|
if (format === 'bili') {
|
|
@@ -75,7 +82,7 @@ const DMAttrUtils = {
|
|
|
75
82
|
* 但由于不知道B站及其它使用该参数程序的读取逻辑,
|
|
76
83
|
* 所以单独提供 bili 格式
|
|
77
84
|
*/
|
|
78
|
-
format?:
|
|
85
|
+
format?: PlatformDanmakuSource,
|
|
79
86
|
) {
|
|
80
87
|
const bin = new SetBin(0)
|
|
81
88
|
if (format === 'bili') {
|
|
@@ -128,7 +135,7 @@ const DMAttrUtils = {
|
|
|
128
135
|
|
|
129
136
|
interface DMBili {
|
|
130
137
|
id: bigint // xml 7
|
|
131
|
-
progress: number // xml 0
|
|
138
|
+
progress: number // xml 0 ; xml s, protobuf ms
|
|
132
139
|
mode: number // xml 1
|
|
133
140
|
fontsize: number // xml 2
|
|
134
141
|
color: number // xml 3
|
|
@@ -208,8 +215,8 @@ interface ExtraArtplayer {
|
|
|
208
215
|
border?: boolean
|
|
209
216
|
}
|
|
210
217
|
interface ExtraBili {
|
|
211
|
-
mode
|
|
212
|
-
pool
|
|
218
|
+
mode?: number //原弹幕类型
|
|
219
|
+
pool?: number //原弹幕池
|
|
213
220
|
adv?: string
|
|
214
221
|
code?: string
|
|
215
222
|
bas?: string
|
|
@@ -231,6 +238,8 @@ export interface ExtraDanUniMerge {
|
|
|
231
238
|
duration: number //持续时间(重复内容第一次出现时间开始到合并了的弹幕中最后一次出现的时间)
|
|
232
239
|
count: number //重复次数
|
|
233
240
|
senders: string[] //发送者
|
|
241
|
+
taolu_count: number //类似弹幕数量
|
|
242
|
+
taolu_senders: string[] //类似弹幕发送者
|
|
234
243
|
}
|
|
235
244
|
export enum ExtraDanUniChapterType {
|
|
236
245
|
Chapter = 'ch', //其它片段(用于标记章节)
|
|
@@ -240,10 +249,24 @@ export enum ExtraDanUniChapterType {
|
|
|
240
249
|
ED = 'ed', //片尾
|
|
241
250
|
Preview = 'prvw', //预告
|
|
242
251
|
Cut = 'cut', //删减(删减版中提供删减说明,提供开始位置、长度)
|
|
243
|
-
|
|
252
|
+
Duplicate = 'dup', //补档(完整版中指明其它平台中删减位置)
|
|
244
253
|
AdBiz = 'biz', //商业广告
|
|
245
254
|
AdUnpaid = 'promo', //推广(无偿/公益)广告
|
|
246
255
|
}
|
|
256
|
+
const ExtraDanUniChapterTypeDict = {
|
|
257
|
+
chs: {
|
|
258
|
+
ch: '其它片段',
|
|
259
|
+
rev: '回顾',
|
|
260
|
+
op: '片头',
|
|
261
|
+
int: '中场',
|
|
262
|
+
ed: '片尾',
|
|
263
|
+
prvw: '预告',
|
|
264
|
+
cut: '删减',
|
|
265
|
+
dup: '补档',
|
|
266
|
+
biz: '商业广告',
|
|
267
|
+
promo: '推广',
|
|
268
|
+
},
|
|
269
|
+
}
|
|
247
270
|
export enum ExtraDanUniChapterAction {
|
|
248
271
|
Disabled = -1,
|
|
249
272
|
ShowOverlay,
|
|
@@ -273,7 +296,7 @@ export type ctime = string | number | bigint | Date
|
|
|
273
296
|
// }
|
|
274
297
|
|
|
275
298
|
export interface UniDMObj {
|
|
276
|
-
|
|
299
|
+
SOID: string
|
|
277
300
|
progress: number
|
|
278
301
|
mode: Modes
|
|
279
302
|
fontsize: number
|
|
@@ -284,8 +307,7 @@ export interface UniDMObj {
|
|
|
284
307
|
weight: number
|
|
285
308
|
pool: Pools
|
|
286
309
|
attr: DMAttr[]
|
|
287
|
-
platform:
|
|
288
|
-
SPMO: string
|
|
310
|
+
platform: PlatformDanmakuSource | string
|
|
289
311
|
extra: string | Extra
|
|
290
312
|
extraStr: string
|
|
291
313
|
DMID: string
|
|
@@ -301,15 +323,16 @@ export class UniDM {
|
|
|
301
323
|
// syncAnchor = BigInt(Date.now())
|
|
302
324
|
constructor(
|
|
303
325
|
/**
|
|
304
|
-
*
|
|
326
|
+
* 资源ID
|
|
327
|
+
* @description 由某一danuni服务确定的某一剧集下不同资源(不同视频站/字幕组具有细节差异)的ID
|
|
305
328
|
*/
|
|
306
|
-
public
|
|
329
|
+
public SOID: string,
|
|
307
330
|
/**
|
|
308
331
|
* 弹幕出现位置(单位s;精度为ms,即保留三位小数)
|
|
309
332
|
*/
|
|
310
333
|
public progress: number = 0,
|
|
311
334
|
/**
|
|
312
|
-
*
|
|
335
|
+
* 弹幕类型
|
|
313
336
|
*/
|
|
314
337
|
public mode: Modes = Modes.Normal,
|
|
315
338
|
/**
|
|
@@ -343,9 +366,9 @@ export class UniDM {
|
|
|
343
366
|
* 权重 用于屏蔽等级 区间:[1,10]
|
|
344
367
|
* @description 参考B站,源弹幕有该参数则直接利用,
|
|
345
368
|
* 本实现默认取5,再经过ruleset匹配加减分数
|
|
346
|
-
* @description
|
|
369
|
+
* @description 为0时表示暂时未计算权重
|
|
347
370
|
*/
|
|
348
|
-
public weight: number =
|
|
371
|
+
public weight: number = 0,
|
|
349
372
|
/**
|
|
350
373
|
* 弹幕池 0:普通池 1:字幕池 2:特殊池(代码/BAS弹幕) 3:互动池(互动弹幕中选择投票快速发送的弹幕)
|
|
351
374
|
*/
|
|
@@ -359,18 +382,7 @@ export class UniDM {
|
|
|
359
382
|
* 初始来源平台
|
|
360
383
|
* `danuni`与任意空值(可隐式转换为false的值)等价
|
|
361
384
|
*/
|
|
362
|
-
public platform?:
|
|
363
|
-
/**
|
|
364
|
-
* Same Platform Multiple Origin
|
|
365
|
-
* @description 解决B站等同一番剧存在港澳台站、多语言配音(不同一CID)的问题,同时方便过滤
|
|
366
|
-
* @description 示例:
|
|
367
|
-
* - main: 主站
|
|
368
|
-
* - hm: 仅港澳
|
|
369
|
-
* - t: 仅台
|
|
370
|
-
* - hmt: 仅港澳台
|
|
371
|
-
* - lang:{ISO语言代号}: 多语言
|
|
372
|
-
*/
|
|
373
|
-
public SPMO?: string,
|
|
385
|
+
public platform?: PlatformDanmakuSource | string,
|
|
374
386
|
/**
|
|
375
387
|
* 弹幕原始数据(不推荐使用)
|
|
376
388
|
* @description 适用于无法解析的B站代码弹幕、Artplayer弹幕样式等
|
|
@@ -386,7 +398,7 @@ export class UniDM {
|
|
|
386
398
|
if (fontsize <= 0) this.fontsize = 25
|
|
387
399
|
if (color <= 0) this.color = 16777215 //虽然不知道为0是否为可用值,但过为少见,利用其作为默认位
|
|
388
400
|
// if (ctime <= 0n) this.ctime = BigInt(Date.now())
|
|
389
|
-
if (weight
|
|
401
|
+
if (weight < 0 || weight > 10) this.weight = 5
|
|
390
402
|
if (pool < Pools.Def || pool > Pools.Ix) this.pool = Pools.Def
|
|
391
403
|
// if (attr < 0 || attr > 0b111) this.attr = 0
|
|
392
404
|
if (!DMID) DMID = this.toDMID()
|
|
@@ -399,7 +411,7 @@ export class UniDM {
|
|
|
399
411
|
static create(args?: Partial<UniDMObj>) {
|
|
400
412
|
return args
|
|
401
413
|
? new UniDM(
|
|
402
|
-
args.
|
|
414
|
+
args.SOID || ID.fromNull().toString(),
|
|
403
415
|
args.progress,
|
|
404
416
|
args.mode,
|
|
405
417
|
args.fontsize,
|
|
@@ -411,7 +423,6 @@ export class UniDM {
|
|
|
411
423
|
args.pool,
|
|
412
424
|
args.attr,
|
|
413
425
|
args.platform,
|
|
414
|
-
args.SPMO,
|
|
415
426
|
typeof args.extra === 'object'
|
|
416
427
|
? JSON.stringify(args.extra)
|
|
417
428
|
: args.extra || args.extraStr,
|
|
@@ -426,14 +437,17 @@ export class UniDM {
|
|
|
426
437
|
// return cleanEmptyObjects(extra) as Extra
|
|
427
438
|
}
|
|
428
439
|
get isFrom3rdPlatform() {
|
|
429
|
-
if (
|
|
440
|
+
if (
|
|
441
|
+
this.platform &&
|
|
442
|
+
PlatformDanmakuSources.includes(this.platform as PlatformDanmakuSource)
|
|
443
|
+
)
|
|
430
444
|
return true
|
|
431
445
|
else return false
|
|
432
446
|
}
|
|
433
447
|
/**
|
|
434
448
|
* 弹幕id
|
|
435
449
|
* @description sha3-256(content+senderID+ctime)截取前8位
|
|
436
|
-
* @description 同一
|
|
450
|
+
* @description 同一SOID下唯一
|
|
437
451
|
*/
|
|
438
452
|
toDMID() {
|
|
439
453
|
return createDMID(this.content, this.senderID, this.ctime)
|
|
@@ -442,12 +456,11 @@ export class UniDM {
|
|
|
442
456
|
const isSame = (k: keyof UniDMObj) => this[k] === dan[k],
|
|
443
457
|
checks = (
|
|
444
458
|
[
|
|
445
|
-
'
|
|
459
|
+
'SOID',
|
|
446
460
|
'content',
|
|
447
461
|
'mode',
|
|
448
462
|
'platform',
|
|
449
463
|
'pool',
|
|
450
|
-
'SPMO',
|
|
451
464
|
] satisfies (keyof UniDMObj)[]
|
|
452
465
|
).every((k) => isSame(k))
|
|
453
466
|
// 如果两个对象的extra都是空对象,只检查基本字段
|
|
@@ -484,7 +497,7 @@ export class UniDM {
|
|
|
484
497
|
)
|
|
485
498
|
}
|
|
486
499
|
minify() {
|
|
487
|
-
type UObj = Partial<UniDMObj> & Pick<UniDMObj, '
|
|
500
|
+
type UObj = Partial<UniDMObj> & Pick<UniDMObj, 'SOID'>
|
|
488
501
|
const def: UObj = UniDM.create(),
|
|
489
502
|
dan: UObj = UniDM.create(this)
|
|
490
503
|
// const prototypes = Object.getOwnPropertyNames(this)
|
|
@@ -492,7 +505,7 @@ export class UniDM {
|
|
|
492
505
|
const k = key as keyof UObj,
|
|
493
506
|
v = dan[k]
|
|
494
507
|
// if (key in prototypes) continue
|
|
495
|
-
if (key === '
|
|
508
|
+
if (key === 'SOID') continue
|
|
496
509
|
else if (!v) delete dan[k]
|
|
497
510
|
else if (v === def[k]) delete dan[k]
|
|
498
511
|
else {
|
|
@@ -502,10 +515,54 @@ export class UniDM {
|
|
|
502
515
|
}
|
|
503
516
|
return JSON.parse(JSON.stringify(dan)) as UObj
|
|
504
517
|
}
|
|
505
|
-
downgradeAdvcancedDan(
|
|
518
|
+
downgradeAdvcancedDan(
|
|
519
|
+
{
|
|
520
|
+
include,
|
|
521
|
+
exclude,
|
|
522
|
+
cleanExtra = false,
|
|
523
|
+
}: {
|
|
524
|
+
include?: (keyof Extra)[]
|
|
525
|
+
exclude?: (keyof Extra)[]
|
|
526
|
+
cleanExtra?: boolean
|
|
527
|
+
} = { include: [], exclude: [] },
|
|
528
|
+
) {
|
|
506
529
|
if (!this.extra) return this
|
|
507
530
|
else {
|
|
531
|
+
if (!include) include = []
|
|
532
|
+
if (!exclude) exclude = []
|
|
533
|
+
const check = (k: keyof Extra) =>
|
|
534
|
+
include?.includes(k) || !exclude?.includes(k)
|
|
508
535
|
// TODO 分别对 mode7/8/9 command artplayer等正常播放器无法绘制的弹幕做降级处理
|
|
536
|
+
const clone = UniDM.create(this)
|
|
537
|
+
clone.mode = Modes.Top
|
|
538
|
+
if (check('danuni') && clone.extra.danuni) {
|
|
539
|
+
const danuni = clone.extra.danuni
|
|
540
|
+
if (danuni.merge) {
|
|
541
|
+
const merge = danuni.merge
|
|
542
|
+
clone.content = `${this.content} x${merge.count}`
|
|
543
|
+
} else if (danuni.chapter) {
|
|
544
|
+
const chapter = danuni.chapter
|
|
545
|
+
if (chapter.type === ExtraDanUniChapterType.Cut)
|
|
546
|
+
clone.content = `[提示]${clone.platform}源${ExtraDanUniChapterTypeDict.chs[chapter.type]}了${chapter.duration}秒`
|
|
547
|
+
else if (chapter.type === ExtraDanUniChapterType.Duplicate)
|
|
548
|
+
clone.content = `[提示(${ExtraDanUniChapterTypeDict.chs[chapter.type]})]${clone.platform}源-${chapter.duration}秒`
|
|
549
|
+
else
|
|
550
|
+
clone.content = `[空降(${ExtraDanUniChapterTypeDict.chs[chapter.type]})]${TimeFormat.fromS(clone.progress + chapter.duration)}`
|
|
551
|
+
}
|
|
552
|
+
} else if (check('bili') && clone.extra.bili) {
|
|
553
|
+
const bili = clone.extra.bili
|
|
554
|
+
if (bili.mode === 7 && bili.adv) {
|
|
555
|
+
clone.content = `[B站高级弹幕]${JSON.parse(bili.adv)[4] || ''}`
|
|
556
|
+
} else if (bili.command) {
|
|
557
|
+
const command = bili.command
|
|
558
|
+
clone.content = `[B站指令弹幕]${command.content}`
|
|
559
|
+
clone.fontsize = 36
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
clone.senderID = 'compat[bot]@dan-any'
|
|
563
|
+
clone.attr.push('Compatible')
|
|
564
|
+
if (cleanExtra) clone.extraStr = undefined
|
|
565
|
+
return clone
|
|
509
566
|
}
|
|
510
567
|
}
|
|
511
568
|
/**
|
|
@@ -547,6 +604,7 @@ export class UniDM {
|
|
|
547
604
|
let mode = Modes.Normal
|
|
548
605
|
switch (fmt) {
|
|
549
606
|
case 'bili':
|
|
607
|
+
// 类型 1 2 3:普通弹幕 4:底部弹幕 5:顶部弹幕 6:逆向弹幕 7:高级弹幕 8:代码弹幕 9:BAS弹幕(pool必须为2)
|
|
550
608
|
switch (oriMode) {
|
|
551
609
|
case 4:
|
|
552
610
|
mode = Modes.Bottom
|
|
@@ -591,12 +649,12 @@ export class UniDM {
|
|
|
591
649
|
}
|
|
592
650
|
return mode
|
|
593
651
|
}
|
|
594
|
-
static fromBili(args: DMBili,
|
|
652
|
+
static fromBili(args: DMBili, cid?: bigint) {
|
|
595
653
|
interface TExtra extends Extra {
|
|
596
654
|
bili: ExtraBili
|
|
597
655
|
}
|
|
598
656
|
if (args.oid && !cid) cid = args.oid
|
|
599
|
-
const
|
|
657
|
+
const SOID = `def::${ID.fromBili({ cid })}`,
|
|
600
658
|
senderID = ID.fromBili({ midHash: args.midHash })
|
|
601
659
|
let mode = Modes.Normal
|
|
602
660
|
const pool = args.pool, //暂时不做处理,兼容bili的pool格式
|
|
@@ -634,7 +692,7 @@ export class UniDM {
|
|
|
634
692
|
// else if (args.mode === 9) extra.bili.bas = args.content
|
|
635
693
|
return this.create({
|
|
636
694
|
...args,
|
|
637
|
-
|
|
695
|
+
SOID: SOID.toString(),
|
|
638
696
|
// progress: args.progress,
|
|
639
697
|
mode,
|
|
640
698
|
// fontsize: args.fontsize,
|
|
@@ -644,9 +702,8 @@ export class UniDM {
|
|
|
644
702
|
ctime: this.transCtime(args.ctime, 's'),
|
|
645
703
|
weight: args.weight ? args.weight : pool === Pools.Ix ? 1 : 0,
|
|
646
704
|
pool,
|
|
647
|
-
attr: DMAttrUtils.fromBin(args.attr,
|
|
648
|
-
platform:
|
|
649
|
-
SPMO,
|
|
705
|
+
attr: DMAttrUtils.fromBin(args.attr, PlatformVideoSource.Bilibili),
|
|
706
|
+
platform: PlatformVideoSource.Bilibili,
|
|
650
707
|
// 需改进,7=>advanced 8=>code 9=>bas 互动=>command
|
|
651
708
|
// 同时塞进无法/无需直接解析的数据
|
|
652
709
|
// 另开一个解析器,为大部分播放器(无法解析该类dm)做文本类型降级处理
|
|
@@ -654,13 +711,13 @@ export class UniDM {
|
|
|
654
711
|
args.mode >= 7 ? JSON.stringify(extra, BigIntSerializer) : undefined,
|
|
655
712
|
})
|
|
656
713
|
}
|
|
657
|
-
static fromBiliCommand(args: DMBiliCommand,
|
|
714
|
+
static fromBiliCommand(args: DMBiliCommand, cid?: bigint) {
|
|
658
715
|
if (args.oid && !cid) cid = args.oid
|
|
659
|
-
const
|
|
716
|
+
const SOID = ID.fromBili({ cid }),
|
|
660
717
|
senderID = ID.fromBili({ mid: args.mid })
|
|
661
718
|
return this.create({
|
|
662
719
|
...args,
|
|
663
|
-
|
|
720
|
+
SOID: SOID.toString(),
|
|
664
721
|
// progress: args.progress,
|
|
665
722
|
mode: Modes.Ext,
|
|
666
723
|
// fontsize: args.fontsize,
|
|
@@ -671,8 +728,7 @@ export class UniDM {
|
|
|
671
728
|
weight: 10,
|
|
672
729
|
pool: Pools.Adv,
|
|
673
730
|
attr: ['Protect'],
|
|
674
|
-
platform:
|
|
675
|
-
SPMO,
|
|
731
|
+
platform: PlatformVideoSource.Bilibili,
|
|
676
732
|
extra: JSON.stringify(
|
|
677
733
|
{
|
|
678
734
|
bili: {
|
|
@@ -684,11 +740,11 @@ export class UniDM {
|
|
|
684
740
|
})
|
|
685
741
|
}
|
|
686
742
|
static fromDplayer(args: DMDplayer, playerID: string, domain: string) {
|
|
687
|
-
const
|
|
743
|
+
const SOID = ID.fromUnknown(playerID, domain),
|
|
688
744
|
senderID = ID.fromUnknown(args.midHash, domain)
|
|
689
745
|
return this.create({
|
|
690
746
|
...args,
|
|
691
|
-
|
|
747
|
+
SOID: SOID.toString(),
|
|
692
748
|
// progress: args.progress,
|
|
693
749
|
mode: this.transMode(args.mode, 'dplayer'),
|
|
694
750
|
// fontsize: 25,
|
|
@@ -711,7 +767,7 @@ export class UniDM {
|
|
|
711
767
|
}
|
|
712
768
|
}
|
|
713
769
|
static fromArtplayer(args: DMArtplayer, playerID: string, domain: string) {
|
|
714
|
-
const
|
|
770
|
+
const SOID = ID.fromUnknown(playerID, domain),
|
|
715
771
|
senderID = ID.fromUnknown('', domain)
|
|
716
772
|
let extra = args.border
|
|
717
773
|
? ({ artplayer: { border: args.border, style: {} } } as Extra)
|
|
@@ -726,7 +782,7 @@ export class UniDM {
|
|
|
726
782
|
}
|
|
727
783
|
return this.create({
|
|
728
784
|
...args,
|
|
729
|
-
|
|
785
|
+
SOID: SOID.toString(),
|
|
730
786
|
// progress: args.progress,
|
|
731
787
|
mode: this.transMode(args.mode, 'artplayer'),
|
|
732
788
|
// fontsize: 25,
|
|
@@ -752,12 +808,12 @@ export class UniDM {
|
|
|
752
808
|
static fromDDplay(
|
|
753
809
|
args: DMDDplay,
|
|
754
810
|
episodeId: string,
|
|
755
|
-
domain =
|
|
811
|
+
domain = PlatformDanmakuOnlySource.DanDanPlay,
|
|
756
812
|
) {
|
|
757
|
-
const
|
|
813
|
+
const SOID = ID.fromUnknown(`def::${episodeId}`, domain)
|
|
758
814
|
return this.create({
|
|
759
815
|
...args,
|
|
760
|
-
|
|
816
|
+
SOID: SOID.toString(),
|
|
761
817
|
// progress: args.progress,
|
|
762
818
|
mode: this.transMode(args.mode, 'ddplay'),
|
|
763
819
|
// fontsize: 25,
|
package/src/utils/id-gen.ts
CHANGED
|
@@ -1,44 +1,9 @@
|
|
|
1
1
|
import jsSHA from 'jssha'
|
|
2
2
|
import type { ctime } from './dm-gen'
|
|
3
|
+
import type { PlatformSource } from './platform'
|
|
3
4
|
|
|
4
5
|
import { UniDM } from './dm-gen'
|
|
5
|
-
|
|
6
|
-
export const domainPreset = {
|
|
7
|
-
// acfun: 'acfun.cn',
|
|
8
|
-
// baha: 'ani.gamer.com.tw',
|
|
9
|
-
// bgm: 'bgm.tv',
|
|
10
|
-
// bili: 'b23.tv',
|
|
11
|
-
// bglobal: 'biliintl.com',
|
|
12
|
-
// ddplay: 'dandanplay.com',
|
|
13
|
-
acfun: 'acfun',
|
|
14
|
-
baha: 'baha',
|
|
15
|
-
bgm: 'bgm',
|
|
16
|
-
bili: 'bili', //b23
|
|
17
|
-
bglobal: 'bglobal', //bintl
|
|
18
|
-
ddplay: 'ddplay',
|
|
19
|
-
tucao: 'tucao',
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type platfrom =
|
|
23
|
-
| 'acfun'
|
|
24
|
-
| 'baha'
|
|
25
|
-
| 'bili'
|
|
26
|
-
| 'bglobal'
|
|
27
|
-
| 'ddplay'
|
|
28
|
-
| 'danuni'
|
|
29
|
-
| 'tucao'
|
|
30
|
-
| 'other'
|
|
31
|
-
export const platforms = Object.keys(domainPreset) as platfrom[]
|
|
32
|
-
// export const platforms = [
|
|
33
|
-
// 'acfun',
|
|
34
|
-
// 'baha',
|
|
35
|
-
// 'bili',
|
|
36
|
-
// 'bglobal',
|
|
37
|
-
// 'ddplay',
|
|
38
|
-
// 'danuni',
|
|
39
|
-
// 'tucao',
|
|
40
|
-
// // 'other',
|
|
41
|
-
// ]
|
|
6
|
+
import { PlatformVideoSource } from './platform'
|
|
42
7
|
|
|
43
8
|
export class UniID {
|
|
44
9
|
constructor(
|
|
@@ -54,22 +19,18 @@ export class UniID {
|
|
|
54
19
|
* - `{any}.danuni` (若使用IP或无域名,请使用该domain,防止隐私泄露/无法解析)
|
|
55
20
|
* #### 注意
|
|
56
21
|
* - `any`值建议为UUID/ULID/NanoID以防同步错误
|
|
57
|
-
* ### 非DanUni
|
|
58
|
-
* - `acfun.cn`
|
|
59
|
-
* - `ani.gamer.com.tw` (Baha)
|
|
60
|
-
* - `bgm.tv` (bangumi)
|
|
61
|
-
* - `b23.tv` (比bilibili.com短,省空间)
|
|
62
|
-
* - `biliintl.com` (即bilibili.tv)
|
|
63
|
-
* - `dandanplay.com`
|
|
64
|
-
* - `tucao` (由于其域名常变,故分配固定解析,运行时解析)
|
|
22
|
+
* ### 非DanUni弹幕服务建议使用预设,或自行填写域名
|
|
65
23
|
*/
|
|
66
|
-
public domain: string,
|
|
24
|
+
public domain: PlatformSource | string,
|
|
67
25
|
) {}
|
|
68
26
|
toString() {
|
|
69
27
|
return `${this.id}@${this.domain}`
|
|
70
28
|
}
|
|
71
|
-
static fromNull(domain?: string) {
|
|
72
|
-
return new UniID(
|
|
29
|
+
static fromNull(domain?: PlatformSource | 'runtime' | string) {
|
|
30
|
+
return new UniID(
|
|
31
|
+
domain === 'runtime' ? 'runtime' : 'anonymous',
|
|
32
|
+
domain || 'danuni',
|
|
33
|
+
)
|
|
73
34
|
}
|
|
74
35
|
static fromBili({
|
|
75
36
|
cid,
|
|
@@ -80,31 +41,23 @@ export class UniID {
|
|
|
80
41
|
mid?: number | bigint
|
|
81
42
|
midHash?: string
|
|
82
43
|
}) {
|
|
83
|
-
if (cid) return new UniID(cid.toString(),
|
|
84
|
-
else if (mid) return new UniID(mid.toString(),
|
|
85
|
-
else if (midHash) return new UniID(midHash,
|
|
86
|
-
else return this.fromNull(
|
|
44
|
+
if (cid) return new UniID(cid.toString(), PlatformVideoSource.Bilibili)
|
|
45
|
+
else if (mid) return new UniID(mid.toString(), PlatformVideoSource.Bilibili)
|
|
46
|
+
else if (midHash) return new UniID(midHash, PlatformVideoSource.Bilibili)
|
|
47
|
+
else return this.fromNull(PlatformVideoSource.Bilibili)
|
|
87
48
|
}
|
|
88
49
|
static fromUnknown(
|
|
89
50
|
id: string,
|
|
90
51
|
/**
|
|
91
|
-
*
|
|
52
|
+
* 可使用预设
|
|
92
53
|
*/
|
|
93
|
-
domain:
|
|
54
|
+
domain: PlatformSource | string,
|
|
94
55
|
) {
|
|
95
|
-
// domain = preset2domain(domain).domain
|
|
96
56
|
if (id) return new UniID(id, domain)
|
|
97
57
|
else return this.fromNull(domain)
|
|
98
58
|
}
|
|
99
59
|
}
|
|
100
60
|
|
|
101
|
-
// export function preset2domain(domain: platfrom | string) {
|
|
102
|
-
// for (const [k, v] of Object.entries(domainPreset)) {
|
|
103
|
-
// if (domain === k) return { platform: k, domain: v }
|
|
104
|
-
// }
|
|
105
|
-
// return { platform: 'other', domain: domain }
|
|
106
|
-
// }
|
|
107
|
-
|
|
108
61
|
export function createDMID(
|
|
109
62
|
content: string = '',
|
|
110
63
|
senderID: string,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export enum PlatformInfoSource {
|
|
2
|
+
Bangumi = 'bgm',
|
|
3
|
+
TMDB = 'tmdb',
|
|
4
|
+
}
|
|
5
|
+
export const PlatformInfoSources = Object.values(PlatformInfoSource)
|
|
6
|
+
|
|
7
|
+
export enum PlatformVideoSource {
|
|
8
|
+
Acfun = 'acfun',
|
|
9
|
+
Baha = 'baha',
|
|
10
|
+
Bilibili = 'bili',
|
|
11
|
+
BilibiliGlobal = 'bglobal',
|
|
12
|
+
Iqiyi = 'iqiyi',
|
|
13
|
+
Tencent = 'tencent',
|
|
14
|
+
Youku = 'youku',
|
|
15
|
+
}
|
|
16
|
+
export const PlatformVideoSources = Object.values(PlatformVideoSource)
|
|
17
|
+
|
|
18
|
+
export enum PlatformDanmakuOnlySource {
|
|
19
|
+
DanDanPlay = 'ddplay',
|
|
20
|
+
TuCao = 'tucao',
|
|
21
|
+
}
|
|
22
|
+
export const PlatformDanmakuOnlySources = Object.values(
|
|
23
|
+
PlatformDanmakuOnlySource,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
export type PlatformDanmakuSource =
|
|
27
|
+
| PlatformVideoSource
|
|
28
|
+
| PlatformDanmakuOnlySource
|
|
29
|
+
export const PlatformDanmakuSources = [
|
|
30
|
+
...PlatformVideoSources,
|
|
31
|
+
...PlatformDanmakuOnlySources,
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
export type PlatformSource = PlatformInfoSource | PlatformDanmakuSource
|
|
35
|
+
export const PlatformSources = [
|
|
36
|
+
...PlatformInfoSources,
|
|
37
|
+
...PlatformDanmakuSources,
|
|
38
|
+
]
|
package/tsconfig.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
|
10
10
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
|
11
11
|
/* Language and Environment */
|
|
12
|
-
"target": "ES2021"
|
|
12
|
+
"target": "ES2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
|
13
13
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
|
14
14
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
|
15
15
|
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
|
23
23
|
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
|
24
24
|
/* Modules */
|
|
25
|
-
"module": "ESNext"
|
|
25
|
+
"module": "ESNext" /* Skip type checking all .d.ts files. */,
|
|
26
26
|
"moduleResolution": "Node",
|
|
27
27
|
// "rootDir": "./", /* Specify the root folder within your source files. */
|
|
28
28
|
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
|
38
38
|
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
|
39
39
|
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
|
40
|
-
"resolveJsonModule": true
|
|
41
|
-
"allowImportingTsExtensions": true
|
|
40
|
+
"resolveJsonModule": true /* Enable importing .json files. */,
|
|
41
|
+
"allowImportingTsExtensions": true /* Ensure that casing is correct in imports. */,
|
|
42
42
|
/* Type Checking */
|
|
43
|
-
"strict": true
|
|
43
|
+
"strict": true /* Enable all strict type-checking options. */,
|
|
44
44
|
"noImplicitAny": true,
|
|
45
45
|
"declaration": true,
|
|
46
|
-
"emitDeclarationOnly": true
|
|
46
|
+
"emitDeclarationOnly": true /* Specify what module code is generated. */,
|
|
47
47
|
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
|
48
48
|
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
|
49
49
|
/* JavaScript Support */
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
|
58
58
|
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
|
59
59
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
|
60
|
-
"outDir": "./types"
|
|
60
|
+
"outDir": "./types" /* Specify an output folder for all emitted files. */,
|
|
61
61
|
// "removeComments": true, /* Disable emitting comments. */
|
|
62
62
|
// "noEmit": true, /* Disable emitting files from a compilation. */
|
|
63
63
|
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
|
@@ -77,9 +77,9 @@
|
|
|
77
77
|
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
|
|
78
78
|
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
|
|
79
79
|
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
|
80
|
-
"esModuleInterop": true
|
|
80
|
+
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
|
81
81
|
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
|
82
|
-
"forceConsistentCasingInFileNames": true
|
|
82
|
+
"forceConsistentCasingInFileNames": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */,
|
|
83
83
|
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
|
84
84
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
|
85
85
|
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
|
@@ -101,10 +101,6 @@
|
|
|
101
101
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
|
102
102
|
"skipLibCheck": true
|
|
103
103
|
},
|
|
104
|
-
"include": [
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"exclude": [
|
|
108
|
-
"**/node_modules"
|
|
109
|
-
]
|
|
110
|
-
}
|
|
104
|
+
"include": ["**/src"],
|
|
105
|
+
"exclude": ["**/node_modules"]
|
|
106
|
+
}
|