koishi-plugin-rocom 1.0.1 → 1.0.3

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 (104) hide show
  1. package/lib/client.d.ts +1 -0
  2. package/lib/client.js +75 -10
  3. package/lib/commands/query.js +9 -1
  4. package/lib/img/1-1.DsrH8HWs.png +0 -0
  5. package/lib/img/1-2.C_m0bWhF.png +0 -0
  6. package/lib/img/1-3.RCKDHs5T.png +0 -0
  7. package/lib/img/1-4.uUZC0ie8.png +0 -0
  8. package/lib/img/1-5.RVh9H-hd.png +0 -0
  9. package/lib/img/2-1.DtFVG_cL.png +0 -0
  10. package/lib/img/2-2.D9q6Kuvh.png +0 -0
  11. package/lib/img/2-3.CEMPtBOM.png +0 -0
  12. package/lib/img/2-4.CTt_IEn-.png +0 -0
  13. package/lib/img/2-5.DHDw2Rte.png +0 -0
  14. package/lib/img/3-1.BxPdoaGp.png +0 -0
  15. package/lib/img/3-2.DL9tvB29.png +0 -0
  16. package/lib/img/3-3.DV4kIcUj.png +0 -0
  17. package/lib/img/3-4.BIjdgjzd.png +0 -0
  18. package/lib/img/3-5.CTb-wcJw.png +0 -0
  19. package/lib/img/4-1.BqNyzyq3.png +0 -0
  20. package/lib/img/4-2.Dv_8-ets.png +0 -0
  21. package/lib/img/4-3.CqfVc4t4.png +0 -0
  22. package/lib/img/4-4.BJfb6KYO.png +0 -0
  23. package/lib/img/4-5.CBpEGv60.png +0 -0
  24. package/lib/img/5-1.CvocExIf.png +0 -0
  25. package/lib/img/5-2.t1A1x2Pk.png +0 -0
  26. package/lib/img/5-3.DLqxSx5c.png +0 -0
  27. package/lib/img/5-4.CoNuzHM6.png +0 -0
  28. package/lib/img/5-5.QBGkXfhC.png +0 -0
  29. package/lib/img/6-1.BRlbvdwy.png +0 -0
  30. package/lib/img/6-2.DXVquVOt.png +0 -0
  31. package/lib/img/6-3.Cwq4ZJJB.png +0 -0
  32. package/lib/img/6-4.D4r99Vq9.png +0 -0
  33. package/lib/img/6-5.BBIcXS3X.png +0 -0
  34. package/lib/img/7.Wku3bA4b.png +0 -0
  35. package/lib/img/IMG_20260413_235405.png +0 -0
  36. package/lib/img/WEGAME Ai /346/264/233/345/205/213/346/241/243/346/241/210.png +0 -0
  37. package/lib/img/ad-card.DUI6osKw.png +0 -0
  38. package/lib/img/ai/345/215/241/347/211/207.png +0 -0
  39. package/lib/img/ai/347/202/271/350/257/204/345/255/227/346/256/265bg.png +0 -0
  40. package/lib/img/ai/350/257/204/345/210/206 /345/255/227/346/240/267.png +0 -0
  41. package/lib/img/ai/350/257/204/345/210/206 /350/257/204/345/210/206bg.png +0 -0
  42. package/lib/img/authorize-benefit-bg.our9Ftwk.png +0 -0
  43. package/lib/img/authorize-benefit-img1.DVKFtajb.png +0 -0
  44. package/lib/img/authorize-benefit-inside-bg.DruwTvcR.png +0 -0
  45. package/lib/img/authorize-completed-card-bg.BPW096BZ.png +0 -0
  46. package/lib/img/authorize-completed-card-photo-bg.6Vo9vsjF.png +0 -0
  47. package/lib/img/authorize-completed-header-title.DVcuWKye.png +0 -0
  48. package/lib/img/authorize-header-title.DmTqaMIN.png +0 -0
  49. package/lib/img/authorize-layout-bg-top.DYkKpjn1.png +0 -0
  50. package/lib/img/authorize-layout-bg.C0zTfHsR.png +0 -0
  51. package/lib/img/authorize-qrcode-img-line.DELzcNEj.png +0 -0
  52. package/lib/img/authorize-result-btn-hover.BxebZ_7p.png +0 -0
  53. package/lib/img/authorize-result-btn-normal.p5Vbuw2Q.png +0 -0
  54. package/lib/img/bg.C8CUoi7I.jpg +0 -0
  55. package/lib/img/coin.png +0 -0
  56. package/lib/img/eit-logo.png +0 -0
  57. package/lib/img/ercode-bg.D1ccSQKH.png +0 -0
  58. package/lib/img/fail-icon.ChpzWjNv.png +0 -0
  59. package/lib/img/icon-btn-decorate.Dwyrlnvx.png +0 -0
  60. package/lib/img/icon-chapter.DoUojjEg.png +0 -0
  61. package/lib/img/icon-decorative-book.6KbZJc7F.png +0 -0
  62. package/lib/img/icon-stay-tuned.DHbzz5us.png +0 -0
  63. package/lib/img/logo.cVSpb3sL.png +0 -0
  64. package/lib/img/menu-down.png +0 -0
  65. package/lib/img/menu-up.png +0 -0
  66. package/lib/img/player-bg.png +0 -0
  67. package/lib/img/record-bg.C1mPRb4R.png +0 -0
  68. package/lib/img/roco_icon.png +0 -0
  69. package/lib/img/stats-title.BG5ocjGh.png +0 -0
  70. package/lib/img/wallpaper-pop-l.C8icd3Bp.png +0 -0
  71. package/lib/img/wallpaper-pop.CnlU6_jf.png +0 -0
  72. package/lib/img/win-bg-2.CLgPHdP3.png +0 -0
  73. package/lib/img/win-bg.BgshV29m.png +0 -0
  74. package/lib/img/win-icon.DJfsgL3i.png +0 -0
  75. package/lib/img/xueyingwawa.png +0 -0
  76. package/lib/img/yuanxingshangren.png +0 -0
  77. package/lib/img//344/272/206/344/270/215/350/265/267/347/262/276/347/201/265 half.png +0 -0
  78. package/lib/img//345/215/241/347/211/207/346/225/264/344/275/223bg.png +0 -0
  79. package/lib/img//345/244/264/345/203/217/351/273/221/350/211/262/345/234/206/345/272/225.png +0 -0
  80. package/lib/img//345/256/235/347/256/261/346/240/207-/351/273/221/347/231/275.png +0 -0
  81. package/lib/img//345/256/235/347/256/261/346/240/207.png +0 -0
  82. package/lib/img//345/260/217/346/264/233/345/205/213.png +0 -0
  83. package/lib/img//345/274/202/350/211/262/347/262/276/347/201/265 half.png +0 -0
  84. package/lib/img//346/204/237/345/217/271/345/217/267/357/274/214/344/270/215/347/237/245/351/201/223/345/223/252/351/207/214/350/203/275/347/224/250.png +0 -0
  85. package/lib/img//346/204/237/345/217/271/345/217/267/357/274/214/345/201/217/346/267/261/350/211/262.png +0 -0
  86. package/lib/img//346/220/234/351/233/206/346/203/205/345/206/265.png +0 -0
  87. package/lib/img//346/234/254/345/221/250/350/276/276/345/256/240/345/255/227/346/240/267.png +0 -0
  88. package/lib/img//346/264/233/345/205/213/347/216/213/345/233/275/345/244/247/346/240/207/351/242/230-/347/231/275.png +0 -0
  89. package/lib/img//346/265/205/350/211/262bg.png +0 -0
  90. package/lib/img//346/267/261/350/211/262bg.png +0 -0
  91. package/lib/img//347/202/253/345/275/251/347/262/276/347/201/265 half.png +0 -0
  92. package/lib/img//347/262/276/347/201/265pg.png +0 -0
  93. package/lib/index.js +169 -33
  94. package/lib/render-templates/bind-list/style.css +1 -2
  95. package/lib/render-templates/menu/index.html +3 -3
  96. package/lib/render-templates/package/style.css +1 -2
  97. package/lib/render-templates/personal-card/style.css +1 -1
  98. package/lib/render-templates/record/style.css +2 -3
  99. package/lib/ttf/HYWenHei-85W-1.ttf +0 -0
  100. package/lib/ttf/dundun.xHd_Ee5-.woff2 +0 -0
  101. package/lib/ttf/fzlant.D5FI9Et0.ttf +0 -0
  102. package/package.json +2 -2
  103. package/readme.md +586 -575
  104. package/lib/render-templates/searcheggs/eggs.py +0 -599
package/lib/client.d.ts CHANGED
@@ -14,6 +14,7 @@ export declare class RocomClient {
14
14
  private sanitizeForLog;
15
15
  private headersForLog;
16
16
  private stringifyForLog;
17
+ private isApiKeyPermissionUndeclaredError;
17
18
  private logRequestFailureDetails;
18
19
  private get;
19
20
  private post;
package/lib/client.js CHANGED
@@ -18,9 +18,9 @@ class RocomClient {
18
18
  return '';
19
19
  return uid.trim().replace(/[^a-zA-Z0-9_\- \u4e00-\u9fa5]/g, '').trim();
20
20
  }
21
- wegameHeaders(fwToken = '', userIdentifier = '', clientType = '', clientId = '') {
21
+ wegameHeaders(fwToken = '', userIdentifier = '', clientType = '', clientId = '', includeApiKey = true) {
22
22
  const headers = {};
23
- if (this.apiKey)
23
+ if (includeApiKey && this.apiKey)
24
24
  headers['X-API-Key'] = this.apiKey;
25
25
  if (fwToken)
26
26
  headers['X-Framework-Token'] = fwToken;
@@ -99,6 +99,11 @@ class RocomClient {
99
99
  return String(value);
100
100
  }
101
101
  }
102
+ isApiKeyPermissionUndeclaredError(message) {
103
+ if (!message)
104
+ return false;
105
+ return /未声明\s*api\s*key\s*权限|api\s*key\s*permission|api key 权限/i.test(message);
106
+ }
102
107
  logRequestFailureDetails(method, path, headers, params, body, errorOrResponse) {
103
108
  const err = errorOrResponse;
104
109
  const response = err?.response;
@@ -247,8 +252,8 @@ class RocomClient {
247
252
  return { status: null, data: null };
248
253
  }
249
254
  }
250
- async getIngameTask(ctx, taskId) {
251
- return this.requestWithStatus(ctx, 'GET', `/api/v1/games/rocom/ingame/tasks/${taskId}`, this.wegameHeaders(), { acceptedStatuses: [200, 202] });
255
+ async getIngameTask(ctx, taskId, includeApiKey = true) {
256
+ return this.requestWithStatus(ctx, 'GET', `/api/v1/games/rocom/ingame/tasks/${taskId}`, this.wegameHeaders('', '', '', '', includeApiKey), { acceptedStatuses: [200, 202] });
252
257
  }
253
258
  async qqQrLogin(ctx, userIdentifier) {
254
259
  const params = { client_type: 'bot', client_id: 'koishi', provider: 'rocom' };
@@ -338,7 +343,8 @@ class RocomClient {
338
343
  return null;
339
344
  }
340
345
  const path = '/api/v1/games/rocom/ingame/player/search';
341
- const headers = this.wegameHeaders();
346
+ let includeApiKey = true;
347
+ let headers = this.wegameHeaders();
342
348
  const payload = { uid: sanitizedUid, wait_ms: 5000 };
343
349
  let { status, data } = await this.requestWithStatus(ctx, 'POST', path, headers, {
344
350
  json: payload,
@@ -356,6 +362,29 @@ class RocomClient {
356
362
  if (status === 200 && data && this.isIngamePlayerPayload(data))
357
363
  return data;
358
364
  }
365
+ if (status === null && includeApiKey && this.apiKey && this.isApiKeyPermissionUndeclaredError(this.getLastError(''))) {
366
+ logger.warn('ingame/player/search rejected X-API-Key, retrying without API key');
367
+ includeApiKey = false;
368
+ headers = this.wegameHeaders('', '', '', '', false);
369
+ const retry = await this.requestWithStatus(ctx, 'POST', path, headers, {
370
+ json: payload,
371
+ acceptedStatuses: [200, 202],
372
+ });
373
+ status = retry.status;
374
+ data = retry.data;
375
+ if (status === 200 && data && this.isIngamePlayerPayload(data))
376
+ return data;
377
+ if (status === null) {
378
+ const fallback = await this.requestWithStatus(ctx, 'GET', path, headers, {
379
+ params: payload,
380
+ acceptedStatuses: [200, 202],
381
+ });
382
+ status = fallback.status;
383
+ data = fallback.data;
384
+ if (status === 200 && data && this.isIngamePlayerPayload(data))
385
+ return data;
386
+ }
387
+ }
359
388
  if (!data)
360
389
  return null;
361
390
  if (this.isIngamePlayerPayload(data))
@@ -368,7 +397,7 @@ class RocomClient {
368
397
  }
369
398
  for (let i = 0; i < 8; i++) {
370
399
  await new Promise(resolve => setTimeout(resolve, 1000));
371
- const task = await this.getIngameTask(ctx, taskId);
400
+ const task = await this.getIngameTask(ctx, taskId, includeApiKey);
372
401
  if (task.status === 200)
373
402
  return task.data;
374
403
  if (task.status === null)
@@ -404,7 +433,8 @@ class RocomClient {
404
433
  return null;
405
434
  }
406
435
  const path = '/api/v1/games/rocom/ingame/home/info';
407
- const headers = this.wegameHeaders();
436
+ let includeApiKey = true;
437
+ let headers = this.wegameHeaders();
408
438
  const payload = { uid: sanitizedUid, wait_ms: waitMs };
409
439
  let { status, data } = await this.requestWithStatus(ctx, 'POST', path, headers, {
410
440
  json: payload,
@@ -422,6 +452,29 @@ class RocomClient {
422
452
  if (status === 200 && data && !(data.task_id || data.taskId || data.taskID))
423
453
  return data;
424
454
  }
455
+ if (status === null && includeApiKey && this.apiKey && this.isApiKeyPermissionUndeclaredError(this.getLastError(''))) {
456
+ logger.warn('ingame/home/info rejected X-API-Key, retrying without API key');
457
+ includeApiKey = false;
458
+ headers = this.wegameHeaders('', '', '', '', false);
459
+ const retry = await this.requestWithStatus(ctx, 'POST', path, headers, {
460
+ json: payload,
461
+ acceptedStatuses: [200, 202],
462
+ });
463
+ status = retry.status;
464
+ data = retry.data;
465
+ if (status === 200 && data && !(data.task_id || data.taskId || data.taskID))
466
+ return data;
467
+ if (status === null) {
468
+ const fallback = await this.requestWithStatus(ctx, 'GET', path, headers, {
469
+ params: payload,
470
+ acceptedStatuses: [200, 202],
471
+ });
472
+ status = fallback.status;
473
+ data = fallback.data;
474
+ if (status === 200 && data && !(data.task_id || data.taskId || data.taskID))
475
+ return data;
476
+ }
477
+ }
425
478
  const taskId = data?.task_id || data?.taskId || data?.taskID;
426
479
  if (!taskId) {
427
480
  if (status === 202)
@@ -430,7 +483,7 @@ class RocomClient {
430
483
  }
431
484
  for (let i = 0; i < 10; i++) {
432
485
  await new Promise(resolve => setTimeout(resolve, 1000));
433
- const task = await this.getIngameTask(ctx, taskId);
486
+ const task = await this.getIngameTask(ctx, taskId, includeApiKey);
434
487
  if (task.status === 200)
435
488
  return task.data;
436
489
  if (task.status === null)
@@ -441,10 +494,22 @@ class RocomClient {
441
494
  }
442
495
  async ingameMerchantInfo(ctx, shopId) {
443
496
  const params = { shop_id: shopId };
444
- const data = await this.get(ctx, '/api/v1/games/rocom/ingame/merchant/info', this.wegameHeaders(), params, { silentFailureDetails: true });
497
+ let headers = this.wegameHeaders();
498
+ const data = await this.get(ctx, '/api/v1/games/rocom/ingame/merchant/info', headers, params, { silentFailureDetails: true });
445
499
  if (data)
446
500
  return data;
447
- return this.post(ctx, '/api/v1/games/rocom/ingame/merchant/info', this.wegameHeaders(), params);
501
+ const postData = await this.post(ctx, '/api/v1/games/rocom/ingame/merchant/info', headers, params);
502
+ if (postData)
503
+ return postData;
504
+ if (this.apiKey && this.isApiKeyPermissionUndeclaredError(this.getLastError(''))) {
505
+ logger.warn('ingame/merchant/info rejected X-API-Key, retrying without API key');
506
+ headers = this.wegameHeaders('', '', '', '', false);
507
+ const fallbackData = await this.get(ctx, '/api/v1/games/rocom/ingame/merchant/info', headers, params, { silentFailureDetails: true });
508
+ if (fallbackData)
509
+ return fallbackData;
510
+ return this.post(ctx, '/api/v1/games/rocom/ingame/merchant/info', headers, params);
511
+ }
512
+ return null;
448
513
  }
449
514
  async getFriendship(ctx, fwToken, userIds, userIdentifier = '') {
450
515
  return this.get(ctx, '/api/v1/games/rocom/social/friendship', this.rocomHeaders(fwToken, userIdentifier), { user_ids: userIds });
@@ -373,10 +373,18 @@ function homePlantIcon(deps, iconId) {
373
373
  return deps.renderer.resourceUrl(`render-templates/home/img/home_icon/${text}_2.png`);
374
374
  }
375
375
  let homePlantMapCache = null;
376
+ const HOME_PLANT_MAP_RELATIVE_PATH = node_path_1.default.join('render-templates', 'home', 'data', 'home_item_list.json');
377
+ function resolveHomePlantMapPath() {
378
+ const candidates = [
379
+ node_path_1.default.resolve(__dirname, '..', HOME_PLANT_MAP_RELATIVE_PATH),
380
+ node_path_1.default.resolve(__dirname, HOME_PLANT_MAP_RELATIVE_PATH),
381
+ ];
382
+ return candidates.find(candidate => node_fs_1.default.existsSync(candidate)) || candidates[0];
383
+ }
376
384
  function loadHomePlantMap() {
377
385
  if (homePlantMapCache)
378
386
  return homePlantMapCache;
379
- const filePath = node_path_1.default.resolve(__dirname, '..', 'render-templates', 'home', 'data', 'home_item_list.json');
387
+ const filePath = resolveHomePlantMapPath();
380
388
  try {
381
389
  const data = JSON.parse(node_fs_1.default.readFileSync(filePath, 'utf-8'));
382
390
  homePlantMapCache = data && typeof data === 'object' ? data : {};
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file