@dan-uni/dan-any 1.4.8 → 2.0.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.
Files changed (200) hide show
  1. package/README.md +87 -43
  2. package/dist/adapters.d.mts +2 -0
  3. package/dist/adapters.mjs +1 -0
  4. package/dist/chunk-0Lt9GpW0.mjs +1 -0
  5. package/dist/core/db/schema.d.mts +2 -0
  6. package/dist/core/db/schema.mjs +2 -0
  7. package/dist/core/db/schema.mjs.map +1 -0
  8. package/dist/core/db/utils.d.mts +1707 -0
  9. package/dist/core/db/utils.d.mts.map +1 -0
  10. package/dist/core/db/utils.mjs +1 -0
  11. package/dist/core-BSNwOgso.mjs +2 -0
  12. package/dist/core-BSNwOgso.mjs.map +1 -0
  13. package/dist/core.d.mts +2 -0
  14. package/dist/core.mjs +1 -0
  15. package/dist/db-DWWzkRBb.mjs +41 -0
  16. package/dist/db-DWWzkRBb.mjs.map +1 -0
  17. package/dist/dm-CBYaViIb.mjs +2 -0
  18. package/dist/dm-CBYaViIb.mjs.map +1 -0
  19. package/dist/dm-extra-DrAQCrFv.d.mts +135 -0
  20. package/dist/dm-extra-DrAQCrFv.d.mts.map +1 -0
  21. package/dist/index-5rcmHUF1.d.mts +6195 -0
  22. package/dist/index-5rcmHUF1.d.mts.map +1 -0
  23. package/dist/index.d.mts +4 -0
  24. package/dist/index.mjs +1 -0
  25. package/dist/isSame-Cdw0xkUV.mjs +2 -0
  26. package/dist/isSame-Cdw0xkUV.mjs.map +1 -0
  27. package/dist/plugins.d.mts +105 -0
  28. package/dist/plugins.d.mts.map +1 -0
  29. package/dist/plugins.mjs +2 -0
  30. package/dist/plugins.mjs.map +1 -0
  31. package/dist/schema-BuenbDx9.d.mts +1619 -0
  32. package/dist/schema-BuenbDx9.d.mts.map +1 -0
  33. package/dist/utils.d.mts +25 -0
  34. package/dist/utils.d.mts.map +1 -0
  35. package/dist/utils.mjs +2 -0
  36. package/dist/utils.mjs.map +1 -0
  37. package/package.json +64 -36
  38. package/.babelrc.json +0 -12
  39. package/buf.gen.yaml +0 -10
  40. package/buf.yaml +0 -12
  41. package/dist/browser/1~rslib-runtime.min.js +0 -49
  42. package/dist/browser/index.min.js +0 -13523
  43. package/dist/browser/index.min.js.LICENSE.txt +0 -17
  44. package/dist/browser/plugins/bili.min.js +0 -1
  45. package/dist/browser/plugins/index.min.js +0 -2
  46. package/dist/browser/plugins/stats.min.js +0 -10
  47. package/dist/browser/src/ass-gen/__tests__/canvas.test.d.ts +0 -1
  48. package/dist/browser/src/ass-gen/__tests__/generate.test.d.ts +0 -1
  49. package/dist/browser/src/ass-gen/ass/create.d.ts +0 -4
  50. package/dist/browser/src/ass-gen/ass/dialogue.d.ts +0 -16
  51. package/dist/browser/src/ass-gen/ass/event.d.ts +0 -2
  52. package/dist/browser/src/ass-gen/ass/info.d.ts +0 -8
  53. package/dist/browser/src/ass-gen/ass/raw.d.ts +0 -14
  54. package/dist/browser/src/ass-gen/ass/style.d.ts +0 -2
  55. package/dist/browser/src/ass-gen/config.d.ts +0 -2
  56. package/dist/browser/src/ass-gen/index.d.ts +0 -30
  57. package/dist/browser/src/ass-gen/types.d.ts +0 -71
  58. package/dist/browser/src/ass-gen/util/color.d.ts +0 -18
  59. package/dist/browser/src/ass-gen/util/danconvert.d.ts +0 -5
  60. package/dist/browser/src/ass-gen/util/index.d.ts +0 -4
  61. package/dist/browser/src/ass-gen/util/lang.d.ts +0 -3
  62. package/dist/browser/src/ass-gen/util/layout.d.ts +0 -4
  63. package/dist/browser/src/index.d.ts +0 -283
  64. package/dist/browser/src/index.test.d.ts +0 -1
  65. package/dist/browser/src/plugins/bili/dedupe.d.ts +0 -3
  66. package/dist/browser/src/plugins/bili/history-danmaku-fast-forward.d.ts +0 -18
  67. package/dist/browser/src/plugins/bili/index.d.ts +0 -2
  68. package/dist/browser/src/plugins/bili/index.test.d.ts +0 -1
  69. package/dist/browser/src/plugins/index.d.ts +0 -2
  70. package/dist/browser/src/plugins/stats/getLatestDan.d.ts +0 -6
  71. package/dist/browser/src/plugins/stats/index.d.ts +0 -1
  72. package/dist/browser/src/plugins/stats/index.test.d.ts +0 -1
  73. package/dist/browser/src/proto/gen/bilibili/community/service/dm/v1/dm_pb.d.ts +0 -3426
  74. package/dist/browser/src/proto/gen/danuni/danmaku/v1/danmaku_pb.d.ts +0 -176
  75. package/dist/browser/src/utils/dm-gen.d.ts +0 -309
  76. package/dist/browser/src/utils/dm-gen.test.d.ts +0 -1
  77. package/dist/browser/src/utils/fileParser.d.ts +0 -3
  78. package/dist/browser/src/utils/id-gen.d.ts +0 -50
  79. package/dist/browser/src/utils/platform.d.ts +0 -24
  80. package/dist/node/0~rslib-runtime.js +0 -23
  81. package/dist/node/index.js +0 -2099
  82. package/dist/node/plugins/bili.js +0 -1
  83. package/dist/node/plugins/index.js +0 -2
  84. package/dist/node/plugins/stats.js +0 -10
  85. package/dist/node/src/ass-gen/__tests__/canvas.test.d.ts +0 -1
  86. package/dist/node/src/ass-gen/__tests__/generate.test.d.ts +0 -1
  87. package/dist/node/src/ass-gen/ass/create.d.ts +0 -4
  88. package/dist/node/src/ass-gen/ass/dialogue.d.ts +0 -16
  89. package/dist/node/src/ass-gen/ass/event.d.ts +0 -2
  90. package/dist/node/src/ass-gen/ass/info.d.ts +0 -8
  91. package/dist/node/src/ass-gen/ass/raw.d.ts +0 -14
  92. package/dist/node/src/ass-gen/ass/style.d.ts +0 -2
  93. package/dist/node/src/ass-gen/config.d.ts +0 -2
  94. package/dist/node/src/ass-gen/index.d.ts +0 -30
  95. package/dist/node/src/ass-gen/types.d.ts +0 -71
  96. package/dist/node/src/ass-gen/util/color.d.ts +0 -18
  97. package/dist/node/src/ass-gen/util/danconvert.d.ts +0 -5
  98. package/dist/node/src/ass-gen/util/index.d.ts +0 -4
  99. package/dist/node/src/ass-gen/util/lang.d.ts +0 -3
  100. package/dist/node/src/ass-gen/util/layout.d.ts +0 -4
  101. package/dist/node/src/index.d.ts +0 -283
  102. package/dist/node/src/index.test.d.ts +0 -1
  103. package/dist/node/src/plugins/bili/dedupe.d.ts +0 -3
  104. package/dist/node/src/plugins/bili/history-danmaku-fast-forward.d.ts +0 -18
  105. package/dist/node/src/plugins/bili/index.d.ts +0 -2
  106. package/dist/node/src/plugins/bili/index.test.d.ts +0 -1
  107. package/dist/node/src/plugins/index.d.ts +0 -2
  108. package/dist/node/src/plugins/stats/getLatestDan.d.ts +0 -6
  109. package/dist/node/src/plugins/stats/index.d.ts +0 -1
  110. package/dist/node/src/plugins/stats/index.test.d.ts +0 -1
  111. package/dist/node/src/proto/gen/bilibili/community/service/dm/v1/dm_pb.d.ts +0 -3426
  112. package/dist/node/src/proto/gen/danuni/danmaku/v1/danmaku_pb.d.ts +0 -176
  113. package/dist/node/src/utils/dm-gen.d.ts +0 -309
  114. package/dist/node/src/utils/dm-gen.test.d.ts +0 -1
  115. package/dist/node/src/utils/fileParser.d.ts +0 -3
  116. package/dist/node/src/utils/id-gen.d.ts +0 -50
  117. package/dist/node/src/utils/platform.d.ts +0 -24
  118. package/dist/umd/index.umd.min.js +0 -32093
  119. package/dist/umd/index.umd.min.js.LICENSE.txt +0 -34
  120. package/dist/umd/plugins/bili.umd.min.js +0 -32004
  121. package/dist/umd/plugins/bili.umd.min.js.LICENSE.txt +0 -34
  122. package/dist/umd/plugins/index.umd.min.js +0 -32020
  123. package/dist/umd/plugins/index.umd.min.js.LICENSE.txt +0 -34
  124. package/dist/umd/plugins/stats.umd.min.js +0 -39
  125. package/dist/umd/src/ass-gen/__tests__/canvas.test.d.ts +0 -1
  126. package/dist/umd/src/ass-gen/__tests__/generate.test.d.ts +0 -1
  127. package/dist/umd/src/ass-gen/ass/create.d.ts +0 -4
  128. package/dist/umd/src/ass-gen/ass/dialogue.d.ts +0 -16
  129. package/dist/umd/src/ass-gen/ass/event.d.ts +0 -2
  130. package/dist/umd/src/ass-gen/ass/info.d.ts +0 -8
  131. package/dist/umd/src/ass-gen/ass/raw.d.ts +0 -14
  132. package/dist/umd/src/ass-gen/ass/style.d.ts +0 -2
  133. package/dist/umd/src/ass-gen/config.d.ts +0 -2
  134. package/dist/umd/src/ass-gen/index.d.ts +0 -30
  135. package/dist/umd/src/ass-gen/types.d.ts +0 -71
  136. package/dist/umd/src/ass-gen/util/color.d.ts +0 -18
  137. package/dist/umd/src/ass-gen/util/danconvert.d.ts +0 -5
  138. package/dist/umd/src/ass-gen/util/index.d.ts +0 -4
  139. package/dist/umd/src/ass-gen/util/lang.d.ts +0 -3
  140. package/dist/umd/src/ass-gen/util/layout.d.ts +0 -4
  141. package/dist/umd/src/index.d.ts +0 -283
  142. package/dist/umd/src/index.test.d.ts +0 -1
  143. package/dist/umd/src/plugins/bili/dedupe.d.ts +0 -3
  144. package/dist/umd/src/plugins/bili/history-danmaku-fast-forward.d.ts +0 -18
  145. package/dist/umd/src/plugins/bili/index.d.ts +0 -2
  146. package/dist/umd/src/plugins/bili/index.test.d.ts +0 -1
  147. package/dist/umd/src/plugins/index.d.ts +0 -2
  148. package/dist/umd/src/plugins/stats/getLatestDan.d.ts +0 -6
  149. package/dist/umd/src/plugins/stats/index.d.ts +0 -1
  150. package/dist/umd/src/plugins/stats/index.test.d.ts +0 -1
  151. package/dist/umd/src/proto/gen/bilibili/community/service/dm/v1/dm_pb.d.ts +0 -3426
  152. package/dist/umd/src/proto/gen/danuni/danmaku/v1/danmaku_pb.d.ts +0 -176
  153. package/dist/umd/src/utils/dm-gen.d.ts +0 -309
  154. package/dist/umd/src/utils/dm-gen.test.d.ts +0 -1
  155. package/dist/umd/src/utils/fileParser.d.ts +0 -3
  156. package/dist/umd/src/utils/id-gen.d.ts +0 -50
  157. package/dist/umd/src/utils/platform.d.ts +0 -24
  158. package/plugins/package.json +0 -6
  159. package/rslib.config.ts +0 -101
  160. package/src/ass-gen/__tests__/898651903.xml +0 -1619
  161. package/src/ass-gen/__tests__/898651903.xml.ass +0 -1516
  162. package/src/ass-gen/__tests__/canvas.test.ts +0 -15
  163. package/src/ass-gen/__tests__/generate.test.ts +0 -26
  164. package/src/ass-gen/ass/create.ts +0 -37
  165. package/src/ass-gen/ass/dialogue.ts +0 -90
  166. package/src/ass-gen/ass/event.ts +0 -57
  167. package/src/ass-gen/ass/info.ts +0 -27
  168. package/src/ass-gen/ass/raw.ts +0 -78
  169. package/src/ass-gen/ass/style.ts +0 -66
  170. package/src/ass-gen/config.ts +0 -45
  171. package/src/ass-gen/index.ts +0 -73
  172. package/src/ass-gen/types.ts +0 -76
  173. package/src/ass-gen/util/color.ts +0 -55
  174. package/src/ass-gen/util/danconvert.ts +0 -43
  175. package/src/ass-gen/util/index.ts +0 -10
  176. package/src/ass-gen/util/lang.ts +0 -35
  177. package/src/ass-gen/util/layout.ts +0 -242
  178. package/src/index.test.ts +0 -157
  179. package/src/index.ts +0 -1144
  180. package/src/plugins/bili/README.md +0 -87
  181. package/src/plugins/bili/dedupe.ts +0 -29
  182. package/src/plugins/bili/history-danmaku-fast-forward.ts +0 -86
  183. package/src/plugins/bili/index.test.ts +0 -129
  184. package/src/plugins/bili/index.ts +0 -2
  185. package/src/plugins/index.ts +0 -2
  186. package/src/plugins/stats/README.md +0 -44
  187. package/src/plugins/stats/getLatestDan.ts +0 -13
  188. package/src/plugins/stats/index.test.ts +0 -39
  189. package/src/plugins/stats/index.ts +0 -1
  190. package/src/proto/gen/bilibili/community/service/dm/v1/dm_pb.ts +0 -4072
  191. package/src/proto/gen/danuni/danmaku/v1/danmaku_pb.ts +0 -223
  192. package/src/proto/src/bilibili/community/service/dm/v1/dm.proto +0 -1095
  193. package/src/proto/src/danuni/danmaku/v1/danmaku.proto +0 -52
  194. package/src/utils/dm-gen.test.ts +0 -129
  195. package/src/utils/dm-gen.ts +0 -1082
  196. package/src/utils/fileParser.ts +0 -37
  197. package/src/utils/id-gen.ts +0 -73
  198. package/src/utils/platform.ts +0 -38
  199. package/tsconfig.json +0 -108
  200. package/types/tsconfig.tsbuildinfo +0 -1
@@ -1,1082 +0,0 @@
1
- import { Expose, plainToInstance } from 'class-transformer'
2
- import {
3
- IsDate,
4
- IsEmail,
5
- isEmail,
6
- IsEnum,
7
- IsInt,
8
- IsNotEmpty,
9
- IsNumber,
10
- IsOptional,
11
- IsString,
12
- Max,
13
- Min,
14
- validateOrReject,
15
- } from 'class-validator'
16
- import TimeFormat from 'hh-mm-ss'
17
- import JSONbig from 'json-bigint'
18
- import type { DM_JSON_BiliCommandGrpc } from '..'
19
- import type { PlatformDanmakuSource } from './platform'
20
-
21
- import { createDMID, DMIDGenerator, UniID as ID } from './id-gen'
22
- import {
23
- PlatformDanmakuOnlySource,
24
- PlatformDanmakuSources,
25
- PlatformVideoSource,
26
- } from './platform'
27
-
28
- const JSON = JSONbig({ useNativeBigInt: true })
29
-
30
- function cleanEmptyObjects(obj: object): object {
31
- if (obj === null || typeof obj !== 'object') {
32
- return obj
33
- }
34
- if (Array.isArray(obj)) {
35
- return obj
36
- }
37
- const cleaned: any = {}
38
- for (const [key, value] of Object.entries(obj)) {
39
- const cleanedValue = cleanEmptyObjects(value)
40
- if (
41
- cleanedValue !== undefined &&
42
- (typeof cleanedValue !== 'object' ||
43
- Object.keys(cleanedValue).length !== 0)
44
- ) {
45
- cleaned[key] = cleanedValue
46
- }
47
- }
48
- return Object.keys(cleaned).length > 0 ? cleaned : {}
49
- }
50
-
51
- class SetBin {
52
- constructor(public bin: number) {}
53
- set1(bit: number) {
54
- this.bin |= 1 << bit
55
- }
56
- set0(bit: number) {
57
- this.bin &= ~(1 << bit)
58
- }
59
- }
60
-
61
- /**
62
- * 获得数字的二进制,每位以boolean(true/false)表示1/0,从低位向高位
63
- * @param number 任意进制数字
64
- */
65
- const toBits = (number: number) => {
66
- // 低速方案
67
- // return [...number.toString(2)].map(Number)
68
- // 高速方案,位运算允许范围内更快
69
- const bits: boolean[] = []
70
- do {
71
- bits.unshift(!!(number & 1)) // boolean[]
72
- // bits.unshift(number & 1) // (0|1)[]
73
- number >>= 1
74
- } while (number)
75
- return bits.toReversed()
76
- }
77
-
78
- export enum DMAttr {
79
- Protect = 'Protect',
80
- FromLive = 'FromLive',
81
- HighLike = 'HighLike',
82
- Compatible = 'Compatible', // 由dan-any进行过兼容处理的弹幕,可能丢失部分信息
83
- Reported = 'Reported', // 在DanUni上被多人举报过的弹幕
84
- Unchecked = 'Unchecked', // 在DanUni上未被审核过的弹幕
85
- HasEvent = 'HasEvent', // 该弹幕当前在DanUni上存在事件(如点赞/举报等)
86
- Hide = 'Hide', // 由于其它原因需要隐藏的弹幕(建议在server端不返回该类弹幕)
87
- }
88
- const DMAttrUtils = {
89
- fromBin(bin: number = 0, format?: PlatformDanmakuSource) {
90
- const array = toBits(bin)
91
- const attr: DMAttr[] = []
92
- if (format === 'bili') {
93
- if (array[0]) attr.push(DMAttr.Protect)
94
- if (array[1]) attr.push(DMAttr.FromLive)
95
- if (array[2]) attr.push(DMAttr.HighLike)
96
- }
97
- return attr
98
- },
99
- toBin(
100
- attr: DMAttr[] = [],
101
- /**
102
- * 对于二进制格式的读取,应该分别读取各位,
103
- * 但由于不知道B站及其它使用该参数程序的读取逻辑,
104
- * 所以单独提供 bili 格式
105
- */
106
- format?: PlatformDanmakuSource,
107
- ) {
108
- const bin = new SetBin(0)
109
- if (format === 'bili') {
110
- if (attr.includes(DMAttr.Protect)) bin.set1(0)
111
- if (attr.includes(DMAttr.FromLive)) bin.set1(1)
112
- if (attr.includes(DMAttr.HighLike)) bin.set1(2)
113
- }
114
- return bin.bin
115
- },
116
- }
117
- // class DMAttr {
118
- // constructor(
119
- // /**
120
- // * 保护
121
- // */
122
- // public protect: boolean = false,
123
- // /**
124
- // * 直播
125
- // */
126
- // public live: boolean = false,
127
- // /**
128
- // * 高赞
129
- // */
130
- // public highpraise: boolean = false,
131
- // ) {}
132
- // toBin(
133
- // /**
134
- // * 对于二进制格式的读取,应该分别读取各位,
135
- // * 但由于不知道B站及其它使用该参数程序的读取逻辑,
136
- // * 所以单独提供 bili 格式
137
- // */
138
- // format?: platfrom,
139
- // ) {
140
- // const bin = new SetBin(0)
141
- // if (this.protect) bin.set1(0)
142
- // if (this.live) bin.set1(1)
143
- // if (this.highpraise) bin.set1(2)
144
- // if (format === 'bili') return bin.bin
145
- // return bin.bin
146
- // }
147
- // static fromBin(bin: number = 0, format?: platfrom) {
148
- // const array = toBits(bin)
149
- // if (format === 'bili') {
150
- // return new DMAttr(array[0], array[1], array[2])
151
- // } else {
152
- // return new DMAttr(array[0], array[1], array[2])
153
- // }
154
- // }
155
- // }
156
-
157
- interface DMBili {
158
- id: bigint // xml 7
159
- progress: number // xml 0 ; xml s, protobuf ms
160
- mode: number // xml 1
161
- fontsize: number // xml 2
162
- color: number // xml 3
163
- mid?: bigint // 仅创作中心源
164
- midHash: string // xml 6
165
- /**
166
- * 特殊类型解析:
167
- * - [ohh] : /oh{2,}/gi
168
- * - [前方高能]
169
- * - [...] (JS数组) : 高级弹幕
170
- */
171
- content: string // xml content
172
- ctime: bigint // xml 4
173
- pool: number // xml 5
174
- weight?: number // xml 8
175
- action?: string
176
- idStr?: string
177
- attr?: number
178
- animation?: string
179
- extra?: string
180
- colorful?: number
181
- type?: number
182
- oid?: bigint
183
- }
184
- interface DMBiliCommand extends DM_JSON_BiliCommandGrpc {}
185
- interface DMDplayer {
186
- /**
187
- * 进度(秒)
188
- */
189
- progress: number
190
- mode: number
191
- color: number
192
- midHash: string
193
- content: string
194
- }
195
- interface DMArtplayer {
196
- /**
197
- * 进度(秒)
198
- */
199
- progress: number
200
- mode: number
201
- color: number
202
- content: string
203
- border?: boolean
204
- style?: object
205
- }
206
- interface DMDDPlay {
207
- cid: bigint
208
- /**
209
- * content
210
- */
211
- m: string
212
- /**
213
- * p[0]
214
- */
215
- progress: number
216
- /**
217
- * p[1]
218
- */
219
- mode: number
220
- /**
221
- * p[2]
222
- */
223
- color: number
224
- /**
225
- * p[3]
226
- */
227
- uid: string
228
- }
229
-
230
- export interface Extra {
231
- artplayer?: ExtraArtplayer
232
- bili?: ExtraBili
233
- danuni?: ExtraDanUni
234
- }
235
- interface ExtraArtplayer {
236
- style?: object
237
- border?: boolean
238
- }
239
- interface ExtraBili {
240
- mode?: number //原弹幕类型
241
- pool?: number //原弹幕池
242
- dmid?: bigint //原弹幕ID
243
- attr?: number //原弹幕属性
244
- mid?: bigint //发送者mid(仅创作中心源、command弹幕)
245
- adv?: string
246
- code?: string
247
- bas?: string
248
- command?: DMBiliCommand
249
- }
250
- export interface ExtraDanUni {
251
- chapter?: ExtraDanUniChapter
252
- merge?: ExtraDanUniMerge
253
- }
254
- export interface ExtraDanUniChapter {
255
- // seg: {
256
- // st: number //开始时刻
257
- // } //起止时间(ms)
258
- duration: number //持续时间
259
- type: ExtraDanUniChapterType
260
- // action: ExtraDanUniChapterAction
261
- }
262
- export interface ExtraDanUniMerge {
263
- duration: number //持续时间(重复内容第一次出现时间开始到合并了的弹幕中最后一次出现的时间)
264
- count: number //重复次数
265
- senders: string[] //发送者
266
- taolu_count: number //类似弹幕数量
267
- taolu_senders: string[] //类似弹幕发送者
268
- }
269
- export enum ExtraDanUniChapterType {
270
- Chapter = 'ch', //其它片段(用于标记章节)
271
- Review = 'rev', //回顾
272
- OP = 'op', //片头
273
- Intermission = 'int', //中场
274
- ED = 'ed', //片尾
275
- Preview = 'prvw', //预告
276
- Cut = 'cut', //删减(删减版中提供删减说明,提供开始位置、长度)
277
- Duplicate = 'dup', //补档(完整版中指明其它平台中删减位置)
278
- AdBiz = 'biz', //商业广告
279
- AdUnpaid = 'promo', //推广(无偿/公益)广告
280
- }
281
- const ExtraDanUniChapterTypeDict = {
282
- chs: {
283
- ch: '其它片段',
284
- rev: '回顾',
285
- op: '片头',
286
- int: '中场',
287
- ed: '片尾',
288
- prvw: '预告',
289
- cut: '删减',
290
- dup: '补档',
291
- biz: '商业广告',
292
- promo: '推广',
293
- },
294
- }
295
- export enum ExtraDanUniChapterAction {
296
- Disabled = -1,
297
- ShowOverlay,
298
- ManualSkip,
299
- AutoSkip,
300
- }
301
-
302
- export enum Modes {
303
- Normal,
304
- Bottom,
305
- Top,
306
- Reverse, //逆向弹幕
307
- Ext, //需要读取extra的弹幕,用于兼容bili等复杂弹幕
308
- }
309
- export enum Pools {
310
- Def, //默认池
311
- Sub, //重要池,建议强制加载,含字幕、科普、空降等
312
- Adv, //高级弹幕专用池,均需读取extra
313
- Ix, //互动池
314
- }
315
-
316
- export type ctime = string | number | bigint | Date
317
- // enum ctimeFmt {
318
- // bigintStr = 'bigintStr',
319
- // dateObj = 'dateObj',
320
- // dateStr = 'dateStr',
321
- // }
322
-
323
- export interface UniDMObj {
324
- SOID: string
325
- progress: number
326
- mode: Modes
327
- fontsize: number
328
- color: number
329
- senderID: string
330
- content: string
331
- ctime: Date
332
- weight: number
333
- pool: Pools
334
- attr: DMAttr[]
335
- platform: PlatformDanmakuSource | string
336
- extra: string | Extra
337
- extraStr: string
338
- DMID: string
339
- }
340
-
341
- interface Options {
342
- dmid?: boolean | number | DMIDGenerator
343
- }
344
-
345
- export class UniDM {
346
- /**
347
- * 资源ID
348
- * @description 由某一danuni服务确定的某一剧集下不同资源(不同视频站/字幕组具有细节差异)的ID
349
- */
350
- @IsEmail({ require_tld: false })
351
- @IsString()
352
- @IsNotEmpty()
353
- @Expose()
354
- public SOID: string = ID.fromNull().toString()
355
- /**
356
- * 弹幕出现位置(单位s;精度为ms,即保留三位小数)
357
- */
358
- @Min(0)
359
- @IsNumber()
360
- @IsNotEmpty()
361
- @Expose()
362
- public progress: number = 0
363
- /**
364
- * 弹幕类型
365
- */
366
- @IsEnum(Modes)
367
- @IsNotEmpty()
368
- @Expose()
369
- public mode: Modes = Modes.Normal
370
- /**
371
- * 字号
372
- * @default 25
373
- * - 12
374
- * - 16
375
- * - 18:小
376
- * - 25:标准
377
- * - 36:大
378
- * - 45
379
- * - 64
380
- */
381
- @Max(64)
382
- @Min(12)
383
- @IsNumber()
384
- @IsNotEmpty()
385
- @Expose()
386
- public fontsize: number = 25
387
- /**
388
- * 颜色
389
- * @description 为DEC值(十进制RGB888值),默认白色
390
- * @default 16777215
391
- */
392
- @IsNumber()
393
- @IsNotEmpty()
394
- @Expose()
395
- public color: number = 16777215
396
- /**
397
- * 发送者 senderID
398
- */
399
- @IsEmail({ require_tld: false })
400
- @IsString()
401
- @IsNotEmpty()
402
- @Expose()
403
- public senderID: string = ID.fromNull().toString()
404
- /**
405
- * 正文
406
- */
407
- @IsString()
408
- @IsNotEmpty()
409
- @Expose()
410
- public content: string = ''
411
- /**
412
- * 发送时间
413
- */
414
- @IsDate()
415
- @IsNotEmpty()
416
- @Expose()
417
- public ctime: Date = new Date()
418
- /**
419
- * 权重 用于屏蔽等级 区间:[0,11]
420
- * @description 参考B站,源弹幕有该参数则直接利用,
421
- * 本实现默认取5,再经过ruleset匹配加减分数
422
- * @description 为0时表示暂时未计算权重
423
- */
424
- @Max(11)
425
- @Min(0)
426
- @IsInt()
427
- @IsNotEmpty()
428
- @Expose()
429
- public weight: number = 0
430
- /**
431
- * 弹幕池 0:普通池 1:字幕池 2:特殊池(代码/BAS弹幕) 3:互动池(互动弹幕中选择投票快速发送的弹幕)
432
- */
433
- @IsEnum(Pools)
434
- @IsNotEmpty()
435
- @Expose()
436
- public pool: Pools = Pools.Def
437
- /**
438
- * 弹幕属性位(bin求AND)
439
- * bit0:保护 bit1:直播 bit2:高赞
440
- */
441
- @IsEnum(DMAttr, { each: true })
442
- @IsNotEmpty()
443
- @Expose()
444
- public attr: DMAttr[] = []
445
- /**
446
- * 初始来源平台
447
- * `danuni`与任意空值(可隐式转换为false的值)等价
448
- */
449
- @IsString()
450
- @IsOptional()
451
- @Expose()
452
- public platform?: PlatformDanmakuSource | string
453
- /**
454
- * 弹幕原始数据(不推荐使用)
455
- * @description 适用于无法解析的B站代码弹幕、Artplayer弹幕样式等
456
- * @description 初步约定:
457
- * - Artplayer: style不为空时,将其JSON.stringify()存入
458
- */
459
- @IsString()
460
- @IsOptional()
461
- @Expose()
462
- public extraStr?: string
463
- @IsString()
464
- @IsOptional()
465
- @Expose()
466
- public DMID?: string
467
- private options: Options = { dmid: createDMID }
468
- @Expose()
469
- init(options?: Options) {
470
- this.options = options || this.options
471
- const def = new UniDM()
472
-
473
- if (this.options.dmid === undefined || this.options.dmid === true)
474
- this.options.dmid = createDMID
475
-
476
- this.content = String(this.content)
477
- this.ctime = UniDM.transCtime(this.ctime)
478
-
479
- if (!this.SOID) this.SOID = def.SOID
480
- if (!this.progress) this.progress = def.progress
481
- if (!this.mode) this.mode = def.mode
482
- if (!this.fontsize) this.fontsize = def.fontsize
483
- if (!this.color) this.color = def.color
484
- if (!this.senderID) this.senderID = def.senderID
485
- if (!this.content) this.content = def.content
486
- if (!this.ctime) this.ctime = def.ctime
487
- if (!this.weight) this.weight = def.weight
488
- if (!this.pool) this.pool = def.pool
489
- if (!this.attr) this.attr = def.attr
490
-
491
- if (!this.DMID && this.options.dmid !== false) this.DMID = this.toDMID()
492
- this.progress = Number.parseFloat(this.progress.toFixed(3))
493
- if (this.extraStr)
494
- this.extraStr = JSON.stringify(
495
- cleanEmptyObjects(JSON.parse(this.extraStr)),
496
- )
497
- if (this.extraStr === '{}') this.extraStr = undefined
498
- else if (this.mode !== Modes.Ext) {
499
- const checkExtraBili = (obj?: ExtraBili) =>
500
- obj
501
- ? (['adv', 'bas', 'code', 'command'] as (keyof ExtraBili)[]).some(
502
- (k) => obj[k],
503
- )
504
- : false
505
- if (
506
- this.extra.artplayer ||
507
- this.extra.danuni?.chapter ||
508
- checkExtraBili(this.extra.bili)
509
- )
510
- this.mode = Modes.Ext
511
- }
512
- return this
513
- }
514
- @Expose()
515
- async validate() {
516
- return validateOrReject(this)
517
- }
518
- static create(pjson?: Partial<UniDMObj>, options?: Options) {
519
- return pjson
520
- ? plainToInstance(
521
- UniDM,
522
- pjson.extra
523
- ? {
524
- ...pjson,
525
- extraStr: pjson.extra
526
- ? JSON.stringify(pjson.extra)
527
- : pjson.extraStr,
528
- }
529
- : pjson,
530
- { excludeExtraneousValues: true },
531
- ).init(options)
532
- : new UniDM()
533
- }
534
- @Expose()
535
- get extra(): Extra {
536
- const extra = JSON.parse(this.extraStr || '{}')
537
- // this.extraStr = JSON.stringify(cleanEmptyObjects(extra))
538
- return extra
539
- // return cleanEmptyObjects(extra) as Extra
540
- }
541
- @Expose()
542
- get isFrom3rdPlatform() {
543
- if (
544
- this.platform &&
545
- PlatformDanmakuSources.includes(this.platform as PlatformDanmakuSource)
546
- )
547
- return true
548
- else return false
549
- }
550
- /**
551
- * 弹幕id
552
- * @description sha3-256(content+senderID+ctime)截取前8位
553
- * @description 同一SOID下唯一
554
- */
555
- @Expose()
556
- toDMID() {
557
- if (this.options.dmid === false) return
558
- else if (this.options.dmid === true) return createDMID(this)
559
- else if (typeof this.options.dmid === 'number')
560
- return createDMID(this, this.options.dmid)
561
- return this.options.dmid!(this)
562
- }
563
- @Expose()
564
- isSameAs(dan: UniDM, options?: { skipDanuniMerge?: boolean }): boolean {
565
- // 引用相同直接返回
566
- if (this === dan) return true
567
- // 不支持比较高级弹幕
568
- if (this.mode === Modes.Ext || dan.mode === Modes.Ext) return false
569
- // 合并过视为不同,防止存在合并完成弹幕后再次合并造成计数错误
570
- if (
571
- !options?.skipDanuniMerge &&
572
- (this.extra.danuni?.merge || dan.extra.danuni?.merge)
573
- )
574
- return false
575
- // 如果是bili弹幕,则以dmid判断是否相同
576
- if (this.extra.bili?.dmid && dan.extra.bili?.dmid) {
577
- // 当来源不同(标准源/创作中心源)时,视为不同弹幕
578
- if (
579
- (this.extra.bili.dmid && !dan.extra.bili.dmid) ||
580
- (!this.extra.bili.dmid && dan.extra.bili.dmid)
581
- )
582
- return false
583
- if (this.extra.bili.dmid === dan.extra.bili.dmid) return true
584
- else return false
585
- }
586
- // 如果是artplayer弹幕,需额外比较extra项目
587
- if (
588
- (this.extra.artplayer && !dan.extra.artplayer) ||
589
- (!this.extra.artplayer && dan.extra.artplayer)
590
- )
591
- return false
592
- else if (
593
- this.extra.artplayer &&
594
- dan.extra.artplayer &&
595
- (this.extra.artplayer.border !== dan.extra.artplayer.border ||
596
- JSON.stringify(this.extra.artplayer.style) !==
597
- JSON.stringify(dan.extra.artplayer.style))
598
- )
599
- return false
600
- const isSame = (k: keyof UniDMObj) => this[k] === dan[k]
601
- const checks = (
602
- [
603
- 'SOID',
604
- 'content',
605
- 'mode',
606
- 'pool',
607
- 'platform',
608
- ] satisfies (keyof UniDMObj)[]
609
- ).every((k) => isSame(k))
610
- // 忽略使用了extra字段却不在mode里标记的弹幕
611
- return checks
612
- }
613
- @Expose()
614
- minify() {
615
- type UObj = Partial<UniDMObj> & Pick<UniDMObj, 'SOID'>
616
- const def = new UniDM()
617
- const result: UObj = { SOID: this.SOID }
618
- if (this.progress !== def.progress) result.progress = this.progress
619
- if (this.mode !== def.mode) result.mode = this.mode
620
- if (this.fontsize !== def.fontsize) result.fontsize = this.fontsize
621
- if (this.color !== def.color) result.color = this.color
622
- if (this.senderID !== def.senderID) result.senderID = this.senderID
623
- if (this.content !== def.content) result.content = this.content
624
- if (this.weight !== def.weight) result.weight = this.weight
625
- if (this.pool !== def.pool) result.pool = this.pool
626
- if (this.attr.length > 0) result.attr = this.attr
627
- if (this.platform !== undefined) result.platform = this.platform
628
- if (this.extraStr && this.extraStr !== '{}') result.extraStr = this.extraStr
629
- if (this.DMID !== undefined && this.options.dmid) result.DMID = this.DMID
630
- return result
631
- }
632
- @Expose()
633
- downgradeAdvcancedDan({
634
- include,
635
- exclude,
636
- cleanExtra = false,
637
- }: {
638
- include?: (keyof Extra)[]
639
- exclude?: (keyof Extra)[]
640
- cleanExtra?: boolean
641
- } = {}) {
642
- if (this.extra) {
643
- if (!include) include = []
644
- if (!exclude) exclude = []
645
- const check = (k: keyof Extra) =>
646
- include?.includes(k) || !exclude?.includes(k)
647
- // TODO 分别对 mode7/8/9 command artplayer等正常播放器无法绘制的弹幕做降级处理
648
- const clone = UniDM.create(this)
649
- clone.mode = Modes.Top
650
- if (check('danuni') && clone.extra.danuni) {
651
- const danuni = clone.extra.danuni
652
- if (danuni.merge) {
653
- const merge = danuni.merge
654
- clone.content = `${this.content} x${merge.count}`
655
- } else if (danuni.chapter) {
656
- const chapter = danuni.chapter
657
- if (chapter.type === ExtraDanUniChapterType.Cut)
658
- clone.content = `[提示]${clone.platform}源${ExtraDanUniChapterTypeDict.chs[chapter.type]}了${chapter.duration}秒`
659
- else if (chapter.type === ExtraDanUniChapterType.Duplicate)
660
- clone.content = `[提示(${ExtraDanUniChapterTypeDict.chs[chapter.type]})]${clone.platform}源-${chapter.duration}秒`
661
- else
662
- clone.content = `[空降(${ExtraDanUniChapterTypeDict.chs[chapter.type]})]${TimeFormat.fromS(clone.progress + chapter.duration)}`
663
- }
664
- } else if (check('bili') && clone.extra.bili) {
665
- const bili = clone.extra.bili
666
- if (bili.mode === 7 && bili.adv) {
667
- clone.content = `[B站高级弹幕]${JSON.parse(bili.adv)[4] || ''}`
668
- } else if (bili.command) {
669
- const command = bili.command
670
- clone.content = `[B站指令弹幕]${command.content}`
671
- clone.fontsize = 36
672
- }
673
- }
674
- clone.senderID = 'compat[bot]@dan-any'
675
- clone.attr.push(DMAttr.Compatible)
676
- if (cleanExtra) clone.extraStr = undefined
677
- return clone
678
- } else return this
679
- }
680
- /**
681
- * 将各种类型的时间进行格式化
682
- * @param oriCtime
683
- * @param tsUnit 当`oriCtime`为数字类型表时间戳时的单位;
684
- * 为 毫秒(ms)/秒(s)
685
- * @returns {Date} Date格式时间
686
- */
687
- static transCtime(oriCtime: ctime, tsUnit?: 'ms' | 's'): Date {
688
- function isMsTs(ts: number | bigint) {
689
- if (tsUnit === 'ms') return true
690
- else if (tsUnit === 's') return false
691
- else return ts < 100000000
692
- }
693
- if (typeof oriCtime === 'number' || typeof oriCtime === 'bigint')
694
- if (isMsTs(oriCtime)) return new Date(Number(oriCtime))
695
- else return new Date(Number(oriCtime) * 1000)
696
- else if (typeof oriCtime === 'string') {
697
- if (/^\d+n$/.test(oriCtime))
698
- return new Date(Number(oriCtime.slice(0, -1)))
699
- // else return Date.parse(oriCtime)
700
- else return new Date(oriCtime)
701
- }
702
- // } else if (typeof oriCtime === 'object') return BigInt(oriCtime.getTime())
703
- else return oriCtime // BigInt(Date.now())
704
- }
705
- // static reviveCtime(ctime: bigint, fmt: ctimeFmt = ctimeFmt.bigintStr) {
706
- // if (fmt === ctimeFmt.dateObj || fmt === ctimeFmt.dateStr) {
707
- // const date = new Date(Number(ctime))
708
- // if (fmt === ctimeFmt.dateStr) return date.toString()
709
- // else return date
710
- // } else return ctime.toString() + 'n'
711
- // }
712
- static transMode(
713
- oriMode: number,
714
- fmt: 'bili' | 'dplayer' | 'artplayer' | 'ddplay',
715
- ): Modes {
716
- let mode = Modes.Normal
717
- switch (fmt) {
718
- case 'bili':
719
- // 类型 1 2 3:普通弹幕 4:底部弹幕 5:顶部弹幕 6:逆向弹幕 7:高级弹幕 8:代码弹幕 9:BAS弹幕(pool必须为2)
720
- switch (oriMode) {
721
- case 4:
722
- mode = Modes.Bottom
723
- break
724
- case 5:
725
- mode = Modes.Top
726
- break
727
- case 6:
728
- mode = Modes.Reverse
729
- break
730
- case 7:
731
- mode = Modes.Ext
732
- break
733
- case 8:
734
- mode = Modes.Ext
735
- break
736
- case 9:
737
- mode = Modes.Ext
738
- break
739
- }
740
- break
741
-
742
- case 'dplayer':
743
- if (oriMode === 1) mode = Modes.Top
744
- else if (oriMode === 2) mode = Modes.Bottom
745
- break
746
-
747
- case 'artplayer':
748
- if (oriMode === 1) mode = Modes.Top
749
- else if (oriMode === 2) mode = Modes.Bottom
750
- break
751
-
752
- case 'ddplay':
753
- // 弹幕模式:1-普通弹幕,4-底部弹幕,5-顶部弹幕
754
- // 其适配为bili格式子集
755
- mode = this.transMode(oriMode, 'bili')
756
- break
757
-
758
- default:
759
- mode = Modes.Normal
760
- break
761
- }
762
- return mode
763
- }
764
- static parseBiliSingle(p: string, c: string) {
765
- const p_arr = p.split(',')
766
- return {
767
- content: c,
768
- progress: Number.parseFloat(p_arr[0]),
769
- mode: Number.parseInt(p_arr[1]),
770
- fontsize: Number.parseInt(p_arr[2]),
771
- color: Number.parseInt(p_arr[3]),
772
- ctime: BigInt(p_arr[4]),
773
- pool: Number.parseInt(p_arr[5]),
774
- midHash: p_arr[6],
775
- id: BigInt(p_arr[7]),
776
- weight: Number.parseInt(p_arr[8]),
777
- }
778
- }
779
- static fromBili(
780
- args: DMBili,
781
- cid?: bigint,
782
- options?: Options,
783
- recSOID?: string,
784
- ) {
785
- interface TExtra extends Extra {
786
- bili: ExtraBili
787
- }
788
- if (args.oid && !cid) cid = args.oid
789
- const SOID =
790
- recSOID || `def_${PlatformVideoSource.Bilibili}+${ID.fromBili({ cid })}`
791
- const senderID = isEmail(args.midHash, { require_tld: false })
792
- ? args.midHash
793
- : ID.fromBili({ midHash: args.midHash })
794
- let mode: Modes
795
- const pool = args.pool //暂时不做处理,兼容bili的pool格式
796
- const extra: TExtra = {
797
- bili: {
798
- mode: args.mode,
799
- pool: args.pool,
800
- dmid: args.id,
801
- attr: args.attr,
802
- mid: args.mid,
803
- },
804
- }
805
- //重复 transMode ,但此处有关于extra的额外处理
806
- switch (args.mode) {
807
- case 4:
808
- mode = Modes.Bottom
809
- break
810
- case 5:
811
- mode = Modes.Top
812
- break
813
- case 6:
814
- mode = Modes.Reverse
815
- break
816
- case 7:
817
- mode = Modes.Ext
818
- extra.bili.adv = args.content
819
- break
820
- case 8:
821
- mode = Modes.Ext
822
- extra.bili.code = args.content
823
- break
824
- case 9:
825
- mode = Modes.Ext
826
- extra.bili.bas = args.content
827
- break
828
-
829
- default:
830
- mode = Modes.Normal
831
- break
832
- }
833
- return this.create(
834
- {
835
- ...args,
836
- SOID,
837
- // progress: args.progress,
838
- mode,
839
- // fontsize: args.fontsize,
840
- // color: args.color,
841
- senderID: senderID.toString(),
842
- // content: args.content,
843
- ctime: this.transCtime(args.ctime, 's'),
844
- weight: args.weight || (pool === Pools.Ix ? 1 : 0),
845
- pool,
846
- attr: DMAttrUtils.fromBin(args.attr, PlatformVideoSource.Bilibili),
847
- platform: PlatformVideoSource.Bilibili,
848
- // 需改进,7=>advanced 8=>code 9=>bas 互动=>command
849
- // 同时塞进无法/无需直接解析的数据
850
- // 另开一个解析器,为大部分播放器(无法解析该类dm)做文本类型降级处理
851
- extra,
852
- },
853
- options,
854
- )
855
- }
856
- @Expose()
857
- toBiliXML(options?: {
858
- skipBiliCommand?: boolean
859
- /**
860
- * 见 ../index.ts UniPool.toBiliXML() 的 options,该option不宜手动调用,判断逻辑未封装
861
- */
862
- avoidSenderIDWithAt?: boolean
863
- }) {
864
- if (options?.skipBiliCommand && this.extra.bili?.command) {
865
- return null
866
- }
867
- const recMode = (mode: Modes, extra?: ExtraBili) => {
868
- switch (mode) {
869
- case Modes.Normal:
870
- return 1
871
- case Modes.Bottom:
872
- return 4
873
- case Modes.Top:
874
- return 5
875
- case Modes.Reverse:
876
- return 6
877
- case Modes.Ext:
878
- if (!extra) return 1
879
- else if (extra.adv) return 7
880
- else if (extra.code) return 8
881
- else if (extra.bas) return 9
882
- else return 1
883
- default:
884
- return 1
885
- }
886
- }
887
- const rMode = this.extra.bili?.mode || recMode(this.mode, this.extra?.bili)
888
- let content
889
- switch (rMode) {
890
- case 7:
891
- content = this.extra?.bili?.adv
892
- break
893
- case 8:
894
- content = this.extra?.bili?.code
895
- break
896
- case 9:
897
- content = this.extra?.bili?.bas
898
- break
899
- default:
900
- content = this.content
901
- break
902
- }
903
- return {
904
- '#text': content ?? this.content,
905
- '@_p': [
906
- this.progress,
907
- rMode,
908
- this.fontsize,
909
- this.color,
910
- this.ctime.getTime() / 1000,
911
- this.extra.bili?.pool || this.pool, // 目前pool与bili兼容
912
- options?.avoidSenderIDWithAt
913
- ? this.senderID.replaceAll(`@${PlatformVideoSource.Bilibili}`, '')
914
- : this.senderID,
915
- this.extra.bili?.dmid || this.DMID || this.toDMID(),
916
- this.weight,
917
- ].join(','),
918
- }
919
- }
920
- static fromBiliCommand(args: DMBiliCommand, cid?: bigint, options?: Options) {
921
- if (args.oid && !cid) cid = args.oid
922
- const SOID = `def_${PlatformVideoSource.Bilibili}+${ID.fromBili({ cid })}`
923
- const senderID = ID.fromBili({ mid: args.mid })
924
- return this.create(
925
- {
926
- ...args,
927
- SOID,
928
- // progress: args.progress,
929
- mode: Modes.Ext,
930
- // fontsize: args.fontsize,
931
- // color: args.color,
932
- senderID: senderID.toString(),
933
- // content: args.content,
934
- ctime: new Date(`${args.ctime} GMT+0800`), // 无视本地时区,按照B站的东8区计算时间
935
- weight: 11,
936
- pool: Pools.Adv,
937
- attr: [DMAttr.Protect],
938
- platform: PlatformVideoSource.Bilibili,
939
- extra: {
940
- bili: {
941
- dmid: args.id,
942
- attr: args.attr,
943
- mid: args.mid,
944
- command: args,
945
- },
946
- },
947
- },
948
- options,
949
- )
950
- }
951
- static fromDplayer(
952
- args: DMDplayer,
953
- playerID: string,
954
- domain: string,
955
- options?: Options,
956
- ) {
957
- const SOID = ID.fromUnknown(playerID, domain)
958
- const senderID = ID.fromUnknown(args.midHash, domain)
959
- return this.create(
960
- {
961
- ...args,
962
- SOID: SOID.toString(),
963
- // progress: args.progress,
964
- mode: this.transMode(args.mode, 'dplayer'),
965
- // fontsize: 25,
966
- // color: args.color,
967
- senderID: senderID.toString(),
968
- // content: args.content,
969
- platform: domain,
970
- },
971
- options,
972
- )
973
- }
974
- @Expose()
975
- toDplayer(): DMDplayer {
976
- let mode = 0
977
- if (this.mode === Modes.Top) mode = 1
978
- else if (this.mode === Modes.Bottom) mode = 2
979
- return {
980
- mode,
981
- progress: this.progress,
982
- color: this.color,
983
- midHash: this.senderID,
984
- content: this.content,
985
- }
986
- }
987
- static fromArtplayer(
988
- args: DMArtplayer,
989
- playerID: string,
990
- domain: string,
991
- options?: Options,
992
- ) {
993
- const SOID = ID.fromUnknown(playerID, domain)
994
- const senderID = ID.fromUnknown('', domain)
995
- let extra = args.border
996
- ? ({ artplayer: { border: args.border, style: {} } } as Extra)
997
- : undefined
998
- if (args.style) {
999
- if (extra)
1000
- extra = {
1001
- ...extra,
1002
- artplayer: {
1003
- ...extra.artplayer,
1004
- border: args.border,
1005
- style: args.style,
1006
- },
1007
- }
1008
- else extra = { artplayer: { border: args.border, style: args.style } }
1009
- }
1010
- return this.create(
1011
- {
1012
- ...args,
1013
- SOID: SOID.toString(),
1014
- // progress: args.progress,
1015
- mode: this.transMode(args.mode, 'artplayer'),
1016
- // fontsize: 25,
1017
- // color: args.color,
1018
- senderID: senderID.toString(),
1019
- // content: args.content,
1020
- platform: domain,
1021
- extra, //optional BigINt parser
1022
- },
1023
- options,
1024
- )
1025
- }
1026
- @Expose()
1027
- toArtplayer(): DMArtplayer {
1028
- let mode = 0
1029
- if (this.mode === Modes.Top) mode = 1
1030
- else if (this.mode === Modes.Bottom) mode = 2
1031
- return {
1032
- progress: this.progress,
1033
- mode,
1034
- color: this.color,
1035
- content: this.content,
1036
- border: this.extra.artplayer?.border,
1037
- style: this.extra.artplayer?.style,
1038
- }
1039
- }
1040
- static fromDDPlay(
1041
- args: DMDDPlay,
1042
- episodeId: string,
1043
- domain = PlatformDanmakuOnlySource.DanDanPlay,
1044
- options?: Options,
1045
- ) {
1046
- const SOID = ID.fromUnknown(
1047
- `def_${PlatformDanmakuOnlySource.DanDanPlay}+${episodeId}`,
1048
- domain,
1049
- )
1050
- return this.create(
1051
- {
1052
- ...args,
1053
- SOID: SOID.toString(),
1054
- // progress: args.progress,
1055
- mode: this.transMode(args.mode, 'ddplay'),
1056
- // fontsize: 25,
1057
- // color: args.color,
1058
- senderID: args.uid,
1059
- content: args.m,
1060
- platform: domain,
1061
- DMID: args.cid.toString(), //无需 new ID() 获取带suffix的ID
1062
- },
1063
- options,
1064
- )
1065
- }
1066
- @Expose()
1067
- toDDPlay(): DMDDPlay {
1068
- let mode = 1
1069
- if (this.mode === Modes.Top) mode = 5
1070
- else if (this.mode === Modes.Bottom) mode = 4
1071
- return {
1072
- progress: this.progress,
1073
- mode,
1074
- color: this.color,
1075
- uid: this.senderID,
1076
- m: this.content,
1077
- cid: this.DMID
1078
- ? BigInt(`0x${Buffer.from(this.DMID).toString('hex')}`)
1079
- : 0n,
1080
- }
1081
- }
1082
- }