@dan-uni/dan-any 1.3.0 → 1.3.3

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.
@@ -10,6 +10,7 @@ interface DanUniConvertTip {
10
10
  version: string;
11
11
  data?: string;
12
12
  }
13
+ export type DM_JSON_DanuniMin = Partial<UniDMTools.UniDMObj>[];
13
14
  export interface DM_XML_Bili {
14
15
  i: {
15
16
  chatserver: string;
@@ -200,9 +201,9 @@ export declare class UniPool {
200
201
  minify(): (Partial<UniDMTools.UniDMObj> & Pick<UniDMTools.UniDMObj, "SOID">)[];
201
202
  static import(file: unknown, options?: Options,
202
203
  /**
203
- * 加载指定解析模块,为空则全选
204
+ * 加载指定解析模块,为空则全选,为字符串则视为文件名解析加载模块
204
205
  */
205
- mod?: ('json' | 'str' | 'bin')[]): {
206
+ mod?: string | ('json' | 'str' | 'bin')[]): {
206
207
  pool: UniPool;
207
208
  fmt: DM_format;
208
209
  };
@@ -213,6 +214,7 @@ export declare class UniPool {
213
214
  }) | (DM_JSON_DDPlay & {
214
215
  danuni?: DanUniConvertTip;
215
216
  });
217
+ static fromMin(json: DM_JSON_DanuniMin, options?: Options): UniPool;
216
218
  static fromPb(bin: Uint8Array | ArrayBuffer, options?: Options): UniPool;
217
219
  /**
218
220
  * 转为 protobuf 二进制
@@ -0,0 +1,3 @@
1
+ export declare function fileParser(file: unknown, mod: 'bin'): ArrayBuffer | Uint8Array;
2
+ export declare function fileParser(file: unknown, mod: 'string'): string;
3
+ export declare function fileParser<T extends object>(file: unknown, mod: 'json'): T;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dan-uni/dan-any",
3
3
  "type": "module",
4
- "version": "1.3.0",
4
+ "version": "1.3.3",
5
5
  "description": "A danmaku transformer lib, supporting danmaku from different platforms.",
6
6
  "author": "rinne",
7
7
  "license": "LGPL-3.0-or-later",
@@ -35,9 +35,8 @@
35
35
  "@bufbuild/protobuf": "^2.11.0",
36
36
  "base16384": "^1.0.0",
37
37
  "class-transformer": "^0.5.1",
38
- "class-validator": "^0.14.3",
39
- "fast-xml-parser": "^5.3.6",
40
- "fs-extra": "^11.3.3",
38
+ "class-validator": "^0.15.1",
39
+ "fast-xml-parser": "^5.5.8",
41
40
  "hh-mm-ss": "^1.2.0",
42
41
  "json-bigint": "^1.0.0",
43
42
  "jssha": "^3.3.1",
@@ -45,13 +44,12 @@
45
44
  "reflect-metadata": "^0.2.2"
46
45
  },
47
46
  "devDependencies": {
48
- "@bufbuild/buf": "^1.65.0",
47
+ "@bufbuild/buf": "^1.66.1",
49
48
  "@bufbuild/protoc-gen-es": "^2.11.0",
50
- "@types/fs-extra": "^11.0.4",
51
49
  "@types/hh-mm-ss": "^1.2.3",
52
50
  "@types/json-bigint": "^1.0.4",
53
51
  "@types/luxon": "^3.7.1",
54
- "canvas": "^3.2.1",
52
+ "canvas": "^3.2.2",
55
53
  "protobufjs": "^8.0.0"
56
54
  }
57
55
  }
package/src/index.test.ts CHANGED
@@ -37,6 +37,8 @@ describe('转化自', () => {
37
37
  const imp = UniPool.import(xml)
38
38
  expect(imp.fmt).toBe('bili.xml')
39
39
  expect(imp.pool).toEqual(pool)
40
+ const imp2 = UniPool.import(xml, undefined, 'test-bili.xml')
41
+ expect(imp2).toEqual(imp)
40
42
  })
41
43
  it('artplayer(json)', () => {
42
44
  const json = {
@@ -56,7 +58,10 @@ describe('转化自', () => {
56
58
  console.info(pool)
57
59
  const imp = UniPool.import(json)
58
60
  expect(imp.fmt).toBe('artplayer.json')
61
+ // 该适配器ctime始终为now,无法双向测试
59
62
  // expect(imp.pool).toEqual(pool)
63
+ UniPool.import(json, undefined, 'test-artplayer.json')
64
+ // expect(imp2).toEqual(imp)
60
65
  })
61
66
  it('ass[双向]', () => {
62
67
  const canvas = createCanvas(50, 50)
@@ -67,6 +72,8 @@ describe('转化自', () => {
67
72
  const imp = UniPool.import(ass)
68
73
  expect(imp.fmt).toBe('common.ass')
69
74
  expect(imp.pool).toEqual(pool)
75
+ const imp2 = UniPool.import(ass, undefined, 'test-common.ass')
76
+ expect(imp2).toEqual(imp)
70
77
  })
71
78
  it('pb[双向]', () => {
72
79
  const pool = UniPool.fromBiliXML(xml)
@@ -75,6 +82,8 @@ describe('转化自', () => {
75
82
  const imp = UniPool.import(pb)
76
83
  expect(imp.fmt).toBe('danuni.binpb')
77
84
  expect(imp.pool).toEqual(pool)
85
+ const imp2 = UniPool.import(pb, undefined, 'test-danuni.binpb')
86
+ expect(imp2).toEqual(imp)
78
87
  })
79
88
  it('DDplay[双向]', () => {
80
89
  const pool = UniPool.fromBiliXML(xml)
@@ -82,7 +91,20 @@ describe('转化自', () => {
82
91
  console.info(UniPool.fromDDPlay(ddplay, '1'))
83
92
  const imp = UniPool.import(ddplay)
84
93
  expect(imp.fmt).toBe('ddplay.json')
94
+ // 该适配器ctime始终为now,无法双向测试
95
+ UniPool.import(ddplay, undefined, 'test-ddplay.json')
96
+ // expect(imp2).toEqual(imp)
97
+ })
98
+ it('min[双向]', () => {
99
+ const pool = UniPool.fromBiliXML(xml)
100
+ const min = pool.minify()
101
+ console.info(min)
102
+ const imp = UniPool.import(min)
103
+ expect(imp.fmt).toBe('danuni.min.json')
104
+ // 该适配器ctime始终为now,无法双向测试
85
105
  // expect(imp.pool).toEqual(pool)
106
+ UniPool.import(min, undefined, 'test-danuni.min.json')
107
+ // expect(imp2).toEqual(imp)
86
108
  })
87
109
  })
88
110
 
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'reflect-metadata/lite'
2
2
 
3
- import { isJSON, isObject, isString } from 'class-validator'
3
+ import { isJSON, isString } from 'class-validator'
4
4
  import { XMLBuilder, XMLParser } from 'fast-xml-parser'
5
5
  import JSONbig from 'json-bigint'
6
6
  import type { Options as AssGenOptions, CanvasCtx } from './ass-gen'
@@ -26,6 +26,7 @@ import { ListDanResponseSchema } from './proto/gen/danuni/danmaku/v1/danmaku_pb'
26
26
 
27
27
  import { UniDM } from './utils/dm-gen'
28
28
  import * as UniDMTools from './utils/dm-gen'
29
+ import { fileParser } from './utils/fileParser'
29
30
  import { UniID as ID } from './utils/id-gen'
30
31
  import * as UniIDTools from './utils/id-gen'
31
32
  import * as platform from './utils/platform'
@@ -45,6 +46,8 @@ interface DanUniConvertTip {
45
46
  data?: string
46
47
  }
47
48
 
49
+ export type DM_JSON_DanuniMin = Partial<UniDMTools.UniDMObj>[]
50
+
48
51
  export interface DM_XML_Bili {
49
52
  i: {
50
53
  chatserver: string
@@ -449,10 +452,120 @@ export class UniPool {
449
452
  file: unknown,
450
453
  options?: Options,
451
454
  /**
452
- * 加载指定解析模块,为空则全选
455
+ * 加载指定解析模块,为空则全选,为字符串则视为文件名解析加载模块
453
456
  */
454
- mod?: ('json' | 'str' | 'bin')[],
457
+ mod?: string | ('json' | 'str' | 'bin')[],
455
458
  ): { pool: UniPool; fmt: DM_format } {
459
+ const handlers = {
460
+ [DM_format.DanuniJson]: (json: UniDM[]) => ({
461
+ pool: new UniPool(json, options),
462
+ fmt: DM_format.DanuniJson,
463
+ }),
464
+ [DM_format.DanuniMinJson]: (json: DM_JSON_DanuniMin) => ({
465
+ pool: this.fromMin(json, options),
466
+ fmt: DM_format.DanuniMinJson,
467
+ }),
468
+ [DM_format.DanuniPbBin]: (
469
+ file: ArrayBuffer | Uint8Array<ArrayBufferLike>,
470
+ ) => ({
471
+ pool: this.fromPb(file),
472
+ fmt: DM_format.DanuniPbBin,
473
+ }),
474
+ [DM_format.BiliXml]: (file: string) => ({
475
+ pool: this.fromBiliXML(file, options),
476
+ fmt: DM_format.BiliXml,
477
+ }),
478
+ [DM_format.BiliPbBin]: (
479
+ file: ArrayBuffer | Uint8Array<ArrayBufferLike>,
480
+ ) => ({
481
+ pool: this.fromBiliGrpc(file),
482
+ fmt: DM_format.BiliPbBin,
483
+ }),
484
+ [DM_format.BiliCmdPbBin]: (
485
+ file: ArrayBuffer | Uint8Array<ArrayBufferLike>,
486
+ ) => ({
487
+ pool: this.fromBiliCommandGrpc(file),
488
+ fmt: DM_format.BiliCmdPbBin,
489
+ }),
490
+ [DM_format.BiliUpJson]: (json: DM_JSON_BiliUp) => ({
491
+ pool: this.fromBiliUp(json, options),
492
+ fmt: DM_format.BiliUpJson,
493
+ }),
494
+ [DM_format.DplayerJson]: (
495
+ json: DM_JSON_Dplayer & {
496
+ danuni?: DanUniConvertTip
497
+ },
498
+ ) => ({
499
+ pool: this.fromDplayer(
500
+ json,
501
+ json.danuni?.data ?? '',
502
+ undefined,
503
+ options,
504
+ ),
505
+ fmt: DM_format.DplayerJson,
506
+ }),
507
+ [DM_format.ArtplayerJson]: (
508
+ json: DM_JSON_Artplayer & {
509
+ danuni?: DanUniConvertTip
510
+ },
511
+ ) => ({
512
+ pool: this.fromArtplayer(
513
+ json,
514
+ json.danuni?.data ?? '',
515
+ undefined,
516
+ options,
517
+ ),
518
+ fmt: DM_format.ArtplayerJson,
519
+ }),
520
+ [DM_format.DdplayJson]: (
521
+ json: DM_JSON_DDPlay & {
522
+ danuni?: DanUniConvertTip
523
+ },
524
+ ) => ({
525
+ pool: this.fromDDPlay(json, json.danuni?.data ?? '', options),
526
+ fmt: DM_format.DdplayJson,
527
+ }),
528
+ [DM_format.CommonAss]: (file: string) => ({
529
+ pool: this.fromASS(file, options),
530
+ fmt: DM_format.CommonAss,
531
+ }),
532
+ }
533
+
534
+ if (typeof mod === 'string') {
535
+ const fn = mod
536
+ // 直接按照默认模式处理匹配后缀的文件
537
+ try {
538
+ if (fn.endsWith(DM_format.DanuniJson)) {
539
+ return handlers[DM_format.DanuniJson](fileParser(file, 'json'))
540
+ } else if (fn.endsWith(DM_format.DanuniMinJson))
541
+ return handlers[DM_format.DanuniMinJson](fileParser(file, 'json'))
542
+ else if (fn.endsWith(DM_format.DanuniPbBin))
543
+ return handlers[DM_format.DanuniPbBin](fileParser(file, 'bin'))
544
+ else if (fn.endsWith(DM_format.BiliXml))
545
+ return handlers[DM_format.BiliXml](fileParser(file, 'string'))
546
+ else if (fn.endsWith(DM_format.BiliPbBin))
547
+ return handlers[DM_format.BiliPbBin](fileParser(file, 'bin'))
548
+ else if (fn.endsWith(DM_format.BiliCmdPbBin))
549
+ return handlers[DM_format.BiliCmdPbBin](fileParser(file, 'bin'))
550
+ else if (fn.endsWith(DM_format.BiliUpJson))
551
+ return handlers[DM_format.BiliUpJson](fileParser(file, 'json'))
552
+ else if (fn.endsWith(DM_format.DplayerJson))
553
+ return handlers[DM_format.DplayerJson](fileParser(file, 'json'))
554
+ else if (fn.endsWith(DM_format.ArtplayerJson))
555
+ return handlers[DM_format.ArtplayerJson](fileParser(file, 'json'))
556
+ else if (fn.endsWith(DM_format.DdplayJson))
557
+ return handlers[DM_format.DdplayJson](fileParser(file, 'json'))
558
+ else if (fn.endsWith(DM_format.CommonAss))
559
+ return handlers[DM_format.CommonAss](fileParser(file, 'string'))
560
+ } catch {}
561
+ // 按照后缀设定启用模块
562
+ const ext = fn.split('.').pop()?.toLowerCase()
563
+ if (ext) {
564
+ if (ext === 'json') mod = ['json']
565
+ else if (['xml', 'ass'].includes(ext)) mod = ['str']
566
+ else if (['binpb', 'bin', 'so'].includes(ext)) mod = ['bin']
567
+ }
568
+ }
456
569
  if (!mod) mod = ['json', 'str', 'bin']
457
570
  const err = '无法识别该文件,请手动指定格式!'
458
571
  const parseJSON = (
@@ -463,42 +576,23 @@ export class UniPool {
463
576
  ): { pool: UniPool; fmt: DM_format } | undefined => {
464
577
  try {
465
578
  if (Array.isArray(json) && json.every((d) => d.SOID)) {
466
- return { pool: new UniPool(json, options), fmt: DM_format.DanuniJson }
579
+ return handlers[DM_format.DanuniMinJson](json) // 使用兼容性参数,danuni.min.json解析器可以解析danuni.json
467
580
  } else if (json.danmuku && json.danmuku.every((d) => d.text)) {
468
- return {
469
- pool: this.fromArtplayer(
470
- json,
471
- json.danuni?.data ?? '',
472
- undefined,
473
- options,
474
- ),
475
- fmt: DM_format.ArtplayerJson,
476
- }
581
+ return handlers[DM_format.ArtplayerJson](json)
477
582
  } else if (
478
583
  json.count &&
479
584
  json.comments &&
480
585
  Array.isArray(json.comments) &&
481
586
  json.comments.every((d) => d.m)
482
587
  ) {
483
- return {
484
- pool: this.fromDDPlay(json, json.danuni?.data ?? '', options),
485
- fmt: DM_format.DdplayJson,
486
- }
588
+ return handlers[DM_format.DdplayJson](json)
487
589
  } else if (
488
590
  json.code == 0 &&
489
591
  json.data &&
490
592
  Array.isArray(json.data) &&
491
593
  json.data.every((d) => Array.isArray(d))
492
594
  ) {
493
- return {
494
- pool: this.fromDplayer(
495
- json,
496
- json.danuni?.data ?? '',
497
- undefined,
498
- options,
499
- ),
500
- fmt: DM_format.DplayerJson,
501
- }
595
+ return handlers[DM_format.DplayerJson](json)
502
596
  } else if (
503
597
  json.code == 0 &&
504
598
  json.message == '0' &&
@@ -508,10 +602,7 @@ export class UniPool {
508
602
  Array.isArray(json.data.result) &&
509
603
  json.data.result.every((d) => d.id && d.oid)
510
604
  ) {
511
- return {
512
- pool: this.fromBiliUp(json, options),
513
- fmt: DM_format.BiliUpJson,
514
- }
605
+ return handlers[DM_format.BiliUpJson](json)
515
606
  }
516
607
  } catch {}
517
608
  }
@@ -531,33 +622,26 @@ export class UniPool {
531
622
  try {
532
623
  const xmlParser = new XMLParser({ ignoreAttributes: false })
533
624
  const xml = xmlParser.parse(file)
534
- if (xml?.i?.d)
535
- return {
536
- pool: this.fromBiliXML(file, options),
537
- fmt: DM_format.BiliXml,
538
- }
625
+ if (xml?.i?.d) return handlers[DM_format.BiliXml](file)
539
626
  } catch {}
540
627
  try {
541
- return { pool: this.fromASS(file, options), fmt: DM_format.CommonAss }
628
+ return handlers[DM_format.CommonAss](file)
542
629
  } catch {}
543
630
  }
544
631
  }
545
632
  let errmesg
546
- if (isObject(file)) {
633
+ if (typeof file === 'object' || Array.isArray(file)) {
547
634
  if (file instanceof ArrayBuffer || file instanceof Uint8Array) {
548
635
  // pure-bin (pb)
549
636
  if (mod.includes('bin')) {
550
637
  try {
551
- return { pool: this.fromPb(file), fmt: DM_format.DanuniPbBin }
638
+ return handlers[DM_format.DanuniPbBin](file)
552
639
  } catch {}
553
640
  try {
554
- return { pool: this.fromBiliGrpc(file), fmt: DM_format.BiliPbBin }
641
+ return handlers[DM_format.BiliPbBin](file)
555
642
  } catch {}
556
643
  try {
557
- return {
558
- pool: this.fromBiliCommandGrpc(file),
559
- fmt: DM_format.BiliCmdPbBin,
560
- }
644
+ return handlers[DM_format.BiliCmdPbBin](file)
561
645
  } catch {}
562
646
  }
563
647
  // str-bin (pure-str + json-str)
@@ -614,6 +698,9 @@ export class UniPool {
614
698
  }
615
699
  }
616
700
  }
701
+ static fromMin(json: DM_JSON_DanuniMin, options?: Options) {
702
+ return new UniPool(json.map((d: any) => UniDM.create(d, options)))
703
+ }
617
704
  static fromPb(bin: Uint8Array | ArrayBuffer, options?: Options) {
618
705
  const data = fromBinary(ListDanResponseSchema, new Uint8Array(bin))
619
706
  return new UniPool(
@@ -479,7 +479,7 @@ export class UniDM {
479
479
  if (!this.SOID) this.SOID = def.SOID
480
480
  if (!this.progress) this.progress = def.progress
481
481
  if (!this.mode) this.mode = def.mode
482
- if (!this.fontsize) this.fontsize = def.mode
482
+ if (!this.fontsize) this.fontsize = def.fontsize
483
483
  if (!this.color) this.color = def.color
484
484
  if (!this.senderID) this.senderID = def.senderID
485
485
  if (!this.content) this.content = def.content
@@ -0,0 +1,37 @@
1
+ export function fileParser(file: unknown, mod: 'bin'): ArrayBuffer | Uint8Array
2
+ export function fileParser(file: unknown, mod: 'string'): string
3
+ export function fileParser<T extends object>(file: unknown, mod: 'json'): T
4
+ export function fileParser(
5
+ file: unknown,
6
+ mod: 'bin' | 'string' | 'json',
7
+ ): ArrayBuffer | Uint8Array | string | object {
8
+ const isBinary = file instanceof ArrayBuffer || file instanceof Uint8Array
9
+ switch (mod) {
10
+ case 'bin': {
11
+ if (isBinary) return file
12
+ throw new TypeError('Expected binary data for mod "bin"')
13
+ }
14
+ case 'string': {
15
+ if (typeof file === 'string') return file
16
+ if (isBinary) return new TextDecoder().decode(file)
17
+ throw new TypeError('Expected binary data or string for mod "string"')
18
+ }
19
+ case 'json': {
20
+ if (typeof file === 'object' && file !== null && !isBinary) return file
21
+ if (typeof file !== 'string' && !isBinary) {
22
+ throw new TypeError(
23
+ 'Expected object, JSON string, or binary data for mod "json"',
24
+ )
25
+ }
26
+ const str =
27
+ typeof file === 'string' ? file : new TextDecoder().decode(file)
28
+ try {
29
+ return JSON.parse(str)
30
+ } catch {
31
+ throw new Error('Invalid JSON string')
32
+ }
33
+ }
34
+ default:
35
+ throw new Error(`Unsupported mod "${mod}"`)
36
+ }
37
+ }