koishi-plugin-cs2-update-log 2.3.0 → 2.3.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 (2) hide show
  1. package/lib/index.js +82 -15
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -80,6 +80,9 @@ function apply(ctx, config) {
80
80
  };
81
81
  let stateInitialized = false;
82
82
  let polling = false;
83
+ let appReady = false;
84
+ let stateLoadPromise;
85
+ let initialPollStarted = false;
83
86
  function clearRuntimeCache(reason) {
84
87
  cache.rssFetchedAt = 0;
85
88
  cache.rssItems = [];
@@ -107,7 +110,9 @@ function apply(ctx, config) {
107
110
  }
108
111
  async function saveState(recentItems) {
109
112
  try {
110
- const recentGids = recentItems.map((item) => item.gid).filter(Boolean);
113
+ const recentGids = recentItems
114
+ .map((item) => item.gid)
115
+ .filter((gid) => gid && knownGids.has(gid));
111
116
  const recentSet = new Set(recentGids);
112
117
  const gids = [
113
118
  ...recentGids,
@@ -240,7 +245,11 @@ function apply(ctx, config) {
240
245
  let pushed = 0;
241
246
  for (const item of freshItems) {
242
247
  const classified = classifyNews(item);
243
- await pushNews(classified);
248
+ const delivered = await pushNews(classified);
249
+ if (!delivered) {
250
+ logger.warn('新闻未成功送达,保留 gid 等待重试:gid=%s title=%s', item.gid, item.title);
251
+ continue;
252
+ }
244
253
  knownGids.add(item.gid);
245
254
  pushed += 1;
246
255
  }
@@ -268,22 +277,55 @@ function apply(ctx, config) {
268
277
  async function pushNews(news) {
269
278
  if (!config.targets.length) {
270
279
  logger.warn('未配置推送目标,已跳过:%s', news.item.title);
271
- return;
280
+ return false;
281
+ }
282
+ const deliveries = config.targets.map((target) => ({
283
+ target,
284
+ bot: findTargetBot(ctx, target),
285
+ }));
286
+ const unavailable = deliveries.filter(({ bot }) => !bot);
287
+ if (unavailable.length) {
288
+ for (const { target } of unavailable) {
289
+ logger.warn('找不到在线推送机器人 platform=%s selfId=%s', target.platform, target.selfId || '*');
290
+ }
291
+ return false;
272
292
  }
273
293
  const content = await buildNewsContent(news);
274
- await Promise.all(config.targets.map(async (target) => {
294
+ const results = await Promise.all(deliveries.map(async ({ target, bot }) => {
275
295
  try {
276
- const bot = findTargetBot(ctx, target);
277
- if (!bot) {
278
- logger.warn('找不到推送机器人 platform=%s selfId=%s', target.platform, target.selfId || '*');
279
- return;
280
- }
296
+ if (!bot)
297
+ return false;
281
298
  await bot.sendMessage(target.channelId, content);
299
+ return true;
282
300
  }
283
301
  catch (error) {
284
302
  logger.error('推送到 channelId=%s 失败:%s', target.channelId, formatError(error));
303
+ return false;
285
304
  }
286
305
  }));
306
+ return results.every(Boolean);
307
+ }
308
+ function ensureStateLoaded() {
309
+ return stateLoadPromise ||= loadState();
310
+ }
311
+ function allTargetBotsOnline() {
312
+ return !!config.targets.length && config.targets.every((target) => !!findTargetBot(ctx, target));
313
+ }
314
+ async function pollWhenTargetsOnline(source) {
315
+ if (!appReady) {
316
+ logger.debug('应用尚未 ready,跳过本次 %s 轮询。', source);
317
+ return 0;
318
+ }
319
+ await ensureStateLoaded();
320
+ if (!allTargetBotsOnline()) {
321
+ logger.debug('目标机器人尚未全部在线,跳过本次 %s 轮询。', source);
322
+ return 0;
323
+ }
324
+ if (!initialPollStarted) {
325
+ initialPollStarted = true;
326
+ return pollAndPush('startup');
327
+ }
328
+ return pollAndPush(source);
287
329
  }
288
330
  async function renderOrFallbackText(news, title, bodyMarkdown, link) {
289
331
  const puppeteer = ctx.puppeteer;
@@ -440,7 +482,9 @@ function apply(ctx, config) {
440
482
  });
441
483
  ctx.command('cs2log.push', '手动检查并推送新的 CS2 官方公告')
442
484
  .action(async () => {
443
- const pushed = await pollAndPush('manual');
485
+ if (!allTargetBotsOnline())
486
+ return '目标机器人尚未在线,暂未执行推送。';
487
+ const pushed = await pollWhenTargetsOnline('manual');
444
488
  return pushed ? `已推送 ${pushed} 条新的 CS2 官方新闻。` : '没有发现新的 CS2 官方新闻。';
445
489
  });
446
490
  ctx.command('cs2log.test', '测试推送最近 2 条 CS2 官方新闻')
@@ -457,15 +501,36 @@ function apply(ctx, config) {
457
501
  }
458
502
  return `已向当前会话触发 ${testItems.length} 条 CS2 官方新闻测试推送。本次测试不会写入 gid 判重 state。`;
459
503
  });
460
- ctx.on('ready', () => {
461
- void loadState()
462
- .then(() => pollAndPush('startup'))
463
- .catch((error) => {
504
+ ctx.on('ready', async () => {
505
+ appReady = true;
506
+ try {
507
+ await pollWhenTargetsOnline('startup');
508
+ }
509
+ catch (error) {
464
510
  logger.error('启动 CS2 新闻轮询失败:%s', formatError(error));
511
+ }
512
+ });
513
+ ctx.on('bot-status-updated', async (bot) => {
514
+ if (bot.status !== 1 /* Universal.Status.ONLINE */)
515
+ return;
516
+ const matchesTarget = config.targets.some((target) => {
517
+ if (target.platform && bot.platform !== target.platform)
518
+ return false;
519
+ if (target.selfId && bot.selfId !== target.selfId)
520
+ return false;
521
+ return true;
465
522
  });
523
+ if (!matchesTarget)
524
+ return;
525
+ try {
526
+ await pollWhenTargetsOnline('online');
527
+ }
528
+ catch (error) {
529
+ logger.error('机器人上线后检查 CS2 新闻失败:%s', formatError(error));
530
+ }
466
531
  });
467
532
  ctx.setInterval(() => {
468
- void pollAndPush('timer');
533
+ void pollWhenTargetsOnline('timer');
469
534
  }, Math.max(5, config.interval) * 1000);
470
535
  ctx.setInterval(() => {
471
536
  clearRuntimeCache('short cache interval');
@@ -881,6 +946,8 @@ body {
881
946
  function findTargetBot(ctx, target) {
882
947
  const bots = Array.from(ctx.bots || []);
883
948
  return bots.find((bot) => {
949
+ if (bot.status !== 1 /* Universal.Status.ONLINE */)
950
+ return false;
884
951
  if (target.platform && bot.platform !== target.platform)
885
952
  return false;
886
953
  if (target.selfId && bot.selfId !== target.selfId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-cs2-update-log",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "Koishi plugin for monitoring CS2 official Steam announcements and update logs.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",