@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/src/index.ts CHANGED
@@ -1,8 +1,6 @@
1
1
  import { XMLParser } from 'fast-xml-parser'
2
2
  import type { Options as AssGenOptions } from './ass-gen'
3
3
  import type { CommandDm as DM_JSON_BiliCommandGrpc } from './proto/gen/bili/dm_pb'
4
- // import type * as UniDMType from './utils/dm-gen'
5
- import type { platfrom } from './utils/id-gen'
6
4
 
7
5
  import { create, fromBinary, toBinary } from '@bufbuild/protobuf'
8
6
  import {
@@ -23,6 +21,7 @@ import { DanmakuReplySchema } from './proto/gen/danuni_pb'
23
21
  import { UniDM } from './utils/dm-gen'
24
22
  import * as UniDMTools from './utils/dm-gen'
25
23
  import * as UniIDTools from './utils/id-gen'
24
+ import * as platform from './utils/platform'
26
25
 
27
26
  export interface DM_XML_Bili {
28
27
  i: {
@@ -48,11 +47,11 @@ export interface DM_JSON_Dplayer {
48
47
  }
49
48
  export interface DM_JSON_Artplayer {
50
49
  text: string // 弹幕文本
51
- time?: number // 弹幕时间, 默认为当前播放器时间
52
- mode?: number // 弹幕模式: 0: 滚动(默认),1: 顶部,2: 底部
50
+ time?: number // 弹幕时间,默认为当前播放器时间
51
+ mode?: number // 弹幕模式:0: 滚动 (默认),1: 顶部,2: 底部
53
52
  color?: string // 弹幕颜色,默认为白色
54
- border?: boolean // 弹幕是否有描边, 默认为 false
55
- style?: {} // 弹幕自定义样式, 默认为空对象
53
+ border?: boolean // 弹幕是否有描边,默认为 false
54
+ style?: {} // 弹幕自定义样式,默认为空对象
56
55
  }
57
56
  export interface DM_JSON_DDPlay {
58
57
  count: number | string
@@ -78,22 +77,143 @@ export type DM_format =
78
77
  type shareItems = Partial<
79
78
  Pick<
80
79
  UniDMTools.UniDMObj,
81
- 'FCID' | 'senderID' | 'platform' | 'SPMO' | 'pool' | 'mode'
80
+ 'SOID' | 'senderID' | 'platform' | 'SOID' | 'pool' | 'mode' | 'color'
82
81
  >
83
82
  >
84
83
 
84
+ type UniPoolPipe = (that: UniPool) => Promise<UniPool>
85
+ type UniPoolPipeSync = (that: UniPool) => UniPool
86
+
87
+ interface Options {
88
+ dedupe?: boolean
89
+ }
90
+
85
91
  export class UniPool {
86
- readonly shared: shareItems = {}
87
- constructor(public dans: UniDM[]) {
88
- function isShared(key: keyof UniDMTools.UniDMObj) {
89
- return new Set(dans.map((d) => d[key])).size === 1
92
+ constructor(
93
+ public dans: UniDM[],
94
+ public options: Options = {},
95
+ ) {
96
+ if (options.dedupe !== false) options.dedupe = true
97
+ if (this.options.dedupe) this.dedupe()
98
+ }
99
+ async pipe(fn: UniPoolPipe): Promise<UniPool> {
100
+ return fn(this)
101
+ }
102
+ pipeSync(fn: UniPoolPipeSync): UniPool {
103
+ return fn(this)
104
+ }
105
+ get shared(): shareItems {
106
+ const isShared = (key: keyof UniDMTools.UniDMObj) => {
107
+ return this.dans.every((d) => d[key])
108
+ }
109
+ return {
110
+ SOID: isShared('SOID') ? this.dans[0].SOID : undefined,
111
+ senderID: isShared('senderID') ? this.dans[0].senderID : undefined,
112
+ platform: isShared('platform') ? this.dans[0].platform : undefined,
113
+ pool: isShared('pool') ? this.dans[0].pool : undefined,
114
+ mode: isShared('mode') ? this.dans[0].mode : undefined,
115
+ color: isShared('color') ? this.dans[0].color : undefined,
116
+ }
117
+ }
118
+ get stat() {
119
+ const default_stat = {
120
+ SOID: [] as { val: string; count: number }[],
121
+ mode: [
122
+ { val: UniDMTools.Modes.Normal, count: 0 },
123
+ { val: UniDMTools.Modes.Bottom, count: 0 },
124
+ { val: UniDMTools.Modes.Top, count: 0 },
125
+ { val: UniDMTools.Modes.Reverse, count: 0 },
126
+ { val: UniDMTools.Modes.Ext, count: 0 },
127
+ ],
128
+ fontsize: [
129
+ // { val: 18, count: 0 },
130
+ // { val: 25, count: 0 },
131
+ // { val: 36, count: 0 },
132
+ ] as { val: number; count: number }[],
133
+ color: [] as { val: number; count: number }[],
134
+ senderID: [] as { val: string; count: number }[],
135
+ content: [] as { val: string; count: number }[],
136
+ weight: [] as { val: number; count: number }[],
137
+ pool: [
138
+ { val: UniDMTools.Pools.Def, count: 0 },
139
+ { val: UniDMTools.Pools.Sub, count: 0 },
140
+ { val: UniDMTools.Pools.Adv, count: 0 },
141
+ { val: UniDMTools.Pools.Ix, count: 0 },
142
+ ],
143
+ platform: [] as { val?: string; count: number }[],
144
+ }
145
+ type Stat = typeof default_stat
146
+ const stat = this.dans.reduce((s, d): Stat => {
147
+ const SOID = s.SOID.find((i) => i.val === d.SOID)
148
+ if (!SOID) {
149
+ s.SOID.push({ val: d.SOID, count: 1 })
150
+ } else {
151
+ SOID.count++
152
+ }
153
+ const mode = s.mode.find((i) => i.val === d.mode)
154
+ if (!mode) {
155
+ s.mode.push({ val: d.mode, count: 1 })
156
+ } else {
157
+ mode.count++
158
+ }
159
+ const fontsize = s.fontsize.find((i) => i.val === d.fontsize)
160
+ if (!fontsize) {
161
+ s.fontsize.push({ val: d.fontsize, count: 1 })
162
+ } else {
163
+ fontsize.count++
164
+ }
165
+ const color = s.color.find((i) => i.val === d.color)
166
+ if (!color) {
167
+ s.color.push({ val: d.color, count: 1 })
168
+ } else {
169
+ color.count++
170
+ }
171
+ const senderID = s.senderID.find((i) => i.val === d.senderID)
172
+ if (!senderID) {
173
+ s.senderID.push({ val: d.senderID, count: 1 })
174
+ } else {
175
+ senderID.count++
176
+ }
177
+ const content = s.content.find((i) => i.val === d.content)
178
+ if (!content) {
179
+ s.content.push({ val: d.content, count: 1 })
180
+ } else {
181
+ content.count++
182
+ }
183
+ const weight = s.weight.find((i) => i.val === d.weight)
184
+ if (!weight) {
185
+ s.weight.push({ val: d.weight, count: 1 })
186
+ } else {
187
+ weight.count++
188
+ }
189
+ const pool = s.pool.find((i) => i.val === d.pool)
190
+ if (!pool) {
191
+ s.pool.push({ val: d.pool, count: 1 })
192
+ } else {
193
+ pool.count++
194
+ }
195
+ const platform = s.platform.find((i) => i.val === d.platform)
196
+ if (!platform) {
197
+ s.platform.push({ val: d.platform, count: 1 })
198
+ } else {
199
+ platform.count++
200
+ }
201
+ return s
202
+ }, default_stat)
203
+ return stat
204
+ }
205
+ get most() {
206
+ const s = this.stat
207
+ return {
208
+ mode: s.mode.sort((a, b) => b.count - a.count)[0].val,
209
+ fontsize: s.fontsize.sort((a, b) => b.count - a.count)[0].val,
210
+ color: s.color.sort((a, b) => b.count - a.count)[0].val,
211
+ senderID: s.senderID.sort((a, b) => b.count - a.count)[0].val,
212
+ content: s.content.sort((a, b) => b.count - a.count)[0].val,
213
+ weight: s.weight.sort((a, b) => b.count - a.count)[0].val,
214
+ pool: s.pool.sort((a, b) => b.count - a.count)[0].val,
215
+ platform: s.platform.sort((a, b) => b.count - a.count)[0].val,
90
216
  }
91
- if (isShared('FCID')) this.shared.FCID = dans[0].FCID
92
- if (isShared('senderID')) this.shared.senderID = dans[0].senderID
93
- if (isShared('platform')) this.shared.platform = dans[0].platform
94
- if (isShared('SPMO')) this.shared.SPMO = dans[0].SPMO
95
- if (isShared('pool')) this.shared.pool = dans[0].pool
96
- if (isShared('mode')) this.shared.mode = dans[0].mode
97
217
  }
98
218
  static create() {
99
219
  return new UniPool([])
@@ -117,17 +237,29 @@ export class UniPool {
117
237
  if (this.shared[key]) return [this]
118
238
  const set = new Set(this.dans.map((d) => d[key]))
119
239
  return [...set].map((v) => {
120
- return new UniPool(this.dans.filter((d) => d[key] === v))
240
+ return new UniPool(
241
+ this.dans.filter((d) => d[key] === v),
242
+ { dedupe: false },
243
+ )
121
244
  })
122
245
  }
246
+ /**
247
+ * 基于DMID的基本去重功能,用于解决该class下dans为array而非Set的问题
248
+ */
249
+ private dedupe() {
250
+ const map = new Map()
251
+ this.dans.forEach((d) => map.set(d.DMID || d.toDMID(), d))
252
+ this.dans = [...map.values()]
253
+ this.options.dedupe = false
254
+ }
123
255
  /**
124
256
  * 合并一定时间段内的重复弹幕,防止同屏出现过多
125
- * @param lifetime 查重时间区段,单位秒 (默认为0,表示不查重)
257
+ * @param lifetime 查重时间区段,单位秒 (默认为 0,表示不查重)
126
258
  */
127
259
  merge(lifetime = 0) {
128
- if (!this.shared.FCID) {
260
+ if (!this.shared.SOID) {
129
261
  console.error(
130
- "本功能仅支持同弹幕库内使用,可先 .split('FCID') 在分别使用",
262
+ "本功能仅支持同弹幕库内使用,可先 .split('SOID') 在分别使用",
131
263
  )
132
264
  return this
133
265
  }
@@ -140,7 +272,7 @@ export class UniPool {
140
272
  ]
141
273
  >(
142
274
  ([result, cache, mergeObj], danmaku) => {
143
- const key = ['content', 'mode', 'platform', 'pool', 'SPMO']
275
+ const key = ['SOID', 'content', 'mode', 'platform', 'pool']
144
276
  .map((k) => danmaku[k as keyof UniDM])
145
277
  .join('|')
146
278
  const cached = cache[key]
@@ -158,6 +290,8 @@ export class UniPool {
158
290
  count: senders.length,
159
291
  duration: danmaku.progress - cached.progress,
160
292
  senders,
293
+ taolu_count: senders.length,
294
+ taolu_senders: senders,
161
295
  }
162
296
  danmaku.extraStr = JSON.stringify(extra)
163
297
  cache[key] = danmaku
@@ -168,6 +302,8 @@ export class UniPool {
168
302
  count: 1,
169
303
  duration: 0,
170
304
  senders: [danmaku.senderID],
305
+ taolu_count: 1,
306
+ taolu_senders: [danmaku.senderID],
171
307
  }
172
308
  cache[key] = danmaku
173
309
  // 初始化merge信息,包含第一个sender
@@ -184,7 +320,7 @@ export class UniPool {
184
320
  // 处理结果,删除senders<=1的merge字段
185
321
  const [result, _cache, mergeObj] = mergeContext
186
322
  result.forEach((danmaku, i) => {
187
- const key = ['content', 'mode', 'platform', 'pool', 'SPMO']
323
+ const key = ['SOID', 'content', 'mode', 'platform', 'pool']
188
324
  .map((k) => danmaku[k as keyof UniDM])
189
325
  .join('|')
190
326
  const extra = result[i].extra,
@@ -210,7 +346,10 @@ export class UniPool {
210
346
  ? JSON.stringify(updatedExtra)
211
347
  : undefined
212
348
  } else {
213
- result[i].senderID = 'merge@bot'
349
+ result[i].senderID = 'merge[bot]@dan-any'
350
+ result[i].attr
351
+ ? result[i].attr.push('Protect')
352
+ : (result[i].attr = ['Protect'])
214
353
  }
215
354
  }
216
355
  })
@@ -222,7 +361,7 @@ export class UniPool {
222
361
  convert2(format: DM_format, continue_on_error = false) {
223
362
  switch (format) {
224
363
  case 'danuni.json':
225
- return JSON.stringify(this.dans)
364
+ return this.dans
226
365
  case 'danuni.bin':
227
366
  return this.toPb()
228
367
  // case 'bili.xml':
@@ -240,7 +379,7 @@ export class UniPool {
240
379
  case 'common.ass':
241
380
  return this.toASS()
242
381
  default: {
243
- const message = 'unknown format or unsupported now!'
382
+ const message = '(err) Unknown format or unsupported now!'
244
383
  if (continue_on_error) return message
245
384
  else throw new Error(message)
246
385
  }
@@ -252,7 +391,7 @@ export class UniPool {
252
391
  data.danmakus.map(
253
392
  (d) =>
254
393
  new UniDM(
255
- d.FCID,
394
+ d.SOID,
256
395
  d.progress,
257
396
  d.mode as number,
258
397
  d.fontsize,
@@ -264,7 +403,6 @@ export class UniPool {
264
403
  d.pool as number,
265
404
  d.attr as UniDMTools.DMAttr[],
266
405
  d.platform,
267
- d.SPMO,
268
406
  d.extra,
269
407
  d.DMID,
270
408
  ),
@@ -280,7 +418,7 @@ export class UniPool {
280
418
  create(DanmakuReplySchema, {
281
419
  danmakus: this.dans.map((d) => {
282
420
  return {
283
- FCID: d.FCID,
421
+ SOID: d.SOID,
284
422
  DMID: d.DMID,
285
423
  progress: d.progress,
286
424
  mode: d.mode as number,
@@ -293,14 +431,13 @@ export class UniPool {
293
431
  pool: d.pool as number,
294
432
  attr: d.attr,
295
433
  platform: d.platform,
296
- SPMO: d.SPMO,
297
434
  extra: d.extraStr,
298
435
  }
299
436
  }),
300
437
  }),
301
438
  )
302
439
  }
303
- static fromBiliXML(xml: string, SPMO?: string) {
440
+ static fromBiliXML(xml: string) {
304
441
  const parser = new XMLParser({ ignoreAttributes: false }),
305
442
  oriData: DM_XML_Bili = parser.parse(xml),
306
443
  dans = oriData.i.d
@@ -321,32 +458,29 @@ export class UniPool {
321
458
  id: BigInt(p_arr[7]),
322
459
  weight: Number.parseInt(p_arr[8]),
323
460
  },
324
- SPMO,
325
461
  BigInt(oriData.i.chatid),
326
462
  )
327
463
  }),
328
464
  )
329
465
  }
330
- static fromBiliGrpc(bin: Uint8Array | ArrayBuffer, SPMO?: string) {
466
+ static fromBiliGrpc(bin: Uint8Array | ArrayBuffer) {
331
467
  const data = fromBinary(DmSegMobileReplySchema, new Uint8Array(bin)),
332
468
  json = data.elems
333
469
  return new UniPool(
334
470
  json.map((d) => {
335
- return UniDM.fromBili(d, SPMO)
471
+ return UniDM.fromBili({ ...d, progress: d.progress / 1000 })
336
472
  }),
337
473
  )
338
474
  }
339
475
  /**
340
- *
341
476
  * @param bin 符合`DmWebViewReplySchema`(bili视频meta)的protobuf二进制
342
- * @param SPMO
343
477
  */
344
- static fromBiliCommandGrpc(bin: Uint8Array | ArrayBuffer, SPMO?: string) {
478
+ static fromBiliCommandGrpc(bin: Uint8Array | ArrayBuffer) {
345
479
  const data = fromBinary(DmWebViewReplySchema, new Uint8Array(bin)),
346
480
  json = data.commandDms
347
481
  return new UniPool(
348
482
  json.map((d) => {
349
- return UniDM.fromBiliCommand(d, SPMO)
483
+ return UniDM.fromBiliCommand(d)
350
484
  }),
351
485
  )
352
486
  }
@@ -420,7 +554,7 @@ export class UniPool {
420
554
  }
421
555
  })
422
556
  }
423
- static fromDDPlay(json: DM_JSON_DDPlay, episodeId: string, domain?: string) {
557
+ static fromDDPlay(json: DM_JSON_DDPlay, episodeId: string) {
424
558
  return new UniPool(
425
559
  json.comments.map((d) => {
426
560
  const p_arr = d.p.split(',')
@@ -434,7 +568,6 @@ export class UniPool {
434
568
  uid: p_arr[3],
435
569
  },
436
570
  episodeId,
437
- domain,
438
571
  )
439
572
  }),
440
573
  )
@@ -456,18 +589,18 @@ export class UniPool {
456
589
  return parseAssRawField(ass)
457
590
  }
458
591
  toASS(options: AssGenOptions = { substyle: {} }): string {
459
- const fn = this.shared.FCID
592
+ const fn = this.shared.SOID
460
593
  return generateASS(this, { filename: fn, title: fn, ...options })
461
594
  }
462
595
  }
463
596
 
464
597
  export {
598
+ platform,
465
599
  // UniPool,
466
600
  UniDM,
467
601
  UniDMTools,
468
602
  UniIDTools,
469
603
  type DM_JSON_BiliCommandGrpc,
470
- type platfrom,
471
604
  // type UniDMType,
472
605
  // type UniIDType,
473
606
  }
@@ -1,9 +1,9 @@
1
- // @generated by protoc-gen-es v2.2.3 with parameter "target=ts"
1
+ // @generated by protoc-gen-es v2.6.0 with parameter "target=ts"
2
2
  // @generated from file bili/dm.proto (package bilibili.community.service.dm.v1, syntax proto3)
3
3
  /* eslint-disable */
4
4
 
5
- import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv1";
6
- import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv1";
5
+ import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2";
6
+ import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2";
7
7
  import type { Message } from "@bufbuild/protobuf";
8
8
 
9
9
  /**
@@ -1,9 +1,9 @@
1
- // @generated by protoc-gen-es v2.2.3 with parameter "target=ts"
1
+ // @generated by protoc-gen-es v2.6.0 with parameter "target=ts"
2
2
  // @generated from file danuni.proto (package danuni.danmaku.v1, syntax proto3)
3
3
  /* eslint-disable */
4
4
 
5
- import type { GenEnum, GenFile, GenMessage } from "@bufbuild/protobuf/codegenv1";
6
- import { enumDesc, fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv1";
5
+ import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2";
6
+ import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2";
7
7
  import type { Timestamp } from "@bufbuild/protobuf/wkt";
8
8
  import { file_google_protobuf_timestamp } from "@bufbuild/protobuf/wkt";
9
9
  import type { Message } from "@bufbuild/protobuf";
@@ -12,16 +12,38 @@ import type { Message } from "@bufbuild/protobuf";
12
12
  * Describes the file danuni.proto.
13
13
  */
14
14
  export const file_danuni: GenFile = /*@__PURE__*/
15
- fileDesc("CgxkYW51bmkucHJvdG8SEWRhbnVuaS5kYW5tYWt1LnYxIt4CCgdEYW5tYWt1EgwKBEZDSUQYASABKAkSDAoERE1JRBgCIAEoCRIQCghwcm9ncmVzcxgDIAEoBRIlCgRtb2RlGAQgASgOMhcuZGFudW5pLmRhbm1ha3UudjEuTW9kZRIQCghmb250c2l6ZRgFIAEoBRINCgVjb2xvchgGIAEoBRIQCghzZW5kZXJJRBgHIAEoCRIPCgdjb250ZW50GAggASgJEikKBWN0aW1lGAkgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIOCgZ3ZWlnaHQYCiABKAUSJQoEcG9vbBgLIAEoDjIXLmRhbnVuaS5kYW5tYWt1LnYxLlBvb2wSDAoEYXR0chgMIAMoCRIQCghwbGF0Zm9ybRgNIAEoCRIRCgRTUE1PGA4gASgJSACIAQESEgoFZXh0cmEYDyABKAlIAYgBAUIHCgVfU1BNT0IICgZfZXh0cmEiPAoMRGFubWFrdVJlcGx5EiwKCGRhbm1ha3VzGAEgAygLMhouZGFudW5pLmRhbm1ha3UudjEuRGFubWFrdSo9CgRNb2RlEgoKBk5vcm1hbBAAEgoKBkJvdHRvbRABEgcKA1RvcBACEgsKB1JldmVyc2UQAxIHCgNFeHQQBCopCgRQb29sEgcKA0RlZhAAEgcKA1N1YhABEgcKA0FkdhACEgYKAkl4EANQAGIGcHJvdG8z", [file_google_protobuf_timestamp]);
15
+ fileDesc("CgxkYW51bmkucHJvdG8SEWRhbnVuaS5kYW5tYWt1LnYxIjIKCmxpc3REYW5SZXESCgoCSUQYASABKAkSEAoDc2VnGAIgASgFSACIAQFCBgoEX3NlZyLCAgoHRGFubWFrdRIMCgRTT0lEGAEgASgJEgwKBERNSUQYAiABKAkSEAoIcHJvZ3Jlc3MYAyABKAUSJQoEbW9kZRgEIAEoDjIXLmRhbnVuaS5kYW5tYWt1LnYxLk1vZGUSEAoIZm9udHNpemUYBSABKAUSDQoFY29sb3IYBiABKAUSEAoIc2VuZGVySUQYByABKAkSDwoHY29udGVudBgIIAEoCRIpCgVjdGltZRgJIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGd2VpZ2h0GAogASgFEiUKBHBvb2wYCyABKA4yFy5kYW51bmkuZGFubWFrdS52MS5Qb29sEgwKBGF0dHIYDCADKAkSEAoIcGxhdGZvcm0YDSABKAkSEgoFZXh0cmEYDiABKAlIAIgBAUIICgZfZXh0cmEiPAoMRGFubWFrdVJlcGx5EiwKCGRhbm1ha3VzGAEgAygLMhouZGFudW5pLmRhbm1ha3UudjEuRGFubWFrdSo9CgRNb2RlEgoKBk5vcm1hbBAAEgoKBkJvdHRvbRABEgcKA1RvcBACEgsKB1JldmVyc2UQAxIHCgNFeHQQBCopCgRQb29sEgcKA0RlZhAAEgcKA1N1YhABEgcKA0FkdhACEgYKAkl4EAMyXQoORGFubWFrdVNlcnZpY2USSwoHbGlzdERhbhIdLmRhbnVuaS5kYW5tYWt1LnYxLmxpc3REYW5SZXEaHy5kYW51bmkuZGFubWFrdS52MS5EYW5tYWt1UmVwbHkiAFAAYgZwcm90bzM", [file_google_protobuf_timestamp]);
16
+
17
+ /**
18
+ * @generated from message danuni.danmaku.v1.listDanReq
19
+ */
20
+ export type listDanReq = Message<"danuni.danmaku.v1.listDanReq"> & {
21
+ /**
22
+ * @generated from field: string ID = 1;
23
+ */
24
+ ID: string;
25
+
26
+ /**
27
+ * @generated from field: optional int32 seg = 2;
28
+ */
29
+ seg?: number;
30
+ };
31
+
32
+ /**
33
+ * Describes the message danuni.danmaku.v1.listDanReq.
34
+ * Use `create(listDanReqSchema)` to create a new message.
35
+ */
36
+ export const listDanReqSchema: GenMessage<listDanReq> = /*@__PURE__*/
37
+ messageDesc(file_danuni, 0);
16
38
 
17
39
  /**
18
40
  * @generated from message danuni.danmaku.v1.Danmaku
19
41
  */
20
42
  export type Danmaku = Message<"danuni.danmaku.v1.Danmaku"> & {
21
43
  /**
22
- * @generated from field: string FCID = 1;
44
+ * @generated from field: string SOID = 1;
23
45
  */
24
- FCID: string;
46
+ SOID: string;
25
47
 
26
48
  /**
27
49
  * @generated from field: string DMID = 2;
@@ -84,12 +106,7 @@ export type Danmaku = Message<"danuni.danmaku.v1.Danmaku"> & {
84
106
  platform: string;
85
107
 
86
108
  /**
87
- * @generated from field: optional string SPMO = 14;
88
- */
89
- SPMO?: string;
90
-
91
- /**
92
- * @generated from field: optional string extra = 15;
109
+ * @generated from field: optional string extra = 14;
93
110
  */
94
111
  extra?: string;
95
112
  };
@@ -99,7 +116,7 @@ export type Danmaku = Message<"danuni.danmaku.v1.Danmaku"> & {
99
116
  * Use `create(DanmakuSchema)` to create a new message.
100
117
  */
101
118
  export const DanmakuSchema: GenMessage<Danmaku> = /*@__PURE__*/
102
- messageDesc(file_danuni, 0);
119
+ messageDesc(file_danuni, 1);
103
120
 
104
121
  /**
105
122
  * @generated from message danuni.danmaku.v1.DanmakuReply
@@ -116,7 +133,7 @@ export type DanmakuReply = Message<"danuni.danmaku.v1.DanmakuReply"> & {
116
133
  * Use `create(DanmakuReplySchema)` to create a new message.
117
134
  */
118
135
  export const DanmakuReplySchema: GenMessage<DanmakuReply> = /*@__PURE__*/
119
- messageDesc(file_danuni, 1);
136
+ messageDesc(file_danuni, 2);
120
137
 
121
138
  /**
122
139
  * @generated from enum danuni.danmaku.v1.Mode
@@ -185,3 +202,18 @@ export enum Pool {
185
202
  export const PoolSchema: GenEnum<Pool> = /*@__PURE__*/
186
203
  enumDesc(file_danuni, 1);
187
204
 
205
+ /**
206
+ * @generated from service danuni.danmaku.v1.DanmakuService
207
+ */
208
+ export const DanmakuService: GenService<{
209
+ /**
210
+ * @generated from rpc danuni.danmaku.v1.DanmakuService.listDan
211
+ */
212
+ listDan: {
213
+ methodKind: "unary";
214
+ input: typeof listDanReqSchema;
215
+ output: typeof DanmakuReplySchema;
216
+ },
217
+ }> = /*@__PURE__*/
218
+ serviceDesc(file_danuni, 0);
219
+
@@ -4,6 +4,15 @@ package danuni.danmaku.v1;
4
4
 
5
5
  import public "google/protobuf/timestamp.proto";
6
6
 
7
+ service DanmakuService {
8
+ rpc listDan (listDanReq) returns (DanmakuReply) {}
9
+ }
10
+
11
+ message listDanReq {
12
+ string ID = 1;
13
+ optional int32 seg = 2;
14
+ }
15
+
7
16
  enum Mode {
8
17
  Normal = 0;
9
18
  Bottom = 1;
@@ -20,7 +29,7 @@ enum Pool {
20
29
  }
21
30
 
22
31
  message Danmaku {
23
- string FCID = 1;
32
+ string SOID = 1;
24
33
  string DMID = 2;
25
34
  int32 progress = 3;
26
35
  Mode mode = 4;
@@ -33,8 +42,7 @@ message Danmaku {
33
42
  Pool pool = 11;
34
43
  repeated string attr = 12;
35
44
  string platform = 13;
36
- optional string SPMO = 14;
37
- optional string extra = 15;
45
+ optional string extra = 14;
38
46
  }
39
47
 
40
48
  message DanmakuReply {
@@ -1,8 +1,8 @@
1
- //基于以下注释,根据vitest生成测试用例
2
1
  import { describe, expect, it } from 'vitest'
3
2
  import type { UniDMObj } from './dm-gen'
4
3
 
5
4
  import { UniDM, UniPool } from '..'
5
+ import { ExtraDanUniChapterType } from './dm-gen'
6
6
 
7
7
  const xml = `<i>
8
8
  <chatserver>chat.bilibili.com</chatserver>
@@ -18,6 +18,64 @@ const xml = `<i>
18
18
  <d p="13.499,1,25,16777215,1686301548,3,2848bf1c,1335553202649003264">不喜欢</d>
19
19
  </i>`
20
20
 
21
+ describe('弹幕降级', () => {
22
+ const dans = [
23
+ UniDM.create({
24
+ content: 'test',
25
+ extra: {
26
+ danuni: {
27
+ merge: {
28
+ count: 100,
29
+ duration: 10,
30
+ senders: [],
31
+ taolu_count: 100,
32
+ taolu_senders: [],
33
+ },
34
+ },
35
+ },
36
+ }),
37
+ UniDM.create({
38
+ platform: 'bili',
39
+ extra: {
40
+ danuni: { chapter: { type: ExtraDanUniChapterType.Cut, duration: 3 } },
41
+ },
42
+ }),
43
+ UniDM.create({
44
+ progress: 30,
45
+ extra: {
46
+ danuni: { chapter: { type: ExtraDanUniChapterType.OP, duration: 93 } },
47
+ },
48
+ }),
49
+ UniDM.create({
50
+ platform: 'bili',
51
+ extra: {
52
+ bili: {
53
+ mode: 7,
54
+ adv: '["0.355","0.27","0.8-0","0.6"," 真棒☺",0,0,"0.355",0,"500",0,0,"SimHei",1]',
55
+ },
56
+ },
57
+ }),
58
+ ]
59
+ it('danuni.merge', () => {
60
+ const d = dans[0].downgradeAdvcancedDan({ cleanExtra: true })
61
+ console.info(d)
62
+ expect(d.content).equal('test x100')
63
+ })
64
+ it('danuni.chapter', () => {
65
+ const d1 = dans[1].downgradeAdvcancedDan({ cleanExtra: true })
66
+ console.info(d1)
67
+ expect(d1.content).equal('[提示]bili源删减了3秒')
68
+ const d2 = dans[2].downgradeAdvcancedDan({ cleanExtra: true })
69
+ console.info(d2)
70
+ expect(d2.content).equal('[空降(片头)]02:03')
71
+ })
72
+ it('bili.adv', () => {
73
+ const d = dans[3].downgradeAdvcancedDan({ cleanExtra: true })
74
+ console.info(d)
75
+ expect(d.content).equal('[B站高级弹幕] 真棒☺')
76
+ })
77
+ })
78
+
21
79
  describe('其它', () => {
22
80
  const pool = UniPool.fromBiliXML(xml)
23
81
  it('比较(常规)', () => {
@@ -35,7 +93,7 @@ describe('其它', () => {
35
93
  })
36
94
  it('比较(extra)', () => {
37
95
  const commonSample = {
38
- FCID: 'test@du',
96
+ SOID: 'test@du',
39
97
  content: 'T Sample',
40
98
  extra: {
41
99
  danuni: {
@@ -43,6 +101,8 @@ describe('其它', () => {
43
101
  count: 1,
44
102
  duration: 0,
45
103
  senders: ['test@du'],
104
+ taolu_count: 1,
105
+ taolu_senders: ['test@du'],
46
106
  },
47
107
  },
48
108
  },