dna-api 0.2.7 → 0.3.2

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 DELETED
@@ -1,1736 +0,0 @@
1
- import * as forge from "node-forge"
2
- //#region const
3
- enum RespCode {
4
- ERROR = -999,
5
- OK_ZERO = 0,
6
- OK_HTTP = 200,
7
- BAD_REQUEST = 400,
8
- SERVER_ERROR = 500,
9
- }
10
-
11
- const DNA_GAME_ID = 268
12
- //#endregion
13
-
14
- /**
15
- * DNA API类,用于与DNA游戏服务器交互
16
- */
17
- export class DNAAPI {
18
- public fetchFn?: typeof fetch
19
- public is_h5 = false
20
- public RSA_PUBLIC_KEY =
21
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGpdbezK+eknQZQzPOjp8mr/dP+QHwk8CRkQh6C6qFnfLH3tiyl0pnt3dePuFDnM1PUXGhCkQ157ePJCQgkDU2+mimDmXh0oLFn9zuWSp+U8uLSLX3t3PpJ8TmNCROfUDWvzdbnShqg7JfDmnrOJz49qd234W84nrfTHbzdqeigQIDAQAB"
22
- public BASE_URL = "https://dnabbs-api.yingxiong.com/"
23
- private uploadKey: string = ""
24
-
25
- /**
26
- * 构造函数
27
- * @param dev_code 设备码
28
- * @param uid 用户ID
29
- * @param token 访问令牌
30
- * @param options 选项
31
- * @param options.fetchFn 自定义fetch函数
32
- * @param options.is_h5 是否为H5端
33
- * @param options.rsa_public_key RSA公钥(base64) 设为空字符串从服务器获取
34
- */
35
- constructor(
36
- public dev_code: string,
37
- public token = "",
38
- options: { fetchFn?: typeof fetch; is_h5?: boolean; rsa_public_key?: string } = {},
39
- ) {
40
- this.fetchFn = options.fetchFn
41
- if (options.is_h5 !== undefined) this.is_h5 = options.is_h5
42
- if (options.rsa_public_key !== undefined) this.RSA_PUBLIC_KEY = options.rsa_public_key
43
- }
44
-
45
- /**
46
- * 获取RSA公钥
47
- * @returns RSA公钥(base64)
48
- */
49
- async getRsaPublicKey() {
50
- if (this.RSA_PUBLIC_KEY) {
51
- return this.RSA_PUBLIC_KEY
52
- }
53
- const res = await this._dna_request<{ key: string }>("config/getRsaPublicKey")
54
-
55
- if (res.is_success && res.data) {
56
- const key = res.data.key
57
- if (typeof key === "string") {
58
- this.RSA_PUBLIC_KEY = key
59
- }
60
- }
61
- return this.RSA_PUBLIC_KEY
62
- }
63
-
64
- /**
65
- * 登录
66
- */
67
- async login(mobile: string, code: string) {
68
- const data = { code: code, devCode: this.dev_code, gameList: DNA_GAME_ID, loginType: 1, mobile: mobile }
69
- const res = await this._dna_request<DNALoginRes>("user/sdkLogin", data, { sign: true })
70
- if (res.is_success && res.data) {
71
- const data = res.data
72
- if (typeof data.token === "string") {
73
- this.token = data.token
74
- }
75
- }
76
- return res
77
- }
78
-
79
- /**
80
- * 获取短信验证码
81
- */
82
- async getSmsCode(mobile: string, vJson: string) {
83
- const data = { mobile, isCaptcha: 1, vJson }
84
- return await this._dna_request("user/getSmsCode", data)
85
- }
86
-
87
- /**
88
- * 上传头像
89
- */
90
- async uploadHead(file: File) {
91
- const data = new FormData()
92
- data.append("parts", file)
93
- const res = await this._dna_request<string[]>("user/img/uploadHead", data, { sign: true })
94
- if (res.is_success && res.data) {
95
- res.data = res.data.map((url) => aesDecryptImageUrl(url, this.uploadKey))
96
- }
97
- return res
98
- }
99
-
100
- /**
101
- * 图片上传
102
- */
103
- async uploadImage(file: File) {
104
- const data = new FormData()
105
- data.append("files", file)
106
- data.append("type", "post")
107
- const res = await this._dna_request<string[]>("config/img/upload", data, { sign: true })
108
- if (res.is_success && res.data) {
109
- res.data = res.data.map((url) => aesDecryptImageUrl(url, this.uploadKey))
110
- }
111
- return res
112
- }
113
-
114
- /**
115
- * 获取登录日志
116
- */
117
- async loginLog() {
118
- return await this._dna_request<DNALoginRes>("user/login/log")
119
- }
120
-
121
- /**
122
- * 获取角色列表
123
- */
124
- async getRoleList() {
125
- return await this._dna_request<DNARoleListRes>("role/list")
126
- }
127
-
128
- /**
129
- * 获取默认角色
130
- */
131
- async getDefaultRoleForTool() {
132
- const data = { type: 1 }
133
- return await this._dna_request<DNARoleForToolRes>("role/defaultRoleForTool", data, { sign: true, token: true, tokenSig: true })
134
- }
135
-
136
- /**
137
- * 获取角色详情
138
- */
139
- async getCharDetail(char_id: string, char_eid: string, otherUserId?: string) {
140
- const data = { charId: char_id, charEid: char_eid, type: 1, otherUserId } as any
141
- return await this._dna_request<DNACharDetailRes>("role/getCharDetail", data)
142
- }
143
-
144
- /**
145
- * 获取武器详情
146
- */
147
- async getWeaponDetail(weapon_id: string, weapon_eid: string, otherUserId?: string) {
148
- const data = { weaponId: weapon_id, weaponEid: weapon_eid, type: 1, otherUserId }
149
- return await this._dna_request<DNAWeaponDetailRes>("role/getWeaponDetail", data)
150
- }
151
-
152
- /**
153
- * 获取角色简讯
154
- */
155
- async getShortNoteInfo() {
156
- return await this._dna_request<DNARoleShortNoteRes>("role/getShortNoteInfo")
157
- }
158
-
159
- /**
160
- * 检查是否签到
161
- */
162
- async haveSignIn() {
163
- const data = { gameId: DNA_GAME_ID }
164
- return await this._dna_request<DNAHaveSignInRes>("user/haveSignInNew", data)
165
- }
166
-
167
- /**
168
- * 签到日历
169
- */
170
- async signCalendar() {
171
- const data = { gameId: DNA_GAME_ID }
172
- return await this._dna_request<DNACalendarSignRes>("encourage/signin/show", data)
173
- }
174
-
175
- /** ? */
176
- async soulTask() {
177
- return await this._dna_request("role/soul/task")
178
- }
179
-
180
- /**
181
- * 游戏签到
182
- */
183
- async gameSign(day_award_id: number, period: number) {
184
- const data = {
185
- dayAwardId: day_award_id,
186
- periodId: period,
187
- signinType: 1,
188
- }
189
- return await this._dna_request("encourage/signin/signin", data)
190
- }
191
-
192
- /**
193
- * 皎皎角签到
194
- */
195
- async bbsSign() {
196
- const data = { gameId: DNA_GAME_ID }
197
- return await this._dna_request("user/signIn", data)
198
- }
199
-
200
- /**
201
- * 获取任务进度
202
- */
203
- async getTaskProcess() {
204
- const data = { gameId: DNA_GAME_ID }
205
- return await this._dna_request<DNATaskProcessRes>("encourage/level/getTaskProcess", data)
206
- }
207
-
208
- /**
209
- * 获取帖子列表
210
- * @param forumId 论坛ID
211
- * @param pageIndex 页码
212
- * @param pageSize 每页数量
213
- * @param searchType 搜索类型 1:最新 2:热门
214
- * @param timeType 时间类型 0:全部 1:今日 2:本周 3:本月
215
- * @returns 帖子列表
216
- */
217
- async getPostList(forumId: number = 48, pageIndex: number = 1, pageSize: number = 20, searchType: number = 1, timeType: number = 0) {
218
- const data = {
219
- forumId: forumId,
220
- gameId: DNA_GAME_ID,
221
- pageIndex: pageIndex,
222
- pageSize: pageSize,
223
- searchType: searchType, // 1:最新 2:热门
224
- timeType: timeType, // 0:全部 1:今日 2:本周 3:本月
225
- }
226
- return await this._dna_request<DNAPostListRes>("forum/list", data)
227
- }
228
-
229
- /** 管理员锁定帖子 */
230
- async lockPost(post: { postId: number; gameId?: number; gameForumId: number; operateType: number }) {
231
- const data = {
232
- postId: post.postId,
233
- gameId: post.gameId ?? DNA_GAME_ID,
234
- gameForumId: post.gameForumId,
235
- operateType: post.operateType,
236
- }
237
- return await this._dna_request("forum/moderator/postLock", data)
238
- }
239
-
240
- /** 管理员移动帖子 */
241
- async postDownOrUp(post: { postId: number; gameId?: number; gameForumId: number; operateType: number }) {
242
- const data = {
243
- postId: post.postId,
244
- gameId: post.gameId ?? DNA_GAME_ID,
245
- gameForumId: post.gameForumId,
246
- operateType: post.operateType,
247
- }
248
- return await this._dna_request("forum/moderator/postDownOrUp", data)
249
- }
250
-
251
- /** 管理员设精 */
252
- async postElite(post: { postId: number; gameId?: number; gameForumId: number; operateType: number }) {
253
- const data = {
254
- postId: post.postId,
255
- gameId: post.gameId ?? DNA_GAME_ID,
256
- gameForumId: post.gameForumId,
257
- operateType: post.operateType,
258
- }
259
- return await this._dna_request("forum/moderator/postElite", data)
260
- }
261
-
262
- /** 管理员隐藏帖子 */
263
- async postHide(post: { postId: number; gameId?: number; gameForumId: number; operateType: number }) {
264
- const data = {
265
- postId: post.postId,
266
- gameId: post.gameId ?? DNA_GAME_ID,
267
- gameForumId: post.gameForumId,
268
- operateType: post.operateType,
269
- }
270
- return await this._dna_request("forum/moderator/postHide", data)
271
- }
272
-
273
- /** 管理员设置权重 */
274
- async reRank(post: { postId: number; gameId?: number; gameForumId: number }, weight: number) {
275
- const data = {
276
- postId: post.postId,
277
- gameId: post.gameId ?? DNA_GAME_ID,
278
- gameForumId: post.gameForumId,
279
- weight: weight,
280
- }
281
- return await this._dna_request("forum/moderator/reRank", data)
282
- }
283
-
284
- /** 管理员设置强推 */
285
- async strongRecommend(post: { postId: number; gameId?: number; gameForumId: number }, operateType = 1) {
286
- const data = {
287
- postId: post.postId,
288
- gameId: post.gameId ?? DNA_GAME_ID,
289
- gameForumId: post.gameForumId,
290
- operateType: operateType,
291
- }
292
- return await this._dna_request("forum/moderator/setForceRecommend", data)
293
- }
294
-
295
- /** 管理员删帖 */
296
- async adminDelete(post: { postId: number; gameId?: number; gameForumId: number }, content: string, reasonCode: number) {
297
- const data = {
298
- postId: post.postId,
299
- gameId: post.gameId ?? DNA_GAME_ID,
300
- gameForumId: post.gameForumId,
301
- content: content,
302
- reasonCode: reasonCode,
303
- }
304
- return await this._dna_request("forum/moderator/postDelete", data)
305
- }
306
- /** 管理员移动帖子 */
307
- async adminMovePost(
308
- post: { postId: number; gameId?: number; gameForumId: number },
309
- newGameId: number,
310
- newForumId: number,
311
- newTopicIdStr: string,
312
- ) {
313
- const data = {
314
- postId: post.postId,
315
- gameId: post.gameId ?? DNA_GAME_ID,
316
- gameForumId: post.gameForumId,
317
- newGameId: newGameId,
318
- newForumId: newForumId,
319
- newTopicIdStr: newTopicIdStr,
320
- }
321
- return await this._dna_request("forum/moderator/postMove", data)
322
- }
323
- /** ? */
324
- async adminRefreshTime(post: { postId: number; gameId?: number; gameForumId: number }, refresh: number) {
325
- const data = {
326
- postId: post.postId,
327
- gameId: post.gameId ?? DNA_GAME_ID,
328
- gameForumId: post.gameForumId,
329
- refresh: refresh,
330
- }
331
- return await this._dna_request("forum/moderator/setRefresh", data)
332
- }
333
-
334
- /** 黑名单 */
335
- async blockList() {
336
- return await this._dna_request("user/block/list")
337
- }
338
-
339
- /** 拉黑 */
340
- async blockOther(blockPostId: number, blockUserId: string, type: number) {
341
- const data = {
342
- blockPostId: blockPostId,
343
- blockUserId: blockUserId,
344
- type: type,
345
- }
346
- return await this._dna_request("user/block/list", data)
347
- }
348
-
349
- /** ? */
350
- async viewCommunity() {
351
- return await this._dna_request("encourage/level/viewCommunity")
352
- }
353
-
354
- /** ? */
355
- async viewCount() {
356
- return await this._dna_request("forum/viewCount")
357
- }
358
-
359
- /** ? */
360
- async receiveLog(periodId: number, pageIndex: number, pageSize: number) {
361
- const data = {
362
- periodId: periodId,
363
- pageIndex: pageIndex,
364
- pageSize: pageSize,
365
- }
366
- return await this._dna_request("encourage/signin/receiveLog", data)
367
- }
368
-
369
- /** 收藏 */
370
- async collect(postId: number, toUserId: string, operateType = 1) {
371
- const data = {
372
- operateType: operateType,
373
- postId: postId,
374
- toUserId: toUserId,
375
- }
376
- return await this._dna_request("forum/collect", data)
377
- }
378
-
379
- /** 删除评论 */
380
- async commentDelete(
381
- comment: { id: number; gameId: number; gameForumId: number },
382
- entityType: number,
383
- content: string,
384
- reasonCode: number,
385
- ) {
386
- const data = {
387
- id: comment.id,
388
- gameId: comment.gameId,
389
- gameForumId: comment.gameForumId,
390
- entityType: entityType,
391
- content: content,
392
- reasonCode: reasonCode,
393
- }
394
- return await this._dna_request("forum/collect", data)
395
- }
396
-
397
- /** 推荐列表 */
398
- async recommendList(recIndex: number, newIndex: number, size: number, history: number, gameId = DNA_GAME_ID) {
399
- const data = {
400
- gameId: gameId,
401
- recIndex: recIndex,
402
- newIndex: newIndex,
403
- size: size,
404
- history: history,
405
- }
406
- return await this._dna_request("forum/recommend/list", data)
407
- }
408
-
409
- /** 举报 */
410
- async report(
411
- { commentId = 0, postId = 0, replyId = 0 }: { commentId?: number; postId?: number; replyId?: number },
412
- reportReason = 1,
413
- reportType = 1,
414
- ) {
415
- const data = {
416
- commentId: commentId,
417
- postId: postId,
418
- replyId: replyId,
419
- reportReason: reportReason,
420
- reportType: reportType,
421
- }
422
- return await this._dna_request<DNAPostListRes>("forum/recommend/list", data)
423
- }
424
- /** 搜索帖子 */
425
- async searchPost(keyword: number, pageIndex: number, pageSize: number, gameId = DNA_GAME_ID, searchType = 1) {
426
- const data = {
427
- gameId: gameId,
428
- keyword: keyword,
429
- pageIndex: pageIndex,
430
- pageSize: pageSize,
431
- searchType: searchType,
432
- }
433
- return await this._dna_request<DNAPostListRes>("forum/searchPost", data)
434
- }
435
- /** 搜索帖子 */
436
- async searchTopic(keyword: number, pageIndex: number, pageSize = 20, gameId = DNA_GAME_ID) {
437
- const data = {
438
- gameId: gameId,
439
- keyword: keyword,
440
- pageIndex: pageIndex,
441
- pageSize: pageSize,
442
- }
443
- return await this._dna_request<DNAPostListRes>("config/searchTopic", data)
444
- }
445
-
446
- /** 搜索帖子 */
447
- async searchUser(keyword: number, pageIndex: number, pageSize: number) {
448
- const data = {
449
- keyword: keyword,
450
- pageIndex: pageIndex,
451
- pageSize: pageSize,
452
- }
453
- return await this._dna_request<DNAPostListRes>("user/searchUser", data)
454
- }
455
-
456
- /**
457
- * 获取帖子列表
458
- * @param topicId 主题ID
459
- * @param pageIndex 页码
460
- * @param pageSize 每页数量
461
- * @param searchType 搜索类型 1:最新 2:热门
462
- * @param timeType 时间类型 0:全部 1:今日 2:本周 3:本月
463
- * @returns 帖子列表
464
- */
465
- async getPostsByTopic(
466
- topicId: number = 177,
467
- pageIndex: number = 1,
468
- pageSize: number = 20,
469
- searchType: number = 1,
470
- timeType: number = 0,
471
- ) {
472
- const data = {
473
- topicId: topicId,
474
- gameId: DNA_GAME_ID,
475
- pageIndex: pageIndex,
476
- pageSize: pageSize,
477
- searchType: searchType, // 1:最新 2:热门
478
- timeType: timeType, // 0:全部 1:今日 2:本周 3:本月
479
- }
480
- return await this._dna_request<DNAPostListRes>("forum/getPostByTopic", data)
481
- }
482
-
483
- /**
484
- * 获取帖子详情
485
- * @param post_id 帖子ID
486
- * @returns 帖子详情
487
- */
488
- async getPostDetail(post_id: string) {
489
- const data = { postId: post_id }
490
- return await this._dna_request<DNAPostDetailRes>("forum/getPostDetail", data)
491
- }
492
-
493
- /** 关注用户 */
494
- async doFollow(userId: string, unfollow?: boolean) {
495
- const data = {
496
- followUserId: userId,
497
- operateType: unfollow ? 0 : 1,
498
- }
499
- return await this._dna_request("user/followUser", data, { sign: true })
500
- }
501
-
502
- /** 获取关注状态 */
503
- async getFollowState(userId: string) {
504
- const data = {
505
- followUserId: userId,
506
- }
507
- return await this._dna_request("user/isFollow", data)
508
- }
509
-
510
- /**
511
- * 点赞帖子
512
- */
513
- async doLike(post: { gameForumId: string; postId: string; postType: string; userId: string }) {
514
- const data = {
515
- forumId: post.gameForumId,
516
- gameId: DNA_GAME_ID,
517
- likeType: "1",
518
- operateType: "1",
519
- postCommentId: "",
520
- postCommentReplyId: "",
521
- postId: post.postId,
522
- postType: post.postType,
523
- toUserId: post.userId,
524
- }
525
- return await this._dna_request("forum/like", data)
526
- }
527
-
528
- /** 分享帖子 */
529
- async doShare() {
530
- const data = { gameId: DNA_GAME_ID }
531
- return await this._dna_request("encourage/level/shareTask", data)
532
- }
533
-
534
- /** 回复帖子 */
535
- async createComment(post: { userId: string; postId: string; gameForumId: number }, content: string) {
536
- const content_json = JSON.stringify([
537
- {
538
- content,
539
- contentType: "1",
540
- // imgHeight: 0,
541
- // imgWidth: 0,
542
- // url: "",
543
- },
544
- ])
545
- const data = {
546
- postId: post.postId,
547
- forumId: post.gameForumId,
548
- postType: "1",
549
- content: content_json,
550
- }
551
-
552
- return await this._dna_request("forum/comment/createComment", data, {
553
- sign: true,
554
- params: { toUserId: post.userId },
555
- })
556
- }
557
-
558
- /** 回复评论 */
559
- async createReply(post: { userId: string; postId: string; postCommentId: string; gameForumId: number }, content: string) {
560
- const content_json = JSON.stringify([
561
- {
562
- content,
563
- contentType: "1",
564
- imgHeight: 0,
565
- imgWidth: 0,
566
- url: "",
567
- },
568
- ])
569
- const data = {
570
- content: content_json,
571
- forumId: post.gameForumId,
572
- postCommentId: post.postCommentId,
573
- postId: post.postId,
574
- postType: "1",
575
- toUserId: post.userId,
576
- }
577
-
578
- return await this._dna_request("forum/comment/createReply", data, { sign: true, refer: true, params: { toUserId: post.userId } })
579
- }
580
-
581
- /** 回复评论的评论 */
582
- async createReplyList(
583
- post: { userId: string; postId: string; postCommentId: string; postCommentReplyId: string; gameForumId: number },
584
- content: string,
585
- ) {
586
- const content_json = JSON.stringify([
587
- {
588
- content,
589
- contentType: "1",
590
- imgHeight: 0,
591
- imgWidth: 0,
592
- url: "",
593
- },
594
- ])
595
- const data = {
596
- content: content_json,
597
- forumId: post.gameForumId,
598
- postCommentId: post.postCommentId,
599
- postCommentReplyId: post.postCommentReplyId,
600
- postId: post.postId,
601
- postType: "1",
602
- toUserId: post.userId,
603
- }
604
- return await this._dna_request("forum/comment/createReply", data, { sign: true, refer: true, params: { toUserId: post.userId } })
605
- }
606
-
607
- /** 删 */
608
- async deletePost(deleteType: number, id: number) {
609
- return await this._dna_request("forum/more/delete", { deleteType, id }, { sign: true, refer: true })
610
- }
611
-
612
- /**
613
- * 获取用户信息
614
- * @returns 用户信息
615
- */
616
- async getOtherMine(userId = "709542994134436647") {
617
- const data = {
618
- otherUserId: userId,
619
- searchType: 1,
620
- type: 2,
621
- }
622
- return await this._dna_request<DNAMineRes>("user/mine", data)
623
- }
624
-
625
- /**
626
- * 获取用户信息
627
- * @returns 用户信息
628
- */
629
- async getMine() {
630
- return await this._dna_request<DNAMineRes>("user/mine")
631
- }
632
-
633
- async getGameConfig() {
634
- const data = { gameId: DNA_GAME_ID }
635
- return await this._dna_request<DNAGameConfigRes[]>("config/getGameConfig", data)
636
- }
637
-
638
- async getHeaders(options?: {
639
- payload?: Record<string, any> | string | FormData
640
- exparams?: Record<string, any>
641
- dev_code?: string
642
- refer?: boolean
643
- token?: string
644
- tokenSig?: boolean
645
- }) {
646
- let { payload, exparams, dev_code = this.dev_code, refer, token = this.token, tokenSig } = options || {}
647
-
648
- const CONTENT_TYPE = "application/x-www-form-urlencoded; charset=utf-8"
649
- const iosBaseHeader = {
650
- version: "1.1.3",
651
- source: "ios",
652
- "Content-Type": CONTENT_TYPE,
653
- "User-Agent": "DoubleHelix/4 CFNetwork/3860.100.1 Darwin/25.0.0",
654
- }
655
- const h5BaseHeader = {
656
- version: "3.11.0",
657
- source: "h5",
658
- "Content-Type": CONTENT_TYPE,
659
- "User-Agent":
660
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
661
- }
662
- // 默认获取ios头
663
- const headers = { ...(this.is_h5 ? h5BaseHeader : iosBaseHeader) } as Record<string, any>
664
- if (dev_code) {
665
- headers.devCode = dev_code
666
- }
667
- if (refer) {
668
- headers.origin = "https://dnabbs.yingxiong.com"
669
- headers.refer = "https://dnabbs.yingxiong.com/"
670
- }
671
- if (token) {
672
- headers.token = token
673
- }
674
- if (payload instanceof FormData) {
675
- const pk = await this.getRsaPublicKey()
676
- const { signature, key } = build_upload_signature(pk)
677
- headers.t = signature
678
- this.uploadKey = key
679
-
680
- if (exparams) {
681
- for (const [key, value] of Object.entries(exparams)) {
682
- payload.append(key, String(value))
683
- }
684
- }
685
-
686
- delete headers["Content-Type"]
687
- } else if (typeof payload === "object") {
688
- const si = build_signature(payload, tokenSig ? token : "")
689
- Object.assign(payload, { sign: si.s, timestamp: si.t })
690
- if (exparams) {
691
- Object.assign(payload, exparams)
692
- }
693
-
694
- const params = new URLSearchParams()
695
- Object.entries(payload).forEach(([key, value]) => {
696
- params.append(key, String(value))
697
- })
698
- payload = params.toString()
699
-
700
- const rk = si.k
701
- const pk = await this.getRsaPublicKey()
702
- const ek = rsa_encrypt(rk, pk)
703
- if (this.is_h5) {
704
- headers.k = ek
705
- } else {
706
- headers.rk = rk
707
- headers.key = ek
708
- }
709
- }
710
- return { headers, payload }
711
- }
712
-
713
- private async _dna_request<T = any>(
714
- url: string,
715
- data?: any,
716
- options?: {
717
- method?: "GET" | "POST"
718
- sign?: boolean
719
- file?: File
720
- tokenSig?: boolean
721
- token?: boolean
722
- refer?: boolean
723
- params?: Record<string, any>
724
- max_retries?: number
725
- retry_delay?: number
726
- timeout?: number
727
- },
728
- ): Promise<DNAApiResponse<T>> {
729
- let { method = "POST", sign, refer, params, max_retries = 3, retry_delay = 1, timeout = 10000, token, tokenSig } = options || {}
730
- let headers: Record<string, any>
731
- if (sign) {
732
- const { payload: p, headers: h } = await this.getHeaders({
733
- payload: data,
734
- refer,
735
- exparams: params,
736
- token: token ? this.token : undefined,
737
- tokenSig,
738
- })
739
- data = p
740
- headers = h
741
- } else {
742
- const { headers: h } = await this.getHeaders({ token: token ? this.token : undefined })
743
- headers = h
744
- }
745
-
746
- for (let attempt = 0; attempt < max_retries; attempt++) {
747
- try {
748
- let body: string | FormData | undefined = data
749
- if (data && typeof data === "object" && !(data instanceof FormData)) {
750
- const p = new URLSearchParams()
751
- Object.entries(data).forEach(([key, value]) => {
752
- if (value !== undefined) p.append(key, String(value))
753
- })
754
- body = p.toString()
755
- }
756
- const fetchOptions: RequestInit = {
757
- method,
758
- headers,
759
- body,
760
- }
761
-
762
- // 实现超时控制
763
- const controller = new AbortController()
764
- const timeoutId = setTimeout(() => controller.abort(), timeout)
765
-
766
- const initOptions = {
767
- ...fetchOptions,
768
- signal: controller.signal,
769
- }
770
- const response = this.fetchFn
771
- ? await this.fetchFn(`${this.BASE_URL}${url}`, initOptions)
772
- : await fetch(`${this.BASE_URL}${url}`, initOptions)
773
- clearTimeout(timeoutId)
774
-
775
- // 获取响应头的 content-type
776
- const contentType = response.headers.get("content-type") || ""
777
- let raw_res: any
778
-
779
- // 根据 content-type 处理响应数据
780
- if (contentType.includes("text/")) {
781
- const textData = await response.text()
782
- raw_res = {
783
- code: RespCode.ERROR,
784
- data: textData,
785
- }
786
- } else {
787
- raw_res = await response.json()
788
- }
789
-
790
- if (typeof raw_res === "object" && raw_res !== null) {
791
- try {
792
- if (typeof raw_res.data === "string") {
793
- raw_res.data = JSON.parse(raw_res.data)
794
- }
795
- } catch (e) {
796
- // 忽略解析错误
797
- }
798
- }
799
-
800
- return new DNAApiResponse<T>(raw_res)
801
- } catch (e) {
802
- console.error(`请求失败: ${(e as Error).message}`)
803
- if (attempt < max_retries - 1) {
804
- await new Promise((resolve) => setTimeout(resolve, retry_delay * Math.pow(2, attempt)))
805
- }
806
- }
807
- }
808
-
809
- return DNAApiResponse.err("请求服务器失败,已达最大重试次数")
810
- }
811
- }
812
-
813
- enum DNAInstanceMHType {
814
- "角色" = "role",
815
- "武器" = "weapon",
816
- "魔之楔" = "mzx",
817
- "role" = "角色",
818
- "weapon" = "武器",
819
- "mzx" = "魔之楔",
820
- }
821
-
822
- export function getDNAInstanceMHType(key: keyof typeof DNAInstanceMHType) {
823
- return DNAInstanceMHType[key]
824
- }
825
-
826
- //#region 接口定义
827
-
828
- export interface DNAMineRes {
829
- mine: DNAMine
830
- postList: DNAPost[]
831
- hasNext: number
832
- }
833
-
834
- export interface DNAMine {
835
- /** 文章数量 */
836
- articleCount: number
837
- /** 收藏数量 */
838
- collectCount: number
839
- /** 评论数量 */
840
- commentCount: number
841
- /** 粉丝数量 */
842
- fansCount: number
843
- /** 新粉丝数量 */
844
- fansNewCount: number
845
- /** 关注数量 */
846
- followCount: number
847
- /** 性别 */
848
- gender: number
849
- /** 精华数量 */
850
- goldNum: number
851
- /** 头像 */
852
- headUrl: string
853
- /** 是否关注 */
854
- isFollow: number
855
- /** 是否登录用户 */
856
- isLoginUser: number
857
- /** 是否被禁言 */
858
- isMute: number
859
- /** 等级 */
860
- levelTotal: number
861
- /** 点赞数量 */
862
- likeCount: number
863
- /** 手机号 */
864
- mobile: string
865
- /** 管理员列表 */
866
- moderatorVos: any[]
867
- /** 帖子数量 */
868
- postCount: number
869
- /** 注册时间 */
870
- registerTime: string
871
- /** 状态 */
872
- status: number
873
- /** 趋势数量 */
874
- trendCount: number
875
- /** 用户ID */
876
- userId: string
877
- /** 用户名 */
878
- userName: string
879
- }
880
-
881
- export interface DNAGameConfigRes {
882
- /** 游戏所有板块列表 */
883
- gameAllForumList: GameForum[]
884
- /** 游戏ID */
885
- gameId: number
886
- /** 游戏板块图片列表 */
887
- gameForumPictureList: any[]
888
- /** 游戏板块列表 */
889
- gameForumList: GameForum[]
890
- /** 签到按钮图片 */
891
- signBtn: string
892
- sort: number
893
- /** 话题列表 */
894
- topicList: GameTopic[]
895
- /** 背景图片 */
896
- drawBackgroundUrl: string
897
- /** 是否默认游戏 */
898
- gameDefault: number
899
- /** 签到颜色 */
900
- signColor: string
901
- /** 游戏名称 */
902
- gameName: string
903
- /** CM图片2 意味不明 */
904
- drawListUrl: string
905
- /** 英文站点 */
906
- configTab: ConfigTab[]
907
- }
908
-
909
- export interface ConfigTab {
910
- name: string
911
- url: string
912
- }
913
-
914
- export interface GameTopic {
915
- /** 话题背景图片 */
916
- backgroundUrl: string
917
- gameId: number
918
- /** 话题图标 */
919
- topicIconUrl: string
920
- topicId: number
921
- /** 话题名称 */
922
- topicName: string
923
- sort: number
924
- /** 话题描述 */
925
- topicDesc: string
926
- }
927
-
928
- export interface GameForum {
929
- /** 全部=1 普通=3 */
930
- forumDataType: number
931
- /** 固定1 */
932
- forumUiType: number
933
- /** 小红点 */
934
- isTrend: number
935
- /** 夜间模式图标 */
936
- iconWhiteUrl: string
937
- /** 固定1 */
938
- forumType: number
939
- /** 板块名称 */
940
- name: string
941
- forumListShowType: number
942
- /** 图标 */
943
- iconUrl: string
944
- id: number
945
- sort: number
946
- /** 官方 */
947
- isOfficial: number
948
- }
949
-
950
- export interface UserGame {
951
- gameId: number // gameId
952
- gameName: string // gameName
953
- }
954
-
955
- export interface DNALoginRes {
956
- applyCancel?: number // applyCancel
957
- gender?: number // gender
958
- signature?: string // signature
959
- headUrl: string // headUrl
960
- userName: string // userName
961
- userId: string // userId
962
- isOfficial: number // isOfficial
963
- token: string // token
964
- userGameList: UserGame[] // userGameList
965
- isRegister: number // isRegister
966
- status: number // status
967
- /** 是否完成绑定 0: 未绑定, 1: 已绑定 */
968
- isComplete: number
969
- refreshToken: string // refreshToken
970
- }
971
-
972
- export interface DNARoleShowVo {
973
- roleId: string // roleId
974
- headUrl?: string // headUrl
975
- level?: number // level
976
- roleName?: string // roleName
977
- isDefault?: number // isDefault
978
- roleRegisterTime?: string // roleRegisterTime
979
- boundType?: number // boundType
980
- roleBoundId: string // roleBoundId
981
- }
982
-
983
- export interface DNARole {
984
- gameName: string // gameName
985
- showVoList: DNARoleShowVo[] // showVoList
986
- gameId: number // gameId
987
- }
988
-
989
- export interface DNARoleListRes {
990
- roles: DNARole[] // roles
991
- }
992
-
993
- /** 密函 */
994
- export interface DNARoleForToolInstance {
995
- id: number
996
- /** 中文 */
997
- name: string
998
- /** 密函编码 */
999
- code: string
1000
- /** 固定0 */
1001
- on: number
1002
- }
1003
-
1004
- export interface DNARoleForToolInstanceInfo {
1005
- /** 密函列表 */
1006
- instances: DNARoleForToolInstance[] // instances
1007
- }
1008
-
1009
- export interface DraftDoingInfo {
1010
- draftCompleteNum: number // draftCompleteNum
1011
- draftDoingNum: number // draftDoingNum
1012
- /** 结束时间 */
1013
- endTime: string
1014
- /** 产品id */
1015
- productId?: number
1016
- /** 产品名称 */
1017
- productName: string
1018
- /** 开始时间 */
1019
- startTime: string
1020
- }
1021
-
1022
- export interface DraftInfo {
1023
- /** 正在做的锻造 */
1024
- draftDoingInfo?: DraftDoingInfo[]
1025
- /** 正在做的锻造数量 */
1026
- draftDoingNum: number
1027
- /** 最大锻造数量 */
1028
- draftMaxNum: number
1029
- }
1030
-
1031
- export interface DNARoleShortNoteRes {
1032
- /** 迷津进度 */
1033
- rougeLikeRewardCount: number
1034
- /** 迷津总数 */
1035
- rougeLikeRewardTotal: number
1036
- /** 备忘手记进度 */
1037
- currentTaskProgress: number
1038
- /** 备忘手记总数 */
1039
- maxDailyTaskProgress: number
1040
- /** 梦魇进度 */
1041
- hardBossRewardCount: number
1042
- /** 梦魇总数 */
1043
- hardBossRewardTotal: number
1044
- /** 锻造信息 */
1045
- draftInfo: DraftInfo
1046
- }
1047
-
1048
- export interface DNARoleWeapon {
1049
- weaponId: number
1050
- weaponEid: string
1051
- /** 武器类型图标 */
1052
- elementIcon: string
1053
- /** 武器图标 */
1054
- icon: string
1055
- /** 武器等级 */
1056
- level: number
1057
- /** 武器名称 */
1058
- name: string
1059
- /** 精炼等级 */
1060
- skillLevel: number
1061
- /** 是否解锁 */
1062
- unLocked: boolean
1063
- }
1064
-
1065
- export interface DNARoleChar {
1066
- charId: number
1067
- charEid: string
1068
- /** 元素图标 */
1069
- elementIcon: string
1070
- /** 命座等级 */
1071
- gradeLevel: number
1072
- /** 角色图标 */
1073
- icon: string
1074
- /** 角色等级 */
1075
- level: number
1076
- /** 角色名称 */
1077
- name: string
1078
- /** 是否解锁 */
1079
- unLocked: boolean
1080
- }
1081
-
1082
- export interface DNARoleForToolRes {
1083
- /** 角色信息 */
1084
- roleInfo: DNARoleInfo
1085
- /** 密函 */
1086
- instanceInfo: DNARoleForToolInstanceInfo[]
1087
- }
1088
-
1089
- export interface DNARoleShow {
1090
- /** 角色列表 */
1091
- roleChars: DNARoleChar[]
1092
- /** 武器列表 */
1093
- langRangeWeapons: DNARoleWeapon[]
1094
- /** 武器列表 */
1095
- closeWeapons: DNARoleWeapon[]
1096
- /** 角色头像 */
1097
- headUrl: string
1098
- /** 等级 */
1099
- level: number
1100
- /** 成就列表 */
1101
- params: DNARoleAchievement[]
1102
- /** 角色id */
1103
- roleId: string
1104
- /** 角色名称 */
1105
- roleName: string
1106
- /** 迷津 */
1107
- rougeLikeInfo: DNARougeLikeInfo
1108
- }
1109
-
1110
- export interface DNARoleAchievement {
1111
- paramKey: string // paramKey
1112
- paramValue: string // paramValue
1113
- }
1114
-
1115
- export interface DNARoleInfo {
1116
- /** 深渊信息 */
1117
- abyssInfo: DNAAbyssInfo
1118
- /** 角色信息 */
1119
- roleShow: DNARoleShow
1120
- }
1121
-
1122
- export interface DNARougeLikeInfo {
1123
- /** 最大通过等级 */
1124
- maxPassed: number
1125
- /** 最大通过等级名称 */
1126
- maxPassedName: string
1127
- /** 重置时间 */
1128
- resetTime: string
1129
- /** 奖励数量 */
1130
- rewardCount: number
1131
- /** 奖励总数 */
1132
- rewardTotal: number
1133
- /** 天赋信息 */
1134
- talentInfo: DNARougeLikeTalentInfo[]
1135
- }
1136
-
1137
- export interface DNARougeLikeTalentInfo {
1138
- cur: string
1139
- max: string
1140
- }
1141
-
1142
- export interface DNAAbyssInfo {
1143
- /** 阵容 */
1144
- bestTimeVo1: DNABestTimeVo1
1145
- /** 结束时间 */
1146
- endTime: string
1147
- /** 操作名称 */
1148
- operaName: string
1149
- /** 进度名称 */
1150
- progressName: string
1151
- /** 星级 */
1152
- stars: string
1153
- /** 开始时间 */
1154
- startTime: string
1155
- }
1156
-
1157
- /** 深渊阵容 */
1158
- export interface DNABestTimeVo1 {
1159
- /** 角色图标 */
1160
- charIcon: string
1161
- /** 近战武器图标 */
1162
- closeWeaponIcon: string
1163
- /** 远程武器图标 */
1164
- langRangeWeaponIcon: string
1165
- /** 魔灵图标 */
1166
- petIcon: string
1167
- /** 协战角色图标1 */
1168
- phantomCharIcon1: string
1169
- /** 协战武器图标1 */
1170
- phantomWeaponIcon1: string
1171
- /** 协战角色图标2 */
1172
- phantomCharIcon2: string
1173
- /** 协战武器图标2 */
1174
- phantomWeaponIcon2: string
1175
- }
1176
-
1177
- /** 角色属性 */
1178
- export interface DNACharAttribute {
1179
- /** 技能范围 */
1180
- skillRange: string
1181
- /** 强化值 */
1182
- strongValue: string
1183
- /** 技能威力 */
1184
- skillIntensity: string
1185
- /** 武器精通 */
1186
- weaponTags: string[]
1187
- /** 防御 */
1188
- def: number
1189
- /** 仇恨值 */
1190
- enmityValue: string
1191
- /** 技能效益 */
1192
- skillEfficiency: string
1193
- /** 技能耐久 */
1194
- skillSustain: string
1195
- /** 最大生命值 */
1196
- maxHp: number
1197
- /** 攻击 */
1198
- atk: number
1199
- /** 最大护盾 */
1200
- maxES: number
1201
- /** 最大神志 */
1202
- maxSp: number
1203
- }
1204
-
1205
- /** 角色技能 */
1206
- export interface DNARoleSkill {
1207
- /** 技能id */
1208
- skillId: number
1209
- /** 技能图标 */
1210
- icon: string
1211
- /** 技能等级 */
1212
- level: number
1213
- /** 技能名称 */
1214
- skillName: string
1215
- }
1216
-
1217
- /** 溯源 */
1218
- export interface DNARoleTrace {
1219
- /** 溯源图标 */
1220
- icon: string
1221
- /** 溯源描述 */
1222
- description: string
1223
- }
1224
-
1225
- /** 魔之楔 */
1226
- export interface DNARoleMod {
1227
- /** id 没佩戴为-1 */
1228
- id: number
1229
- /** 图标 */
1230
- icon?: string
1231
- /** 质量 */
1232
- quality?: number
1233
- /** 名称 */
1234
- name?: string
1235
- }
1236
-
1237
- export interface DNACharDetail {
1238
- charId: number
1239
- /** 角色属性 */
1240
- attribute: DNACharAttribute
1241
- /** 角色技能 */
1242
- skills: DNARoleSkill[]
1243
- /** 立绘 */
1244
- paint: string
1245
- /** 角色名称 */
1246
- charName: string
1247
- /** 元素图标 */
1248
- elementIcon: string
1249
- /** 溯源 */
1250
- traces: DNARoleTrace[]
1251
- /** 当前魔之楔 */
1252
- currentVolume: number
1253
- /** 最大魔之楔 */
1254
- sumVolume: number
1255
- /** 角色等级 */
1256
- level: number
1257
- /** 角色头像 */
1258
- icon: string
1259
- /** 溯源等级 0-6 */
1260
- gradeLevel: number
1261
- /** 元素名称 */
1262
- elementName: string
1263
- /** 魔之楔列表 */
1264
- modes: DNARoleMod[]
1265
- }
1266
-
1267
- export interface DNACharDetailRes {
1268
- /** 角色详情 */
1269
- charDetail: DNACharDetail
1270
- }
1271
-
1272
- export interface DNAWeaponDetailRes {
1273
- /** 武器详情 */
1274
- weaponDetail: DNAWeaponDetail
1275
- }
1276
-
1277
- export interface DNAWeaponDetail {
1278
- attribute: DNAWeaponAttribute
1279
- currentVolume: number
1280
- description: string
1281
- elementIcon: string
1282
- elementName: string
1283
- icon: string
1284
- id: number
1285
- level: number
1286
- modes: DNARoleMod[]
1287
- name: string
1288
- skillLevel: number
1289
- sumVolume: number
1290
- }
1291
-
1292
- export interface DNAWeaponAttribute {
1293
- atk: number
1294
- crd: number
1295
- cri: number
1296
- speed: number
1297
- trigger: number
1298
- }
1299
-
1300
- export interface DNADayAward {
1301
- gameId: number // gameId
1302
- periodId: number // periodId
1303
- iconUrl: string // iconUrl
1304
- id: number // id
1305
- dayInPeriod: number // dayInPeriod
1306
- updateTime: number // updateTime
1307
- awardNum: number // awardNum
1308
- thirdProductId: string // thirdProductId
1309
- createTime: number // createTime
1310
- awardName: string // awardName
1311
- }
1312
-
1313
- export interface DNACaSignPeriod {
1314
- gameId: number // gameId
1315
- retryCos: number // retryCos
1316
- endDate: number // endDate
1317
- id: number // id
1318
- startDate: number // startDate
1319
- retryTimes: number // retryTimes
1320
- overDays: number // overDays
1321
- createTime: number // createTime
1322
- name: string // name
1323
- }
1324
-
1325
- export interface DNACaSignRoleInfo {
1326
- headUrl: string // headUrl
1327
- roleId: string // roleId
1328
- roleName: string // roleName
1329
- level: number // level
1330
- roleBoundId: string // roleBoundId
1331
- }
1332
-
1333
- export interface DNAHaveSignInRes {
1334
- /** 已签到天数 */
1335
- totalSignInDay: number
1336
- }
1337
-
1338
- export interface DNACalendarSignRes {
1339
- todaySignin: boolean // todaySignin
1340
- userGoldNum: number // userGoldNum
1341
- dayAward: DNADayAward[] // dayAward
1342
- signinTime: number // signinTime
1343
- period: DNACaSignPeriod // period
1344
- roleInfo: DNACaSignRoleInfo // roleInfo
1345
- }
1346
-
1347
- export interface DNABBSTask {
1348
- /** 备注 */
1349
- remark: string
1350
- /** 完成次数 */
1351
- completeTimes: number
1352
- /** 需要次数 */
1353
- times: number
1354
- /** skipType */
1355
- skipType: number
1356
- /** 获取经验 */
1357
- gainExp: number
1358
- /** 进度 */
1359
- process: number
1360
- /** 获取金币 */
1361
- gainGold: number
1362
- /** 任务标识名 */
1363
- markName?: string
1364
- }
1365
-
1366
- export interface DNATaskProcessRes {
1367
- dailyTask: DNABBSTask[] // dailyTask
1368
- }
1369
-
1370
- export interface DNATopicPostListRes {
1371
- postList: DNAPost[]
1372
- topic: DNATopicDetail
1373
- hasNext: number
1374
- }
1375
-
1376
- export interface DNATopicDetail {
1377
- backgroundUrl: string
1378
- gameId: number
1379
- sort: number
1380
- topicDesc: string
1381
- topicIconUrl: string
1382
- topicId: number
1383
- topicName: string
1384
- }
1385
-
1386
- export interface DNAPost {
1387
- browseCount: string
1388
- collectionCount: number
1389
- commentCount: number
1390
- gameForumId: number
1391
- gameId: number
1392
- gameName: string
1393
- imgContent: DNAPostImgContent[]
1394
- imgCount: number
1395
- isCollect: number
1396
- isCreator: number
1397
- isElite: number
1398
- isFollow: number
1399
- isLike: number
1400
- isLock: number
1401
- isOfficial: number
1402
- isPublisher: number
1403
- likeCount: number
1404
- postContent: string
1405
- postCover: string
1406
- postCoverVo: DNAPostCoverVo
1407
- postId: string
1408
- postStatus: number
1409
- postTitle: string
1410
- postType: number
1411
- showTime: string
1412
- topics: DNATopicShort[]
1413
- userHeadUrl: string
1414
- userId: string
1415
- userLevel: number
1416
- userModeratorIdentity: number
1417
- userName: string
1418
- }
1419
-
1420
- export interface DNATopicShort {
1421
- topicId: number
1422
- topicName: string
1423
- }
1424
-
1425
- export interface DNAPostCoverVo {
1426
- imgHeight: number
1427
- imgWidth: number
1428
- }
1429
-
1430
- export interface DNAPostImgContent {
1431
- imgHeight: number
1432
- imgWidth: number
1433
- url: string
1434
- isAbnormal?: boolean
1435
- }
1436
-
1437
- export interface DNAPostListRes {
1438
- postList: DNAPost[] // posts
1439
- topList: any[]
1440
- hasNext: number
1441
- }
1442
-
1443
- export interface DNAPostDetailRes {
1444
- isHotCount: boolean
1445
- gameId: number
1446
- isFollow: number
1447
- isLike: number
1448
- postDetail: DNAPostDetail
1449
- isCollect: number
1450
- hasNext: number
1451
- comment: DNAComment[]
1452
- }
1453
-
1454
- export interface DNAPostDetail {
1455
- auditStatus: number
1456
- browseCount: string
1457
- checkStatus: number
1458
- collectionCount: number
1459
- commentCount: number
1460
- gameForumId: number
1461
- gameForumVo: DNAGameForumVo
1462
- gameId: number
1463
- gameName: string
1464
- headCodeUrl: string
1465
- id: string
1466
- isCreator: number
1467
- isElite: number
1468
- isForceRecommend: number
1469
- isHide: number
1470
- isLock: number
1471
- isMine: number
1472
- isOfficial: number
1473
- isRecommend: number
1474
- isTop: number
1475
- lastEditorTime?: string
1476
- likeCount: number
1477
- postContent: DNAPostContent[]
1478
- postH5Content: string
1479
- postTime: string
1480
- postTitle: string
1481
- postType: number
1482
- postUserId: string
1483
- refreshHour: number
1484
- score: number
1485
- topics: DNATopicShort[]
1486
- userHeadCode: string
1487
- userLevel: number
1488
- userModeratorIdentity: number
1489
- userName: string
1490
- whiteUrl: any[]
1491
- }
1492
-
1493
- export interface DNAPostContent {
1494
- contentType: PostContentType
1495
- imgHeight: number
1496
- imgWidth: number
1497
- url?: string
1498
- content?: string
1499
- contentVideo?: DNAPostContentVideo
1500
- }
1501
-
1502
- export interface DNAComment {
1503
- checkStatus: number
1504
- commentContent: DNAPostContent[]
1505
- commentId: string
1506
- commentTime: string
1507
- contentTextStatus: number
1508
- floor: number
1509
- isCreator: number
1510
- isLike: number
1511
- isMine: number
1512
- isOfficial: number
1513
- isPublisher: number
1514
- likeCount: number
1515
- replyCount: number
1516
- replyVos: DNAReplyVos[]
1517
- userHeadCode?: string
1518
- userHeadUrl: string
1519
- userId: string
1520
- userLevel: number
1521
- userModeratorIdentity: number
1522
- userName: string
1523
- }
1524
-
1525
- export interface DNAReplyVos {
1526
- checkStatus: number
1527
- contentTextStatus: number
1528
- createTime: number
1529
- isCreator: number
1530
- isLike: number
1531
- isMine: number
1532
- isOfficial: number
1533
- isPublisher: number
1534
- likeCount: number
1535
- postCommentId: string
1536
- postCommentReplayId: string
1537
- replyContent: DNAPostContent[]
1538
- replyContentStr: string
1539
- replyId: string
1540
- replyTime: string
1541
- toUserIsCreator: number
1542
- toUserModeratorIdentity: number
1543
- toUserName: string
1544
- userHeadCode?: string
1545
- userHeadUrl: string
1546
- userId: string
1547
- userLevel: number
1548
- userModeratorIdentity: number
1549
- userName: string
1550
- }
1551
-
1552
- export interface DNAGameForumVo {
1553
- forumDataType: number
1554
- forumListShowType: number
1555
- forumType: number
1556
- forumUiType: number
1557
- iconUrl: string
1558
- iconWhiteUrl: string
1559
- id: number
1560
- isOfficial: number
1561
- isTrend: number
1562
- name: string
1563
- sort: number
1564
- }
1565
-
1566
- export enum PostContentType {
1567
- TEXT = 1,
1568
- IMAGE = 2,
1569
- VIDEO = 5,
1570
- }
1571
-
1572
- export interface DNAPostContentVideo {
1573
- videoUrl: string // videoUrl
1574
- coverUrl?: string // coverUrl
1575
- }
1576
-
1577
- class DNAApiResponse<T = any> {
1578
- code: number = 0
1579
- msg: string = ""
1580
- success: boolean = false
1581
- data?: T
1582
-
1583
- constructor(raw_data: any) {
1584
- this.code = raw_data.code || 0
1585
- this.msg = raw_data.msg || ""
1586
- this.success = raw_data.success || false
1587
- this.data = raw_data.data
1588
- }
1589
-
1590
- // 判断是否成功
1591
- get is_success() {
1592
- return this.success && [RespCode.OK_ZERO, RespCode.OK_HTTP].includes(this.code)
1593
- }
1594
-
1595
- // 错误响应静态方法
1596
- static err<T = undefined>(msg: string, code: number = RespCode.ERROR): DNAApiResponse<T> {
1597
- return new DNAApiResponse<T>({ code, msg, data: undefined, success: false })
1598
- }
1599
- }
1600
- //#endregion
1601
-
1602
- //#region utils
1603
-
1604
- // RSA加密函数
1605
- function rsa_encrypt(text: string, public_key_b64: string): string {
1606
- try {
1607
- // 将base64公钥转换为PEM格式
1608
- const lines: string[] = []
1609
- for (let i = 0; i < public_key_b64.length; i += 64) {
1610
- lines.push(public_key_b64.slice(i, i + 64))
1611
- }
1612
- const pem = `-----BEGIN PUBLIC KEY-----\n${lines.join("\n")}\n-----END PUBLIC KEY-----`
1613
-
1614
- // 导入PEM格式的RSA公钥
1615
- const publicKey = forge.pki.publicKeyFromPem(pem)
1616
-
1617
- // 执行PKCS1_v1_5加密
1618
- const textBytes = forge.util.encodeUtf8(text)
1619
- const encrypted = publicKey.encrypt(textBytes)
1620
-
1621
- return forge.util.encode64(encrypted)
1622
- } catch (e) {
1623
- throw new Error(`[DNA] RSA 加密失败: ${(e as Error).message}`)
1624
- }
1625
- }
1626
-
1627
- // 生成随机字符串
1628
- function rand_str(length: number = 16): string {
1629
- const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
1630
- let result = ""
1631
- for (let i = 0; i < length; i++) {
1632
- result += chars.charAt(Math.floor(Math.random() * chars.length))
1633
- }
1634
- return result
1635
- }
1636
-
1637
- // MD5加密并转换为大写
1638
- function md5_upper(text: string): string {
1639
- const md = forge.md.md5.create()
1640
- md.update(text)
1641
- return md.digest().toHex().toUpperCase()
1642
- }
1643
-
1644
- // 签名哈希函数
1645
- function signature_hash(text: string): string {
1646
- function swap_positions(text: string, positions: number[]): string {
1647
- const chars = text.split("")
1648
- for (let i = 1; i < positions.length; i += 2) {
1649
- const p1 = positions[i - 1]
1650
- const p2 = positions[i]
1651
- if (p1 >= 0 && p1 < chars.length && p2 >= 0 && p2 < chars.length) {
1652
- ;[chars[p1], chars[p2]] = [chars[p2], chars[p1]]
1653
- }
1654
- }
1655
- return chars.join("")
1656
- }
1657
- return swap_positions(md5_upper(text), [1, 13, 5, 17, 7, 23])
1658
- }
1659
-
1660
- // 签名函数
1661
- function sign_fI(data: Record<string, any>, secret: string): string {
1662
- const pairs: string[] = []
1663
- const sortedKeys = Object.keys(data).sort()
1664
- for (const k of sortedKeys) {
1665
- const v = data[k]
1666
- if (v !== null && v !== undefined && v !== "") {
1667
- pairs.push(`${k}=${v}`)
1668
- }
1669
- }
1670
- const qs = pairs.join("&")
1671
- return signature_hash(`${qs}&${secret}`)
1672
- }
1673
-
1674
- // XOR编码函数
1675
- function xor_encode(text: string, key: string): string {
1676
- const encoder = new TextEncoder()
1677
- const tb = encoder.encode(text)
1678
- const kb = encoder.encode(key)
1679
- const out: string[] = []
1680
- for (let i = 0; i < tb.length; i++) {
1681
- const b = tb[i]
1682
- const e = (b & 255) + (kb[i % kb.length] & 255)
1683
- out.push(`@${e}`)
1684
- }
1685
- return out.join("")
1686
- }
1687
-
1688
- // 上传图片签名 - 字符交换
1689
- function swapForUploadImgApp(text: string): string {
1690
- const chars = text.split("")
1691
- const swaps = [
1692
- [3, 23],
1693
- [11, 32],
1694
- [22, 42],
1695
- [25, 48],
1696
- ]
1697
- for (const [p1, p2] of swaps) {
1698
- if (p1 < chars.length && p2 < chars.length) {
1699
- ;[chars[p1], chars[p2]] = [chars[p2], chars[p1]]
1700
- }
1701
- }
1702
- return chars.join("")
1703
- }
1704
-
1705
- // AES 解密图片 URL
1706
- function aesDecryptImageUrl(encryptedUrl: string, key: string): string {
1707
- const swapped = swapForUploadImgApp(encryptedUrl)
1708
-
1709
- const encryptedData = forge.util.decode64(swapped)
1710
-
1711
- const decipher = forge.cipher.createDecipher("AES-CBC", key)
1712
- decipher.start({ iv: "A-16-Byte-String" })
1713
- decipher.update(forge.util.createBuffer(encryptedData))
1714
- decipher.finish()
1715
-
1716
- return decipher.output.getBytes()
1717
- }
1718
-
1719
- // 构建上传图片签名(返回签名和密钥)
1720
- function build_upload_signature(public_key: string): { signature: string; key: string } {
1721
- const key = rand_str(16)
1722
- const encrypted = rsa_encrypt(key, public_key)
1723
- const signature = swapForUploadImgApp(encrypted)
1724
- return { signature, key }
1725
- }
1726
-
1727
- // 构建普通签名
1728
- function build_signature(data: Record<string, any>, token?: string): Record<string, any> {
1729
- const ts = Date.now()
1730
- const sign_data = { ...data, timestamp: ts, token }
1731
- const sec = rand_str(16)
1732
- const sig = sign_fI(sign_data, sec)
1733
- const enc = xor_encode(sig, sec)
1734
- return { s: enc, t: ts, k: sec }
1735
- }
1736
- //#endregion