koishi-plugin-rocom 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/lib/client.d.ts +53 -0
  2. package/lib/client.js +473 -0
  3. package/lib/commands/account.d.ts +5 -0
  4. package/lib/commands/account.js +205 -0
  5. package/lib/commands/admin.d.ts +2 -0
  6. package/lib/commands/admin.js +117 -0
  7. package/lib/commands/egg.d.ts +2 -0
  8. package/lib/commands/egg.js +196 -0
  9. package/lib/commands/merchant.d.ts +2 -0
  10. package/lib/commands/merchant.js +242 -0
  11. package/lib/commands/query.d.ts +2 -0
  12. package/lib/commands/query.js +1264 -0
  13. package/lib/commands/wiki.d.ts +2 -0
  14. package/lib/commands/wiki.js +11 -0
  15. package/lib/egg-service.d.ts +229 -0
  16. package/lib/egg-service.js +705 -0
  17. package/lib/index.d.ts +24 -0
  18. package/lib/index.js +3746 -0
  19. package/lib/render-templates/bind-list/index.html +51 -0
  20. package/lib/render-templates/bind-list/style.css +178 -0
  21. package/lib/render-templates/exchange-hall/css/_@astro-renderers.0KDkAyVb.css +1 -0
  22. package/lib/render-templates/exchange-hall/css/index.B3tv56V6.css +1 -0
  23. package/lib/render-templates/exchange-hall/css/index.D2LGPudy.css +1 -0
  24. package/lib/render-templates/exchange-hall/extracted.css +393 -0
  25. package/lib/render-templates/exchange-hall/index.html +99 -0
  26. package/lib/render-templates/exchange-hall/style.css +267 -0
  27. package/lib/render-templates/friendship/index.html +58 -0
  28. package/lib/render-templates/friendship/style.css +182 -0
  29. package/lib/render-templates/home/data/home_item_list.json +122 -0
  30. package/lib/render-templates/home/img/home_icon/100604.png +0 -0
  31. package/lib/render-templates/home/img/home_icon/100604_1.png +0 -0
  32. package/lib/render-templates/home/img/home_icon/100604_2.png +0 -0
  33. package/lib/render-templates/home/img/home_icon/100605.png +0 -0
  34. package/lib/render-templates/home/img/home_icon/100605_1.png +0 -0
  35. package/lib/render-templates/home/img/home_icon/100605_2.png +0 -0
  36. package/lib/render-templates/home/img/home_icon/100606.png +0 -0
  37. package/lib/render-templates/home/img/home_icon/100606_1.png +0 -0
  38. package/lib/render-templates/home/img/home_icon/100606_2.png +0 -0
  39. package/lib/render-templates/home/img/home_icon/100607.png +0 -0
  40. package/lib/render-templates/home/img/home_icon/100607_1.png +0 -0
  41. package/lib/render-templates/home/img/home_icon/100607_2.png +0 -0
  42. package/lib/render-templates/home/img/home_icon/100608.png +0 -0
  43. package/lib/render-templates/home/img/home_icon/100608_1.png +0 -0
  44. package/lib/render-templates/home/img/home_icon/100608_2.png +0 -0
  45. package/lib/render-templates/home/img/home_icon/100622.png +0 -0
  46. package/lib/render-templates/home/img/home_icon/100622_1.png +0 -0
  47. package/lib/render-templates/home/img/home_icon/100622_2.png +0 -0
  48. package/lib/render-templates/home/img/home_icon/100623.png +0 -0
  49. package/lib/render-templates/home/img/home_icon/100623_1.png +0 -0
  50. package/lib/render-templates/home/img/home_icon/100623_2.png +0 -0
  51. package/lib/render-templates/home/img/home_icon/100624.png +0 -0
  52. package/lib/render-templates/home/img/home_icon/100624_1.png +0 -0
  53. package/lib/render-templates/home/img/home_icon/100624_2.png +0 -0
  54. package/lib/render-templates/home/img/home_icon/100627.png +0 -0
  55. package/lib/render-templates/home/img/home_icon/100627_1.png +0 -0
  56. package/lib/render-templates/home/img/home_icon/100627_2.png +0 -0
  57. package/lib/render-templates/home/img/home_icon/100684.png +0 -0
  58. package/lib/render-templates/home/img/home_icon/100684_1.png +0 -0
  59. package/lib/render-templates/home/img/home_icon/100684_2.png +0 -0
  60. package/lib/render-templates/home/img/home_icon/100686.png +0 -0
  61. package/lib/render-templates/home/img/home_icon/100686_1.png +0 -0
  62. package/lib/render-templates/home/img/home_icon/100686_2.png +0 -0
  63. package/lib/render-templates/home/img/home_icon/100687.png +0 -0
  64. package/lib/render-templates/home/img/home_icon/100687_1.png +0 -0
  65. package/lib/render-templates/home/img/home_icon/100687_2.png +0 -0
  66. package/lib/render-templates/home/img/home_icon/100689.png +0 -0
  67. package/lib/render-templates/home/img/home_icon/100689_1.png +0 -0
  68. package/lib/render-templates/home/img/home_icon/100689_2.png +0 -0
  69. package/lib/render-templates/home/img/home_icon/100690.png +0 -0
  70. package/lib/render-templates/home/img/home_icon/100690_1.png +0 -0
  71. package/lib/render-templates/home/img/home_icon/100690_2.png +0 -0
  72. package/lib/render-templates/home/img/home_icon/100691.png +0 -0
  73. package/lib/render-templates/home/img/home_icon/100691_1.png +0 -0
  74. package/lib/render-templates/home/img/home_icon/100691_2.png +0 -0
  75. package/lib/render-templates/home/img/home_icon/100692.png +0 -0
  76. package/lib/render-templates/home/img/home_icon/100692_1.png +0 -0
  77. package/lib/render-templates/home/img/home_icon/100692_2.png +0 -0
  78. package/lib/render-templates/home/img/home_icon/100693.png +0 -0
  79. package/lib/render-templates/home/img/home_icon/100693_1.png +0 -0
  80. package/lib/render-templates/home/img/home_icon/100693_2.png +0 -0
  81. package/lib/render-templates/home/img/home_icon/100694.png +0 -0
  82. package/lib/render-templates/home/img/home_icon/100694_1.png +0 -0
  83. package/lib/render-templates/home/img/home_icon/100694_2.png +0 -0
  84. package/lib/render-templates/home/img/home_icon/100706.png +0 -0
  85. package/lib/render-templates/home/img/home_icon/100706_1.png +0 -0
  86. package/lib/render-templates/home/img/home_icon/100706_2.png +0 -0
  87. package/lib/render-templates/home/img/home_icon/100751.png +0 -0
  88. package/lib/render-templates/home/img/home_icon/100751_1.png +0 -0
  89. package/lib/render-templates/home/img/home_icon/100751_2.png +0 -0
  90. package/lib/render-templates/home/img/home_icon/100755.png +0 -0
  91. package/lib/render-templates/home/img/home_icon/100755_1.png +0 -0
  92. package/lib/render-templates/home/img/home_icon/100755_2.png +0 -0
  93. package/lib/render-templates/home/img/home_icon/100762.png +0 -0
  94. package/lib/render-templates/home/img/home_icon/100762_1.png +0 -0
  95. package/lib/render-templates/home/img/home_icon/100762_2.png +0 -0
  96. package/lib/render-templates/home/img/home_icon/100764.png +0 -0
  97. package/lib/render-templates/home/img/home_icon/100764_1.png +0 -0
  98. package/lib/render-templates/home/img/home_icon/100764_2.png +0 -0
  99. package/lib/render-templates/home/img/home_icon/100869.png +0 -0
  100. package/lib/render-templates/home/img/home_icon/100869_1.png +0 -0
  101. package/lib/render-templates/home/img/home_icon/100869_2.png +0 -0
  102. package/lib/render-templates/home/img/img_HomeVisit_Icon1.png +0 -0
  103. package/lib/render-templates/home/img/img_LevelReward_Bg2.png +0 -0
  104. package/lib/render-templates/home/index.html +139 -0
  105. package/lib/render-templates/home/style.css +537 -0
  106. package/lib/render-templates/ingame-shop/index.html +87 -0
  107. package/lib/render-templates/ingame-shop/style.css +220 -0
  108. package/lib/render-templates/inspect/index.html +47 -0
  109. package/lib/render-templates/inspect/style.css +149 -0
  110. package/lib/render-templates/lineup/index.html +77 -0
  111. package/lib/render-templates/lineup/style.css +255 -0
  112. package/lib/render-templates/lineup-detail/index.html +63 -0
  113. package/lib/render-templates/lineup-detail/style.css +218 -0
  114. package/lib/render-templates/menu/index.html +36 -0
  115. package/lib/render-templates/menu/style.css +126 -0
  116. package/lib/render-templates/package/index.html +115 -0
  117. package/lib/render-templates/package/style.css +352 -0
  118. package/lib/render-templates/personal-card/index.html +292 -0
  119. package/lib/render-templates/personal-card/style.css +2114 -0
  120. package/lib/render-templates/pet-wiki/index.html +118 -0
  121. package/lib/render-templates/pet-wiki/style.css +382 -0
  122. package/lib/render-templates/player-search/index.html +60 -0
  123. package/lib/render-templates/player-search/style.css +192 -0
  124. package/lib/render-templates/record/index.html +86 -0
  125. package/lib/render-templates/record/style.css +322 -0
  126. package/lib/render-templates/searcheggs/Pets.json +104328 -0
  127. package/lib/render-templates/searcheggs/candidates.html +52 -0
  128. package/lib/render-templates/searcheggs/eggs.py +599 -0
  129. package/lib/render-templates/searcheggs/index.html +198 -0
  130. package/lib/render-templates/searcheggs/pair.html +81 -0
  131. package/lib/render-templates/searcheggs/size.html +82 -0
  132. package/lib/render-templates/searcheggs/style.css +586 -0
  133. package/lib/render-templates/searcheggs/want.html +63 -0
  134. package/lib/render-templates/skill-wiki/index.html +68 -0
  135. package/lib/render-templates/skill-wiki/style.css +182 -0
  136. package/lib/render-templates/student/index.html +95 -0
  137. package/lib/render-templates/student/style.css +255 -0
  138. package/lib/render-templates/student-perks/index.html +78 -0
  139. package/lib/render-templates/student-perks/style.css +238 -0
  140. package/lib/render-templates/student-state/index.html +52 -0
  141. package/lib/render-templates/student-state/style.css +157 -0
  142. package/lib/render-templates/yuanxing-shangren/index.html +371 -0
  143. package/lib/render-templates/yuanxing-shangren/style.css +371 -0
  144. package/lib/render.d.ts +11 -0
  145. package/lib/render.js +226 -0
  146. package/lib/role-token.d.ts +27 -0
  147. package/lib/role-token.js +137 -0
  148. package/lib/send-image.d.ts +3 -0
  149. package/lib/send-image.js +135 -0
  150. package/lib/subscription-send.d.ts +8 -0
  151. package/lib/subscription-send.js +48 -0
  152. package/lib/types.d.ts +32 -0
  153. package/lib/types.js +2 -0
  154. package/lib/user.d.ts +67 -0
  155. package/lib/user.js +176 -0
  156. package/package.json +58 -0
  157. package/readme.md +575 -0
@@ -0,0 +1,53 @@
1
+ import { Context } from 'koishi';
2
+ export declare class RocomClient {
3
+ private baseUrl;
4
+ private apiKey;
5
+ private timeout;
6
+ private lastError;
7
+ constructor(baseUrl: string, apiKey: string, timeout?: number);
8
+ private sanitizeUid;
9
+ private wegameHeaders;
10
+ private rocomHeaders;
11
+ private formatHttpError;
12
+ private isSensitiveLogKey;
13
+ private maskSensitiveValue;
14
+ private sanitizeForLog;
15
+ private headersForLog;
16
+ private stringifyForLog;
17
+ private logRequestFailureDetails;
18
+ private get;
19
+ private post;
20
+ private delete;
21
+ private requestWithStatus;
22
+ private getIngameTask;
23
+ qqQrLogin(ctx: Context, userIdentifier: string): Promise<any>;
24
+ qqQrStatus(ctx: Context, fwToken: string, userIdentifier: string): Promise<any>;
25
+ wechatQrLogin(ctx: Context, userIdentifier: string): Promise<any>;
26
+ wechatQrStatus(ctx: Context, fwToken: string, userIdentifier: string): Promise<any>;
27
+ importToken(ctx: Context, tgpId: string, tgpTicket: string, userIdentifier: string): Promise<any>;
28
+ createBinding(ctx: Context, fwToken: string, userIdentifier: string): Promise<any>;
29
+ refreshBinding(ctx: Context, bindingId: string, userIdentifier: string): Promise<any>;
30
+ deleteBinding(ctx: Context, bindingId: string, userIdentifier: string): Promise<boolean>;
31
+ getRole(ctx: Context, fwToken: string, accountType?: number, userIdentifier?: string): Promise<any>;
32
+ getEvaluation(ctx: Context, fwToken: string, userIdentifier?: string): Promise<any>;
33
+ getLastError(defaultMessage?: string): string;
34
+ private setLastError;
35
+ getPetSummary(ctx: Context, fwToken: string, userIdentifier?: string): Promise<any>;
36
+ getCollection(ctx: Context, fwToken: string, userIdentifier?: string): Promise<any>;
37
+ getBattleOverview(ctx: Context, fwToken: string, userIdentifier?: string): Promise<any>;
38
+ getBattleList(ctx: Context, fwToken: string, pageSize?: number, afterTime?: string, userIdentifier?: string): Promise<any>;
39
+ private isIngamePlayerPayload;
40
+ ingamePlayerSearch(ctx: Context, uid: string): Promise<any>;
41
+ getPets(ctx: Context, fwToken: string, petSubset?: number, pageNo?: number, pageSize?: number, userIdentifier?: string): Promise<any>;
42
+ getLineupList(ctx: Context, fwToken: string, pageNo?: number, category?: string, userIdentifier?: string): Promise<any>;
43
+ getExchangePosters(ctx: Context, fwToken: string, pageNo?: number, userIdentifier?: string): Promise<any>;
44
+ getMerchantInfo(ctx: Context, refresh?: boolean): Promise<any>;
45
+ queryPetSize(ctx: Context, diameter: number, weight: number): Promise<any>;
46
+ ingameHomeInfo(ctx: Context, uid: string, waitMs?: number): Promise<any>;
47
+ ingameMerchantInfo(ctx: Context, shopId: string | number): Promise<any>;
48
+ getFriendship(ctx: Context, fwToken: string, userIds: string, userIdentifier?: string): Promise<any>;
49
+ getStudentState(ctx: Context, fwToken: string, accountType?: number, userIdentifier?: string): Promise<any>;
50
+ getStudentPerks(ctx: Context, fwToken: string, area?: number, accountType?: number, userIdentifier?: string): Promise<any>;
51
+ searchWikiPet(ctx: Context, query: string, limit?: number): Promise<any>;
52
+ searchWikiSkill(ctx: Context, query: string, limit?: number): Promise<any>;
53
+ }
package/lib/client.js ADDED
@@ -0,0 +1,473 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RocomClient = void 0;
4
+ const koishi_1 = require("koishi");
5
+ const logger = new koishi_1.Logger('rocom-client');
6
+ class RocomClient {
7
+ baseUrl;
8
+ apiKey;
9
+ timeout;
10
+ lastError = '接口异常';
11
+ constructor(baseUrl, apiKey, timeout = 15000) {
12
+ this.baseUrl = baseUrl.replace(/\/$/, '');
13
+ this.apiKey = apiKey;
14
+ this.timeout = timeout;
15
+ }
16
+ sanitizeUid(uid) {
17
+ if (!uid)
18
+ return '';
19
+ return uid.trim().replace(/[^a-zA-Z0-9_\- \u4e00-\u9fa5]/g, '').trim();
20
+ }
21
+ wegameHeaders(fwToken = '', userIdentifier = '', clientType = '', clientId = '') {
22
+ const headers = {};
23
+ if (this.apiKey)
24
+ headers['X-API-Key'] = this.apiKey;
25
+ if (fwToken)
26
+ headers['X-Framework-Token'] = fwToken;
27
+ if (userIdentifier)
28
+ headers['X-User-Identifier'] = this.sanitizeUid(userIdentifier);
29
+ if (clientType)
30
+ headers['X-Client-Type'] = clientType;
31
+ if (clientId)
32
+ headers['X-Client-ID'] = clientId;
33
+ return headers;
34
+ }
35
+ rocomHeaders(fwToken, userIdentifier = '') {
36
+ const headers = { 'X-Framework-Token': fwToken };
37
+ if (this.apiKey)
38
+ headers['X-API-Key'] = this.apiKey;
39
+ if (userIdentifier)
40
+ headers['X-User-Identifier'] = this.sanitizeUid(userIdentifier);
41
+ return headers;
42
+ }
43
+ formatHttpError(e) {
44
+ const err = e;
45
+ const response = err?.response;
46
+ if (response) {
47
+ const body = response.data;
48
+ const bodyMessage = body && typeof body === 'object'
49
+ ? body.message || body.msg || body.error || JSON.stringify(body)
50
+ : body;
51
+ const prefix = response.status ? `HTTP ${response.status}` : 'HTTP error';
52
+ return bodyMessage ? `${prefix}: ${bodyMessage}` : `${prefix}: ${response.statusText || err?.message || 'unknown'}`;
53
+ }
54
+ return err?.message || String(e);
55
+ }
56
+ isSensitiveLogKey(key) {
57
+ return /api[-_]?key|authorization|cookie|framework[-_]?token|password|secret|ticket|token/i.test(key);
58
+ }
59
+ maskSensitiveValue(value) {
60
+ if (typeof value !== 'string')
61
+ return value;
62
+ if (!value)
63
+ return value;
64
+ if (value.length <= 8)
65
+ return '***';
66
+ return `${value.slice(0, 4)}...${value.slice(-4)}`;
67
+ }
68
+ sanitizeForLog(value, key = '') {
69
+ if (this.isSensitiveLogKey(key))
70
+ return this.maskSensitiveValue(value);
71
+ if (!value || typeof value !== 'object')
72
+ return value;
73
+ if (Array.isArray(value))
74
+ return value.map(item => this.sanitizeForLog(item));
75
+ const result = {};
76
+ for (const [entryKey, entryValue] of Object.entries(value)) {
77
+ result[entryKey] = this.sanitizeForLog(entryValue, entryKey);
78
+ }
79
+ return result;
80
+ }
81
+ headersForLog(headers) {
82
+ if (!headers || typeof headers !== 'object')
83
+ return headers;
84
+ const iterableHeaders = headers;
85
+ if (typeof iterableHeaders.forEach === 'function') {
86
+ const result = {};
87
+ iterableHeaders.forEach((value, key) => {
88
+ result[key] = this.sanitizeForLog(value, key);
89
+ });
90
+ return result;
91
+ }
92
+ return this.sanitizeForLog(headers);
93
+ }
94
+ stringifyForLog(value) {
95
+ try {
96
+ return JSON.stringify(value, null, 2);
97
+ }
98
+ catch {
99
+ return String(value);
100
+ }
101
+ }
102
+ logRequestFailureDetails(method, path, headers, params, body, errorOrResponse) {
103
+ const err = errorOrResponse;
104
+ const response = err?.response;
105
+ const details = {
106
+ request: {
107
+ method,
108
+ url: `${this.baseUrl}${path}`,
109
+ path,
110
+ params: this.sanitizeForLog(params),
111
+ body: this.sanitizeForLog(body),
112
+ headers: this.sanitizeForLog(headers),
113
+ timeout: this.timeout,
114
+ },
115
+ response: response ? {
116
+ status: response.status,
117
+ statusText: response.statusText,
118
+ headers: this.headersForLog(response.headers),
119
+ body: this.sanitizeForLog(response.data),
120
+ } : undefined,
121
+ apiResponse: response ? undefined : this.sanitizeForLog(errorOrResponse),
122
+ error: response || err?.message || err?.stack ? {
123
+ name: err?.name,
124
+ message: err?.message,
125
+ code: err?.code,
126
+ stack: err?.stack,
127
+ } : undefined,
128
+ };
129
+ console.warn(`[rocom-client] ${method} ${path} detailed failure\n${this.stringifyForLog(details)}`);
130
+ }
131
+ async get(ctx, path, headers, params, options) {
132
+ try {
133
+ const resp = await ctx.http.get(`${this.baseUrl}${path}`, {
134
+ headers,
135
+ params,
136
+ timeout: this.timeout,
137
+ });
138
+ if (resp?.code !== 0) {
139
+ this.setLastError(resp?.message || '接口返回异常');
140
+ logger.warn(path + ' error: ' + (resp?.message || 'unknown'));
141
+ if (!options?.silentFailureDetails) {
142
+ this.logRequestFailureDetails('GET', path, headers, params, undefined, resp);
143
+ }
144
+ return null;
145
+ }
146
+ return resp?.data ?? {};
147
+ }
148
+ catch (e) {
149
+ const message = this.formatHttpError(e);
150
+ this.setLastError(message);
151
+ if (!options?.silentFailureDetails) {
152
+ this.logRequestFailureDetails('GET', path, headers, params, undefined, e);
153
+ }
154
+ const err = e;
155
+ if (err?.response) {
156
+ logger.warn('GET ' + path + ' failed: ' + message);
157
+ }
158
+ else {
159
+ logger.error('GET ' + path + ' failed: ' + message);
160
+ }
161
+ return null;
162
+ }
163
+ }
164
+ async post(ctx, path, headers, json, params) {
165
+ try {
166
+ const resp = await ctx.http.post(`${this.baseUrl}${path}`, json, {
167
+ headers,
168
+ params,
169
+ timeout: this.timeout,
170
+ });
171
+ if (resp?.code !== 0) {
172
+ this.setLastError(resp?.message || '接口返回异常');
173
+ logger.warn(path + ' error: ' + (resp?.message || 'unknown'));
174
+ this.logRequestFailureDetails('POST', path, headers, params, json, resp);
175
+ return null;
176
+ }
177
+ return resp?.data ?? {};
178
+ }
179
+ catch (e) {
180
+ const message = this.formatHttpError(e);
181
+ this.setLastError(message);
182
+ this.logRequestFailureDetails('POST', path, headers, params, json, e);
183
+ const err = e;
184
+ if (err?.response) {
185
+ logger.warn('POST ' + path + ' failed: ' + message);
186
+ }
187
+ else {
188
+ logger.error('POST ' + path + ' failed: ' + message);
189
+ }
190
+ return null;
191
+ }
192
+ }
193
+ async delete(ctx, path, headers) {
194
+ try {
195
+ const resp = await ctx.http("DELETE", `${this.baseUrl}${path}`, { headers, timeout: this.timeout });
196
+ if (resp?.code !== 0) {
197
+ this.setLastError(resp?.message || '接口返回异常');
198
+ logger.warn(path + ' error: ' + (resp?.message || 'unknown'));
199
+ this.logRequestFailureDetails('DELETE', path, headers, undefined, undefined, resp);
200
+ return null;
201
+ }
202
+ return resp?.data ?? {};
203
+ }
204
+ catch (e) {
205
+ const message = this.formatHttpError(e);
206
+ this.setLastError(message);
207
+ this.logRequestFailureDetails('DELETE', path, headers, undefined, undefined, e);
208
+ const err = e;
209
+ if (err?.response) {
210
+ logger.warn('DELETE ' + path + ' failed: ' + message);
211
+ }
212
+ else {
213
+ logger.error('DELETE ' + path + ' failed: ' + message);
214
+ }
215
+ return null;
216
+ }
217
+ }
218
+ // Login and binding APIs.
219
+ async requestWithStatus(ctx, method, path, headers, options = {}) {
220
+ const acceptedStatuses = options.acceptedStatuses || [200];
221
+ try {
222
+ const response = await ctx.http(method, `${this.baseUrl}${path}`, {
223
+ headers,
224
+ params: options.params,
225
+ data: options.json,
226
+ timeout: this.timeout,
227
+ validateStatus: () => true,
228
+ });
229
+ const status = Number(response?.status ?? response?.statusCode ?? 200);
230
+ const body = response?.data !== undefined ? response.data : response;
231
+ if (body?.code !== undefined && body.code !== 0) {
232
+ this.setLastError(body.message || body.msg || '接口返回异常');
233
+ this.logRequestFailureDetails(method, path, headers, options.params, options.json, body);
234
+ return { status: null, data: null };
235
+ }
236
+ const data = body?.code !== undefined ? (body.data ?? {}) : (body ?? {});
237
+ if (!acceptedStatuses.includes(status)) {
238
+ this.setLastError(`HTTP ${status}`);
239
+ this.logRequestFailureDetails(method, path, headers, options.params, options.json, response);
240
+ }
241
+ return { status, data };
242
+ }
243
+ catch (e) {
244
+ const message = this.formatHttpError(e);
245
+ this.setLastError(message);
246
+ this.logRequestFailureDetails(method, path, headers, options.params, options.json, e);
247
+ return { status: null, data: null };
248
+ }
249
+ }
250
+ async getIngameTask(ctx, taskId) {
251
+ return this.requestWithStatus(ctx, 'GET', `/api/v1/games/rocom/ingame/tasks/${taskId}`, this.wegameHeaders(), { acceptedStatuses: [200, 202] });
252
+ }
253
+ async qqQrLogin(ctx, userIdentifier) {
254
+ const params = { client_type: 'bot', client_id: 'koishi', provider: 'rocom' };
255
+ if (userIdentifier)
256
+ params.user_identifier = this.sanitizeUid(userIdentifier);
257
+ return this.get(ctx, '/api/v1/login/wegame/qr', this.wegameHeaders('', userIdentifier, 'bot', 'koishi'), params);
258
+ }
259
+ async qqQrStatus(ctx, fwToken, userIdentifier) {
260
+ const params = {};
261
+ if (userIdentifier)
262
+ params.user_identifier = this.sanitizeUid(userIdentifier);
263
+ return this.get(ctx, '/api/v1/login/wegame/status', this.wegameHeaders(fwToken, userIdentifier, 'bot', 'koishi'), params);
264
+ }
265
+ async wechatQrLogin(ctx, userIdentifier) {
266
+ const params = { client_type: 'bot', client_id: 'koishi', provider: 'rocom' };
267
+ if (userIdentifier)
268
+ params.user_identifier = this.sanitizeUid(userIdentifier);
269
+ return this.get(ctx, '/api/v1/login/wegame/wechat/qr', this.wegameHeaders('', userIdentifier, 'bot', 'koishi'), params);
270
+ }
271
+ async wechatQrStatus(ctx, fwToken, userIdentifier) {
272
+ const params = {};
273
+ if (userIdentifier)
274
+ params.user_identifier = this.sanitizeUid(userIdentifier);
275
+ return this.get(ctx, '/api/v1/login/wegame/wechat/status', this.wegameHeaders(fwToken, userIdentifier, 'bot', 'koishi'), params);
276
+ }
277
+ async importToken(ctx, tgpId, tgpTicket, userIdentifier) {
278
+ const body = { tgp_id: tgpId, tgp_ticket: tgpTicket, provider: 'rocom', client_type: 'bot', client_id: 'koishi' };
279
+ if (userIdentifier)
280
+ body.user_identifier = this.sanitizeUid(userIdentifier);
281
+ return this.post(ctx, '/api/v1/login/wegame/token', this.wegameHeaders('', userIdentifier, 'bot', 'koishi'), body);
282
+ }
283
+ async createBinding(ctx, fwToken, userIdentifier) {
284
+ const payload = { framework_token: fwToken, user_identifier: this.sanitizeUid(userIdentifier), client_type: 'bot', client_id: 'koishi' };
285
+ return this.post(ctx, '/api/v1/user/bindings', this.wegameHeaders('', userIdentifier, 'bot', 'koishi'), payload);
286
+ }
287
+ async refreshBinding(ctx, bindingId, userIdentifier) {
288
+ return this.post(ctx, `/api/v1/user/bindings/${bindingId}/refresh`, this.wegameHeaders('', userIdentifier), {});
289
+ }
290
+ async deleteBinding(ctx, bindingId, userIdentifier) {
291
+ const res = await this.delete(ctx, `/api/v1/user/bindings/${bindingId}`, this.wegameHeaders('', userIdentifier));
292
+ return res !== null;
293
+ }
294
+ // 洛克王国游戏数据接口
295
+ async getRole(ctx, fwToken, accountType, userIdentifier = '') {
296
+ const params = {};
297
+ if (accountType)
298
+ params.account_type = accountType;
299
+ return this.get(ctx, '/api/v1/games/rocom/profile/role', this.rocomHeaders(fwToken, userIdentifier), params);
300
+ }
301
+ async getEvaluation(ctx, fwToken, userIdentifier = '') {
302
+ return this.get(ctx, '/api/v1/games/rocom/profile/evaluation', this.rocomHeaders(fwToken, userIdentifier), undefined, { silentFailureDetails: true });
303
+ }
304
+ getLastError(defaultMessage = '接口异常') {
305
+ return this.lastError || defaultMessage;
306
+ }
307
+ setLastError(message) {
308
+ this.lastError = message || '接口异常';
309
+ }
310
+ async getPetSummary(ctx, fwToken, userIdentifier = '') {
311
+ return this.get(ctx, '/api/v1/games/rocom/profile/pet-summary', this.rocomHeaders(fwToken, userIdentifier));
312
+ }
313
+ async getCollection(ctx, fwToken, userIdentifier = '') {
314
+ return this.get(ctx, '/api/v1/games/rocom/profile/collection', this.rocomHeaders(fwToken, userIdentifier));
315
+ }
316
+ async getBattleOverview(ctx, fwToken, userIdentifier = '') {
317
+ return this.get(ctx, '/api/v1/games/rocom/profile/battle-overview', this.rocomHeaders(fwToken, userIdentifier));
318
+ }
319
+ async getBattleList(ctx, fwToken, pageSize = 4, afterTime = '', userIdentifier = '') {
320
+ const params = { page_size: pageSize };
321
+ if (afterTime)
322
+ params.after_time = afterTime;
323
+ return this.get(ctx, '/api/v1/games/rocom/battle/list', this.rocomHeaders(fwToken, userIdentifier), params);
324
+ }
325
+ isIngamePlayerPayload(data) {
326
+ if (!data || typeof data !== 'object')
327
+ return false;
328
+ return Boolean(Array.isArray(data.rows)
329
+ || Array.isArray(data.notes)
330
+ || data.title
331
+ || data.nickname
332
+ || data.uid);
333
+ }
334
+ async ingamePlayerSearch(ctx, uid) {
335
+ const sanitizedUid = this.sanitizeUid(uid);
336
+ if (!sanitizedUid) {
337
+ this.setLastError('UID 涓嶈兘涓虹┖');
338
+ return null;
339
+ }
340
+ const path = '/api/v1/games/rocom/ingame/player/search';
341
+ const headers = this.wegameHeaders();
342
+ const payload = { uid: sanitizedUid, wait_ms: 5000 };
343
+ let { status, data } = await this.requestWithStatus(ctx, 'POST', path, headers, {
344
+ json: payload,
345
+ acceptedStatuses: [200, 202],
346
+ });
347
+ if (status === 200 && data && this.isIngamePlayerPayload(data))
348
+ return data;
349
+ if (status === null) {
350
+ const fallback = await this.requestWithStatus(ctx, 'GET', path, headers, {
351
+ params: payload,
352
+ acceptedStatuses: [200, 202],
353
+ });
354
+ status = fallback.status;
355
+ data = fallback.data;
356
+ if (status === 200 && data && this.isIngamePlayerPayload(data))
357
+ return data;
358
+ }
359
+ if (!data)
360
+ return null;
361
+ if (this.isIngamePlayerPayload(data))
362
+ return data;
363
+ const taskId = data.task_id || data.taskId || data.taskID;
364
+ if (!taskId) {
365
+ if (status === 202)
366
+ this.setLastError('玩家搜索任务已入队,但未返回 task_id');
367
+ return data;
368
+ }
369
+ for (let i = 0; i < 8; i++) {
370
+ await new Promise(resolve => setTimeout(resolve, 1000));
371
+ const task = await this.getIngameTask(ctx, taskId);
372
+ if (task.status === 200)
373
+ return task.data;
374
+ if (task.status === null)
375
+ return null;
376
+ }
377
+ this.setLastError('Player search task is still queued, please retry later (task_id: ' + taskId + ')');
378
+ return null;
379
+ }
380
+ async getPets(ctx, fwToken, petSubset = 0, pageNo = 1, pageSize = 10, userIdentifier = '') {
381
+ const params = { pet_subset: petSubset, page_no: pageNo, page_size: pageSize };
382
+ return this.get(ctx, '/api/v1/games/rocom/battle/pets', this.rocomHeaders(fwToken, userIdentifier), params);
383
+ }
384
+ async getLineupList(ctx, fwToken, pageNo = 1, category = '', userIdentifier = '') {
385
+ const params = { page_no: pageNo };
386
+ if (category)
387
+ params.category = category;
388
+ return this.get(ctx, '/api/v1/games/rocom/lineup/list', this.rocomHeaders(fwToken, userIdentifier), params);
389
+ }
390
+ async getExchangePosters(ctx, fwToken, pageNo = 1, userIdentifier = '') {
391
+ const params = { page_no: Math.max(pageNo, 1), refresh: 'false' };
392
+ return this.get(ctx, '/api/v1/games/rocom/exchange/posters', this.wegameHeaders(fwToken, userIdentifier), params);
393
+ }
394
+ async getMerchantInfo(ctx, refresh = false) {
395
+ return this.get(ctx, '/api/v1/games/rocom/merchant/info', this.wegameHeaders(), { refresh: refresh ? 'true' : 'false' });
396
+ }
397
+ async queryPetSize(ctx, diameter, weight) {
398
+ return this.get(ctx, '/api/v1/games/rocom/pet/size-query', this.wegameHeaders(), { diameter, weight });
399
+ }
400
+ async ingameHomeInfo(ctx, uid, waitMs = 5000) {
401
+ const sanitizedUid = this.sanitizeUid(uid);
402
+ if (!sanitizedUid) {
403
+ this.setLastError('UID 涓嶈兘涓虹┖');
404
+ return null;
405
+ }
406
+ const path = '/api/v1/games/rocom/ingame/home/info';
407
+ const headers = this.wegameHeaders();
408
+ const payload = { uid: sanitizedUid, wait_ms: waitMs };
409
+ let { status, data } = await this.requestWithStatus(ctx, 'POST', path, headers, {
410
+ json: payload,
411
+ acceptedStatuses: [200, 202],
412
+ });
413
+ if (status === 200 && data && !(data.task_id || data.taskId || data.taskID))
414
+ return data;
415
+ if (status === null) {
416
+ const fallback = await this.requestWithStatus(ctx, 'GET', path, headers, {
417
+ params: payload,
418
+ acceptedStatuses: [200, 202],
419
+ });
420
+ status = fallback.status;
421
+ data = fallback.data;
422
+ if (status === 200 && data && !(data.task_id || data.taskId || data.taskID))
423
+ return data;
424
+ }
425
+ const taskId = data?.task_id || data?.taskId || data?.taskID;
426
+ if (!taskId) {
427
+ if (status === 202)
428
+ this.setLastError('家园查询任务已入队,但未返回 task_id');
429
+ return null;
430
+ }
431
+ for (let i = 0; i < 10; i++) {
432
+ await new Promise(resolve => setTimeout(resolve, 1000));
433
+ const task = await this.getIngameTask(ctx, taskId);
434
+ if (task.status === 200)
435
+ return task.data;
436
+ if (task.status === null)
437
+ return null;
438
+ }
439
+ this.setLastError(`Home query task is still queued, please retry later (task_id: ${taskId})`);
440
+ return null;
441
+ }
442
+ async ingameMerchantInfo(ctx, shopId) {
443
+ const params = { shop_id: shopId };
444
+ const data = await this.get(ctx, '/api/v1/games/rocom/ingame/merchant/info', this.wegameHeaders(), params, { silentFailureDetails: true });
445
+ if (data)
446
+ return data;
447
+ return this.post(ctx, '/api/v1/games/rocom/ingame/merchant/info', this.wegameHeaders(), params);
448
+ }
449
+ async getFriendship(ctx, fwToken, userIds, userIdentifier = '') {
450
+ return this.get(ctx, '/api/v1/games/rocom/social/friendship', this.rocomHeaders(fwToken, userIdentifier), { user_ids: userIds });
451
+ }
452
+ async getStudentState(ctx, fwToken, accountType, userIdentifier = '') {
453
+ const params = {};
454
+ if (accountType !== undefined)
455
+ params.account_type = accountType;
456
+ return this.get(ctx, '/api/v1/games/rocom/activity/student-state', this.rocomHeaders(fwToken, userIdentifier), params);
457
+ }
458
+ async getStudentPerks(ctx, fwToken, area, accountType, userIdentifier = '') {
459
+ const params = {};
460
+ if (area !== undefined)
461
+ params.area = area;
462
+ if (accountType !== undefined)
463
+ params.account_type = accountType;
464
+ return this.get(ctx, '/api/v1/games/rocom/activity/perks', this.rocomHeaders(fwToken, userIdentifier), params);
465
+ }
466
+ async searchWikiPet(ctx, query, limit = 10) {
467
+ return this.get(ctx, '/api/v1/games/rocom/wiki/pet', this.wegameHeaders(), { q: query, limit });
468
+ }
469
+ async searchWikiSkill(ctx, query, limit = 10) {
470
+ return this.get(ctx, '/api/v1/games/rocom/wiki/skill', this.wegameHeaders(), { q: query, limit });
471
+ }
472
+ }
473
+ exports.RocomClient = RocomClient;
@@ -0,0 +1,5 @@
1
+ import { PluginDeps } from '../types';
2
+ export declare function getPrimaryToken(deps: PluginDeps, userId: string): Promise<string>;
3
+ export declare function notLoggedInHint(): string;
4
+ export declare function saveBindingWithRoleInfo(deps: PluginDeps, session: any, fwToken: string, loginType: string, userId: string): Promise<void>;
5
+ export declare function register(deps: PluginDeps): void;