koishi-plugin-ets2-tools-tmp 2.4.2 → 2.5.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/command/tmpFootprint.js +9 -0
- package/lib/command/tmpVersionCheck.js +170 -0
- package/lib/index.js +36 -3
- package/package.json +1 -1
- package/readme.md +4 -2
|
@@ -78,6 +78,12 @@ module.exports = async (ctx, session, serverType, tmpId, date) => {
|
|
|
78
78
|
endTime = lastMonth.endOf('month').format('YYYY-MM-DD HH:mm:ss');
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
if (date === 'lastThreeMonths') {
|
|
82
|
+
const threeMonthsAgo = dayjs().subtract(3, 'month');
|
|
83
|
+
startTime = threeMonthsAgo.startOf('month').format('YYYY-MM-DD HH:mm:ss');
|
|
84
|
+
endTime = dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss');
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
if (!startTime || !endTime) {
|
|
82
88
|
return '日期传递错误';
|
|
83
89
|
}
|
|
@@ -110,6 +116,9 @@ module.exports = async (ctx, session, serverType, tmpId, date) => {
|
|
|
110
116
|
if (date === 'lastMonth') {
|
|
111
117
|
return `上月暂无数据`;
|
|
112
118
|
}
|
|
119
|
+
if (date === 'lastThreeMonths') {
|
|
120
|
+
return `近三个月暂无数据`;
|
|
121
|
+
}
|
|
113
122
|
return '暂无数据';
|
|
114
123
|
}
|
|
115
124
|
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VersionCheckService = void 0;
|
|
4
|
+
|
|
5
|
+
const koishi_1 = require("koishi");
|
|
6
|
+
|
|
7
|
+
class VersionCheckService {
|
|
8
|
+
constructor(ctx, config) {
|
|
9
|
+
this.ctx = ctx;
|
|
10
|
+
this.cfg = config;
|
|
11
|
+
this.currentVersion = null;
|
|
12
|
+
this.timers = [];
|
|
13
|
+
this.logger = this.initLogger();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
initLogger() {
|
|
17
|
+
return {
|
|
18
|
+
debug: (message, ...args) => {
|
|
19
|
+
if (this.cfg.debugMode) {
|
|
20
|
+
this.ctx.logger.debug(`[TMP-BOT DEBUG] ${message}`, ...args);
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
info: (message, ...args) => {
|
|
24
|
+
this.ctx.logger.info(`[TMP-BOT] ${message}`, ...args);
|
|
25
|
+
},
|
|
26
|
+
warn: (message, ...args) => {
|
|
27
|
+
this.ctx.logger.warn(`[TMP-BOT WARN] ${message}`, ...args);
|
|
28
|
+
},
|
|
29
|
+
error: (message, ...args) => {
|
|
30
|
+
this.ctx.logger.error(`[TMP-BOT ERROR] ${message}`, ...args);
|
|
31
|
+
},
|
|
32
|
+
api: (message, data) => {
|
|
33
|
+
if (this.cfg.debug?.logApiResponses) {
|
|
34
|
+
this.ctx.logger.info(`[TMP-BOT API] ${message}`, data ? JSON.stringify(data, null, 2) : "");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
start() {
|
|
41
|
+
this.setupVersionCheck();
|
|
42
|
+
this.ctx.on("dispose", () => this.cleanup());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setupVersionCheck() {
|
|
46
|
+
this.logger.info("设置TMP版本检查服务");
|
|
47
|
+
|
|
48
|
+
this.logger.debug("启动时立即检查版本");
|
|
49
|
+
this.checkVersion();
|
|
50
|
+
|
|
51
|
+
const checkInterval = this.cfg.checkInterval * 60 * 1000;
|
|
52
|
+
this.logger.info(`设置定时版本检查,间隔: ${this.cfg.checkInterval} 分钟`);
|
|
53
|
+
|
|
54
|
+
const intervalTimer = setInterval(async () => {
|
|
55
|
+
this.logger.debug("执行定时版本检查");
|
|
56
|
+
await this.checkVersion();
|
|
57
|
+
}, checkInterval);
|
|
58
|
+
this.timers.push(intervalTimer);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async checkVersion() {
|
|
62
|
+
try {
|
|
63
|
+
const apiUrl = "https://api.truckersmp.com/v2/version";
|
|
64
|
+
this.logger.api(`请求TMP版本API: ${apiUrl}`);
|
|
65
|
+
|
|
66
|
+
const startTime = Date.now();
|
|
67
|
+
const response = await this.ctx.http.get(apiUrl, { timeout: 10000 });
|
|
68
|
+
const duration = Date.now() - startTime;
|
|
69
|
+
this.logger.api(`TMP版本API响应耗时: ${duration}ms`);
|
|
70
|
+
|
|
71
|
+
if (response && response.name) {
|
|
72
|
+
const versionInfo = {
|
|
73
|
+
name: response.name,
|
|
74
|
+
time: this.convertToUTC8(response.time),
|
|
75
|
+
supported_game_version: response.supported_game_version,
|
|
76
|
+
supported_ats_game_version: response.supported_ats_game_version
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
this.logger.info(`获取到TMP版本信息: ${versionInfo.name} (${versionInfo.time})`);
|
|
80
|
+
|
|
81
|
+
if (this.currentVersion && this.currentVersion.name !== versionInfo.name) {
|
|
82
|
+
this.logger.info(`检测到版本更新: ${this.currentVersion.name} -> ${versionInfo.name}`);
|
|
83
|
+
await this.sendVersionUpdateNotification(this.currentVersion, versionInfo);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.currentVersion = versionInfo;
|
|
87
|
+
} else {
|
|
88
|
+
this.logger.error("TMP版本API返回的数据格式不正确");
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
this.logger.error("检查TMP版本失败:", error.message);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
convertToUTC8(utcTimeString) {
|
|
96
|
+
try {
|
|
97
|
+
const utcDate = new Date(utcTimeString);
|
|
98
|
+
const utc8Date = new Date(utcDate.getTime() + 8 * 60 * 60 * 1000);
|
|
99
|
+
const year = utc8Date.getFullYear();
|
|
100
|
+
const month = String(utc8Date.getMonth() + 1).padStart(2, '0');
|
|
101
|
+
const day = String(utc8Date.getDate()).padStart(2, '0');
|
|
102
|
+
const hours = String(utc8Date.getHours()).padStart(2, '0');
|
|
103
|
+
const minutes = String(utc8Date.getMinutes()).padStart(2, '0');
|
|
104
|
+
const seconds = String(utc8Date.getSeconds()).padStart(2, '0');
|
|
105
|
+
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
this.logger.error("转换UTC时间失败:", error.message);
|
|
108
|
+
return utcTimeString;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async sendVersionUpdateNotification(oldVersion, newVersion) {
|
|
113
|
+
const message = `📢 TMP版本更新通知
|
|
114
|
+
|
|
115
|
+
旧版本: ${oldVersion.name}
|
|
116
|
+
新版本: ${newVersion.name}
|
|
117
|
+
|
|
118
|
+
更新时间: ${newVersion.time}(UTC+8)
|
|
119
|
+
欧卡支持版本: ${newVersion.supported_game_version}
|
|
120
|
+
美卡支持版本: ${newVersion.supported_ats_game_version}`;
|
|
121
|
+
|
|
122
|
+
this.logger.info(`发送版本更新通知到 ${this.cfg.groups.length} 个群组`);
|
|
123
|
+
|
|
124
|
+
for (const groupId of this.cfg.groups) {
|
|
125
|
+
try {
|
|
126
|
+
await this.sendToGroup(groupId, message);
|
|
127
|
+
this.logger.info(`已发送版本更新通知到群组 ${groupId}`);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
this.logger.error(`发送版本更新通知到群组 ${groupId} 失败:`, error.message);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async sendToGroup(groupId, message) {
|
|
135
|
+
const onebotBots = this.ctx.bots.filter((bot) => {
|
|
136
|
+
return bot.platform === "onebot";
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
if (onebotBots.length === 0) {
|
|
140
|
+
throw new Error("请启用onebot适配器以发送群消息");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let lastError = null;
|
|
144
|
+
this.logger.debug(`尝试通过 ${onebotBots.length} 个onebot适配器发送消息到群组 ${groupId}`);
|
|
145
|
+
|
|
146
|
+
for (const bot of onebotBots) {
|
|
147
|
+
try {
|
|
148
|
+
await bot.sendMessage(groupId, message);
|
|
149
|
+
this.logger.debug(`已通过 ${bot.platform} 适配器发送消息到群组 ${groupId}`);
|
|
150
|
+
return;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
lastError = error;
|
|
153
|
+
this.logger.warn(`通过 ${bot.platform} 适配器发送消息失败: ${error.message}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
throw lastError || new Error(`所有onebot适配器都无法发送消息到群组 ${groupId}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
cleanup() {
|
|
161
|
+
this.logger.debug("插件卸载,开始清理版本检查服务资源");
|
|
162
|
+
this.timers.forEach((timer) => {
|
|
163
|
+
clearTimeout(timer);
|
|
164
|
+
clearInterval(timer);
|
|
165
|
+
});
|
|
166
|
+
this.timers.length = 0;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
exports.VersionCheckService = VersionCheckService;
|
package/lib/index.js
CHANGED
|
@@ -74,10 +74,11 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
74
74
|
tmpDlcMap: koishi_1.Schema.boolean().default(true).description('是否启用DLC地图查询'),
|
|
75
75
|
tmpMileageRanking: koishi_1.Schema.boolean().default(true).description('是否启用里程排行榜'),
|
|
76
76
|
tmpVtc: koishi_1.Schema.boolean().default(true).description('是否启用VTC查询'),
|
|
77
|
-
tmpFootprint: koishi_1.Schema.boolean().default(true).description('
|
|
77
|
+
tmpFootprint: koishi_1.Schema.boolean().default(true).description('是否启用足迹查询'),
|
|
78
78
|
mainSettings: koishi_1.Schema.boolean().default(false).description('是否启用车队平台积分查询功能'),
|
|
79
79
|
resetPassword: koishi_1.Schema.boolean().default(false).description('是否启用车队平台重置密码功能'),
|
|
80
|
-
tmpActivityService: koishi_1.Schema.boolean().default(false).description('是否启用车队活动查询')
|
|
80
|
+
tmpActivityService: koishi_1.Schema.boolean().default(false).description('是否启用车队活动查询'),
|
|
81
|
+
tmpVersionCheck: koishi_1.Schema.boolean().default(false).description('是否启用TMP版本更新查询')
|
|
81
82
|
}).description('指令配置'),
|
|
82
83
|
baiduTranslate: koishi_1.Schema.object({
|
|
83
84
|
enable: koishi_1.Schema.boolean().default(false).description('是否启用百度翻译'),
|
|
@@ -98,6 +99,10 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
98
99
|
koishi_1.Schema.const(2).description('热力图')
|
|
99
100
|
]).default(1).description('路况信息展示方式'),
|
|
100
101
|
}).description('路况查询配置'),
|
|
102
|
+
tmpVersionCheck: koishi_1.Schema.object({
|
|
103
|
+
checkInterval: koishi_1.Schema.number().description("版本检查间隔(分钟)").default(30),
|
|
104
|
+
groups: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("接收版本更新通知的群组ID列表").default([])
|
|
105
|
+
}).description("TMP版本更新查询配置"),
|
|
101
106
|
mainSettings: koishi_1.Schema.object({
|
|
102
107
|
settings: koishi_1.Schema.object({
|
|
103
108
|
Name: koishi_1.Schema.string().description("车队名称"),
|
|
@@ -189,7 +194,9 @@ function logDisabledCommands(ctx, cfg) {
|
|
|
189
194
|
{ key: 'tmpVtc', label: 'vtc查询' },
|
|
190
195
|
{ key: 'tmpFootprint', label: '足迹查询' },
|
|
191
196
|
{ key: 'resetPassword', label: '重置密码' },
|
|
192
|
-
{ key: 'mainSettings', label: '查询积分' }
|
|
197
|
+
{ key: 'mainSettings', label: '查询积分' },
|
|
198
|
+
{ key: 'tmpActivityService', label: '车队活动查询' },
|
|
199
|
+
{ key: 'tmpVersionCheck', label: 'TMP版本更新查询' }
|
|
193
200
|
];
|
|
194
201
|
for (const item of commandList) {
|
|
195
202
|
if (commandFlags[item.key] !== false) enabled.push(item.label);
|
|
@@ -276,6 +283,18 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
276
283
|
.example("上月足迹p 12345")
|
|
277
284
|
.action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.promods, tmpId, 'lastMonth'));
|
|
278
285
|
|
|
286
|
+
ctx.command('近三个月足迹 [tmpId:string]')
|
|
287
|
+
.usage("查询ETS服务器今日足迹")
|
|
288
|
+
.example("近三个月足迹")
|
|
289
|
+
.example("近三个月足迹 12345")
|
|
290
|
+
.action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.ets, tmpId, 'lastThreeMonths'));
|
|
291
|
+
|
|
292
|
+
ctx.command('近三个月足迹p [tmpId:string]')
|
|
293
|
+
.usage("查询Promods服务器今日足迹")
|
|
294
|
+
.example("近三个月足迹p足迹p")
|
|
295
|
+
.example("近三个月足迹p 12345")
|
|
296
|
+
.action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.promods, tmpId, 'lastThreeMonths'));
|
|
297
|
+
|
|
279
298
|
ctx.command('本月足迹 [tmpId:string]')
|
|
280
299
|
.usage("查询ETS服务器今日足迹")
|
|
281
300
|
.example("本月足迹")
|
|
@@ -361,6 +380,20 @@ function apply(ctx, cfg) {
|
|
|
361
380
|
} else if (cfg.debugMode) {
|
|
362
381
|
ctx.logger.debug("[TMP-BOT] 活动查询功能已禁用");
|
|
363
382
|
}
|
|
383
|
+
|
|
384
|
+
if (cfg.commands?.tmpVersionCheck) {
|
|
385
|
+
const { VersionCheckService } = require('./command/tmpVersionCheck');
|
|
386
|
+
const versionCheckConfig = {
|
|
387
|
+
checkInterval: cfg.tmpVersionCheck.checkInterval,
|
|
388
|
+
groups: cfg.tmpVersionCheck.groups,
|
|
389
|
+
debugMode: cfg.debugMode,
|
|
390
|
+
debug: cfg.tmpActivityService?.debug
|
|
391
|
+
};
|
|
392
|
+
const versionCheckService = new VersionCheckService(ctx, versionCheckConfig);
|
|
393
|
+
versionCheckService.start();
|
|
394
|
+
} else if (cfg.debugMode) {
|
|
395
|
+
ctx.logger.debug("[TMP-BOT] TMP版本更新查询功能已禁用");
|
|
396
|
+
}
|
|
364
397
|
}
|
|
365
398
|
__name(apply, "apply");
|
|
366
399
|
0 && (module.exports = {
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
- **游戏资源查询**:地图DLC价格、TMP版本信息一键获取
|
|
15
15
|
- **排行与积分**:总里程/今日里程排行榜、车队平台积分查询
|
|
16
16
|
- **VTC与规则**:支持指定VTC ID查询,提供TruckersMP官方规则快速链接
|
|
17
|
+
- **TMP版本更新通知**:支持TMP版本更新通知
|
|
17
18
|
|
|
18
19
|
### 🚚 车队活动管理
|
|
19
20
|
- **双数据源支持**:同时对接车队平台和TruckersMP API获取活动数据
|
|
@@ -108,12 +109,13 @@
|
|
|
108
109
|
| 活动查询 | 手动检查今日活动数据,返回活动数量统计 | 活动查询 |
|
|
109
110
|
| 今日/昨日足迹 <tmpId> | 查看今日/昨日除p服外的足迹 | 今日/昨日足迹 123456 |
|
|
110
111
|
| 今日/昨日足迹p <tmpId> | 查看今日/昨日p服的足迹 | 今日/昨日足迹p 123456 |
|
|
111
|
-
|
|
|
112
|
-
|
|
|
112
|
+
| 本月/上月/近三个月足迹 <tmpId> | 查看本月/上月除p服外的足迹 | 本月/上月/近三个月足迹 123456 |
|
|
113
|
+
| 本月/上月/近三个月足迹p <tmpId> | 查看本月/上月p服的足迹 | 本月/上月/近三个月足迹p 123456 |
|
|
113
114
|
|
|
114
115
|
## 📝 使用方法
|
|
115
116
|
|
|
116
117
|
### 自动功能
|
|
118
|
+
- TMP更新时通知
|
|
117
119
|
- 每日凌晨2点自动重置活动数据
|
|
118
120
|
- 按配置时间自动检查活动数据与档位状态
|
|
119
121
|
- 向管理群发送档位上传状态提醒
|