dna-api 0.2.1 → 0.2.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/dist/index.d.ts CHANGED
@@ -3,7 +3,6 @@
3
3
  */
4
4
  export declare class DNAAPI {
5
5
  dev_code: string;
6
- uid: string;
7
6
  token: string;
8
7
  fetchFn: typeof fetch;
9
8
  is_h5: boolean;
@@ -18,7 +17,7 @@ export declare class DNAAPI {
18
17
  * @param options.is_h5 是否为H5端
19
18
  * @param options.rsa_public_key RSA公钥(base64) 设为空字符串从服务器获取
20
19
  */
21
- constructor(dev_code: string, uid?: string, token?: string, options?: {
20
+ constructor(dev_code: string, token?: string, options?: {
22
21
  fetchFn?: typeof fetch;
23
22
  is_h5?: boolean;
24
23
  rsa_public_key?: string;
@@ -31,7 +30,7 @@ export declare class DNAAPI {
31
30
  /**
32
31
  * 登录
33
32
  */
34
- login(mobile: string, code: string, dev_code: string): Promise<DNAApiResponse<DNALoginRes>>;
33
+ login(mobile: string, code: string): Promise<DNAApiResponse<DNALoginRes>>;
35
34
  /**
36
35
  * 获取登录日志
37
36
  */
@@ -96,18 +95,61 @@ export declare class DNAAPI {
96
95
  doShare(): Promise<DNAApiResponse<any>>;
97
96
  doReply(post: Record<string, any>, content: string): Promise<DNAApiResponse<any>>;
98
97
  getAnnList(): Promise<DNAApiResponse<DNAPostListRes>>;
98
+ getGameConfig(): Promise<DNAApiResponse<DNAGameConfigRes>>;
99
99
  getHeaders(options?: {
100
100
  payload?: Record<string, any> | string;
101
101
  exparams?: Record<string, any>;
102
102
  dev_code?: string;
103
103
  refer?: boolean;
104
104
  token?: string;
105
+ tokenSig?: boolean;
105
106
  }): Promise<{
106
107
  headers: Record<string, any>;
107
108
  payload: string | undefined;
108
109
  }>;
109
110
  private _dna_request;
110
111
  }
112
+ export interface DNAGameConfigRes {
113
+ /** 游戏背景图 */
114
+ backgroundUrl: string;
115
+ /** 游戏封面图 */
116
+ coverUrl: string;
117
+ /** 默认游戏 */
118
+ gameDefault: number;
119
+ /** 游戏ID */
120
+ gameId: number;
121
+ /** 游戏名称 */
122
+ gameName: string;
123
+ /** 游戏描述 */
124
+ gameDesc: string;
125
+ gameForumList: GameForum[];
126
+ gameAllForumList: GameForum[];
127
+ /** 游戏板块图片列表 */
128
+ gameForumPictureList: unknown[];
129
+ /** 游戏Wiki列表 */
130
+ gameWikiVoList: GameWikiVo[];
131
+ }
132
+ export interface GameWikiVo {
133
+ id: number;
134
+ iconUrl: string;
135
+ param: {
136
+ postId: string;
137
+ topicId: string;
138
+ };
139
+ postId: string;
140
+ toAppAndroid: string;
141
+ url: string;
142
+ wikiName: string;
143
+ wikiType: number;
144
+ }
145
+ export interface GameForum {
146
+ /** 游戏ID */
147
+ gameId: number;
148
+ /** 板块ID */
149
+ forumId: number;
150
+ /** 板块名称 */
151
+ forumName: string;
152
+ }
111
153
  export interface UserGame {
112
154
  gameId: number;
113
155
  gameName: string;
@@ -221,6 +263,7 @@ export interface WeaponInsForTool {
221
263
  }
222
264
  export interface RoleInsForTool {
223
265
  charEid?: string;
266
+ /** 角色id */
224
267
  charId: number;
225
268
  /** 元素图标 */
226
269
  elementIcon: string;
@@ -246,6 +289,8 @@ export interface RoleShowForTool {
246
289
  langRangeWeapons: WeaponInsForTool[];
247
290
  /** 武器列表 */
248
291
  closeWeapons: WeaponInsForTool[];
292
+ /** 角色头像 */
293
+ headUrl: string;
249
294
  /** 等级 */
250
295
  level: number;
251
296
  /** 成就列表 */
@@ -254,8 +299,12 @@ export interface RoleShowForTool {
254
299
  roleId: string;
255
300
  /** 角色名称 */
256
301
  roleName: string;
302
+ /** 迷津 */
303
+ rougeLikeInfo: RougeLikeInfo;
257
304
  }
258
305
  export interface RoleInfoForTool {
306
+ /** 深渊信息 */
307
+ abyssInfo: AbyssInfo;
259
308
  /** 角色信息 */
260
309
  roleShow: RoleShowForTool;
261
310
  }
@@ -265,6 +314,52 @@ export interface DNARoleForToolRes {
265
314
  /** 密函 */
266
315
  instanceInfo: DNARoleForToolInstanceInfo[];
267
316
  }
317
+ export interface RougeLikeInfo {
318
+ /** 最大通过等级 */
319
+ maxPassed: number;
320
+ /** 最大通过等级名称 */
321
+ maxPassedName: string;
322
+ /** 重置时间 */
323
+ resetTime: string;
324
+ /** 奖励数量 */
325
+ rewardCount: number;
326
+ /** 奖励总数 */
327
+ rewardTotal: number;
328
+ /** 天赋信息 */
329
+ talentInfo: RougeLikeTalentInfo[];
330
+ }
331
+ export interface RougeLikeTalentInfo {
332
+ cur: string;
333
+ max: string;
334
+ }
335
+ export interface AbyssInfo {
336
+ /** 最佳时间 */
337
+ bestTimeVo1: BestTimeVo1;
338
+ /** 结束时间 */
339
+ endTime: string;
340
+ /** 操作名称 */
341
+ operaName: string;
342
+ /** 进度名称 */
343
+ progressName: string;
344
+ /** 星级 */
345
+ stars: string;
346
+ /** 开始时间 */
347
+ startTime: string;
348
+ }
349
+ export interface BestTimeVo1 {
350
+ /** 角色图标 */
351
+ charIcon: string;
352
+ /** 近战武器图标 */
353
+ closeWeaponIcon: string;
354
+ /** 远程武器图标 */
355
+ langRangeWeaponIcon: string;
356
+ /** 魔灵图标 */
357
+ petIcon: string;
358
+ phantomCharIcon1: string;
359
+ phantomCharIcon2: string;
360
+ phantomWeaponIcon1: string;
361
+ phantomWeaponIcon2: string;
362
+ }
268
363
  export interface RoleAttribute {
269
364
  /** 技能范围 */
270
365
  skillRange: string;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import*as g from"node-forge";var F="https://dnabbs-api.yingxiong.com",S=`${F}/user/sdkLogin`,m=`${F}/config/getRsaPublicKey`,w=`${F}/user/login/log`,C=`${F}/role/list`,k=`${F}/role/defaultRoleForTool`,E=`${F}/role/getCharDetail`,h=`${F}/weapon/detail`,l=`${F}/role/getShortNoteInfo`,T=`${F}/encourage/signin/show`,M=`${F}/encourage/signin/signin`,U=`${F}/user/signIn`,D=`${F}/user/haveSignInNew`,y=`${F}/encourage/level/getTaskProcess`,c=`${F}/forum/list`,I=`${F}/forum/getPostDetail`,L=`${F}/forum/like`,N=`${F}/encourage/level/shareTask`,R=`${F}/forum/comment/createComment`,A=`${F}/user/mine`;var K=268;class i{dev_code;uid;token;fetchFn;is_h5=!1;rsa_public_key="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGpdbezK+eknQZQzPOjp8mr/dP+QHwk8CRkQh6C6qFnfLH3tiyl0pnt3dePuFDnM1PUXGhCkQ157ePJCQgkDU2+mimDmXh0oLFn9zuWSp+U8uLSLX3t3PpJ8TmNCROfUDWvzdbnShqg7JfDmnrOJz49qd234W84nrfTHbzdqeigQIDAQAB";constructor(z,J="",Z="",Q={}){this.dev_code=z;this.uid=J;this.token=Z;if(this.fetchFn=Q.fetchFn||fetch.bind(window),Q.is_h5!==void 0)this.is_h5=Q.is_h5;if(Q.rsa_public_key!==void 0)this.rsa_public_key=Q.rsa_public_key}async getRsaPublicKey(){if(this.rsa_public_key)return this.rsa_public_key;let z=await this._dna_request(m);if(z.is_success&&z.data){let J=z.data.key;if(typeof J==="string")this.rsa_public_key=J}return this.rsa_public_key}async login(z,J,Z){let Q={mobile:z,code:J,gameList:K},$=await this._dna_request(S,Q,{sign:!0,refer:!0});if($.is_success&&$.data){let q=$.data;if(typeof q.userId==="string")this.uid=q.userId;if(typeof q.token==="string")this.token=q.token}return $}async loginLog(){return await this._dna_request(w)}async getRoleList(){return await this._dna_request(C)}async getDefaultRoleForTool(){let z={type:1};return await this._dna_request(k,z,{sign:!0})}async getRoleDetail(z,J){let Z={charId:z,charEid:J,type:1};return await this._dna_request(E,Z)}async getWeaponDetail(z){let J={weaponId:z,type:1};return await this._dna_request(h,J)}async getShortNoteInfo(){return await this._dna_request(l)}async haveSignIn(){let z={gameId:K};return await this._dna_request(D,z)}async signCalendar(){let z={gameId:K};return await this._dna_request(T,z)}async gameSign(z,J){let Z={dayAwardId:z,periodId:J,signinType:1};return await this._dna_request(M,Z)}async bbsSign(){let z={gameId:K};return await this._dna_request(U,z)}async getTaskProcess(){let z={gameId:K};return await this._dna_request(y,z)}async getPostList(){let z={forumId:46,gameId:K,pageIndex:1,pageSize:20,searchType:1,timeType:0};return await this._dna_request(c,z)}async getPostDetail(z){let J={postId:z};try{return await this._dna_request(I,J)}catch(Z){return console.error("get_post_detail",Z),v.err("请求皎皎角服务失败")}}async doLike(z){let J={forumId:z.gameForumId,gameId:K,likeType:"1",operateType:"1",postCommentId:"",postCommentReplyId:"",postId:z.postId,postType:z.postType,toUserId:z.userId};try{return await this._dna_request(L,J)}catch(Z){return console.error("do_like",Z),v.err("请求皎皎角服务失败")}}async doShare(){let z={gameId:K};try{return await this._dna_request(N,z)}catch(J){return console.error("do_share",J),v.err("请求皎皎角服务失败")}}async doReply(z,J){let Z=JSON.stringify([{content:J,contentType:"1",imgHeight:0,imgWidth:0,url:""}]),Q={postId:z.postId,forumId:z.gameForumId||47,postType:"1",content:Z};return await this._dna_request(R,Q,{sign:!0,refer:!0,params:{toUserId:z.userId}})}async getAnnList(){let z={otherUserId:"709542994134436647",searchType:1,type:2};return await this._dna_request(A,z)}async getHeaders(z){let{payload:J,exparams:Z,dev_code:Q=this.dev_code,refer:$,token:q=this.token}=z||{},j="application/x-www-form-urlencoded; charset=utf-8",V={version:"1.1.3",source:"ios","Content-Type":"application/x-www-form-urlencoded; charset=utf-8","User-Agent":"DoubleHelix/4 CFNetwork/3860.100.1 Darwin/25.0.0"},b={version:"3.11.0",source:"h5","Content-Type":"application/x-www-form-urlencoded; charset=utf-8","User-Agent":"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"},X={...this.is_h5?b:V};if(Q)X.devCode=Q;if($)X.origin="https://dnabbs.yingxiong.com",X.refer="https://dnabbs.yingxiong.com/";if(q)X.token=q;if(typeof J==="object"){let f=a(J);if(Object.assign(J,{sign:f.s,timestamp:f.t}),Z)Object.assign(J,Z);let W=new URLSearchParams;Object.entries(J).forEach(([x,G])=>{W.append(x,String(G))}),J=W.toString();let B=f.k,H=await this.getRsaPublicKey(),P=r(B,H);if(this.is_h5)X.k=P;else X.rk=B,X.key=P}return{headers:X,payload:J}}async _dna_request(z,J,Z){let{method:Q="POST",sign:$,refer:q,params:j,max_retries:V=3,retry_delay:b=1,timeout:X=1e4}=Z||{},f;if($){let{payload:W,headers:B}=await this.getHeaders({payload:J,refer:q,exparams:j});J=W,f=B}else{let{headers:W}=await this.getHeaders();f=W}for(let W=0;W<V;W++)try{let B={method:Q,headers:f,body:J},H=new AbortController,P=setTimeout(()=>H.abort(),X),x=await this.fetchFn(z,{...B,signal:H.signal});clearTimeout(P);let G=x.headers.get("content-type")||"",Y;if(G.includes("text/")){let O=await x.text();Y={code:-999,data:O}}else Y=await x.json();if(typeof Y==="object"&&Y!==null)try{if(typeof Y.data==="string")Y.data=JSON.parse(Y.data)}catch(O){}return console.debug(`[DNA] url:[${z}] headers:[${JSON.stringify(f)}] data:[${JSON.stringify(J)}] raw_res:${JSON.stringify(Y)}`),new v(Y)}catch(B){if(console.error(`请求失败: ${B.message}`),W<V-1)await new Promise((H)=>setTimeout(H,b*Math.pow(2,W)))}return v.err("请求服务器失败,已达最大重试次数")}}var u;((j)=>{j.角色="role";j.武器="weapon";j.魔之楔="mzx";j.role="角色";j.weapon="武器";j.mzx="魔之楔"})(u||={});function t(z){return u[z]}var n;((Q)=>{Q[Q.TEXT=1]="TEXT";Q[Q.IMAGE=2]="IMAGE";Q[Q.VIDEO=5]="VIDEO"})(n||={});class v{code=0;msg="";success=!1;data;constructor(z){this.code=z.code||0,this.msg=z.msg||"",this.success=z.success||!1,this.data=z.data}get is_success(){return this.success&&[0,200].includes(this.code)}static err(z,J=-999){return new v({code:J,msg:z,data:void 0,success:!1})}}function r(z,J){try{let Z=[];for(let V=0;V<J.length;V+=64)Z.push(J.slice(V,V+64));let Q=`-----BEGIN PUBLIC KEY-----
2
- ${Z.join(`
1
+ import*as g from"node-forge";var V="https://dnabbs-api.yingxiong.com",S=`${V}/user/sdkLogin`,G=`${V}/config/getRsaPublicKey`,k=`${V}/user/login/log`,h=`${V}/role/list`,E=`${V}/role/defaultRoleForTool`,l=`${V}/role/getCharDetail`,T=`${V}/weapon/detail`,U=`${V}/role/getShortNoteInfo`,M=`${V}/encourage/signin/show`,y=`${V}/encourage/signin/signin`,D=`${V}/user/signIn`,c=`${V}/user/haveSignInNew`,I=`${V}/encourage/level/getTaskProcess`,L=`${V}/forum/list`,N=`${V}/forum/getPostDetail`,R=`${V}/forum/like`,A=`${V}/encourage/level/shareTask`,i=`${V}/forum/comment/createComment`,n=`${V}/config/getGameConfig`,d=`${V}/user/mine`;var f=268;class r{dev_code;token;fetchFn;is_h5=!1;rsa_public_key="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGpdbezK+eknQZQzPOjp8mr/dP+QHwk8CRkQh6C6qFnfLH3tiyl0pnt3dePuFDnM1PUXGhCkQ157ePJCQgkDU2+mimDmXh0oLFn9zuWSp+U8uLSLX3t3PpJ8TmNCROfUDWvzdbnShqg7JfDmnrOJz49qd234W84nrfTHbzdqeigQIDAQAB";constructor(z,J="",Q={}){this.dev_code=z;this.token=J;if(this.fetchFn=Q.fetchFn||fetch.bind(window),Q.is_h5!==void 0)this.is_h5=Q.is_h5;if(Q.rsa_public_key!==void 0)this.rsa_public_key=Q.rsa_public_key}async getRsaPublicKey(){if(this.rsa_public_key)return this.rsa_public_key;let z=await this._dna_request(G);if(z.is_success&&z.data){let J=z.data.key;if(typeof J==="string")this.rsa_public_key=J}return this.rsa_public_key}async login(z,J){let Q={mobile:z,code:J,gameList:f},Z=await this._dna_request(S,Q,{sign:!0,refer:!0});if(Z.is_success&&Z.data){let j=Z.data;if(typeof j.token==="string")this.token=j.token}return Z}async loginLog(){return await this._dna_request(k)}async getRoleList(){return await this._dna_request(h)}async getDefaultRoleForTool(){let z={type:1};return await this._dna_request(E,z,{sign:!0,token:!0,tokenSig:!0})}async getRoleDetail(z,J){let Q={charId:z,charEid:J,type:1};return await this._dna_request(l,Q)}async getWeaponDetail(z){let J={weaponId:z,type:1};return await this._dna_request(T,J)}async getShortNoteInfo(){return await this._dna_request(U)}async haveSignIn(){let z={gameId:f};return await this._dna_request(c,z)}async signCalendar(){let z={gameId:f};return await this._dna_request(M,z)}async gameSign(z,J){let Q={dayAwardId:z,periodId:J,signinType:1};return await this._dna_request(y,Q)}async bbsSign(){let z={gameId:f};return await this._dna_request(D,z)}async getTaskProcess(){let z={gameId:f};return await this._dna_request(I,z)}async getPostList(){let z={forumId:46,gameId:f,pageIndex:1,pageSize:20,searchType:1,timeType:0};return await this._dna_request(L,z)}async getPostDetail(z){let J={postId:z};try{return await this._dna_request(N,J)}catch(Q){return console.error("get_post_detail",Q),H.err("请求皎皎角服务失败")}}async doLike(z){let J={forumId:z.gameForumId,gameId:f,likeType:"1",operateType:"1",postCommentId:"",postCommentReplyId:"",postId:z.postId,postType:z.postType,toUserId:z.userId};try{return await this._dna_request(R,J)}catch(Q){return console.error("do_like",Q),H.err("请求皎皎角服务失败")}}async doShare(){let z={gameId:f};try{return await this._dna_request(A,z)}catch(J){return console.error("do_share",J),H.err("请求皎皎角服务失败")}}async doReply(z,J){let Q=JSON.stringify([{content:J,contentType:"1",imgHeight:0,imgWidth:0,url:""}]),Z={postId:z.postId,forumId:z.gameForumId||47,postType:"1",content:Q};return await this._dna_request(i,Z,{sign:!0,refer:!0,params:{toUserId:z.userId}})}async getAnnList(){let z={otherUserId:"709542994134436647",searchType:1,type:2};return await this._dna_request(d,z)}async getGameConfig(){let z={gameId:f};return await this._dna_request(n,z)}async getHeaders(z){let{payload:J,exparams:Q,dev_code:Z=this.dev_code,refer:j,token:q=this.token,tokenSig:$}=z||{},W="application/x-www-form-urlencoded; charset=utf-8",b={version:"1.1.3",source:"ios","Content-Type":"application/x-www-form-urlencoded; charset=utf-8","User-Agent":"DoubleHelix/4 CFNetwork/3860.100.1 Darwin/25.0.0"},u={version:"3.11.0",source:"h5","Content-Type":"application/x-www-form-urlencoded; charset=utf-8","User-Agent":"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"},X={...this.is_h5?u:b};if(Z)X.devCode=Z;if(j)X.origin="https://dnabbs.yingxiong.com",X.refer="https://dnabbs.yingxiong.com/";if(q)X.token=q;if(typeof J==="object"){let x=zz(J,$?q:"");if(Object.assign(J,{sign:x.s,timestamp:x.t}),Q)Object.assign(J,Q);let B=new URLSearchParams;Object.entries(J).forEach(([O,P])=>{B.append(O,String(P))}),J=B.toString();let F=x.k,K=await this.getRsaPublicKey(),v=_(F,K);if(this.is_h5)X.k=v;else X.rk=F,X.key=v}return{headers:X,payload:J}}async _dna_request(z,J,Q){let{method:Z="POST",sign:j,refer:q,params:$,max_retries:W=3,retry_delay:b=1,timeout:u=1e4,token:X,tokenSig:x}=Q||{},B;if(j){let{payload:F,headers:K}=await this.getHeaders({payload:J,refer:q,exparams:$,token:X?this.token:void 0,tokenSig:x});J=F,B=K}else{let{headers:F}=await this.getHeaders({token:X?this.token:void 0});B=F}for(let F=0;F<W;F++)try{let K={method:Z,headers:B,body:J},v=new AbortController,O=setTimeout(()=>v.abort(),u),P=await this.fetchFn(z,{...K,signal:v.signal});clearTimeout(O);let C=P.headers.get("content-type")||"",Y;if(C.includes("text/")){let m=await P.text();Y={code:-999,data:m}}else Y=await P.json();if(typeof Y==="object"&&Y!==null)try{if(typeof Y.data==="string")Y.data=JSON.parse(Y.data)}catch(m){}return console.debug(`[DNA] url:[${z}] headers:[${JSON.stringify(B)}] data:[${JSON.stringify(J)}] raw_res:${JSON.stringify(Y)}`),new H(Y)}catch(K){if(console.error(`请求失败: ${K.message}`),F<W-1)await new Promise((v)=>setTimeout(v,b*Math.pow(2,F)))}return H.err("请求服务器失败,已达最大重试次数")}}var w;(($)=>{$.角色="role";$.武器="weapon";$.魔之楔="mzx";$.role="角色";$.weapon="武器";$.mzx="魔之楔"})(w||={});function Jz(z){return w[z]}var p;((Z)=>{Z[Z.TEXT=1]="TEXT";Z[Z.IMAGE=2]="IMAGE";Z[Z.VIDEO=5]="VIDEO"})(p||={});class H{code=0;msg="";success=!1;data;constructor(z){this.code=z.code||0,this.msg=z.msg||"",this.success=z.success||!1,this.data=z.data}get is_success(){return this.success&&[0,200].includes(this.code)}static err(z,J=-999){return new H({code:J,msg:z,data:void 0,success:!1})}}function _(z,J){try{let Q=[];for(let W=0;W<J.length;W+=64)Q.push(J.slice(W,W+64));let Z=`-----BEGIN PUBLIC KEY-----
2
+ ${Q.join(`
3
3
  `)}
4
- -----END PUBLIC KEY-----`,$=g.pki.publicKeyFromPem(Q),q=g.util.encodeUtf8(z),j=$.encrypt(q);return g.util.encode64(j)}catch(Z){throw Error(`[DNA] RSA 加密失败: ${Z.message}`)}}function d(z=16){let Z="";for(let Q=0;Q<z;Q++)Z+="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.floor(Math.random()*62));return Z}function _(z){let J=g.md.md5.create();return J.update(z),J.digest().toHex().toUpperCase()}function p(z){function J(Z,Q){let $=Z.split("");for(let q=1;q<Q.length;q+=2){let j=Q[q-1],V=Q[q];if(j>=0&&j<$.length&&V>=0&&V<$.length)[$[j],$[V]]=[$[V],$[j]]}return $.join("")}return J(_(z),[1,13,5,17,7,23])}function o(z,J){let Z=[],Q=Object.keys(z).sort();for(let q of Q){let j=z[q];if(j!==null&&j!==void 0&&j!=="")Z.push(`${q}=${j}`)}let $=Z.join("&");return p(`${$}&${J}`)}function s(z,J){let Z=new TextEncoder,Q=Z.encode(z),$=Z.encode(J),q=[];for(let j=0;j<Q.length;j++){let b=(Q[j]&255)+($[j%$.length]&255);q.push(`@${b}`)}return q.join("")}function a(z,J){let Z=Date.now(),Q={...z,timestamp:Z,token:J},$=d(16),q=o(Q,$);return{s:s(q,$),t:Z,k:$}}export{t as getDNAInstanceMHType,n as PostContentType,i as DNAAPI};
4
+ -----END PUBLIC KEY-----`,j=g.pki.publicKeyFromPem(Z),q=g.util.encodeUtf8(z),$=j.encrypt(q);return g.util.encode64($)}catch(Q){throw Error(`[DNA] RSA 加密失败: ${Q.message}`)}}function o(z=16){let Q="";for(let Z=0;Z<z;Z++)Q+="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.floor(Math.random()*62));return Q}function s(z){let J=g.md.md5.create();return J.update(z),J.digest().toHex().toUpperCase()}function a(z){function J(Q,Z){let j=Q.split("");for(let q=1;q<Z.length;q+=2){let $=Z[q-1],W=Z[q];if($>=0&&$<j.length&&W>=0&&W<j.length)[j[$],j[W]]=[j[W],j[$]]}return j.join("")}return J(s(z),[1,13,5,17,7,23])}function t(z,J){let Q=[],Z=Object.keys(z).sort();for(let q of Z){let $=z[q];if($!==null&&$!==void 0&&$!=="")Q.push(`${q}=${$}`)}let j=Q.join("&");return a(`${j}&${J}`)}function e(z,J){let Q=new TextEncoder,Z=Q.encode(z),j=Q.encode(J),q=[];for(let $=0;$<Z.length;$++){let b=(Z[$]&255)+(j[$%j.length]&255);q.push(`@${b}`)}return q.join("")}function zz(z,J){let Q=Date.now(),Z={...z,timestamp:Q,token:J},j=o(16),q=t(Z,j);return{s:e(q,j),t:Q,k:j}}export{Jz as getDNAInstanceMHType,p as PostContentType,r as DNAAPI};
5
5
 
6
- //# debugId=C84AFE6A92A188B264756E2164756E21
6
+ //# debugId=4DD031288FECB34D64756E2164756E21
package/dist/index.js.map CHANGED
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["..\\src\\index.ts"],
4
4
  "sourcesContent": [
5
- "import * as forge from \"node-forge\"\r\n//#region const\r\nconst MAIN_URL = \"https://dnabbs-api.yingxiong.com\"\r\nconst LOGIN_URL = `${MAIN_URL}/user/sdkLogin`\r\nconst GET_RSA_PUBLIC_KEY_URL = `${MAIN_URL}/config/getRsaPublicKey`\r\nconst LOGIN_LOG_URL = `${MAIN_URL}/user/login/log`\r\nconst ROLE_LIST_URL = `${MAIN_URL}/role/list`\r\nconst ROLE_FOR_TOOL_URL = `${MAIN_URL}/role/defaultRoleForTool`\r\nconst ROLE_DETAIL_URL = `${MAIN_URL}/role/getCharDetail`\r\nconst WEAPON_DETAIL_URL = `${MAIN_URL}/weapon/detail`\r\nconst SHORT_NOTE_URL = `${MAIN_URL}/role/getShortNoteInfo`\r\nconst SIGN_CALENDAR_URL = `${MAIN_URL}/encourage/signin/show`\r\nconst GAME_SIGN_URL = `${MAIN_URL}/encourage/signin/signin`\r\nconst BBS_SIGN_URL = `${MAIN_URL}/user/signIn`\r\nconst HAVE_SIGN_IN_URL = `${MAIN_URL}/user/haveSignInNew`\r\nconst GET_TASK_PROCESS_URL = `${MAIN_URL}/encourage/level/getTaskProcess`\r\nconst GET_POST_LIST_URL = `${MAIN_URL}/forum/list`\r\nconst GET_POST_DETAIL_URL = `${MAIN_URL}/forum/getPostDetail`\r\nconst LIKE_POST_URL = `${MAIN_URL}/forum/like`\r\nconst SHARE_POST_URL = `${MAIN_URL}/encourage/level/shareTask`\r\nconst REPLY_POST_URL = `${MAIN_URL}/forum/comment/createComment`\r\nconst ANN_LIST_URL = `${MAIN_URL}/user/mine`\r\n\r\nenum RespCode {\r\n ERROR = -999,\r\n OK_ZERO = 0,\r\n OK_HTTP = 200,\r\n BAD_REQUEST = 400,\r\n SERVER_ERROR = 500,\r\n}\r\n\r\nconst DNA_GAME_ID = 268\r\n//#endregion\r\n\r\n/**\r\n * DNA API类,用于与DNA游戏服务器交互\r\n */\r\nexport class DNAAPI {\r\n public fetchFn: typeof fetch\r\n public is_h5 = false\r\n public rsa_public_key =\r\n \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGpdbezK+eknQZQzPOjp8mr/dP+QHwk8CRkQh6C6qFnfLH3tiyl0pnt3dePuFDnM1PUXGhCkQ157ePJCQgkDU2+mimDmXh0oLFn9zuWSp+U8uLSLX3t3PpJ8TmNCROfUDWvzdbnShqg7JfDmnrOJz49qd234W84nrfTHbzdqeigQIDAQAB\"\r\n\r\n /**\r\n * 构造函数\r\n * @param dev_code 设备码\r\n * @param uid 用户ID\r\n * @param token 访问令牌\r\n * @param options 选项\r\n * @param options.fetchFn 自定义fetch函数\r\n * @param options.is_h5 是否为H5端\r\n * @param options.rsa_public_key RSA公钥(base64) 设为空字符串从服务器获取\r\n */\r\n constructor(\r\n public dev_code: string,\r\n public uid = \"\",\r\n public token = \"\",\r\n options: { fetchFn?: typeof fetch; is_h5?: boolean; rsa_public_key?: string } = {},\r\n ) {\r\n this.fetchFn = options.fetchFn || fetch.bind(window)\r\n if (options.is_h5 !== undefined) this.is_h5 = options.is_h5\r\n if (options.rsa_public_key !== undefined) this.rsa_public_key = options.rsa_public_key\r\n }\r\n\r\n /**\r\n * 获取RSA公钥\r\n * @returns RSA公钥(base64)\r\n */\r\n async getRsaPublicKey() {\r\n if (this.rsa_public_key) {\r\n return this.rsa_public_key\r\n }\r\n const res = await this._dna_request<{ key: string }>(GET_RSA_PUBLIC_KEY_URL)\r\n\r\n if (res.is_success && res.data) {\r\n const key = res.data.key\r\n if (typeof key === \"string\") {\r\n this.rsa_public_key = key\r\n }\r\n }\r\n return this.rsa_public_key\r\n }\r\n\r\n /**\r\n * 登录\r\n */\r\n async login(mobile: string, code: string, dev_code: string) {\r\n const data = { mobile, code, gameList: DNA_GAME_ID }\r\n const res = await this._dna_request<DNALoginRes>(LOGIN_URL, data, { sign: true, refer: true })\r\n if (res.is_success && res.data) {\r\n const data = res.data\r\n if (typeof data.userId === \"string\") {\r\n this.uid = data.userId\r\n }\r\n if (typeof data.token === \"string\") {\r\n this.token = data.token\r\n }\r\n }\r\n return res\r\n }\r\n\r\n /**\r\n * 获取登录日志\r\n */\r\n async loginLog() {\r\n return await this._dna_request<DNALoginRes>(LOGIN_LOG_URL)\r\n }\r\n\r\n /**\r\n * 获取角色列表\r\n */\r\n async getRoleList() {\r\n return await this._dna_request<DNARoleListRes>(ROLE_LIST_URL)\r\n }\r\n\r\n /**\r\n * 获取默认角色\r\n */\r\n async getDefaultRoleForTool() {\r\n const data = { type: 1 }\r\n return await this._dna_request<DNARoleForToolRes>(ROLE_FOR_TOOL_URL, data, { sign: true })\r\n }\r\n\r\n /**\r\n * 获取角色详情\r\n */\r\n async getRoleDetail(char_id: string, char_eid: string) {\r\n const data = { charId: char_id, charEid: char_eid, type: 1 }\r\n return await this._dna_request<DNARoleDetailRes>(ROLE_DETAIL_URL, data)\r\n }\r\n\r\n /**\r\n * 获取武器详情\r\n */\r\n async getWeaponDetail(weapon_id: string) {\r\n const data = { weaponId: weapon_id, type: 1 }\r\n return await this._dna_request<DNARoleDetailRes>(WEAPON_DETAIL_URL, data)\r\n }\r\n\r\n /**\r\n * 获取角色简讯\r\n */\r\n async getShortNoteInfo() {\r\n return await this._dna_request<DNARoleShortNoteRes>(SHORT_NOTE_URL)\r\n }\r\n\r\n /**\r\n * 检查是否签到\r\n */\r\n async haveSignIn() {\r\n const data = { gameId: DNA_GAME_ID }\r\n return await this._dna_request<DNAHaveSignInRes>(HAVE_SIGN_IN_URL, data)\r\n }\r\n\r\n /**\r\n * 签到日历\r\n */\r\n async signCalendar() {\r\n const data = { gameId: DNA_GAME_ID }\r\n return await this._dna_request<DNACalendarSignRes>(SIGN_CALENDAR_URL, data)\r\n }\r\n\r\n /**\r\n * 游戏签到\r\n */\r\n async gameSign(day_award_id: number, period: number) {\r\n const data = {\r\n dayAwardId: day_award_id,\r\n periodId: period,\r\n signinType: 1,\r\n }\r\n return await this._dna_request(GAME_SIGN_URL, data)\r\n }\r\n\r\n /**\r\n * 皎皎角签到\r\n */\r\n async bbsSign() {\r\n const data = { gameId: DNA_GAME_ID }\r\n return await this._dna_request(BBS_SIGN_URL, data)\r\n }\r\n\r\n /**\r\n * 获取任务进度\r\n */\r\n async getTaskProcess() {\r\n const data = { gameId: DNA_GAME_ID }\r\n return await this._dna_request<DNATaskProcessRes>(GET_TASK_PROCESS_URL, data)\r\n }\r\n\r\n /**\r\n * 获取帖子列表\r\n */\r\n async getPostList() {\r\n const data = {\r\n forumId: 46, // 全部\r\n gameId: DNA_GAME_ID,\r\n pageIndex: 1,\r\n pageSize: 20,\r\n searchType: 1, // 1:最新 2:热门\r\n timeType: 0,\r\n }\r\n return await this._dna_request<DNAPostListRes>(GET_POST_LIST_URL, data)\r\n }\r\n\r\n /**\r\n * 获取帖子详情\r\n */\r\n async getPostDetail(post_id: string) {\r\n const data = { postId: post_id }\r\n try {\r\n return await this._dna_request<DNAPostDetailRes>(GET_POST_DETAIL_URL, data)\r\n } catch (e) {\r\n console.error(\"get_post_detail\", e as Error)\r\n return DNAApiResponse.err(\"请求皎皎角服务失败\")\r\n }\r\n }\r\n\r\n /**\r\n * 点赞帖子\r\n */\r\n async doLike(post: { gameForumId: string; postId: string; postType: string; userId: string }) {\r\n const data = {\r\n forumId: post.gameForumId,\r\n gameId: DNA_GAME_ID,\r\n likeType: \"1\",\r\n operateType: \"1\",\r\n postCommentId: \"\",\r\n postCommentReplyId: \"\",\r\n postId: post.postId,\r\n postType: post.postType,\r\n toUserId: post.userId,\r\n }\r\n try {\r\n return await this._dna_request(LIKE_POST_URL, data)\r\n } catch (e) {\r\n console.error(\"do_like\", e as Error)\r\n return DNAApiResponse.err(\"请求皎皎角服务失败\")\r\n }\r\n }\r\n\r\n // 分享帖子\r\n async doShare() {\r\n const data = { gameId: DNA_GAME_ID }\r\n try {\r\n return await this._dna_request(SHARE_POST_URL, data)\r\n } catch (e) {\r\n console.error(\"do_share\", e as Error)\r\n return DNAApiResponse.err(\"请求皎皎角服务失败\")\r\n }\r\n }\r\n\r\n // 回复帖子\r\n async doReply(post: Record<string, any>, content: string) {\r\n const content_json = JSON.stringify([\r\n {\r\n content,\r\n contentType: \"1\",\r\n imgHeight: 0,\r\n imgWidth: 0,\r\n url: \"\",\r\n },\r\n ])\r\n const data = {\r\n postId: post.postId,\r\n forumId: post.gameForumId || 47,\r\n postType: \"1\",\r\n content: content_json,\r\n }\r\n\r\n return await this._dna_request(REPLY_POST_URL, data, { sign: true, refer: true, params: { toUserId: post.userId } })\r\n }\r\n\r\n // 获取游戏公告列表\r\n async getAnnList() {\r\n const data = {\r\n otherUserId: \"709542994134436647\",\r\n searchType: 1,\r\n type: 2,\r\n }\r\n return await this._dna_request<DNAPostListRes>(ANN_LIST_URL, data)\r\n }\r\n\r\n async getHeaders(options?: {\r\n payload?: Record<string, any> | string\r\n exparams?: Record<string, any>\r\n dev_code?: string\r\n refer?: boolean\r\n token?: string\r\n }) {\r\n let { payload, exparams, dev_code = this.dev_code, refer, token = this.token } = options || {}\r\n\r\n const CONTENT_TYPE = \"application/x-www-form-urlencoded; charset=utf-8\"\r\n const iosBaseHeader = {\r\n version: \"1.1.3\",\r\n source: \"ios\",\r\n \"Content-Type\": CONTENT_TYPE,\r\n \"User-Agent\": \"DoubleHelix/4 CFNetwork/3860.100.1 Darwin/25.0.0\",\r\n }\r\n const h5BaseHeader = {\r\n version: \"3.11.0\",\r\n source: \"h5\",\r\n \"Content-Type\": CONTENT_TYPE,\r\n \"User-Agent\":\r\n \"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\",\r\n }\r\n // 默认获取ios头\r\n const headers = { ...(this.is_h5 ? h5BaseHeader : iosBaseHeader) } as Record<string, any>\r\n if (dev_code) {\r\n headers.devCode = dev_code\r\n }\r\n if (refer) {\r\n headers.origin = \"https://dnabbs.yingxiong.com\"\r\n headers.refer = \"https://dnabbs.yingxiong.com/\"\r\n }\r\n if (token) {\r\n headers.token = token\r\n }\r\n if (typeof payload === \"object\") {\r\n const si = build_signature(payload)\r\n Object.assign(payload, { sign: si.s, timestamp: si.t })\r\n if (exparams) {\r\n Object.assign(payload, exparams)\r\n }\r\n\r\n const params = new URLSearchParams()\r\n Object.entries(payload).forEach(([key, value]) => {\r\n params.append(key, String(value))\r\n })\r\n payload = params.toString()\r\n\r\n const rk = si.k\r\n const pk = await this.getRsaPublicKey()\r\n const ek = rsa_encrypt(rk, pk)\r\n if (this.is_h5) {\r\n headers.k = ek\r\n } else {\r\n headers.rk = rk\r\n headers.key = ek\r\n }\r\n }\r\n return { headers, payload }\r\n }\r\n\r\n private async _dna_request<T = any>(\r\n url: string,\r\n data?: any,\r\n options?: {\r\n method?: \"GET\" | \"POST\"\r\n sign?: boolean\r\n refer?: boolean\r\n params?: Record<string, any>\r\n max_retries?: number\r\n retry_delay?: number\r\n timeout?: number\r\n },\r\n ): Promise<DNAApiResponse<T>> {\r\n let { method = \"POST\", sign, refer, params, max_retries = 3, retry_delay = 1, timeout = 10000 } = options || {}\r\n let headers: Record<string, any>\r\n if (sign) {\r\n const { payload: p, headers: h } = await this.getHeaders({ payload: data, refer, exparams: params })\r\n data = p\r\n headers = h\r\n } else {\r\n const { headers: h } = await this.getHeaders()\r\n headers = h\r\n }\r\n\r\n for (let attempt = 0; attempt < max_retries; attempt++) {\r\n try {\r\n const fetchOptions: RequestInit = {\r\n method,\r\n headers,\r\n body: data,\r\n }\r\n\r\n // 实现超时控制\r\n const controller = new AbortController()\r\n const timeoutId = setTimeout(() => controller.abort(), timeout)\r\n\r\n const response = await this.fetchFn(url, {\r\n ...fetchOptions,\r\n signal: controller.signal,\r\n })\r\n clearTimeout(timeoutId)\r\n\r\n // 获取响应头的 content-type\r\n const contentType = response.headers.get(\"content-type\") || \"\"\r\n let raw_res: any\r\n\r\n // 根据 content-type 处理响应数据\r\n if (contentType.includes(\"text/\")) {\r\n const textData = await response.text()\r\n raw_res = {\r\n code: RespCode.ERROR,\r\n data: textData,\r\n }\r\n } else {\r\n raw_res = await response.json()\r\n }\r\n\r\n if (typeof raw_res === \"object\" && raw_res !== null) {\r\n try {\r\n if (typeof raw_res.data === \"string\") {\r\n raw_res.data = JSON.parse(raw_res.data)\r\n }\r\n } catch (e) {\r\n // 忽略解析错误\r\n }\r\n }\r\n\r\n console.debug(\r\n `[DNA] url:[${url}] headers:[${JSON.stringify(headers)}] data:[${JSON.stringify(data)}] raw_res:${JSON.stringify(raw_res)}`,\r\n )\r\n return new DNAApiResponse<T>(raw_res)\r\n } catch (e) {\r\n console.error(`请求失败: ${(e as Error).message}`)\r\n if (attempt < max_retries - 1) {\r\n await new Promise((resolve) => setTimeout(resolve, retry_delay * Math.pow(2, attempt)))\r\n }\r\n }\r\n }\r\n\r\n return DNAApiResponse.err(\"请求服务器失败,已达最大重试次数\")\r\n }\r\n}\r\n\r\n//#region 接口定义\r\n\r\nexport interface UserGame {\r\n gameId: number // gameId\r\n gameName: string // gameName\r\n}\r\n\r\nexport interface DNALoginRes {\r\n applyCancel?: number // applyCancel\r\n gender?: number // gender\r\n signature?: string // signature\r\n headUrl: string // headUrl\r\n userName: string // userName\r\n userId: string // userId\r\n isOfficial: number // isOfficial\r\n token: string // token\r\n userGameList: UserGame[] // userGameList\r\n isRegister: number // isRegister\r\n status: number // status\r\n /** 是否完成绑定 0: 未绑定, 1: 已绑定 */\r\n isComplete: number\r\n refreshToken: string // refreshToken\r\n}\r\n\r\nexport interface DNARoleShowVo {\r\n roleId: string // roleId\r\n headUrl?: string // headUrl\r\n level?: number // level\r\n roleName?: string // roleName\r\n isDefault?: number // isDefault\r\n roleRegisterTime?: string // roleRegisterTime\r\n boundType?: number // boundType\r\n roleBoundId: string // roleBoundId\r\n}\r\n\r\nexport interface DNARole {\r\n gameName: string // gameName\r\n showVoList: DNARoleShowVo[] // showVoList\r\n gameId: number // gameId\r\n}\r\n\r\nexport interface DNARoleListRes {\r\n roles: DNARole[] // roles\r\n}\r\n\r\n/** 密函 */\r\nexport interface DNARoleForToolInstance {\r\n id: number // id\r\n name: string // name\r\n /** 密函编码 */\r\n code: string\r\n on: number // 0\r\n}\r\n\r\nenum DNAInstanceMHType {\r\n \"角色\" = \"role\",\r\n \"武器\" = \"weapon\",\r\n \"魔之楔\" = \"mzx\",\r\n \"role\" = \"角色\",\r\n \"weapon\" = \"武器\",\r\n \"mzx\" = \"魔之楔\",\r\n}\r\n\r\nexport function getDNAInstanceMHType(key: keyof typeof DNAInstanceMHType) {\r\n return DNAInstanceMHType[key]\r\n}\r\n\r\nexport interface DNARoleForToolInstanceInfo {\r\n /** 密函列表 */\r\n instances: DNARoleForToolInstance[] // instances\r\n /** 密函类型 */\r\n mh_type?: DNAInstanceMHType // 密函类型\r\n}\r\n\r\nexport interface DraftDoingInfo {\r\n draftCompleteNum: number // draftCompleteNum\r\n draftDoingNum: number // draftDoingNum\r\n /** 结束时间 */\r\n endTime: string\r\n /** 产品id */\r\n productId?: number\r\n /** 产品名称 */\r\n productName: string\r\n /** 开始时间 */\r\n startTime: string\r\n}\r\n\r\nexport interface DraftInfo {\r\n /** 正在做的锻造 */\r\n draftDoingInfo?: DraftDoingInfo[]\r\n /** 正在做的锻造数量 */\r\n draftDoingNum: number\r\n /** 最大锻造数量 */\r\n draftMaxNum: number\r\n}\r\n\r\nexport interface DNARoleShortNoteRes {\r\n /** 迷津进度 */\r\n rougeLikeRewardCount: number\r\n /** 迷津总数 */\r\n rougeLikeRewardTotal: number\r\n /** 备忘手记进度 */\r\n currentTaskProgress: number\r\n /** 备忘手记总数 */\r\n maxDailyTaskProgress: number\r\n /** 梦魇进度 */\r\n hardBossRewardCount: number\r\n /** 梦魇总数 */\r\n hardBossRewardTotal: number\r\n /** 锻造信息 */\r\n draftInfo: DraftInfo\r\n}\r\n\r\nexport interface WeaponInsForTool {\r\n /** 武器类型图标 */\r\n elementIcon: string\r\n /** 武器图标 */\r\n icon: string\r\n /** 武器等级 */\r\n level: number\r\n /** 武器名称 */\r\n name: string\r\n /** 是否解锁 */\r\n unLocked: boolean\r\n weaponEid?: string\r\n weaponId: number\r\n}\r\n\r\nexport interface RoleInsForTool {\r\n charEid?: string\r\n charId: number\r\n /** 元素图标 */\r\n elementIcon: string\r\n /** 命座等级 */\r\n gradeLevel: number\r\n /** 角色图标 */\r\n icon: string\r\n /** 角色等级 */\r\n level: number\r\n /** 角色名称 */\r\n name: string\r\n /** 是否解锁 */\r\n unLocked: boolean\r\n}\r\n\r\nexport interface RoleAchievement {\r\n paramKey: string // paramKey\r\n paramValue: string // paramValue\r\n}\r\n\r\nexport interface RoleShowForTool {\r\n /** 角色列表 */\r\n roleChars: RoleInsForTool[]\r\n /** 武器列表 */\r\n langRangeWeapons: WeaponInsForTool[]\r\n /** 武器列表 */\r\n closeWeapons: WeaponInsForTool[]\r\n /** 等级 */\r\n level: number\r\n /** 成就列表 */\r\n params: RoleAchievement[]\r\n /** 角色id */\r\n roleId: string\r\n /** 角色名称 */\r\n roleName: string\r\n}\r\n\r\nexport interface RoleInfoForTool {\r\n /** 角色信息 */\r\n roleShow: RoleShowForTool\r\n}\r\n\r\nexport interface DNARoleForToolRes {\r\n /** 角色信息 */\r\n roleInfo: RoleInfoForTool\r\n /** 密函 */\r\n instanceInfo: DNARoleForToolInstanceInfo[]\r\n}\r\n\r\nexport interface RoleAttribute {\r\n /** 技能范围 */\r\n skillRange: string\r\n /** 强化值 */\r\n strongValue: string\r\n /** 技能威力 */\r\n skillIntensity: string\r\n /** 武器精通 */\r\n weaponTags: string[]\r\n /** 防御 */\r\n defense: number\r\n /** 仇恨值 */\r\n enmityValue: string\r\n /** 技能效益 */\r\n skillEfficiency: string\r\n /** 技能耐久 */\r\n skillSustain: string\r\n /** 最大生命值 */\r\n maxHp: number\r\n /** 攻击 */\r\n atk: number\r\n /** 最大护盾 */\r\n maxES: number\r\n /** 最大神志 */\r\n maxSp: number\r\n}\r\n\r\nexport interface RoleSkill {\r\n /** 技能id */\r\n skillId: number\r\n /** 技能图标 */\r\n icon: string\r\n /** 技能等级 */\r\n level: number\r\n /** 技能名称 */\r\n skillName: string\r\n}\r\n\r\nexport interface RoleTrace {\r\n /** 溯源图标 */\r\n icon: string\r\n /** 溯源描述 */\r\n description: string\r\n}\r\n\r\nexport interface Mode {\r\n /** id 没佩戴为-1 */\r\n id: number\r\n /** 图标 */\r\n icon?: string\r\n /** 质量 */\r\n quality?: number\r\n /** 名称 */\r\n name?: string\r\n}\r\n\r\nexport interface RoleDetail {\r\n /** 角色属性 */\r\n attribute: RoleAttribute\r\n /** 角色技能 */\r\n skills: RoleSkill[]\r\n /** 立绘 */\r\n paint: string\r\n /** 角色名称 */\r\n charName: string\r\n /** 元素图标 */\r\n elementIcon: string\r\n /** 溯源 */\r\n traces: RoleTrace[]\r\n /** 当前魔之楔 */\r\n currentVolume: number\r\n /** 最大魔之楔 */\r\n sumVolume: number\r\n /** 角色等级 */\r\n level: number\r\n /** 角色头像 */\r\n icon: string\r\n /** 溯源等级 0-6 */\r\n gradeLevel: number\r\n /** 元素名称 */\r\n elementName: string\r\n /** mode */\r\n modes: Mode[]\r\n}\r\n\r\nexport interface DNARoleDetailRes {\r\n /** 角色详情 */\r\n charDetail: RoleDetail\r\n}\r\n\r\nexport interface DNADayAward {\r\n gameId: number // gameId\r\n periodId: number // periodId\r\n iconUrl: string // iconUrl\r\n id: number // id\r\n dayInPeriod: number // dayInPeriod\r\n updateTime: number // updateTime\r\n awardNum: number // awardNum\r\n thirdProductId: string // thirdProductId\r\n createTime: number // createTime\r\n awardName: string // awardName\r\n}\r\n\r\nexport interface DNACaSignPeriod {\r\n gameId: number // gameId\r\n retryCos: number // retryCos\r\n endDate: number // endDate\r\n id: number // id\r\n startDate: number // startDate\r\n retryTimes: number // retryTimes\r\n overDays: number // overDays\r\n createTime: number // createTime\r\n name: string // name\r\n}\r\n\r\nexport interface DNACaSignRoleInfo {\r\n headUrl: string // headUrl\r\n roleId: string // roleId\r\n roleName: string // roleName\r\n level: number // level\r\n roleBoundId: string // roleBoundId\r\n}\r\n\r\nexport interface DNAHaveSignInRes {\r\n /** 已签到天数 */\r\n totalSignInDay: number\r\n}\r\n\r\nexport interface DNACalendarSignRes {\r\n todaySignin: boolean // todaySignin\r\n userGoldNum: number // userGoldNum\r\n dayAward: DNADayAward[] // dayAward\r\n signinTime: number // signinTime\r\n period: DNACaSignPeriod // period\r\n roleInfo: DNACaSignRoleInfo // roleInfo\r\n}\r\n\r\nexport interface DNABBSTask {\r\n /** 备注 */\r\n remark: string\r\n /** 完成次数 */\r\n completeTimes: number\r\n /** 需要次数 */\r\n times: number\r\n /** skipType */\r\n skipType: number\r\n /** 获取经验 */\r\n gainExp: number\r\n /** 进度 */\r\n process: number\r\n /** 获取金币 */\r\n gainGold: number\r\n /** 任务标识名 */\r\n markName?: string\r\n}\r\n\r\nexport interface DNATaskProcessRes {\r\n dailyTask: DNABBSTask[] // dailyTask\r\n}\r\n\r\nexport interface DNAPostListRes {\r\n postList: DNAPost[] // posts\r\n}\r\n\r\nexport interface DNAPost {\r\n postId: number // postId\r\n title: string // title\r\n}\r\n\r\nexport interface DNAPostDetailRes {\r\n postDetail: DNAPostDetail // post\r\n}\r\n\r\nexport interface DNAPostDetail {\r\n postId: number // postId\r\n postTime: number // postTime\r\n postContent: DNAPostContent[] // postContent\r\n title: string // title\r\n}\r\n\r\nexport enum PostContentType {\r\n TEXT = 1,\r\n IMAGE = 2,\r\n VIDEO = 5,\r\n}\r\n\r\nexport interface DNAPostContent {\r\n contentType: PostContentType // content\r\n content: string // content\r\n url?: string // url\r\n contentVideo?: DNAPostContentVideo // contentVideo\r\n}\r\n\r\nexport interface DNAPostContentVideo {\r\n videoUrl: string // videoUrl\r\n coverUrl?: string // coverUrl\r\n}\r\n\r\n// interface DNAWikiDetail {\r\n// name: string // name\r\n// }\r\n\r\n// interface DNAWikiRes {\r\n// wikis: DNAWikiDetail[] // wikis\r\n// }\r\n\r\nclass DNAApiResponse<T = any> {\r\n code: number = 0\r\n msg: string = \"\"\r\n success: boolean = false\r\n data?: T\r\n\r\n constructor(raw_data: any) {\r\n this.code = raw_data.code || 0\r\n this.msg = raw_data.msg || \"\"\r\n this.success = raw_data.success || false\r\n this.data = raw_data.data\r\n }\r\n\r\n // 判断是否成功\r\n get is_success() {\r\n return this.success && [RespCode.OK_ZERO, RespCode.OK_HTTP].includes(this.code)\r\n }\r\n\r\n // 错误响应静态方法\r\n static err<T = undefined>(msg: string, code: number = RespCode.ERROR): DNAApiResponse<T> {\r\n return new DNAApiResponse<T>({ code, msg, data: undefined, success: false })\r\n }\r\n}\r\n//#endregion\r\n\r\n//#region utils\r\n\r\n// RSA加密函数\r\nfunction rsa_encrypt(text: string, public_key_b64: string): string {\r\n try {\r\n // 将base64公钥转换为PEM格式\r\n const lines: string[] = []\r\n for (let i = 0; i < public_key_b64.length; i += 64) {\r\n lines.push(public_key_b64.slice(i, i + 64))\r\n }\r\n const pem = `-----BEGIN PUBLIC KEY-----\\n${lines.join(\"\\n\")}\\n-----END PUBLIC KEY-----`\r\n\r\n // 导入PEM格式的RSA公钥\r\n const publicKey = forge.pki.publicKeyFromPem(pem)\r\n\r\n // 执行PKCS1_v1_5加密\r\n const textBytes = forge.util.encodeUtf8(text)\r\n const encrypted = publicKey.encrypt(textBytes)\r\n\r\n return forge.util.encode64(encrypted)\r\n } catch (e) {\r\n throw new Error(`[DNA] RSA 加密失败: ${(e as Error).message}`)\r\n }\r\n}\r\n\r\n// 生成随机字符串\r\nfunction rand_str(length: number = 16): string {\r\n const chars = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"\r\n let result = \"\"\r\n for (let i = 0; i < length; i++) {\r\n result += chars.charAt(Math.floor(Math.random() * chars.length))\r\n }\r\n return result\r\n}\r\n\r\n// MD5加密并转换为大写\r\nfunction md5_upper(text: string): string {\r\n const md = forge.md.md5.create()\r\n md.update(text)\r\n return md.digest().toHex().toUpperCase()\r\n}\r\n\r\n// 签名哈希函数\r\nfunction signature_hash(text: string): string {\r\n function swap_positions(text: string, positions: number[]): string {\r\n const chars = text.split(\"\")\r\n for (let i = 1; i < positions.length; i += 2) {\r\n const p1 = positions[i - 1]\r\n const p2 = positions[i]\r\n if (p1 >= 0 && p1 < chars.length && p2 >= 0 && p2 < chars.length) {\r\n ;[chars[p1], chars[p2]] = [chars[p2], chars[p1]]\r\n }\r\n }\r\n return chars.join(\"\")\r\n }\r\n\r\n return swap_positions(md5_upper(text), [1, 13, 5, 17, 7, 23])\r\n}\r\n\r\n// 签名函数\r\nfunction sign_fI(data: Record<string, any>, secret: string): string {\r\n const pairs: string[] = []\r\n const sortedKeys = Object.keys(data).sort()\r\n for (const k of sortedKeys) {\r\n const v = data[k]\r\n if (v !== null && v !== undefined && v !== \"\") {\r\n pairs.push(`${k}=${v}`)\r\n }\r\n }\r\n const qs = pairs.join(\"&\")\r\n return signature_hash(`${qs}&${secret}`)\r\n}\r\n\r\n// XOR编码函数\r\nfunction xor_encode(text: string, key: string): string {\r\n const encoder = new TextEncoder()\r\n const tb = encoder.encode(text)\r\n const kb = encoder.encode(key)\r\n const out: string[] = []\r\n for (let i = 0; i < tb.length; i++) {\r\n const b = tb[i]\r\n const e = (b & 255) + (kb[i % kb.length] & 255)\r\n out.push(`@${e}`)\r\n }\r\n return out.join(\"\")\r\n}\r\n\r\n// 构建签名\r\nfunction build_signature(data: Record<string, any>, token?: string): Record<string, any> {\r\n const ts = Date.now()\r\n const sign_data = { ...data, timestamp: ts, token }\r\n const sec = rand_str(16)\r\n const sig = sign_fI(sign_data, sec)\r\n const enc = xor_encode(sig, sec)\r\n return { s: enc, t: ts, k: sec }\r\n}\r\n\r\n//#endregion\r\n"
5
+ "import * as forge from \"node-forge\"\r\n//#region const\r\nconst MAIN_URL = \"https://dnabbs-api.yingxiong.com\"\r\nconst LOGIN_URL = `${MAIN_URL}/user/sdkLogin`\r\nconst GET_RSA_PUBLIC_KEY_URL = `${MAIN_URL}/config/getRsaPublicKey`\r\nconst LOGIN_LOG_URL = `${MAIN_URL}/user/login/log`\r\nconst ROLE_LIST_URL = `${MAIN_URL}/role/list`\r\nconst ROLE_FOR_TOOL_URL = `${MAIN_URL}/role/defaultRoleForTool`\r\nconst ROLE_DETAIL_URL = `${MAIN_URL}/role/getCharDetail`\r\nconst WEAPON_DETAIL_URL = `${MAIN_URL}/weapon/detail`\r\nconst SHORT_NOTE_URL = `${MAIN_URL}/role/getShortNoteInfo`\r\nconst SIGN_CALENDAR_URL = `${MAIN_URL}/encourage/signin/show`\r\nconst GAME_SIGN_URL = `${MAIN_URL}/encourage/signin/signin`\r\nconst BBS_SIGN_URL = `${MAIN_URL}/user/signIn`\r\nconst HAVE_SIGN_IN_URL = `${MAIN_URL}/user/haveSignInNew`\r\nconst GET_TASK_PROCESS_URL = `${MAIN_URL}/encourage/level/getTaskProcess`\r\nconst GET_POST_LIST_URL = `${MAIN_URL}/forum/list`\r\nconst GET_POST_DETAIL_URL = `${MAIN_URL}/forum/getPostDetail`\r\nconst LIKE_POST_URL = `${MAIN_URL}/forum/like`\r\nconst SHARE_POST_URL = `${MAIN_URL}/encourage/level/shareTask`\r\nconst REPLY_POST_URL = `${MAIN_URL}/forum/comment/createComment`\r\nconst GET_GAME_CONFIG_URL = `${MAIN_URL}/config/getGameConfig`\r\nconst ANN_LIST_URL = `${MAIN_URL}/user/mine`\r\n\r\nenum RespCode {\r\n ERROR = -999,\r\n OK_ZERO = 0,\r\n OK_HTTP = 200,\r\n BAD_REQUEST = 400,\r\n SERVER_ERROR = 500,\r\n}\r\n\r\nconst DNA_GAME_ID = 268\r\n//#endregion\r\n\r\n/**\r\n * DNA API类,用于与DNA游戏服务器交互\r\n */\r\nexport class DNAAPI {\r\n public fetchFn: typeof fetch\r\n public is_h5 = false\r\n public rsa_public_key =\r\n \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGpdbezK+eknQZQzPOjp8mr/dP+QHwk8CRkQh6C6qFnfLH3tiyl0pnt3dePuFDnM1PUXGhCkQ157ePJCQgkDU2+mimDmXh0oLFn9zuWSp+U8uLSLX3t3PpJ8TmNCROfUDWvzdbnShqg7JfDmnrOJz49qd234W84nrfTHbzdqeigQIDAQAB\"\r\n\r\n /**\r\n * 构造函数\r\n * @param dev_code 设备码\r\n * @param uid 用户ID\r\n * @param token 访问令牌\r\n * @param options 选项\r\n * @param options.fetchFn 自定义fetch函数\r\n * @param options.is_h5 是否为H5端\r\n * @param options.rsa_public_key RSA公钥(base64) 设为空字符串从服务器获取\r\n */\r\n constructor(\r\n public dev_code: string,\r\n public token = \"\",\r\n options: { fetchFn?: typeof fetch; is_h5?: boolean; rsa_public_key?: string } = {},\r\n ) {\r\n this.fetchFn = options.fetchFn || fetch.bind(window)\r\n if (options.is_h5 !== undefined) this.is_h5 = options.is_h5\r\n if (options.rsa_public_key !== undefined) this.rsa_public_key = options.rsa_public_key\r\n }\r\n\r\n /**\r\n * 获取RSA公钥\r\n * @returns RSA公钥(base64)\r\n */\r\n async getRsaPublicKey() {\r\n if (this.rsa_public_key) {\r\n return this.rsa_public_key\r\n }\r\n const res = await this._dna_request<{ key: string }>(GET_RSA_PUBLIC_KEY_URL)\r\n\r\n if (res.is_success && res.data) {\r\n const key = res.data.key\r\n if (typeof key === \"string\") {\r\n this.rsa_public_key = key\r\n }\r\n }\r\n return this.rsa_public_key\r\n }\r\n\r\n /**\r\n * 登录\r\n */\r\n async login(mobile: string, code: string) {\r\n const data = { mobile, code, gameList: DNA_GAME_ID }\r\n const res = await this._dna_request<DNALoginRes>(LOGIN_URL, data, { sign: true, refer: true })\r\n if (res.is_success && res.data) {\r\n const data = res.data\r\n if (typeof data.token === \"string\") {\r\n this.token = data.token\r\n }\r\n }\r\n return res\r\n }\r\n\r\n /**\r\n * 获取登录日志\r\n */\r\n async loginLog() {\r\n return await this._dna_request<DNALoginRes>(LOGIN_LOG_URL)\r\n }\r\n\r\n /**\r\n * 获取角色列表\r\n */\r\n async getRoleList() {\r\n return await this._dna_request<DNARoleListRes>(ROLE_LIST_URL)\r\n }\r\n\r\n /**\r\n * 获取默认角色\r\n */\r\n async getDefaultRoleForTool() {\r\n const data = { type: 1 }\r\n return await this._dna_request<DNARoleForToolRes>(ROLE_FOR_TOOL_URL, data, { sign: true, token: true, tokenSig: true })\r\n }\r\n\r\n /**\r\n * 获取角色详情\r\n */\r\n async getRoleDetail(char_id: string, char_eid: string) {\r\n const data = { charId: char_id, charEid: char_eid, type: 1 }\r\n return await this._dna_request<DNARoleDetailRes>(ROLE_DETAIL_URL, data)\r\n }\r\n\r\n /**\r\n * 获取武器详情\r\n */\r\n async getWeaponDetail(weapon_id: string) {\r\n const data = { weaponId: weapon_id, type: 1 }\r\n return await this._dna_request<DNARoleDetailRes>(WEAPON_DETAIL_URL, data)\r\n }\r\n\r\n /**\r\n * 获取角色简讯\r\n */\r\n async getShortNoteInfo() {\r\n return await this._dna_request<DNARoleShortNoteRes>(SHORT_NOTE_URL)\r\n }\r\n\r\n /**\r\n * 检查是否签到\r\n */\r\n async haveSignIn() {\r\n const data = { gameId: DNA_GAME_ID }\r\n return await this._dna_request<DNAHaveSignInRes>(HAVE_SIGN_IN_URL, data)\r\n }\r\n\r\n /**\r\n * 签到日历\r\n */\r\n async signCalendar() {\r\n const data = { gameId: DNA_GAME_ID }\r\n return await this._dna_request<DNACalendarSignRes>(SIGN_CALENDAR_URL, data)\r\n }\r\n\r\n /**\r\n * 游戏签到\r\n */\r\n async gameSign(day_award_id: number, period: number) {\r\n const data = {\r\n dayAwardId: day_award_id,\r\n periodId: period,\r\n signinType: 1,\r\n }\r\n return await this._dna_request(GAME_SIGN_URL, data)\r\n }\r\n\r\n /**\r\n * 皎皎角签到\r\n */\r\n async bbsSign() {\r\n const data = { gameId: DNA_GAME_ID }\r\n return await this._dna_request(BBS_SIGN_URL, data)\r\n }\r\n\r\n /**\r\n * 获取任务进度\r\n */\r\n async getTaskProcess() {\r\n const data = { gameId: DNA_GAME_ID }\r\n return await this._dna_request<DNATaskProcessRes>(GET_TASK_PROCESS_URL, data)\r\n }\r\n\r\n /**\r\n * 获取帖子列表\r\n */\r\n async getPostList() {\r\n const data = {\r\n forumId: 46, // 全部\r\n gameId: DNA_GAME_ID,\r\n pageIndex: 1,\r\n pageSize: 20,\r\n searchType: 1, // 1:最新 2:热门\r\n timeType: 0,\r\n }\r\n return await this._dna_request<DNAPostListRes>(GET_POST_LIST_URL, data)\r\n }\r\n\r\n /**\r\n * 获取帖子详情\r\n */\r\n async getPostDetail(post_id: string) {\r\n const data = { postId: post_id }\r\n try {\r\n return await this._dna_request<DNAPostDetailRes>(GET_POST_DETAIL_URL, data)\r\n } catch (e) {\r\n console.error(\"get_post_detail\", e as Error)\r\n return DNAApiResponse.err(\"请求皎皎角服务失败\")\r\n }\r\n }\r\n\r\n /**\r\n * 点赞帖子\r\n */\r\n async doLike(post: { gameForumId: string; postId: string; postType: string; userId: string }) {\r\n const data = {\r\n forumId: post.gameForumId,\r\n gameId: DNA_GAME_ID,\r\n likeType: \"1\",\r\n operateType: \"1\",\r\n postCommentId: \"\",\r\n postCommentReplyId: \"\",\r\n postId: post.postId,\r\n postType: post.postType,\r\n toUserId: post.userId,\r\n }\r\n try {\r\n return await this._dna_request(LIKE_POST_URL, data)\r\n } catch (e) {\r\n console.error(\"do_like\", e as Error)\r\n return DNAApiResponse.err(\"请求皎皎角服务失败\")\r\n }\r\n }\r\n\r\n // 分享帖子\r\n async doShare() {\r\n const data = { gameId: DNA_GAME_ID }\r\n try {\r\n return await this._dna_request(SHARE_POST_URL, data)\r\n } catch (e) {\r\n console.error(\"do_share\", e as Error)\r\n return DNAApiResponse.err(\"请求皎皎角服务失败\")\r\n }\r\n }\r\n\r\n // 回复帖子\r\n async doReply(post: Record<string, any>, content: string) {\r\n const content_json = JSON.stringify([\r\n {\r\n content,\r\n contentType: \"1\",\r\n imgHeight: 0,\r\n imgWidth: 0,\r\n url: \"\",\r\n },\r\n ])\r\n const data = {\r\n postId: post.postId,\r\n forumId: post.gameForumId || 47,\r\n postType: \"1\",\r\n content: content_json,\r\n }\r\n\r\n return await this._dna_request(REPLY_POST_URL, data, { sign: true, refer: true, params: { toUserId: post.userId } })\r\n }\r\n\r\n // 获取游戏公告列表\r\n async getAnnList() {\r\n const data = {\r\n otherUserId: \"709542994134436647\",\r\n searchType: 1,\r\n type: 2,\r\n }\r\n return await this._dna_request<DNAPostListRes>(ANN_LIST_URL, data)\r\n }\r\n\r\n async getGameConfig() {\r\n const data = { gameId: DNA_GAME_ID }\r\n return await this._dna_request<DNAGameConfigRes>(GET_GAME_CONFIG_URL, data)\r\n }\r\n\r\n async getHeaders(options?: {\r\n payload?: Record<string, any> | string\r\n exparams?: Record<string, any>\r\n dev_code?: string\r\n refer?: boolean\r\n token?: string\r\n tokenSig?: boolean\r\n }) {\r\n let { payload, exparams, dev_code = this.dev_code, refer, token = this.token, tokenSig } = options || {}\r\n\r\n const CONTENT_TYPE = \"application/x-www-form-urlencoded; charset=utf-8\"\r\n const iosBaseHeader = {\r\n version: \"1.1.3\",\r\n source: \"ios\",\r\n \"Content-Type\": CONTENT_TYPE,\r\n \"User-Agent\": \"DoubleHelix/4 CFNetwork/3860.100.1 Darwin/25.0.0\",\r\n }\r\n const h5BaseHeader = {\r\n version: \"3.11.0\",\r\n source: \"h5\",\r\n \"Content-Type\": CONTENT_TYPE,\r\n \"User-Agent\":\r\n \"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\",\r\n }\r\n // 默认获取ios头\r\n const headers = { ...(this.is_h5 ? h5BaseHeader : iosBaseHeader) } as Record<string, any>\r\n if (dev_code) {\r\n headers.devCode = dev_code\r\n }\r\n if (refer) {\r\n headers.origin = \"https://dnabbs.yingxiong.com\"\r\n headers.refer = \"https://dnabbs.yingxiong.com/\"\r\n }\r\n if (token) {\r\n headers.token = token\r\n }\r\n if (typeof payload === \"object\") {\r\n const si = build_signature(payload, tokenSig ? token : \"\")\r\n Object.assign(payload, { sign: si.s, timestamp: si.t })\r\n if (exparams) {\r\n Object.assign(payload, exparams)\r\n }\r\n\r\n const params = new URLSearchParams()\r\n Object.entries(payload).forEach(([key, value]) => {\r\n params.append(key, String(value))\r\n })\r\n payload = params.toString()\r\n\r\n const rk = si.k\r\n const pk = await this.getRsaPublicKey()\r\n const ek = rsa_encrypt(rk, pk)\r\n if (this.is_h5) {\r\n headers.k = ek\r\n } else {\r\n headers.rk = rk\r\n headers.key = ek\r\n }\r\n }\r\n return { headers, payload }\r\n }\r\n\r\n private async _dna_request<T = any>(\r\n url: string,\r\n data?: any,\r\n options?: {\r\n method?: \"GET\" | \"POST\"\r\n sign?: boolean\r\n tokenSig?: boolean\r\n token?: boolean\r\n refer?: boolean\r\n params?: Record<string, any>\r\n max_retries?: number\r\n retry_delay?: number\r\n timeout?: number\r\n },\r\n ): Promise<DNAApiResponse<T>> {\r\n let { method = \"POST\", sign, refer, params, max_retries = 3, retry_delay = 1, timeout = 10000, token, tokenSig } = options || {}\r\n let headers: Record<string, any>\r\n if (sign) {\r\n const { payload: p, headers: h } = await this.getHeaders({\r\n payload: data,\r\n refer,\r\n exparams: params,\r\n token: token ? this.token : undefined,\r\n tokenSig,\r\n })\r\n data = p\r\n headers = h\r\n } else {\r\n const { headers: h } = await this.getHeaders({ token: token ? this.token : undefined })\r\n headers = h\r\n }\r\n\r\n for (let attempt = 0; attempt < max_retries; attempt++) {\r\n try {\r\n const fetchOptions: RequestInit = {\r\n method,\r\n headers,\r\n body: data,\r\n }\r\n\r\n // 实现超时控制\r\n const controller = new AbortController()\r\n const timeoutId = setTimeout(() => controller.abort(), timeout)\r\n\r\n const response = await this.fetchFn(url, {\r\n ...fetchOptions,\r\n signal: controller.signal,\r\n })\r\n clearTimeout(timeoutId)\r\n\r\n // 获取响应头的 content-type\r\n const contentType = response.headers.get(\"content-type\") || \"\"\r\n let raw_res: any\r\n\r\n // 根据 content-type 处理响应数据\r\n if (contentType.includes(\"text/\")) {\r\n const textData = await response.text()\r\n raw_res = {\r\n code: RespCode.ERROR,\r\n data: textData,\r\n }\r\n } else {\r\n raw_res = await response.json()\r\n }\r\n\r\n if (typeof raw_res === \"object\" && raw_res !== null) {\r\n try {\r\n if (typeof raw_res.data === \"string\") {\r\n raw_res.data = JSON.parse(raw_res.data)\r\n }\r\n } catch (e) {\r\n // 忽略解析错误\r\n }\r\n }\r\n\r\n console.debug(\r\n `[DNA] url:[${url}] headers:[${JSON.stringify(headers)}] data:[${JSON.stringify(data)}] raw_res:${JSON.stringify(raw_res)}`,\r\n )\r\n return new DNAApiResponse<T>(raw_res)\r\n } catch (e) {\r\n console.error(`请求失败: ${(e as Error).message}`)\r\n if (attempt < max_retries - 1) {\r\n await new Promise((resolve) => setTimeout(resolve, retry_delay * Math.pow(2, attempt)))\r\n }\r\n }\r\n }\r\n\r\n return DNAApiResponse.err(\"请求服务器失败,已达最大重试次数\")\r\n }\r\n}\r\n\r\n//#region 接口定义\r\n\r\nexport interface DNAGameConfigRes {\r\n /** 游戏背景图 */\r\n backgroundUrl: string\r\n /** 游戏封面图 */\r\n coverUrl: string\r\n /** 默认游戏 */\r\n gameDefault: number\r\n /** 游戏ID */\r\n gameId: number\r\n /** 游戏名称 */\r\n gameName: string\r\n /** 游戏描述 */\r\n gameDesc: string\r\n gameForumList: GameForum[] // gameConfig\r\n gameAllForumList: GameForum[] // gameAllForumList\r\n /** 游戏板块图片列表 */\r\n gameForumPictureList: unknown[]\r\n /** 游戏Wiki列表 */\r\n gameWikiVoList: GameWikiVo[]\r\n}\r\n\r\nexport interface GameWikiVo {\r\n id: number\r\n iconUrl: string\r\n param: {\r\n postId: string\r\n topicId: string\r\n }\r\n postId: string\r\n toAppAndroid: string\r\n url: string\r\n wikiName: string\r\n wikiType: number\r\n}\r\n\r\nexport interface GameForum {\r\n /** 游戏ID */\r\n gameId: number\r\n /** 板块ID */\r\n forumId: number\r\n /** 板块名称 */\r\n forumName: string\r\n}\r\n\r\nexport interface UserGame {\r\n gameId: number // gameId\r\n gameName: string // gameName\r\n}\r\n\r\nexport interface DNALoginRes {\r\n applyCancel?: number // applyCancel\r\n gender?: number // gender\r\n signature?: string // signature\r\n headUrl: string // headUrl\r\n userName: string // userName\r\n userId: string // userId\r\n isOfficial: number // isOfficial\r\n token: string // token\r\n userGameList: UserGame[] // userGameList\r\n isRegister: number // isRegister\r\n status: number // status\r\n /** 是否完成绑定 0: 未绑定, 1: 已绑定 */\r\n isComplete: number\r\n refreshToken: string // refreshToken\r\n}\r\n\r\nexport interface DNARoleShowVo {\r\n roleId: string // roleId\r\n headUrl?: string // headUrl\r\n level?: number // level\r\n roleName?: string // roleName\r\n isDefault?: number // isDefault\r\n roleRegisterTime?: string // roleRegisterTime\r\n boundType?: number // boundType\r\n roleBoundId: string // roleBoundId\r\n}\r\n\r\nexport interface DNARole {\r\n gameName: string // gameName\r\n showVoList: DNARoleShowVo[] // showVoList\r\n gameId: number // gameId\r\n}\r\n\r\nexport interface DNARoleListRes {\r\n roles: DNARole[] // roles\r\n}\r\n\r\n/** 密函 */\r\nexport interface DNARoleForToolInstance {\r\n id: number // id\r\n name: string // name\r\n /** 密函编码 */\r\n code: string\r\n on: number // 0\r\n}\r\n\r\nenum DNAInstanceMHType {\r\n \"角色\" = \"role\",\r\n \"武器\" = \"weapon\",\r\n \"魔之楔\" = \"mzx\",\r\n \"role\" = \"角色\",\r\n \"weapon\" = \"武器\",\r\n \"mzx\" = \"魔之楔\",\r\n}\r\n\r\nexport function getDNAInstanceMHType(key: keyof typeof DNAInstanceMHType) {\r\n return DNAInstanceMHType[key]\r\n}\r\n\r\nexport interface DNARoleForToolInstanceInfo {\r\n /** 密函列表 */\r\n instances: DNARoleForToolInstance[] // instances\r\n /** 密函类型 */\r\n mh_type?: DNAInstanceMHType // 密函类型\r\n}\r\n\r\nexport interface DraftDoingInfo {\r\n draftCompleteNum: number // draftCompleteNum\r\n draftDoingNum: number // draftDoingNum\r\n /** 结束时间 */\r\n endTime: string\r\n /** 产品id */\r\n productId?: number\r\n /** 产品名称 */\r\n productName: string\r\n /** 开始时间 */\r\n startTime: string\r\n}\r\n\r\nexport interface DraftInfo {\r\n /** 正在做的锻造 */\r\n draftDoingInfo?: DraftDoingInfo[]\r\n /** 正在做的锻造数量 */\r\n draftDoingNum: number\r\n /** 最大锻造数量 */\r\n draftMaxNum: number\r\n}\r\n\r\nexport interface DNARoleShortNoteRes {\r\n /** 迷津进度 */\r\n rougeLikeRewardCount: number\r\n /** 迷津总数 */\r\n rougeLikeRewardTotal: number\r\n /** 备忘手记进度 */\r\n currentTaskProgress: number\r\n /** 备忘手记总数 */\r\n maxDailyTaskProgress: number\r\n /** 梦魇进度 */\r\n hardBossRewardCount: number\r\n /** 梦魇总数 */\r\n hardBossRewardTotal: number\r\n /** 锻造信息 */\r\n draftInfo: DraftInfo\r\n}\r\n\r\nexport interface WeaponInsForTool {\r\n /** 武器类型图标 */\r\n elementIcon: string\r\n /** 武器图标 */\r\n icon: string\r\n /** 武器等级 */\r\n level: number\r\n /** 武器名称 */\r\n name: string\r\n /** 是否解锁 */\r\n unLocked: boolean\r\n weaponEid?: string\r\n weaponId: number\r\n}\r\n\r\nexport interface RoleInsForTool {\r\n charEid?: string\r\n /** 角色id */\r\n charId: number\r\n /** 元素图标 */\r\n elementIcon: string\r\n /** 命座等级 */\r\n gradeLevel: number\r\n /** 角色图标 */\r\n icon: string\r\n /** 角色等级 */\r\n level: number\r\n /** 角色名称 */\r\n name: string\r\n /** 是否解锁 */\r\n unLocked: boolean\r\n}\r\n\r\nexport interface RoleAchievement {\r\n paramKey: string // paramKey\r\n paramValue: string // paramValue\r\n}\r\n\r\nexport interface RoleShowForTool {\r\n /** 角色列表 */\r\n roleChars: RoleInsForTool[]\r\n /** 武器列表 */\r\n langRangeWeapons: WeaponInsForTool[]\r\n /** 武器列表 */\r\n closeWeapons: WeaponInsForTool[]\r\n /** 角色头像 */\r\n headUrl: string\r\n /** 等级 */\r\n level: number\r\n /** 成就列表 */\r\n params: RoleAchievement[]\r\n /** 角色id */\r\n roleId: string\r\n /** 角色名称 */\r\n roleName: string\r\n /** 迷津 */\r\n rougeLikeInfo: RougeLikeInfo\r\n}\r\n\r\nexport interface RoleInfoForTool {\r\n /** 深渊信息 */\r\n abyssInfo: AbyssInfo\r\n /** 角色信息 */\r\n roleShow: RoleShowForTool\r\n}\r\n\r\nexport interface DNARoleForToolRes {\r\n /** 角色信息 */\r\n roleInfo: RoleInfoForTool\r\n /** 密函 */\r\n instanceInfo: DNARoleForToolInstanceInfo[]\r\n}\r\n\r\nexport interface RougeLikeInfo {\r\n /** 最大通过等级 */\r\n maxPassed: number\r\n /** 最大通过等级名称 */\r\n maxPassedName: string\r\n /** 重置时间 */\r\n resetTime: string\r\n /** 奖励数量 */\r\n rewardCount: number\r\n /** 奖励总数 */\r\n rewardTotal: number\r\n /** 天赋信息 */\r\n talentInfo: RougeLikeTalentInfo[]\r\n}\r\n\r\nexport interface RougeLikeTalentInfo {\r\n cur: string\r\n max: string\r\n}\r\n\r\nexport interface AbyssInfo {\r\n /** 最佳时间 */\r\n bestTimeVo1: BestTimeVo1\r\n /** 结束时间 */\r\n endTime: string\r\n /** 操作名称 */\r\n operaName: string\r\n /** 进度名称 */\r\n progressName: string\r\n /** 星级 */\r\n stars: string\r\n /** 开始时间 */\r\n startTime: string\r\n}\r\n\r\nexport interface BestTimeVo1 {\r\n /** 角色图标 */\r\n charIcon: string\r\n /** 近战武器图标 */\r\n closeWeaponIcon: string\r\n /** 远程武器图标 */\r\n langRangeWeaponIcon: string\r\n /** 魔灵图标 */\r\n petIcon: string\r\n phantomCharIcon1: string\r\n phantomCharIcon2: string\r\n phantomWeaponIcon1: string\r\n phantomWeaponIcon2: string\r\n}\r\n\r\nexport interface RoleAttribute {\r\n /** 技能范围 */\r\n skillRange: string\r\n /** 强化值 */\r\n strongValue: string\r\n /** 技能威力 */\r\n skillIntensity: string\r\n /** 武器精通 */\r\n weaponTags: string[]\r\n /** 防御 */\r\n defense: number\r\n /** 仇恨值 */\r\n enmityValue: string\r\n /** 技能效益 */\r\n skillEfficiency: string\r\n /** 技能耐久 */\r\n skillSustain: string\r\n /** 最大生命值 */\r\n maxHp: number\r\n /** 攻击 */\r\n atk: number\r\n /** 最大护盾 */\r\n maxES: number\r\n /** 最大神志 */\r\n maxSp: number\r\n}\r\n\r\nexport interface RoleSkill {\r\n /** 技能id */\r\n skillId: number\r\n /** 技能图标 */\r\n icon: string\r\n /** 技能等级 */\r\n level: number\r\n /** 技能名称 */\r\n skillName: string\r\n}\r\n\r\nexport interface RoleTrace {\r\n /** 溯源图标 */\r\n icon: string\r\n /** 溯源描述 */\r\n description: string\r\n}\r\n\r\nexport interface Mode {\r\n /** id 没佩戴为-1 */\r\n id: number\r\n /** 图标 */\r\n icon?: string\r\n /** 质量 */\r\n quality?: number\r\n /** 名称 */\r\n name?: string\r\n}\r\n\r\nexport interface RoleDetail {\r\n /** 角色属性 */\r\n attribute: RoleAttribute\r\n /** 角色技能 */\r\n skills: RoleSkill[]\r\n /** 立绘 */\r\n paint: string\r\n /** 角色名称 */\r\n charName: string\r\n /** 元素图标 */\r\n elementIcon: string\r\n /** 溯源 */\r\n traces: RoleTrace[]\r\n /** 当前魔之楔 */\r\n currentVolume: number\r\n /** 最大魔之楔 */\r\n sumVolume: number\r\n /** 角色等级 */\r\n level: number\r\n /** 角色头像 */\r\n icon: string\r\n /** 溯源等级 0-6 */\r\n gradeLevel: number\r\n /** 元素名称 */\r\n elementName: string\r\n /** mode */\r\n modes: Mode[]\r\n}\r\n\r\nexport interface DNARoleDetailRes {\r\n /** 角色详情 */\r\n charDetail: RoleDetail\r\n}\r\n\r\nexport interface DNADayAward {\r\n gameId: number // gameId\r\n periodId: number // periodId\r\n iconUrl: string // iconUrl\r\n id: number // id\r\n dayInPeriod: number // dayInPeriod\r\n updateTime: number // updateTime\r\n awardNum: number // awardNum\r\n thirdProductId: string // thirdProductId\r\n createTime: number // createTime\r\n awardName: string // awardName\r\n}\r\n\r\nexport interface DNACaSignPeriod {\r\n gameId: number // gameId\r\n retryCos: number // retryCos\r\n endDate: number // endDate\r\n id: number // id\r\n startDate: number // startDate\r\n retryTimes: number // retryTimes\r\n overDays: number // overDays\r\n createTime: number // createTime\r\n name: string // name\r\n}\r\n\r\nexport interface DNACaSignRoleInfo {\r\n headUrl: string // headUrl\r\n roleId: string // roleId\r\n roleName: string // roleName\r\n level: number // level\r\n roleBoundId: string // roleBoundId\r\n}\r\n\r\nexport interface DNAHaveSignInRes {\r\n /** 已签到天数 */\r\n totalSignInDay: number\r\n}\r\n\r\nexport interface DNACalendarSignRes {\r\n todaySignin: boolean // todaySignin\r\n userGoldNum: number // userGoldNum\r\n dayAward: DNADayAward[] // dayAward\r\n signinTime: number // signinTime\r\n period: DNACaSignPeriod // period\r\n roleInfo: DNACaSignRoleInfo // roleInfo\r\n}\r\n\r\nexport interface DNABBSTask {\r\n /** 备注 */\r\n remark: string\r\n /** 完成次数 */\r\n completeTimes: number\r\n /** 需要次数 */\r\n times: number\r\n /** skipType */\r\n skipType: number\r\n /** 获取经验 */\r\n gainExp: number\r\n /** 进度 */\r\n process: number\r\n /** 获取金币 */\r\n gainGold: number\r\n /** 任务标识名 */\r\n markName?: string\r\n}\r\n\r\nexport interface DNATaskProcessRes {\r\n dailyTask: DNABBSTask[] // dailyTask\r\n}\r\n\r\nexport interface DNAPostListRes {\r\n postList: DNAPost[] // posts\r\n}\r\n\r\nexport interface DNAPost {\r\n postId: number // postId\r\n title: string // title\r\n}\r\n\r\nexport interface DNAPostDetailRes {\r\n postDetail: DNAPostDetail // post\r\n}\r\n\r\nexport interface DNAPostDetail {\r\n postId: number // postId\r\n postTime: number // postTime\r\n postContent: DNAPostContent[] // postContent\r\n title: string // title\r\n}\r\n\r\nexport enum PostContentType {\r\n TEXT = 1,\r\n IMAGE = 2,\r\n VIDEO = 5,\r\n}\r\n\r\nexport interface DNAPostContent {\r\n contentType: PostContentType // content\r\n content: string // content\r\n url?: string // url\r\n contentVideo?: DNAPostContentVideo // contentVideo\r\n}\r\n\r\nexport interface DNAPostContentVideo {\r\n videoUrl: string // videoUrl\r\n coverUrl?: string // coverUrl\r\n}\r\n\r\n// interface DNAWikiDetail {\r\n// name: string // name\r\n// }\r\n\r\n// interface DNAWikiRes {\r\n// wikis: DNAWikiDetail[] // wikis\r\n// }\r\n\r\nclass DNAApiResponse<T = any> {\r\n code: number = 0\r\n msg: string = \"\"\r\n success: boolean = false\r\n data?: T\r\n\r\n constructor(raw_data: any) {\r\n this.code = raw_data.code || 0\r\n this.msg = raw_data.msg || \"\"\r\n this.success = raw_data.success || false\r\n this.data = raw_data.data\r\n }\r\n\r\n // 判断是否成功\r\n get is_success() {\r\n return this.success && [RespCode.OK_ZERO, RespCode.OK_HTTP].includes(this.code)\r\n }\r\n\r\n // 错误响应静态方法\r\n static err<T = undefined>(msg: string, code: number = RespCode.ERROR): DNAApiResponse<T> {\r\n return new DNAApiResponse<T>({ code, msg, data: undefined, success: false })\r\n }\r\n}\r\n//#endregion\r\n\r\n//#region utils\r\n\r\n// RSA加密函数\r\nfunction rsa_encrypt(text: string, public_key_b64: string): string {\r\n try {\r\n // 将base64公钥转换为PEM格式\r\n const lines: string[] = []\r\n for (let i = 0; i < public_key_b64.length; i += 64) {\r\n lines.push(public_key_b64.slice(i, i + 64))\r\n }\r\n const pem = `-----BEGIN PUBLIC KEY-----\\n${lines.join(\"\\n\")}\\n-----END PUBLIC KEY-----`\r\n\r\n // 导入PEM格式的RSA公钥\r\n const publicKey = forge.pki.publicKeyFromPem(pem)\r\n\r\n // 执行PKCS1_v1_5加密\r\n const textBytes = forge.util.encodeUtf8(text)\r\n const encrypted = publicKey.encrypt(textBytes)\r\n\r\n return forge.util.encode64(encrypted)\r\n } catch (e) {\r\n throw new Error(`[DNA] RSA 加密失败: ${(e as Error).message}`)\r\n }\r\n}\r\n\r\n// 生成随机字符串\r\nfunction rand_str(length: number = 16): string {\r\n const chars = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"\r\n let result = \"\"\r\n for (let i = 0; i < length; i++) {\r\n result += chars.charAt(Math.floor(Math.random() * chars.length))\r\n }\r\n return result\r\n}\r\n\r\n// MD5加密并转换为大写\r\nfunction md5_upper(text: string): string {\r\n const md = forge.md.md5.create()\r\n md.update(text)\r\n return md.digest().toHex().toUpperCase()\r\n}\r\n\r\n// 签名哈希函数\r\nfunction signature_hash(text: string): string {\r\n function swap_positions(text: string, positions: number[]): string {\r\n const chars = text.split(\"\")\r\n for (let i = 1; i < positions.length; i += 2) {\r\n const p1 = positions[i - 1]\r\n const p2 = positions[i]\r\n if (p1 >= 0 && p1 < chars.length && p2 >= 0 && p2 < chars.length) {\r\n ;[chars[p1], chars[p2]] = [chars[p2], chars[p1]]\r\n }\r\n }\r\n return chars.join(\"\")\r\n }\r\n return swap_positions(md5_upper(text), [1, 13, 5, 17, 7, 23])\r\n}\r\n\r\n// 签名函数\r\nfunction sign_fI(data: Record<string, any>, secret: string): string {\r\n const pairs: string[] = []\r\n const sortedKeys = Object.keys(data).sort()\r\n for (const k of sortedKeys) {\r\n const v = data[k]\r\n if (v !== null && v !== undefined && v !== \"\") {\r\n pairs.push(`${k}=${v}`)\r\n }\r\n }\r\n const qs = pairs.join(\"&\")\r\n return signature_hash(`${qs}&${secret}`)\r\n}\r\n\r\n// XOR编码函数\r\nfunction xor_encode(text: string, key: string): string {\r\n const encoder = new TextEncoder()\r\n const tb = encoder.encode(text)\r\n const kb = encoder.encode(key)\r\n const out: string[] = []\r\n for (let i = 0; i < tb.length; i++) {\r\n const b = tb[i]\r\n const e = (b & 255) + (kb[i % kb.length] & 255)\r\n out.push(`@${e}`)\r\n }\r\n return out.join(\"\")\r\n}\r\n\r\n// 构建签名\r\nfunction build_signature(data: Record<string, any>, token?: string): Record<string, any> {\r\n const ts = Date.now()\r\n const sign_data = { ...data, timestamp: ts, token }\r\n const sec = rand_str(16)\r\n const sig = sign_fI(sign_data, sec)\r\n const enc = xor_encode(sig, sec)\r\n return { s: enc, t: ts, k: sec }\r\n}\r\n//#endregion\r\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "C84AFE6A92A188B264756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "4DD031288FECB34D64756E2164756E21",
9
9
  "names": []
10
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dna-api",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "dna bbs api",
5
5
  "author": {
6
6
  "name": "pa001024",
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ const GET_POST_DETAIL_URL = `${MAIN_URL}/forum/getPostDetail`
19
19
  const LIKE_POST_URL = `${MAIN_URL}/forum/like`
20
20
  const SHARE_POST_URL = `${MAIN_URL}/encourage/level/shareTask`
21
21
  const REPLY_POST_URL = `${MAIN_URL}/forum/comment/createComment`
22
+ const GET_GAME_CONFIG_URL = `${MAIN_URL}/config/getGameConfig`
22
23
  const ANN_LIST_URL = `${MAIN_URL}/user/mine`
23
24
 
24
25
  enum RespCode {
@@ -53,7 +54,6 @@ export class DNAAPI {
53
54
  */
54
55
  constructor(
55
56
  public dev_code: string,
56
- public uid = "",
57
57
  public token = "",
58
58
  options: { fetchFn?: typeof fetch; is_h5?: boolean; rsa_public_key?: string } = {},
59
59
  ) {
@@ -84,14 +84,11 @@ export class DNAAPI {
84
84
  /**
85
85
  * 登录
86
86
  */
87
- async login(mobile: string, code: string, dev_code: string) {
87
+ async login(mobile: string, code: string) {
88
88
  const data = { mobile, code, gameList: DNA_GAME_ID }
89
89
  const res = await this._dna_request<DNALoginRes>(LOGIN_URL, data, { sign: true, refer: true })
90
90
  if (res.is_success && res.data) {
91
91
  const data = res.data
92
- if (typeof data.userId === "string") {
93
- this.uid = data.userId
94
- }
95
92
  if (typeof data.token === "string") {
96
93
  this.token = data.token
97
94
  }
@@ -118,7 +115,7 @@ export class DNAAPI {
118
115
  */
119
116
  async getDefaultRoleForTool() {
120
117
  const data = { type: 1 }
121
- return await this._dna_request<DNARoleForToolRes>(ROLE_FOR_TOOL_URL, data, { sign: true })
118
+ return await this._dna_request<DNARoleForToolRes>(ROLE_FOR_TOOL_URL, data, { sign: true, token: true, tokenSig: true })
122
119
  }
123
120
 
124
121
  /**
@@ -281,14 +278,20 @@ export class DNAAPI {
281
278
  return await this._dna_request<DNAPostListRes>(ANN_LIST_URL, data)
282
279
  }
283
280
 
281
+ async getGameConfig() {
282
+ const data = { gameId: DNA_GAME_ID }
283
+ return await this._dna_request<DNAGameConfigRes>(GET_GAME_CONFIG_URL, data)
284
+ }
285
+
284
286
  async getHeaders(options?: {
285
287
  payload?: Record<string, any> | string
286
288
  exparams?: Record<string, any>
287
289
  dev_code?: string
288
290
  refer?: boolean
289
291
  token?: string
292
+ tokenSig?: boolean
290
293
  }) {
291
- let { payload, exparams, dev_code = this.dev_code, refer, token = this.token } = options || {}
294
+ let { payload, exparams, dev_code = this.dev_code, refer, token = this.token, tokenSig } = options || {}
292
295
 
293
296
  const CONTENT_TYPE = "application/x-www-form-urlencoded; charset=utf-8"
294
297
  const iosBaseHeader = {
@@ -317,7 +320,7 @@ export class DNAAPI {
317
320
  headers.token = token
318
321
  }
319
322
  if (typeof payload === "object") {
320
- const si = build_signature(payload)
323
+ const si = build_signature(payload, tokenSig ? token : "")
321
324
  Object.assign(payload, { sign: si.s, timestamp: si.t })
322
325
  if (exparams) {
323
326
  Object.assign(payload, exparams)
@@ -348,6 +351,8 @@ export class DNAAPI {
348
351
  options?: {
349
352
  method?: "GET" | "POST"
350
353
  sign?: boolean
354
+ tokenSig?: boolean
355
+ token?: boolean
351
356
  refer?: boolean
352
357
  params?: Record<string, any>
353
358
  max_retries?: number
@@ -355,14 +360,20 @@ export class DNAAPI {
355
360
  timeout?: number
356
361
  },
357
362
  ): Promise<DNAApiResponse<T>> {
358
- let { method = "POST", sign, refer, params, max_retries = 3, retry_delay = 1, timeout = 10000 } = options || {}
363
+ let { method = "POST", sign, refer, params, max_retries = 3, retry_delay = 1, timeout = 10000, token, tokenSig } = options || {}
359
364
  let headers: Record<string, any>
360
365
  if (sign) {
361
- const { payload: p, headers: h } = await this.getHeaders({ payload: data, refer, exparams: params })
366
+ const { payload: p, headers: h } = await this.getHeaders({
367
+ payload: data,
368
+ refer,
369
+ exparams: params,
370
+ token: token ? this.token : undefined,
371
+ tokenSig,
372
+ })
362
373
  data = p
363
374
  headers = h
364
375
  } else {
365
- const { headers: h } = await this.getHeaders()
376
+ const { headers: h } = await this.getHeaders({ token: token ? this.token : undefined })
366
377
  headers = h
367
378
  }
368
379
 
@@ -427,6 +438,50 @@ export class DNAAPI {
427
438
 
428
439
  //#region 接口定义
429
440
 
441
+ export interface DNAGameConfigRes {
442
+ /** 游戏背景图 */
443
+ backgroundUrl: string
444
+ /** 游戏封面图 */
445
+ coverUrl: string
446
+ /** 默认游戏 */
447
+ gameDefault: number
448
+ /** 游戏ID */
449
+ gameId: number
450
+ /** 游戏名称 */
451
+ gameName: string
452
+ /** 游戏描述 */
453
+ gameDesc: string
454
+ gameForumList: GameForum[] // gameConfig
455
+ gameAllForumList: GameForum[] // gameAllForumList
456
+ /** 游戏板块图片列表 */
457
+ gameForumPictureList: unknown[]
458
+ /** 游戏Wiki列表 */
459
+ gameWikiVoList: GameWikiVo[]
460
+ }
461
+
462
+ export interface GameWikiVo {
463
+ id: number
464
+ iconUrl: string
465
+ param: {
466
+ postId: string
467
+ topicId: string
468
+ }
469
+ postId: string
470
+ toAppAndroid: string
471
+ url: string
472
+ wikiName: string
473
+ wikiType: number
474
+ }
475
+
476
+ export interface GameForum {
477
+ /** 游戏ID */
478
+ gameId: number
479
+ /** 板块ID */
480
+ forumId: number
481
+ /** 板块名称 */
482
+ forumName: string
483
+ }
484
+
430
485
  export interface UserGame {
431
486
  gameId: number // gameId
432
487
  gameName: string // gameName
@@ -555,6 +610,7 @@ export interface WeaponInsForTool {
555
610
 
556
611
  export interface RoleInsForTool {
557
612
  charEid?: string
613
+ /** 角色id */
558
614
  charId: number
559
615
  /** 元素图标 */
560
616
  elementIcon: string
@@ -582,6 +638,8 @@ export interface RoleShowForTool {
582
638
  langRangeWeapons: WeaponInsForTool[]
583
639
  /** 武器列表 */
584
640
  closeWeapons: WeaponInsForTool[]
641
+ /** 角色头像 */
642
+ headUrl: string
585
643
  /** 等级 */
586
644
  level: number
587
645
  /** 成就列表 */
@@ -590,9 +648,13 @@ export interface RoleShowForTool {
590
648
  roleId: string
591
649
  /** 角色名称 */
592
650
  roleName: string
651
+ /** 迷津 */
652
+ rougeLikeInfo: RougeLikeInfo
593
653
  }
594
654
 
595
655
  export interface RoleInfoForTool {
656
+ /** 深渊信息 */
657
+ abyssInfo: AbyssInfo
596
658
  /** 角色信息 */
597
659
  roleShow: RoleShowForTool
598
660
  }
@@ -604,6 +666,56 @@ export interface DNARoleForToolRes {
604
666
  instanceInfo: DNARoleForToolInstanceInfo[]
605
667
  }
606
668
 
669
+ export interface RougeLikeInfo {
670
+ /** 最大通过等级 */
671
+ maxPassed: number
672
+ /** 最大通过等级名称 */
673
+ maxPassedName: string
674
+ /** 重置时间 */
675
+ resetTime: string
676
+ /** 奖励数量 */
677
+ rewardCount: number
678
+ /** 奖励总数 */
679
+ rewardTotal: number
680
+ /** 天赋信息 */
681
+ talentInfo: RougeLikeTalentInfo[]
682
+ }
683
+
684
+ export interface RougeLikeTalentInfo {
685
+ cur: string
686
+ max: string
687
+ }
688
+
689
+ export interface AbyssInfo {
690
+ /** 最佳时间 */
691
+ bestTimeVo1: BestTimeVo1
692
+ /** 结束时间 */
693
+ endTime: string
694
+ /** 操作名称 */
695
+ operaName: string
696
+ /** 进度名称 */
697
+ progressName: string
698
+ /** 星级 */
699
+ stars: string
700
+ /** 开始时间 */
701
+ startTime: string
702
+ }
703
+
704
+ export interface BestTimeVo1 {
705
+ /** 角色图标 */
706
+ charIcon: string
707
+ /** 近战武器图标 */
708
+ closeWeaponIcon: string
709
+ /** 远程武器图标 */
710
+ langRangeWeaponIcon: string
711
+ /** 魔灵图标 */
712
+ petIcon: string
713
+ phantomCharIcon1: string
714
+ phantomCharIcon2: string
715
+ phantomWeaponIcon1: string
716
+ phantomWeaponIcon2: string
717
+ }
718
+
607
719
  export interface RoleAttribute {
608
720
  /** 技能范围 */
609
721
  skillRange: string
@@ -890,7 +1002,6 @@ function signature_hash(text: string): string {
890
1002
  }
891
1003
  return chars.join("")
892
1004
  }
893
-
894
1005
  return swap_positions(md5_upper(text), [1, 13, 5, 17, 7, 23])
895
1006
  }
896
1007
 
@@ -931,5 +1042,4 @@ function build_signature(data: Record<string, any>, token?: string): Record<stri
931
1042
  const enc = xor_encode(sig, sec)
932
1043
  return { s: enc, t: ts, k: sec }
933
1044
  }
934
-
935
1045
  //#endregion