@dan-uni/dan-any 0.2.6 → 0.4.8
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 +10 -3
- package/dist/index.js +1233 -420
- package/dist/index.umd.min.js +4367 -3619
- 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 -13
- 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 +26 -40
- package/dist/src/utils/id-gen.d.ts +9 -32
- package/dist/src/utils/platform.d.ts +24 -0
- package/package.json +10 -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.test.ts +4 -3
- package/src/index.ts +202 -41
- 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 +12 -3
- package/src/utils/dm-gen.ts +106 -59
- package/src/utils/id-gen.ts +19 -62
- package/src/utils/platform.ts +38 -0
- package/tsconfig.json +12 -16
package/src/utils/dm-gen.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import TimeFormat from 'hh-mm-ss'
|
|
2
2
|
import type { DM_JSON_BiliCommandGrpc } from '..'
|
|
3
|
-
import type {
|
|
3
|
+
import type { PlatformDanmakuSource } from './platform'
|
|
4
4
|
|
|
5
|
-
import { createDMID,
|
|
5
|
+
import { createDMID, UniID as ID } from './id-gen'
|
|
6
|
+
import {
|
|
7
|
+
PlatformDanmakuOnlySource,
|
|
8
|
+
PlatformDanmakuSources,
|
|
9
|
+
PlatformVideoSource,
|
|
10
|
+
} from './platform'
|
|
6
11
|
|
|
7
12
|
const BigIntSerializer = (k: string, v: any) =>
|
|
8
13
|
typeof v === 'bigint' ? v.toString() : v
|
|
@@ -19,10 +24,8 @@ function cleanEmptyObjects(obj: object): object {
|
|
|
19
24
|
const cleanedValue = cleanEmptyObjects(value)
|
|
20
25
|
if (
|
|
21
26
|
cleanedValue !== undefined &&
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Object.keys(cleanedValue).length === 0
|
|
25
|
-
)
|
|
27
|
+
(typeof cleanedValue !== 'object' ||
|
|
28
|
+
Object.keys(cleanedValue).length !== 0)
|
|
26
29
|
) {
|
|
27
30
|
cleaned[key] = cleanedValue
|
|
28
31
|
}
|
|
@@ -56,11 +59,13 @@ export type DMAttr =
|
|
|
56
59
|
| 'Protect'
|
|
57
60
|
| 'FromLive'
|
|
58
61
|
| 'HighLike'
|
|
59
|
-
| 'Compatible'
|
|
60
|
-
| 'Reported'
|
|
61
|
-
| '
|
|
62
|
+
| 'Compatible' // 由dan-any进行过兼容处理的弹幕,可能丢失部分信息
|
|
63
|
+
| 'Reported' // 在DanUni上被多人举报过的弹幕
|
|
64
|
+
| 'Unchecked' // 在DanUni上未被审核过的弹幕
|
|
65
|
+
| 'HasEvent' // 该弹幕当前在DanUni上存在事件(如点赞/举报等)
|
|
66
|
+
| 'Hide' // 由于其它原因需要隐藏的弹幕(建议在server端不返回该类弹幕)
|
|
62
67
|
const DMAttrUtils = {
|
|
63
|
-
fromBin(bin: number = 0, format?:
|
|
68
|
+
fromBin(bin: number = 0, format?: PlatformDanmakuSource) {
|
|
64
69
|
const array = toBits(bin),
|
|
65
70
|
attr: DMAttr[] = []
|
|
66
71
|
if (format === 'bili') {
|
|
@@ -77,7 +82,7 @@ const DMAttrUtils = {
|
|
|
77
82
|
* 但由于不知道B站及其它使用该参数程序的读取逻辑,
|
|
78
83
|
* 所以单独提供 bili 格式
|
|
79
84
|
*/
|
|
80
|
-
format?:
|
|
85
|
+
format?: PlatformDanmakuSource,
|
|
81
86
|
) {
|
|
82
87
|
const bin = new SetBin(0)
|
|
83
88
|
if (format === 'bili') {
|
|
@@ -130,7 +135,7 @@ const DMAttrUtils = {
|
|
|
130
135
|
|
|
131
136
|
interface DMBili {
|
|
132
137
|
id: bigint // xml 7
|
|
133
|
-
progress: number // xml 0
|
|
138
|
+
progress: number // xml 0 ; xml s, protobuf ms
|
|
134
139
|
mode: number // xml 1
|
|
135
140
|
fontsize: number // xml 2
|
|
136
141
|
color: number // xml 3
|
|
@@ -233,6 +238,8 @@ export interface ExtraDanUniMerge {
|
|
|
233
238
|
duration: number //持续时间(重复内容第一次出现时间开始到合并了的弹幕中最后一次出现的时间)
|
|
234
239
|
count: number //重复次数
|
|
235
240
|
senders: string[] //发送者
|
|
241
|
+
taolu_count: number //类似弹幕数量
|
|
242
|
+
taolu_senders: string[] //类似弹幕发送者
|
|
236
243
|
}
|
|
237
244
|
export enum ExtraDanUniChapterType {
|
|
238
245
|
Chapter = 'ch', //其它片段(用于标记章节)
|
|
@@ -289,7 +296,7 @@ export type ctime = string | number | bigint | Date
|
|
|
289
296
|
// }
|
|
290
297
|
|
|
291
298
|
export interface UniDMObj {
|
|
292
|
-
|
|
299
|
+
SOID: string
|
|
293
300
|
progress: number
|
|
294
301
|
mode: Modes
|
|
295
302
|
fontsize: number
|
|
@@ -300,8 +307,7 @@ export interface UniDMObj {
|
|
|
300
307
|
weight: number
|
|
301
308
|
pool: Pools
|
|
302
309
|
attr: DMAttr[]
|
|
303
|
-
platform:
|
|
304
|
-
SPMO: string
|
|
310
|
+
platform: PlatformDanmakuSource | string
|
|
305
311
|
extra: string | Extra
|
|
306
312
|
extraStr: string
|
|
307
313
|
DMID: string
|
|
@@ -317,9 +323,10 @@ export class UniDM {
|
|
|
317
323
|
// syncAnchor = BigInt(Date.now())
|
|
318
324
|
constructor(
|
|
319
325
|
/**
|
|
320
|
-
*
|
|
326
|
+
* 资源ID
|
|
327
|
+
* @description 由某一danuni服务确定的某一剧集下不同资源(不同视频站/字幕组具有细节差异)的ID
|
|
321
328
|
*/
|
|
322
|
-
public
|
|
329
|
+
public SOID: string,
|
|
323
330
|
/**
|
|
324
331
|
* 弹幕出现位置(单位s;精度为ms,即保留三位小数)
|
|
325
332
|
*/
|
|
@@ -359,9 +366,9 @@ export class UniDM {
|
|
|
359
366
|
* 权重 用于屏蔽等级 区间:[1,10]
|
|
360
367
|
* @description 参考B站,源弹幕有该参数则直接利用,
|
|
361
368
|
* 本实现默认取5,再经过ruleset匹配加减分数
|
|
362
|
-
* @description
|
|
369
|
+
* @description 为0时表示暂时未计算权重
|
|
363
370
|
*/
|
|
364
|
-
public weight: number =
|
|
371
|
+
public weight: number = 0,
|
|
365
372
|
/**
|
|
366
373
|
* 弹幕池 0:普通池 1:字幕池 2:特殊池(代码/BAS弹幕) 3:互动池(互动弹幕中选择投票快速发送的弹幕)
|
|
367
374
|
*/
|
|
@@ -375,18 +382,7 @@ export class UniDM {
|
|
|
375
382
|
* 初始来源平台
|
|
376
383
|
* `danuni`与任意空值(可隐式转换为false的值)等价
|
|
377
384
|
*/
|
|
378
|
-
public platform?:
|
|
379
|
-
/**
|
|
380
|
-
* Same Platform Multiple Origin
|
|
381
|
-
* @description 解决B站等同一番剧存在港澳台站、多语言配音(不同一CID)的问题,同时方便过滤
|
|
382
|
-
* @description 示例:
|
|
383
|
-
* - main: 主站
|
|
384
|
-
* - hm: 仅港澳
|
|
385
|
-
* - t: 仅台
|
|
386
|
-
* - hmt: 仅港澳台
|
|
387
|
-
* - lang:{ISO语言代号}: 多语言
|
|
388
|
-
*/
|
|
389
|
-
public SPMO?: string,
|
|
385
|
+
public platform?: PlatformDanmakuSource | string,
|
|
390
386
|
/**
|
|
391
387
|
* 弹幕原始数据(不推荐使用)
|
|
392
388
|
* @description 适用于无法解析的B站代码弹幕、Artplayer弹幕样式等
|
|
@@ -402,7 +398,7 @@ export class UniDM {
|
|
|
402
398
|
if (fontsize <= 0) this.fontsize = 25
|
|
403
399
|
if (color <= 0) this.color = 16777215 //虽然不知道为0是否为可用值,但过为少见,利用其作为默认位
|
|
404
400
|
// if (ctime <= 0n) this.ctime = BigInt(Date.now())
|
|
405
|
-
if (weight
|
|
401
|
+
if (weight < 0 || weight > 10) this.weight = 5
|
|
406
402
|
if (pool < Pools.Def || pool > Pools.Ix) this.pool = Pools.Def
|
|
407
403
|
// if (attr < 0 || attr > 0b111) this.attr = 0
|
|
408
404
|
if (!DMID) DMID = this.toDMID()
|
|
@@ -415,7 +411,7 @@ export class UniDM {
|
|
|
415
411
|
static create(args?: Partial<UniDMObj>) {
|
|
416
412
|
return args
|
|
417
413
|
? new UniDM(
|
|
418
|
-
args.
|
|
414
|
+
args.SOID || ID.fromNull().toString(),
|
|
419
415
|
args.progress,
|
|
420
416
|
args.mode,
|
|
421
417
|
args.fontsize,
|
|
@@ -427,7 +423,6 @@ export class UniDM {
|
|
|
427
423
|
args.pool,
|
|
428
424
|
args.attr,
|
|
429
425
|
args.platform,
|
|
430
|
-
args.SPMO,
|
|
431
426
|
typeof args.extra === 'object'
|
|
432
427
|
? JSON.stringify(args.extra)
|
|
433
428
|
: args.extra || args.extraStr,
|
|
@@ -442,14 +437,17 @@ export class UniDM {
|
|
|
442
437
|
// return cleanEmptyObjects(extra) as Extra
|
|
443
438
|
}
|
|
444
439
|
get isFrom3rdPlatform() {
|
|
445
|
-
if (
|
|
440
|
+
if (
|
|
441
|
+
this.platform &&
|
|
442
|
+
PlatformDanmakuSources.includes(this.platform as PlatformDanmakuSource)
|
|
443
|
+
)
|
|
446
444
|
return true
|
|
447
445
|
else return false
|
|
448
446
|
}
|
|
449
447
|
/**
|
|
450
448
|
* 弹幕id
|
|
451
449
|
* @description sha3-256(content+senderID+ctime)截取前8位
|
|
452
|
-
* @description 同一
|
|
450
|
+
* @description 同一SOID下唯一
|
|
453
451
|
*/
|
|
454
452
|
toDMID() {
|
|
455
453
|
return createDMID(this.content, this.senderID, this.ctime)
|
|
@@ -458,12 +456,11 @@ export class UniDM {
|
|
|
458
456
|
const isSame = (k: keyof UniDMObj) => this[k] === dan[k],
|
|
459
457
|
checks = (
|
|
460
458
|
[
|
|
461
|
-
'
|
|
459
|
+
'SOID',
|
|
462
460
|
'content',
|
|
463
461
|
'mode',
|
|
464
462
|
'platform',
|
|
465
463
|
'pool',
|
|
466
|
-
'SPMO',
|
|
467
464
|
] satisfies (keyof UniDMObj)[]
|
|
468
465
|
).every((k) => isSame(k))
|
|
469
466
|
// 如果两个对象的extra都是空对象,只检查基本字段
|
|
@@ -500,7 +497,7 @@ export class UniDM {
|
|
|
500
497
|
)
|
|
501
498
|
}
|
|
502
499
|
minify() {
|
|
503
|
-
type UObj = Partial<UniDMObj> & Pick<UniDMObj, '
|
|
500
|
+
type UObj = Partial<UniDMObj> & Pick<UniDMObj, 'SOID'>
|
|
504
501
|
const def: UObj = UniDM.create(),
|
|
505
502
|
dan: UObj = UniDM.create(this)
|
|
506
503
|
// const prototypes = Object.getOwnPropertyNames(this)
|
|
@@ -508,7 +505,7 @@ export class UniDM {
|
|
|
508
505
|
const k = key as keyof UObj,
|
|
509
506
|
v = dan[k]
|
|
510
507
|
// if (key in prototypes) continue
|
|
511
|
-
if (key === '
|
|
508
|
+
if (key === 'SOID') continue
|
|
512
509
|
else if (!v) delete dan[k]
|
|
513
510
|
else if (v === def[k]) delete dan[k]
|
|
514
511
|
else {
|
|
@@ -562,7 +559,7 @@ export class UniDM {
|
|
|
562
559
|
clone.fontsize = 36
|
|
563
560
|
}
|
|
564
561
|
}
|
|
565
|
-
clone.senderID = 'compat@
|
|
562
|
+
clone.senderID = 'compat[bot]@dan-any'
|
|
566
563
|
clone.attr.push('Compatible')
|
|
567
564
|
if (cleanExtra) clone.extraStr = undefined
|
|
568
565
|
return clone
|
|
@@ -652,12 +649,12 @@ export class UniDM {
|
|
|
652
649
|
}
|
|
653
650
|
return mode
|
|
654
651
|
}
|
|
655
|
-
static fromBili(args: DMBili,
|
|
652
|
+
static fromBili(args: DMBili, cid?: bigint) {
|
|
656
653
|
interface TExtra extends Extra {
|
|
657
654
|
bili: ExtraBili
|
|
658
655
|
}
|
|
659
656
|
if (args.oid && !cid) cid = args.oid
|
|
660
|
-
const
|
|
657
|
+
const SOID = `def::${ID.fromBili({ cid })}`,
|
|
661
658
|
senderID = ID.fromBili({ midHash: args.midHash })
|
|
662
659
|
let mode = Modes.Normal
|
|
663
660
|
const pool = args.pool, //暂时不做处理,兼容bili的pool格式
|
|
@@ -695,7 +692,7 @@ export class UniDM {
|
|
|
695
692
|
// else if (args.mode === 9) extra.bili.bas = args.content
|
|
696
693
|
return this.create({
|
|
697
694
|
...args,
|
|
698
|
-
|
|
695
|
+
SOID: SOID.toString(),
|
|
699
696
|
// progress: args.progress,
|
|
700
697
|
mode,
|
|
701
698
|
// fontsize: args.fontsize,
|
|
@@ -705,9 +702,8 @@ export class UniDM {
|
|
|
705
702
|
ctime: this.transCtime(args.ctime, 's'),
|
|
706
703
|
weight: args.weight ? args.weight : pool === Pools.Ix ? 1 : 0,
|
|
707
704
|
pool,
|
|
708
|
-
attr: DMAttrUtils.fromBin(args.attr,
|
|
709
|
-
platform:
|
|
710
|
-
SPMO,
|
|
705
|
+
attr: DMAttrUtils.fromBin(args.attr, PlatformVideoSource.Bilibili),
|
|
706
|
+
platform: PlatformVideoSource.Bilibili,
|
|
711
707
|
// 需改进,7=>advanced 8=>code 9=>bas 互动=>command
|
|
712
708
|
// 同时塞进无法/无需直接解析的数据
|
|
713
709
|
// 另开一个解析器,为大部分播放器(无法解析该类dm)做文本类型降级处理
|
|
@@ -715,13 +711,65 @@ export class UniDM {
|
|
|
715
711
|
args.mode >= 7 ? JSON.stringify(extra, BigIntSerializer) : undefined,
|
|
716
712
|
})
|
|
717
713
|
}
|
|
718
|
-
|
|
714
|
+
toBiliXML() {
|
|
715
|
+
const recMode = (mode: Modes, extra?: ExtraBili) => {
|
|
716
|
+
switch (mode) {
|
|
717
|
+
case Modes.Normal:
|
|
718
|
+
return 1
|
|
719
|
+
case Modes.Bottom:
|
|
720
|
+
return 4
|
|
721
|
+
case Modes.Top:
|
|
722
|
+
return 5
|
|
723
|
+
case Modes.Reverse:
|
|
724
|
+
return 6
|
|
725
|
+
case Modes.Ext:
|
|
726
|
+
if (!extra) return 1
|
|
727
|
+
else if (extra.adv) return 7
|
|
728
|
+
else if (extra.code) return 8
|
|
729
|
+
else if (extra.bas) return 9
|
|
730
|
+
else return 1
|
|
731
|
+
default:
|
|
732
|
+
return 1
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
const rMode = recMode(this.mode, this.extra?.bili)
|
|
736
|
+
let content
|
|
737
|
+
switch (rMode) {
|
|
738
|
+
case 7:
|
|
739
|
+
content = this.extra?.bili?.adv
|
|
740
|
+
break
|
|
741
|
+
case 8:
|
|
742
|
+
content = this.extra?.bili?.code
|
|
743
|
+
break
|
|
744
|
+
case 9:
|
|
745
|
+
content = this.extra?.bili?.bas
|
|
746
|
+
break
|
|
747
|
+
default:
|
|
748
|
+
content = this.content
|
|
749
|
+
break
|
|
750
|
+
}
|
|
751
|
+
return {
|
|
752
|
+
'#text': content ?? this.content,
|
|
753
|
+
'@_p': [
|
|
754
|
+
this.progress,
|
|
755
|
+
rMode,
|
|
756
|
+
this.fontsize,
|
|
757
|
+
this.color,
|
|
758
|
+
this.ctime.getTime() / 1000,
|
|
759
|
+
this.pool, // 目前pool与bili兼容
|
|
760
|
+
this.senderID,
|
|
761
|
+
this.DMID || this.toDMID(),
|
|
762
|
+
this.weight,
|
|
763
|
+
].join(','),
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
static fromBiliCommand(args: DMBiliCommand, cid?: bigint) {
|
|
719
767
|
if (args.oid && !cid) cid = args.oid
|
|
720
|
-
const
|
|
768
|
+
const SOID = ID.fromBili({ cid }),
|
|
721
769
|
senderID = ID.fromBili({ mid: args.mid })
|
|
722
770
|
return this.create({
|
|
723
771
|
...args,
|
|
724
|
-
|
|
772
|
+
SOID: SOID.toString(),
|
|
725
773
|
// progress: args.progress,
|
|
726
774
|
mode: Modes.Ext,
|
|
727
775
|
// fontsize: args.fontsize,
|
|
@@ -732,8 +780,7 @@ export class UniDM {
|
|
|
732
780
|
weight: 10,
|
|
733
781
|
pool: Pools.Adv,
|
|
734
782
|
attr: ['Protect'],
|
|
735
|
-
platform:
|
|
736
|
-
SPMO,
|
|
783
|
+
platform: PlatformVideoSource.Bilibili,
|
|
737
784
|
extra: JSON.stringify(
|
|
738
785
|
{
|
|
739
786
|
bili: {
|
|
@@ -745,11 +792,11 @@ export class UniDM {
|
|
|
745
792
|
})
|
|
746
793
|
}
|
|
747
794
|
static fromDplayer(args: DMDplayer, playerID: string, domain: string) {
|
|
748
|
-
const
|
|
795
|
+
const SOID = ID.fromUnknown(playerID, domain),
|
|
749
796
|
senderID = ID.fromUnknown(args.midHash, domain)
|
|
750
797
|
return this.create({
|
|
751
798
|
...args,
|
|
752
|
-
|
|
799
|
+
SOID: SOID.toString(),
|
|
753
800
|
// progress: args.progress,
|
|
754
801
|
mode: this.transMode(args.mode, 'dplayer'),
|
|
755
802
|
// fontsize: 25,
|
|
@@ -772,7 +819,7 @@ export class UniDM {
|
|
|
772
819
|
}
|
|
773
820
|
}
|
|
774
821
|
static fromArtplayer(args: DMArtplayer, playerID: string, domain: string) {
|
|
775
|
-
const
|
|
822
|
+
const SOID = ID.fromUnknown(playerID, domain),
|
|
776
823
|
senderID = ID.fromUnknown('', domain)
|
|
777
824
|
let extra = args.border
|
|
778
825
|
? ({ artplayer: { border: args.border, style: {} } } as Extra)
|
|
@@ -787,7 +834,7 @@ export class UniDM {
|
|
|
787
834
|
}
|
|
788
835
|
return this.create({
|
|
789
836
|
...args,
|
|
790
|
-
|
|
837
|
+
SOID: SOID.toString(),
|
|
791
838
|
// progress: args.progress,
|
|
792
839
|
mode: this.transMode(args.mode, 'artplayer'),
|
|
793
840
|
// fontsize: 25,
|
|
@@ -813,12 +860,12 @@ export class UniDM {
|
|
|
813
860
|
static fromDDplay(
|
|
814
861
|
args: DMDDplay,
|
|
815
862
|
episodeId: string,
|
|
816
|
-
domain =
|
|
863
|
+
domain = PlatformDanmakuOnlySource.DanDanPlay,
|
|
817
864
|
) {
|
|
818
|
-
const
|
|
865
|
+
const SOID = ID.fromUnknown(`def::${episodeId}`, domain)
|
|
819
866
|
return this.create({
|
|
820
867
|
...args,
|
|
821
|
-
|
|
868
|
+
SOID: SOID.toString(),
|
|
822
869
|
// progress: args.progress,
|
|
823
870
|
mode: this.transMode(args.mode, 'ddplay'),
|
|
824
871
|
// 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,22 @@ 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
|
) {}
|
|
26
|
+
static fromString(str: string) {
|
|
27
|
+
const [id, domain] = str.split('@')
|
|
28
|
+
return new UniID(id, domain)
|
|
29
|
+
}
|
|
68
30
|
toString() {
|
|
69
31
|
return `${this.id}@${this.domain}`
|
|
70
32
|
}
|
|
71
|
-
static fromNull(domain?: string) {
|
|
72
|
-
return new UniID(
|
|
33
|
+
static fromNull(domain?: PlatformSource | 'runtime' | string) {
|
|
34
|
+
return new UniID(
|
|
35
|
+
domain === 'runtime' ? 'runtime' : 'anonymous',
|
|
36
|
+
domain || 'danuni',
|
|
37
|
+
)
|
|
73
38
|
}
|
|
74
39
|
static fromBili({
|
|
75
40
|
cid,
|
|
@@ -80,31 +45,23 @@ export class UniID {
|
|
|
80
45
|
mid?: number | bigint
|
|
81
46
|
midHash?: string
|
|
82
47
|
}) {
|
|
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(
|
|
48
|
+
if (cid) return new UniID(cid.toString(), PlatformVideoSource.Bilibili)
|
|
49
|
+
else if (mid) return new UniID(mid.toString(), PlatformVideoSource.Bilibili)
|
|
50
|
+
else if (midHash) return new UniID(midHash, PlatformVideoSource.Bilibili)
|
|
51
|
+
else return this.fromNull(PlatformVideoSource.Bilibili)
|
|
87
52
|
}
|
|
88
53
|
static fromUnknown(
|
|
89
54
|
id: string,
|
|
90
55
|
/**
|
|
91
|
-
*
|
|
56
|
+
* 可使用预设
|
|
92
57
|
*/
|
|
93
|
-
domain:
|
|
58
|
+
domain: PlatformSource | string,
|
|
94
59
|
) {
|
|
95
|
-
// domain = preset2domain(domain).domain
|
|
96
60
|
if (id) return new UniID(id, domain)
|
|
97
61
|
else return this.fromNull(domain)
|
|
98
62
|
}
|
|
99
63
|
}
|
|
100
64
|
|
|
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
65
|
export function createDMID(
|
|
109
66
|
content: string = '',
|
|
110
67
|
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
|
+
}
|