@dan-uni/dan-any 0.8.7 → 0.9.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 +209 -20
- package/dist/index.umd.min.js +988 -734
- package/dist/src/ass-gen/index.d.ts +2 -1
- package/dist/src/ass-gen/util/danconvert.d.ts +2 -1
- package/dist/src/index.d.ts +7 -3
- package/package.json +1 -1
- package/src/ass-gen/index.ts +6 -2
- package/src/ass-gen/util/danconvert.ts +9 -2
- package/src/index.test.ts +16 -1
- package/src/index.ts +123 -17
- package/src/utils/dm-gen.ts +1 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Options as UniPoolOptions } from '..';
|
|
1
2
|
import type { RawConfig } from './ass/raw';
|
|
2
3
|
import type { CanvasCtx, SubtitleStyle } from './types';
|
|
3
4
|
import { UniPool } from '..';
|
|
@@ -26,4 +27,4 @@ fs.writeFileSync(`${filename}.ass`, assText, 'utf-8')
|
|
|
26
27
|
```
|
|
27
28
|
*/
|
|
28
29
|
export declare function generateASS(danmaku: UniPool, options: Options, canvasCtx: CanvasCtx): string;
|
|
29
|
-
export declare function parseAssRawField(ass: string): UniPool;
|
|
30
|
+
export declare function parseAssRawField(ass: string, options?: UniPoolOptions): UniPool;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import type { Options as UniPoolOptions } from '../..';
|
|
1
2
|
import type { Danmaku } from '../types';
|
|
2
3
|
import { UniPool } from '../..';
|
|
3
4
|
export declare function UniPool2DanmakuLists(UP: UniPool): Danmaku[];
|
|
4
|
-
export declare function DanmakuList2UniPool(d: Danmaku[]): UniPool;
|
|
5
|
+
export declare function DanmakuList2UniPool(d: Danmaku[], options?: UniPoolOptions): UniPool;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -50,11 +50,11 @@ export interface DM_JSON_DDPlay {
|
|
|
50
50
|
m: string;
|
|
51
51
|
}[];
|
|
52
52
|
}
|
|
53
|
-
export type DM_format = 'danuni.json' | 'danuni.
|
|
53
|
+
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';
|
|
54
54
|
type shareItems = Partial<Pick<UniDMTools.UniDMObj, 'SOID' | 'senderID' | 'platform' | 'SOID' | 'pool' | 'mode' | 'color'>>;
|
|
55
55
|
type UniPoolPipe = (that: UniPool) => Promise<UniPool>;
|
|
56
56
|
type UniPoolPipeSync = (that: UniPool) => UniPool;
|
|
57
|
-
interface Options {
|
|
57
|
+
export interface Options {
|
|
58
58
|
dedupe?: boolean;
|
|
59
59
|
dmid?: boolean | number | UniIDTools.DMIDGenerator;
|
|
60
60
|
}
|
|
@@ -143,6 +143,10 @@ export declare class UniPool {
|
|
|
143
143
|
*/
|
|
144
144
|
merge(lifetime?: number): UniPool;
|
|
145
145
|
minify(): (Partial<UniDMTools.UniDMObj> & Pick<UniDMTools.UniDMObj, "SOID">)[];
|
|
146
|
+
static import(file: unknown, options?: Options): {
|
|
147
|
+
pool: UniPool;
|
|
148
|
+
fmt: DM_format;
|
|
149
|
+
};
|
|
146
150
|
convert2(format: DM_format, continue_on_error?: boolean): string | Uint8Array<ArrayBufferLike> | UniDM[] | (DM_JSON_Dplayer & {
|
|
147
151
|
danuni?: DanUniConvertTip;
|
|
148
152
|
}) | (DM_JSON_Artplayer & {
|
|
@@ -191,7 +195,7 @@ export declare class UniPool {
|
|
|
191
195
|
toDDplay(): DM_JSON_DDPlay & {
|
|
192
196
|
danuni?: DanUniConvertTip;
|
|
193
197
|
};
|
|
194
|
-
static fromASS(ass: string): UniPool;
|
|
198
|
+
static fromASS(ass: string, options?: Options): UniPool;
|
|
195
199
|
/**
|
|
196
200
|
* 转换为ASS字幕格式的弹幕,需播放器支持多行ASS渲染
|
|
197
201
|
*/
|
package/package.json
CHANGED
package/src/ass-gen/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// import parse from './parse/bilibili'
|
|
2
|
+
import type { Options as UniPoolOptions } from '..'
|
|
2
3
|
import type { RawConfig } from './ass/raw'
|
|
3
4
|
import type { CanvasCtx, SubtitleStyle } from './types'
|
|
4
5
|
|
|
@@ -59,8 +60,11 @@ export function generateASS(
|
|
|
59
60
|
return content
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
export function parseAssRawField(
|
|
63
|
+
export function parseAssRawField(
|
|
64
|
+
ass: string,
|
|
65
|
+
options?: UniPoolOptions,
|
|
66
|
+
): UniPool {
|
|
63
67
|
const raw = deRaw(ass)
|
|
64
68
|
if (!raw) return UniPool.create()
|
|
65
|
-
else return DanmakuList2UniPool(raw.list)
|
|
69
|
+
else return DanmakuList2UniPool(raw.list, options)
|
|
66
70
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Options as UniPoolOptions } from '../..'
|
|
1
2
|
import type { Danmaku, RGB } from '../types'
|
|
2
3
|
|
|
3
4
|
import { UniPool } from '../..'
|
|
@@ -31,6 +32,12 @@ export function UniPool2DanmakuLists(UP: UniPool): Danmaku[] {
|
|
|
31
32
|
} satisfies Danmaku
|
|
32
33
|
})
|
|
33
34
|
}
|
|
34
|
-
export function DanmakuList2UniPool(
|
|
35
|
-
|
|
35
|
+
export function DanmakuList2UniPool(
|
|
36
|
+
d: Danmaku[],
|
|
37
|
+
options?: UniPoolOptions,
|
|
38
|
+
): UniPool {
|
|
39
|
+
return new UniPool(
|
|
40
|
+
d.map((d) => UniDM.create(d.extra)),
|
|
41
|
+
options,
|
|
42
|
+
)
|
|
36
43
|
}
|
package/src/index.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//基于以下注释,根据vitest生成测试用例
|
|
2
2
|
import { createCanvas } from 'canvas'
|
|
3
|
-
import { describe, it } from 'vitest'
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
4
|
|
|
5
5
|
import { UniPool } from './index'
|
|
6
6
|
|
|
@@ -35,6 +35,9 @@ describe('转化自', () => {
|
|
|
35
35
|
console.info(pool)
|
|
36
36
|
console.info(pool.toBiliXML())
|
|
37
37
|
console.info(pool.toBiliXML({ avoidSenderIDWithAt: true }))
|
|
38
|
+
const imp = UniPool.import(xml)
|
|
39
|
+
expect(imp.fmt).toBe('bili.xml')
|
|
40
|
+
expect(imp.pool).toEqual(pool)
|
|
38
41
|
})
|
|
39
42
|
it('artplayer(json)', () => {
|
|
40
43
|
const json = {
|
|
@@ -52,6 +55,9 @@ describe('转化自', () => {
|
|
|
52
55
|
pool = UniPool.fromArtplayer(json, 'playerid-test', 'acfun')
|
|
53
56
|
console.info(json)
|
|
54
57
|
console.info(pool)
|
|
58
|
+
const imp = UniPool.import(json)
|
|
59
|
+
expect(imp.fmt).toBe('artplayer.json')
|
|
60
|
+
// expect(imp.pool).toEqual(pool)
|
|
55
61
|
})
|
|
56
62
|
it('ass[双向]', () => {
|
|
57
63
|
const canvas = createCanvas(50, 50)
|
|
@@ -59,16 +65,25 @@ describe('转化自', () => {
|
|
|
59
65
|
const ass = pool.toASS(canvas.getContext('2d'))
|
|
60
66
|
console.info(ass)
|
|
61
67
|
console.info(UniPool.fromASS(ass))
|
|
68
|
+
const imp = UniPool.import(ass)
|
|
69
|
+
expect(imp.fmt).toBe('common.ass')
|
|
70
|
+
expect(imp.pool).toEqual(pool)
|
|
62
71
|
})
|
|
63
72
|
it('pb[双向]', () => {
|
|
64
73
|
const pool = UniPool.fromBiliXML(xml)
|
|
65
74
|
const pb = pool.toPb()
|
|
66
75
|
console.info(UniPool.fromPb(pb))
|
|
76
|
+
const imp = UniPool.import(pb)
|
|
77
|
+
expect(imp.fmt).toBe('danuni.pb.bin')
|
|
78
|
+
expect(imp.pool).toEqual(pool)
|
|
67
79
|
})
|
|
68
80
|
it('DDplay[双向]', () => {
|
|
69
81
|
const pool = UniPool.fromBiliXML(xml)
|
|
70
82
|
const ddplay = pool.toDDplay()
|
|
71
83
|
console.info(UniPool.fromDDPlay(ddplay, '1'))
|
|
84
|
+
const imp = UniPool.import(ddplay)
|
|
85
|
+
expect(imp.fmt).toBe('ddplay.json')
|
|
86
|
+
// expect(imp.pool).toEqual(pool)
|
|
72
87
|
})
|
|
73
88
|
})
|
|
74
89
|
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import 'reflect-metadata/lite'
|
|
2
2
|
|
|
3
|
+
import { isJSON, isObject, isString } from 'class-validator'
|
|
3
4
|
import { XMLBuilder, XMLParser } from 'fast-xml-parser'
|
|
4
5
|
import JSONbig from 'json-bigint'
|
|
5
6
|
import type { Options as AssGenOptions, CanvasCtx } from './ass-gen'
|
|
@@ -86,11 +87,10 @@ export interface DM_JSON_DDPlay {
|
|
|
86
87
|
|
|
87
88
|
export type DM_format =
|
|
88
89
|
| 'danuni.json'
|
|
89
|
-
| 'danuni.bin'
|
|
90
|
-
| 'danuni.pb.zst'
|
|
90
|
+
| 'danuni.pb.bin'
|
|
91
91
|
| 'bili.xml'
|
|
92
|
-
| 'bili.bin'
|
|
93
|
-
| 'bili.cmd.bin'
|
|
92
|
+
| 'bili.pb.bin'
|
|
93
|
+
| 'bili.cmd.pb.bin'
|
|
94
94
|
| 'dplayer.json'
|
|
95
95
|
| 'artplayer.json'
|
|
96
96
|
| 'ddplay.json'
|
|
@@ -106,7 +106,7 @@ type shareItems = Partial<
|
|
|
106
106
|
type UniPoolPipe = (that: UniPool) => Promise<UniPool>
|
|
107
107
|
type UniPoolPipeSync = (that: UniPool) => UniPool
|
|
108
108
|
|
|
109
|
-
interface Options {
|
|
109
|
+
export interface Options {
|
|
110
110
|
dedupe?: boolean
|
|
111
111
|
dmid?: boolean | number | UniIDTools.DMIDGenerator
|
|
112
112
|
}
|
|
@@ -396,11 +396,111 @@ export class UniPool {
|
|
|
396
396
|
minify() {
|
|
397
397
|
return this.dans.map((d) => d.minify())
|
|
398
398
|
}
|
|
399
|
+
static import(
|
|
400
|
+
file: unknown,
|
|
401
|
+
options?: Options,
|
|
402
|
+
): { pool: UniPool; fmt: DM_format } {
|
|
403
|
+
const err = '无法识别该文件,请手动指定格式!'
|
|
404
|
+
const parseJSON = (
|
|
405
|
+
json: DM_JSON_Artplayer &
|
|
406
|
+
DM_JSON_DDPlay &
|
|
407
|
+
DM_JSON_Dplayer & { danuni?: DanUniConvertTip },
|
|
408
|
+
): { pool: UniPool; fmt: DM_format } | undefined => {
|
|
409
|
+
try {
|
|
410
|
+
if (Array.isArray(json) && json.every((d) => d.SOID)) {
|
|
411
|
+
return { pool: new UniPool(json, options), fmt: 'danuni.json' }
|
|
412
|
+
} else if (json.danmuku && json.danmuku.every((d) => d.text)) {
|
|
413
|
+
return {
|
|
414
|
+
pool: this.fromArtplayer(
|
|
415
|
+
json,
|
|
416
|
+
json.danuni?.data ?? '',
|
|
417
|
+
undefined,
|
|
418
|
+
options,
|
|
419
|
+
),
|
|
420
|
+
fmt: 'artplayer.json',
|
|
421
|
+
}
|
|
422
|
+
} else if (
|
|
423
|
+
json.count &&
|
|
424
|
+
json.comments &&
|
|
425
|
+
json.comments.every((d) => d.m)
|
|
426
|
+
) {
|
|
427
|
+
return {
|
|
428
|
+
pool: this.fromDDPlay(json, json.danuni?.data ?? '', options),
|
|
429
|
+
fmt: 'ddplay.json',
|
|
430
|
+
}
|
|
431
|
+
} else if (
|
|
432
|
+
json.code &&
|
|
433
|
+
json.code == 0 &&
|
|
434
|
+
json.data &&
|
|
435
|
+
json.data.every((d) => Array.isArray(d))
|
|
436
|
+
) {
|
|
437
|
+
return {
|
|
438
|
+
pool: this.fromDplayer(
|
|
439
|
+
json,
|
|
440
|
+
json.danuni?.data ?? '',
|
|
441
|
+
undefined,
|
|
442
|
+
options,
|
|
443
|
+
),
|
|
444
|
+
fmt: 'dplayer.json',
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
} catch {}
|
|
448
|
+
}
|
|
449
|
+
const parseStr = (
|
|
450
|
+
file: string,
|
|
451
|
+
): { pool: UniPool; fmt: DM_format } | undefined => {
|
|
452
|
+
try {
|
|
453
|
+
if (isJSON(file)) {
|
|
454
|
+
const json = JSON.parse(file)
|
|
455
|
+
return parseJSON(json)
|
|
456
|
+
}
|
|
457
|
+
} catch {}
|
|
458
|
+
try {
|
|
459
|
+
const xmlParser = new XMLParser({ ignoreAttributes: false })
|
|
460
|
+
const xml = xmlParser.parse(file)
|
|
461
|
+
if (xml?.i?.d)
|
|
462
|
+
return { pool: this.fromBiliXML(file, options), fmt: 'bili.xml' }
|
|
463
|
+
} catch {}
|
|
464
|
+
try {
|
|
465
|
+
return { pool: this.fromASS(file, options), fmt: 'common.ass' }
|
|
466
|
+
} catch {}
|
|
467
|
+
}
|
|
468
|
+
if (isObject(file)) {
|
|
469
|
+
if (file instanceof ArrayBuffer || file instanceof Uint8Array) {
|
|
470
|
+
try {
|
|
471
|
+
const fileStr = new TextDecoder().decode(file)
|
|
472
|
+
const prStr = parseStr(fileStr)
|
|
473
|
+
if (!prStr) throw new Error(`${err}(定位: bin->string)`)
|
|
474
|
+
} catch {}
|
|
475
|
+
try {
|
|
476
|
+
return { pool: this.fromPb(file), fmt: 'danuni.pb.bin' }
|
|
477
|
+
} catch {}
|
|
478
|
+
try {
|
|
479
|
+
return { pool: this.fromBiliGrpc(file), fmt: 'bili.pb.bin' }
|
|
480
|
+
} catch {}
|
|
481
|
+
try {
|
|
482
|
+
return {
|
|
483
|
+
pool: this.fromBiliCommandGrpc(file),
|
|
484
|
+
fmt: 'bili.cmd.pb.bin',
|
|
485
|
+
}
|
|
486
|
+
} catch {}
|
|
487
|
+
} else {
|
|
488
|
+
const prJSON = parseJSON(file as any)
|
|
489
|
+
if (!prJSON) throw new Error(`${err}(定位: json)`)
|
|
490
|
+
return prJSON
|
|
491
|
+
}
|
|
492
|
+
} else if (isString(file)) {
|
|
493
|
+
const prStr = parseStr(file)
|
|
494
|
+
if (!prStr) throw new Error(`${err}(定位: string)`)
|
|
495
|
+
return prStr
|
|
496
|
+
}
|
|
497
|
+
throw new Error(err)
|
|
498
|
+
}
|
|
399
499
|
convert2(format: DM_format, continue_on_error = false) {
|
|
400
500
|
switch (format) {
|
|
401
501
|
case 'danuni.json':
|
|
402
502
|
return this.dans
|
|
403
|
-
case 'danuni.bin':
|
|
503
|
+
case 'danuni.pb.bin':
|
|
404
504
|
return this.toPb()
|
|
405
505
|
case 'bili.xml':
|
|
406
506
|
return this.toBiliXML()
|
|
@@ -435,6 +535,8 @@ export class UniPool {
|
|
|
435
535
|
ctime: timestampDate(d.ctime || timestampNow()),
|
|
436
536
|
pool: d.pool as number,
|
|
437
537
|
attr: d.attr as UniDMTools.DMAttr[],
|
|
538
|
+
extra: undefined,
|
|
539
|
+
extraStr: d.extra,
|
|
438
540
|
},
|
|
439
541
|
options,
|
|
440
542
|
),
|
|
@@ -588,9 +690,6 @@ export class UniPool {
|
|
|
588
690
|
) {
|
|
589
691
|
return new UniPool(
|
|
590
692
|
json.data.map((d) => {
|
|
591
|
-
// let TYPE = 0
|
|
592
|
-
// if (d[1] === 1) TYPE = 5
|
|
593
|
-
// else if (d[1] === 2) TYPE = 4
|
|
594
693
|
return UniDM.fromDplayer(
|
|
595
694
|
{
|
|
596
695
|
content: d[4],
|
|
@@ -611,7 +710,10 @@ export class UniPool {
|
|
|
611
710
|
toDplayer(): DM_JSON_Dplayer & { danuni?: DanUniConvertTip } {
|
|
612
711
|
return {
|
|
613
712
|
code: 0,
|
|
614
|
-
danuni:
|
|
713
|
+
danuni: {
|
|
714
|
+
...DanUniConvertTipTemplate,
|
|
715
|
+
data: this.dans[0].SOID.split('@')[0],
|
|
716
|
+
},
|
|
615
717
|
data: this.dans.map((dan) => {
|
|
616
718
|
const d = dan.toDplayer()
|
|
617
719
|
return [d.progress, d.mode, d.color, d.midHash, d.content]
|
|
@@ -626,9 +728,6 @@ export class UniPool {
|
|
|
626
728
|
) {
|
|
627
729
|
return new UniPool(
|
|
628
730
|
json.danmuku.map((d) => {
|
|
629
|
-
// let TYPE = 0
|
|
630
|
-
// if (d.mode === 1) TYPE = 5
|
|
631
|
-
// else if (d.mode === 2) TYPE = 4
|
|
632
731
|
return UniDM.fromArtplayer(
|
|
633
732
|
{
|
|
634
733
|
content: d.text,
|
|
@@ -648,7 +747,10 @@ export class UniPool {
|
|
|
648
747
|
}
|
|
649
748
|
toArtplayer(): DM_JSON_Artplayer & { danuni?: DanUniConvertTip } {
|
|
650
749
|
return {
|
|
651
|
-
danuni:
|
|
750
|
+
danuni: {
|
|
751
|
+
...DanUniConvertTipTemplate,
|
|
752
|
+
data: this.dans[0].SOID.split('@')[0],
|
|
753
|
+
},
|
|
652
754
|
danmuku: this.dans.map((dan) => {
|
|
653
755
|
const d = dan.toArtplayer()
|
|
654
756
|
return {
|
|
@@ -689,8 +791,12 @@ export class UniPool {
|
|
|
689
791
|
)
|
|
690
792
|
}
|
|
691
793
|
toDDplay(): DM_JSON_DDPlay & { danuni?: DanUniConvertTip } {
|
|
794
|
+
const episodeId = this.dans[0].SOID.split('@')[0].replaceAll(
|
|
795
|
+
`def_${platform.PlatformDanmakuOnlySource.DanDanPlay}+`,
|
|
796
|
+
'',
|
|
797
|
+
)
|
|
692
798
|
return {
|
|
693
|
-
danuni: DanUniConvertTipTemplate,
|
|
799
|
+
danuni: { ...DanUniConvertTipTemplate, data: episodeId },
|
|
694
800
|
count: this.dans.length,
|
|
695
801
|
comments: this.dans.map((dan) => {
|
|
696
802
|
const d = dan.toDDplay()
|
|
@@ -702,8 +808,8 @@ export class UniPool {
|
|
|
702
808
|
}),
|
|
703
809
|
}
|
|
704
810
|
}
|
|
705
|
-
static fromASS(ass: string) {
|
|
706
|
-
return parseAssRawField(ass)
|
|
811
|
+
static fromASS(ass: string, options?: Options) {
|
|
812
|
+
return parseAssRawField(ass, options)
|
|
707
813
|
}
|
|
708
814
|
/**
|
|
709
815
|
* 转换为ASS字幕格式的弹幕,需播放器支持多行ASS渲染
|
package/src/utils/dm-gen.ts
CHANGED