koishi-plugin-ets2-tools-tmp 1.2.1 → 1.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/lib/index.js +67 -49
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -34,9 +34,9 @@ const __copyProps = (to, from, except, desc) => {
|
|
|
34
34
|
if (from && (typeof from === "object" || typeof from === "function")) {
|
|
35
35
|
for (const key of __getOwnPropNames(from))
|
|
36
36
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
37
|
-
__defProp(to, key, {
|
|
38
|
-
get: () => from[key],
|
|
39
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
37
|
+
__defProp(to, key, {
|
|
38
|
+
get: () => from[key],
|
|
39
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
return to;
|
|
@@ -217,9 +217,9 @@ class ActivityService {
|
|
|
217
217
|
const localTime = now.toLocaleString();
|
|
218
218
|
const localDate = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
|
|
219
219
|
const utcDate = now.toISOString().split("T")[0];
|
|
220
|
-
|
|
220
|
+
|
|
221
221
|
this.logger.timing(`开始设置每日定时任务,本地时间: ${localTime}, 本地日期: ${localDate}, UTC日期: ${utcDate}`);
|
|
222
|
-
|
|
222
|
+
|
|
223
223
|
const resetHour = 2;
|
|
224
224
|
const resetMinute = 0;
|
|
225
225
|
const resetDelay = this.getNextTime(resetHour, resetMinute);
|
|
@@ -234,7 +234,7 @@ class ActivityService {
|
|
|
234
234
|
}, resetDelay);
|
|
235
235
|
this.timers.push(resetTimer);
|
|
236
236
|
this.logger.timing(`设置数据重置定时器: ${resetHour}:${resetMinute.toString().padStart(2, "0")}, 延迟: ${resetDelay}ms`);
|
|
237
|
-
|
|
237
|
+
|
|
238
238
|
this.cfg.adminCheckTimes.forEach((timeStr, index) => {
|
|
239
239
|
const [hours, minutes] = timeStr.split(":").map(Number);
|
|
240
240
|
this.setupTimer(hours, minutes, async () => {
|
|
@@ -302,22 +302,22 @@ class ActivityService {
|
|
|
302
302
|
const localTime = now.toLocaleString();
|
|
303
303
|
const localDate = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
|
|
304
304
|
const utcDate = now.toISOString().split("T")[0];
|
|
305
|
-
|
|
305
|
+
|
|
306
306
|
const previousActivityCount = this.todayActivities.length;
|
|
307
307
|
const previousTMPCount = this.todayTMPEvents.length;
|
|
308
308
|
const previousReminderCount = this.sentReminders.size;
|
|
309
309
|
const previousNoActivityNotification = this.sentNoActivityNotification;
|
|
310
|
-
|
|
310
|
+
|
|
311
311
|
this.logger.info(`[数据重置] 开始重置数据,本地时间: ${localTime}, 本地日期: ${localDate}, UTC日期: ${utcDate}`);
|
|
312
312
|
this.logger.info(`[数据重置] 重置前数据: 活动${previousActivityCount}个, TMP${previousTMPCount}个, 提醒${previousReminderCount}个, 无活动通知${previousNoActivityNotification ? "已发送" : "未发送"}`);
|
|
313
|
-
|
|
313
|
+
|
|
314
314
|
this.todayActivities = [];
|
|
315
315
|
this.todayTMPEvents = [];
|
|
316
316
|
this.sentReminders.clear();
|
|
317
317
|
this.sentNoActivityNotification = false;
|
|
318
|
-
|
|
318
|
+
|
|
319
319
|
this.logger.info(`[数据重置] 每日数据已重置: 活动${previousActivityCount}→0, TMP${previousTMPCount}→0, 提醒${previousReminderCount}→0, 无活动通知${previousNoActivityNotification ? "已发送" : "未发送"}→未发送`);
|
|
320
|
-
|
|
320
|
+
|
|
321
321
|
this.updateActivityData().then(() => {
|
|
322
322
|
this.logger.info(`[数据重置] 重置后数据更新完成: 活动${this.todayActivities.length}个, TMP${this.todayTMPEvents.length}个`);
|
|
323
323
|
}).catch(error => {
|
|
@@ -333,7 +333,7 @@ class ActivityService {
|
|
|
333
333
|
this.updateTodayActivities(),
|
|
334
334
|
this.updateTodayTMPEvents()
|
|
335
335
|
]);
|
|
336
|
-
|
|
336
|
+
|
|
337
337
|
const duration = Date.now() - startTime;
|
|
338
338
|
this.logger.info(`活动数据更新完成,耗时: ${duration}ms`);
|
|
339
339
|
this.logger.debug(`今日活动数量: ${this.todayActivities.length}, TMP活动数量: ${this.todayTMPEvents.length}`);
|
|
@@ -345,7 +345,7 @@ class ActivityService {
|
|
|
345
345
|
async updateTodayActivities() {
|
|
346
346
|
try {
|
|
347
347
|
this.todayActivities = [];
|
|
348
|
-
|
|
348
|
+
|
|
349
349
|
const protocol = this.cfg.adminUseHttps ? "https://" : "http://";
|
|
350
350
|
const fullUrl = `${protocol}${this.cfg.adminApiUrl}/api/activity/info/list?token=${this.cfg.adminApiToken}&page=1&limit=50&themeName=`;
|
|
351
351
|
this.logger.api(`请求车队平台API: ${fullUrl.replace(this.cfg.adminApiToken, "***")}`);
|
|
@@ -367,14 +367,14 @@ class ActivityService {
|
|
|
367
367
|
const now = new Date();
|
|
368
368
|
const today = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
|
|
369
369
|
this.logger.debug(`[活动更新] 当前本地日期: ${today}, UTC日期: ${new Date().toISOString().split("T")[0]}`);
|
|
370
|
-
|
|
370
|
+
|
|
371
371
|
const originalCount = response.data.list.length;
|
|
372
372
|
this.logger.debug(`[活动更新] API返回活动总数: ${originalCount}`);
|
|
373
373
|
if (this.cfg.debugMode && originalCount > 0) {
|
|
374
374
|
const activityDates = response.data.list.map(a => `${a.themeName}: ${a.startTime?.split(" ")[0]}`);
|
|
375
375
|
this.logger.debug(`[活动更新] 所有活动日期:`, activityDates);
|
|
376
376
|
}
|
|
377
|
-
|
|
377
|
+
|
|
378
378
|
this.todayActivities = response.data.list.filter((activity) => {
|
|
379
379
|
const activityDate = activity.startTime?.split(" ")[0];
|
|
380
380
|
const isToday = activityDate === today;
|
|
@@ -383,7 +383,7 @@ class ActivityService {
|
|
|
383
383
|
}
|
|
384
384
|
return isToday;
|
|
385
385
|
});
|
|
386
|
-
|
|
386
|
+
|
|
387
387
|
this.logger.info(`[活动更新] 从车队平台找到 ${this.todayActivities.length}/${originalCount} 个今日活动`);
|
|
388
388
|
if (this.cfg.debugMode && this.todayActivities.length > 0) {
|
|
389
389
|
const todayActivityNames = this.todayActivities.map(a => `${a.themeName}: ${a.startTime}`);
|
|
@@ -402,12 +402,12 @@ class ActivityService {
|
|
|
402
402
|
async updateTodayTMPEvents() {
|
|
403
403
|
try {
|
|
404
404
|
this.todayTMPEvents = [];
|
|
405
|
-
|
|
405
|
+
|
|
406
406
|
if (!this.cfg.adminVtcId) {
|
|
407
407
|
this.logger.warn("[TMP活动更新] TMP API请求失败:未配置adminVtcId");
|
|
408
408
|
return;
|
|
409
409
|
}
|
|
410
|
-
|
|
410
|
+
|
|
411
411
|
const tmpApiUrl = `https://api.truckersmp.com/v2/vtc/${this.cfg.adminVtcId}/events/attending/`;
|
|
412
412
|
this.logger.api(`[TMP活动更新] 请求TMP API: ${tmpApiUrl}`);
|
|
413
413
|
|
|
@@ -420,15 +420,15 @@ class ActivityService {
|
|
|
420
420
|
const now = new Date();
|
|
421
421
|
const today = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
|
|
422
422
|
this.logger.debug(`[TMP活动更新] 当前本地日期: ${today}, UTC日期: ${new Date().toISOString().split("T")[0]}`);
|
|
423
|
-
|
|
423
|
+
|
|
424
424
|
const originalCount = response.response.length;
|
|
425
425
|
this.logger.debug(`[TMP活动更新] API返回活动总数: ${originalCount}`);
|
|
426
|
-
|
|
426
|
+
|
|
427
427
|
if (this.cfg.debugMode && originalCount > 0) {
|
|
428
428
|
const eventDates = response.response.map(e => `${e.name}: ${e.start_at?.split(" ")[0]}`);
|
|
429
429
|
this.logger.debug(`[TMP活动更新] 所有活动日期:`, eventDates);
|
|
430
430
|
}
|
|
431
|
-
|
|
431
|
+
|
|
432
432
|
this.todayTMPEvents = response.response.filter((event) => {
|
|
433
433
|
const eventDate = event.start_at?.split(" ")[0];
|
|
434
434
|
const isToday = eventDate === today;
|
|
@@ -437,9 +437,9 @@ class ActivityService {
|
|
|
437
437
|
}
|
|
438
438
|
return isToday;
|
|
439
439
|
});
|
|
440
|
-
|
|
440
|
+
|
|
441
441
|
this.logger.info(`[TMP活动更新] 从TMP找到 ${this.todayTMPEvents.length}/${originalCount} 个今日活动`);
|
|
442
|
-
|
|
442
|
+
|
|
443
443
|
if (this.cfg.debugMode && this.todayTMPEvents.length > 0) {
|
|
444
444
|
const todayEventNames = this.todayTMPEvents.map(e => `${e.name}: ${e.start_at}`);
|
|
445
445
|
this.logger.debug(`[TMP活动更新] 今日活动详情:`, todayEventNames);
|
|
@@ -454,12 +454,12 @@ class ActivityService {
|
|
|
454
454
|
|
|
455
455
|
async checkAndSendProfileReminders() {
|
|
456
456
|
await this.updateActivityData();
|
|
457
|
-
|
|
457
|
+
|
|
458
458
|
if (this.todayActivities.length === 0) {
|
|
459
459
|
this.logger.debug("今日没有活动,跳过档位检查");
|
|
460
460
|
return;
|
|
461
461
|
}
|
|
462
|
-
|
|
462
|
+
|
|
463
463
|
this.logger.debug(`开始检查 ${this.todayActivities.length} 个活动的档位状态`);
|
|
464
464
|
|
|
465
465
|
for (const activity of this.todayActivities) {
|
|
@@ -491,7 +491,7 @@ class ActivityService {
|
|
|
491
491
|
}
|
|
492
492
|
|
|
493
493
|
this.logger.info(`${manualTest ? "手动测试" : "自动"}今日无活动,发送通知到管理群`);
|
|
494
|
-
|
|
494
|
+
|
|
495
495
|
for (const groupId of this.cfg.adminGroups) {
|
|
496
496
|
try {
|
|
497
497
|
await this.sendToGroup(groupId, this.cfg.adminNoActivityMessage, "管理群组");
|
|
@@ -523,6 +523,12 @@ class ActivityService {
|
|
|
523
523
|
let remindersSent = 0;
|
|
524
524
|
this.logger.debug(`检查 ${this.todayActivities.length} 个活动的提醒时间,当前本地日期: ${today}, UTC日期: ${todayUTC}`);
|
|
525
525
|
|
|
526
|
+
if (this.cfg.mainGroups.length === 0) {
|
|
527
|
+
this.logger.warn(`未配置主群组ID (mainGroups为空),活动提醒将无法发送`);
|
|
528
|
+
} else {
|
|
529
|
+
this.logger.debug(`已配置 ${this.cfg.mainGroups.length} 个主群组: ${this.cfg.mainGroups.join(', ')}`);
|
|
530
|
+
}
|
|
531
|
+
|
|
526
532
|
for (const activity of this.todayActivities) {
|
|
527
533
|
try {
|
|
528
534
|
const activityDate = activity.startTime?.split(" ")[0];
|
|
@@ -542,25 +548,35 @@ class ActivityService {
|
|
|
542
548
|
const minutesLeft = Math.floor(totalSecondsLeft / 60);
|
|
543
549
|
const secondsLeft = totalSecondsLeft % 60;
|
|
544
550
|
this.logger.debug(`活动 "${activity.themeName}" 剩余时间: ${minutesLeft} 分 ${secondsLeft} 秒`);
|
|
545
|
-
|
|
551
|
+
this.logger.debug(`活动 "${activity.themeName}" 时间检查: totalSecondsLeft=${totalSecondsLeft}, 触发条件: -300 <= ${totalSecondsLeft} <= 0`);
|
|
552
|
+
|
|
553
|
+
if (totalSecondsLeft >= -300 && totalSecondsLeft <= 0) {
|
|
546
554
|
const startReminderKey = `${activity.id}_started`;
|
|
547
555
|
if (!this.sentReminders.has(startReminderKey)) {
|
|
548
|
-
this.logger.
|
|
556
|
+
this.logger.info(`触发活动开始提醒: ${activity.themeName}`);
|
|
549
557
|
await this.sendActivityStartReminder(activity);
|
|
550
558
|
this.sentReminders.add(startReminderKey);
|
|
551
559
|
remindersSent++;
|
|
560
|
+
} else {
|
|
561
|
+
this.logger.debug(`活动 "${activity.themeName}" 开始提醒已发送过,跳过`);
|
|
552
562
|
}
|
|
563
|
+
} else {
|
|
564
|
+
this.logger.debug(`活动 "${activity.themeName}" 未满足开始提醒条件,当前剩余 ${totalSecondsLeft} 秒`);
|
|
553
565
|
}
|
|
566
|
+
|
|
554
567
|
if (totalSecondsLeft < 0) continue;
|
|
555
568
|
for (const reminderTime of this.cfg.mainActivityReminderTimes) {
|
|
556
569
|
const reminderTimeSeconds = reminderTime * 60;
|
|
557
|
-
|
|
570
|
+
this.logger.debug(`活动 "${activity.themeName}" ${reminderTime}分钟前提醒检查: totalSecondsLeft=${totalSecondsLeft}, reminderTimeSeconds=${reminderTimeSeconds}, 条件: ${reminderTimeSeconds - 60} <= ${totalSecondsLeft} <= ${reminderTimeSeconds}`);
|
|
571
|
+
if (totalSecondsLeft <= reminderTimeSeconds && totalSecondsLeft > reminderTimeSeconds - 60) {
|
|
558
572
|
const reminderKey = `${activity.id}_${reminderTime}`;
|
|
559
573
|
if (!this.sentReminders.has(reminderKey)) {
|
|
560
|
-
this.logger.
|
|
561
|
-
await this.sendActivityReminder(activity,
|
|
574
|
+
this.logger.info(`触发活动前提醒: ${activity.themeName} - ${reminderTime} 分钟前`);
|
|
575
|
+
await this.sendActivityReminder(activity, reminderTime);
|
|
562
576
|
this.sentReminders.add(reminderKey);
|
|
563
577
|
remindersSent++;
|
|
578
|
+
} else {
|
|
579
|
+
this.logger.debug(`活动 "${activity.themeName}" ${reminderTime}分钟前提醒已发送过,跳过`);
|
|
564
580
|
}
|
|
565
581
|
}
|
|
566
582
|
}
|
|
@@ -570,7 +586,9 @@ class ActivityService {
|
|
|
570
586
|
}
|
|
571
587
|
|
|
572
588
|
if (remindersSent > 0) {
|
|
573
|
-
this.logger.
|
|
589
|
+
this.logger.info(`本轮发送了 ${remindersSent} 个活动提醒`);
|
|
590
|
+
} else {
|
|
591
|
+
this.logger.debug(`本轮未发送任何活动提醒`);
|
|
574
592
|
}
|
|
575
593
|
}
|
|
576
594
|
|
|
@@ -619,7 +637,7 @@ class ActivityService {
|
|
|
619
637
|
this.logger.matching(`活动匹配: "${activity.themeName}" - 找到TMP匹配: ${!!tmpEvent}`);
|
|
620
638
|
|
|
621
639
|
const replacements = this.createActivityReplacements(activity, tmpEvent);
|
|
622
|
-
|
|
640
|
+
|
|
623
641
|
let message = this.cfg.mainActivityStartReminderMessage;
|
|
624
642
|
for (const [key, value] of Object.entries(replacements)) {
|
|
625
643
|
message = message.replace(new RegExp(`{${key}}`, "g"), value);
|
|
@@ -631,7 +649,7 @@ class ActivityService {
|
|
|
631
649
|
|
|
632
650
|
message = message.replace(/\\n/g, "\n").trim();
|
|
633
651
|
const fullMessage = `@全体成员\n${message}`;
|
|
634
|
-
|
|
652
|
+
|
|
635
653
|
await this.sendToMainGroups(fullMessage, activity.themeName, "开始提醒");
|
|
636
654
|
} catch (error) {
|
|
637
655
|
this.logger.error(`发送活动开始提醒失败:`, error.message);
|
|
@@ -646,7 +664,7 @@ class ActivityService {
|
|
|
646
664
|
this.logger.matching(`活动匹配: "${activity.themeName}" - 找到TMP匹配: ${!!tmpEvent}`);
|
|
647
665
|
|
|
648
666
|
const replacements = this.createActivityReplacements(activity, tmpEvent, minutesLeft);
|
|
649
|
-
|
|
667
|
+
|
|
650
668
|
let message = this.cfg.mainActivityReminderMessage;
|
|
651
669
|
for (const [key, value] of Object.entries(replacements)) {
|
|
652
670
|
message = message.replace(new RegExp(`{${key}}`, "g"), value);
|
|
@@ -658,7 +676,7 @@ class ActivityService {
|
|
|
658
676
|
|
|
659
677
|
message = message.replace(/\\n/g, "\n").trim();
|
|
660
678
|
const fullMessage = `@全体成员\n${message}`;
|
|
661
|
-
|
|
679
|
+
|
|
662
680
|
await this.sendToMainGroups(fullMessage, activity.themeName, `${minutesLeft}分钟前提醒`);
|
|
663
681
|
} catch (error) {
|
|
664
682
|
this.logger.error(`发送活动提醒失败:`, error.message);
|
|
@@ -721,60 +739,60 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
721
739
|
ctx.command('查询 <tmpId>')
|
|
722
740
|
.usage("查询TMP玩家信息")
|
|
723
741
|
.action(async ({ session }, tmpId) => await commands.tmpQuery(ctx, cfg, session, tmpId));
|
|
724
|
-
|
|
742
|
+
|
|
725
743
|
ctx.command('美卡服务器')
|
|
726
744
|
.usage("查询美国卡车模拟器TMP服务器信息")
|
|
727
745
|
.action(async () => await commands.tmpServer(ctx, cfg, 'ATS'));
|
|
728
|
-
|
|
746
|
+
|
|
729
747
|
ctx.command('欧卡服务器')
|
|
730
748
|
.usage("查询欧洲卡车模拟2TMP服务器信息")
|
|
731
749
|
.action(async () => await commands.tmpServer(ctx, cfg, 'ETS2'));
|
|
732
|
-
|
|
750
|
+
|
|
733
751
|
ctx.command('绑定 <tmpId>')
|
|
734
752
|
.usage("绑定TmpId")
|
|
735
753
|
.action(async ({ session }, tmpId) => await commands.tmpBind(ctx, cfg, session, tmpId));
|
|
736
|
-
|
|
754
|
+
|
|
737
755
|
ctx.command('路况 <serverName>')
|
|
738
756
|
.usage("查询欧洲卡车模拟2服务器路况")
|
|
739
757
|
.example("路况 - s1")
|
|
740
758
|
.action(async ({ session }, serverName) => await commands.tmpTraffic(ctx, cfg, serverName));
|
|
741
|
-
|
|
759
|
+
|
|
742
760
|
ctx.command('定位 <tmpId>')
|
|
743
761
|
.usage("定位玩家线上位置")
|
|
744
762
|
.action(async ({ session }, tmpId) => await commands.tmpPosition(ctx, cfg, session, tmpId));
|
|
745
|
-
|
|
763
|
+
|
|
746
764
|
ctx.command('tmp版本')
|
|
747
765
|
.usage("查询TruckersMP支持的游戏版本")
|
|
748
766
|
.action(async () => await commands.tmpVersion(ctx));
|
|
749
|
-
|
|
767
|
+
|
|
750
768
|
ctx.command('地图dlc价格')
|
|
751
769
|
.usage("查询欧洲卡车模拟2地图dlc价格")
|
|
752
770
|
.action(async ({ session }) => await commands.tmpDlcMap(ctx, session));
|
|
753
|
-
|
|
771
|
+
|
|
754
772
|
ctx.command('里程排行榜')
|
|
755
773
|
.usage("查询欧洲卡车模拟2里程排行榜")
|
|
756
774
|
.action(async ({ session }) => await commands.tmpMileageRanking(ctx, session, MileageRankingType.total));
|
|
757
|
-
|
|
775
|
+
|
|
758
776
|
ctx.command('今日里程排行榜')
|
|
759
777
|
.usage("查询欧洲卡车模拟2今日里程排行榜")
|
|
760
778
|
.action(async ({ session }) => await commands.tmpMileageRanking(ctx, session, MileageRankingType.today));
|
|
761
|
-
|
|
779
|
+
|
|
762
780
|
ctx.command('vtc查询 <vtcid>')
|
|
763
781
|
.usage("查询TruckersMP VTC信息")
|
|
764
782
|
.action(async ({ session }, vtcid) => await commands.tmpVtc(ctx, cfg, session, vtcid));
|
|
765
|
-
|
|
783
|
+
|
|
766
784
|
ctx.command(`重置密码 [targetTeamId:string]`, "重置欧卡车队平台密码")
|
|
767
785
|
.usage("重置自己的密码,或管理员重置指定teamId的密码")
|
|
768
786
|
.example(`重置密码 - 重置自己的密码`)
|
|
769
787
|
.example(`重置密码 - 管理员重置指定teamId的密码`)
|
|
770
788
|
.action(async ({ session }, targetTeamId) => await commands.resetPassword(ctx, cfg, session, targetTeamId));
|
|
771
|
-
|
|
789
|
+
|
|
772
790
|
ctx.command(`查询积分 [targetQQ:string]`, "查询欧卡车队平台积分")
|
|
773
791
|
.usage("查询自己或指定QQ号的积分,在群聊中可@他人查询")
|
|
774
792
|
.example(`查询积分 - 查询自己的积分`)
|
|
775
793
|
.example(`查询积分 123456 - 查询指定QQ号的积分`)
|
|
776
794
|
.action(async ({ session }, targetQQ) => await commands.queryPoint(ctx, cfg, session, targetQQ));
|
|
777
|
-
|
|
795
|
+
|
|
778
796
|
ctx.command('规则查询')
|
|
779
797
|
.action(async () => 'TruckersMP官方规则链接:https://truckersmp.com/knowledge-base/article/746');
|
|
780
798
|
}
|