@dan-uni/dan-any 0.8.7 → 0.9.1
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 +213 -20
- package/dist/index.umd.min.js +992 -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 +124 -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,112 @@ 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 == 0 &&
|
|
433
|
+
json.data &&
|
|
434
|
+
json.data.every((d) => Array.isArray(d))
|
|
435
|
+
) {
|
|
436
|
+
return {
|
|
437
|
+
pool: this.fromDplayer(
|
|
438
|
+
json,
|
|
439
|
+
json.danuni?.data ?? '',
|
|
440
|
+
undefined,
|
|
441
|
+
options,
|
|
442
|
+
),
|
|
443
|
+
fmt: 'dplayer.json',
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
} catch {}
|
|
447
|
+
}
|
|
448
|
+
const parseStr = (
|
|
449
|
+
file: string,
|
|
450
|
+
): { pool: UniPool; fmt: DM_format } | undefined => {
|
|
451
|
+
try {
|
|
452
|
+
if (isJSON(file)) {
|
|
453
|
+
const json = JSON.parse(file)
|
|
454
|
+
return parseJSON(json)
|
|
455
|
+
}
|
|
456
|
+
} catch {}
|
|
457
|
+
try {
|
|
458
|
+
const xmlParser = new XMLParser({ ignoreAttributes: false })
|
|
459
|
+
const xml = xmlParser.parse(file)
|
|
460
|
+
if (xml?.i?.d)
|
|
461
|
+
return { pool: this.fromBiliXML(file, options), fmt: 'bili.xml' }
|
|
462
|
+
} catch {}
|
|
463
|
+
try {
|
|
464
|
+
return { pool: this.fromASS(file, options), fmt: 'common.ass' }
|
|
465
|
+
} catch {}
|
|
466
|
+
}
|
|
467
|
+
let errmesg
|
|
468
|
+
if (isObject(file)) {
|
|
469
|
+
if (file instanceof ArrayBuffer || file instanceof Uint8Array) {
|
|
470
|
+
try {
|
|
471
|
+
return { pool: this.fromPb(file), fmt: 'danuni.pb.bin' }
|
|
472
|
+
} catch {}
|
|
473
|
+
try {
|
|
474
|
+
return { pool: this.fromBiliGrpc(file), fmt: 'bili.pb.bin' }
|
|
475
|
+
} catch {}
|
|
476
|
+
try {
|
|
477
|
+
return {
|
|
478
|
+
pool: this.fromBiliCommandGrpc(file),
|
|
479
|
+
fmt: 'bili.cmd.pb.bin',
|
|
480
|
+
}
|
|
481
|
+
} catch {}
|
|
482
|
+
try {
|
|
483
|
+
const fileStr = new TextDecoder().decode(file)
|
|
484
|
+
const prStr = parseStr(fileStr)
|
|
485
|
+
if (!prStr) errmesg = `${err}(定位: bin->string)`
|
|
486
|
+
else return prStr
|
|
487
|
+
} catch {}
|
|
488
|
+
} else {
|
|
489
|
+
const prJSON = parseJSON(file as any)
|
|
490
|
+
if (!prJSON) throw new Error(`${err}(定位: json)`)
|
|
491
|
+
return prJSON
|
|
492
|
+
}
|
|
493
|
+
} else if (isString(file)) {
|
|
494
|
+
const prStr = parseStr(file)
|
|
495
|
+
if (!prStr) throw new Error(`${err}(定位: string)`)
|
|
496
|
+
return prStr
|
|
497
|
+
}
|
|
498
|
+
throw new Error(errmesg ?? err)
|
|
499
|
+
}
|
|
399
500
|
convert2(format: DM_format, continue_on_error = false) {
|
|
400
501
|
switch (format) {
|
|
401
502
|
case 'danuni.json':
|
|
402
503
|
return this.dans
|
|
403
|
-
case 'danuni.bin':
|
|
504
|
+
case 'danuni.pb.bin':
|
|
404
505
|
return this.toPb()
|
|
405
506
|
case 'bili.xml':
|
|
406
507
|
return this.toBiliXML()
|
|
@@ -435,6 +536,8 @@ export class UniPool {
|
|
|
435
536
|
ctime: timestampDate(d.ctime || timestampNow()),
|
|
436
537
|
pool: d.pool as number,
|
|
437
538
|
attr: d.attr as UniDMTools.DMAttr[],
|
|
539
|
+
extra: undefined,
|
|
540
|
+
extraStr: d.extra,
|
|
438
541
|
},
|
|
439
542
|
options,
|
|
440
543
|
),
|
|
@@ -588,9 +691,6 @@ export class UniPool {
|
|
|
588
691
|
) {
|
|
589
692
|
return new UniPool(
|
|
590
693
|
json.data.map((d) => {
|
|
591
|
-
// let TYPE = 0
|
|
592
|
-
// if (d[1] === 1) TYPE = 5
|
|
593
|
-
// else if (d[1] === 2) TYPE = 4
|
|
594
694
|
return UniDM.fromDplayer(
|
|
595
695
|
{
|
|
596
696
|
content: d[4],
|
|
@@ -611,7 +711,10 @@ export class UniPool {
|
|
|
611
711
|
toDplayer(): DM_JSON_Dplayer & { danuni?: DanUniConvertTip } {
|
|
612
712
|
return {
|
|
613
713
|
code: 0,
|
|
614
|
-
danuni:
|
|
714
|
+
danuni: {
|
|
715
|
+
...DanUniConvertTipTemplate,
|
|
716
|
+
data: this.dans[0].SOID.split('@')[0],
|
|
717
|
+
},
|
|
615
718
|
data: this.dans.map((dan) => {
|
|
616
719
|
const d = dan.toDplayer()
|
|
617
720
|
return [d.progress, d.mode, d.color, d.midHash, d.content]
|
|
@@ -626,9 +729,6 @@ export class UniPool {
|
|
|
626
729
|
) {
|
|
627
730
|
return new UniPool(
|
|
628
731
|
json.danmuku.map((d) => {
|
|
629
|
-
// let TYPE = 0
|
|
630
|
-
// if (d.mode === 1) TYPE = 5
|
|
631
|
-
// else if (d.mode === 2) TYPE = 4
|
|
632
732
|
return UniDM.fromArtplayer(
|
|
633
733
|
{
|
|
634
734
|
content: d.text,
|
|
@@ -648,7 +748,10 @@ export class UniPool {
|
|
|
648
748
|
}
|
|
649
749
|
toArtplayer(): DM_JSON_Artplayer & { danuni?: DanUniConvertTip } {
|
|
650
750
|
return {
|
|
651
|
-
danuni:
|
|
751
|
+
danuni: {
|
|
752
|
+
...DanUniConvertTipTemplate,
|
|
753
|
+
data: this.dans[0].SOID.split('@')[0],
|
|
754
|
+
},
|
|
652
755
|
danmuku: this.dans.map((dan) => {
|
|
653
756
|
const d = dan.toArtplayer()
|
|
654
757
|
return {
|
|
@@ -689,8 +792,12 @@ export class UniPool {
|
|
|
689
792
|
)
|
|
690
793
|
}
|
|
691
794
|
toDDplay(): DM_JSON_DDPlay & { danuni?: DanUniConvertTip } {
|
|
795
|
+
const episodeId = this.dans[0].SOID.split('@')[0].replaceAll(
|
|
796
|
+
`def_${platform.PlatformDanmakuOnlySource.DanDanPlay}+`,
|
|
797
|
+
'',
|
|
798
|
+
)
|
|
692
799
|
return {
|
|
693
|
-
danuni: DanUniConvertTipTemplate,
|
|
800
|
+
danuni: { ...DanUniConvertTipTemplate, data: episodeId },
|
|
694
801
|
count: this.dans.length,
|
|
695
802
|
comments: this.dans.map((dan) => {
|
|
696
803
|
const d = dan.toDDplay()
|
|
@@ -702,8 +809,8 @@ export class UniPool {
|
|
|
702
809
|
}),
|
|
703
810
|
}
|
|
704
811
|
}
|
|
705
|
-
static fromASS(ass: string) {
|
|
706
|
-
return parseAssRawField(ass)
|
|
812
|
+
static fromASS(ass: string, options?: Options) {
|
|
813
|
+
return parseAssRawField(ass, options)
|
|
707
814
|
}
|
|
708
815
|
/**
|
|
709
816
|
* 转换为ASS字幕格式的弹幕,需播放器支持多行ASS渲染
|
package/src/utils/dm-gen.ts
CHANGED