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