koishi-plugin-ets2-tools-tmp 1.2.2 → 1.3.0

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 CHANGED
@@ -20,6 +20,7 @@ const commands = {
20
20
  queryPoint: require('./command/ets-app/queryPoint'),
21
21
  tmpVtc: require('./command/tmpVtc')
22
22
  };
23
+ const { ActivityService } = require('./command/tmpActivityService');
23
24
 
24
25
  const __defProp = Object.defineProperty;
25
26
  const __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -58,741 +59,187 @@ exports.inject = {
58
59
 
59
60
  exports.Config = koishi_1.Schema.intersect([
60
61
  koishi_1.Schema.object({
61
- baiduTranslateEnable: koishi_1.Schema.boolean().default(false).description('启用百度翻译'),
62
- baiduTranslateAppId: koishi_1.Schema.string().description('百度翻译APP ID'),
63
- baiduTranslateKey: koishi_1.Schema.string().description('百度翻译秘钥'),
64
- baiduTranslateCacheEnable: koishi_1.Schema.boolean().default(false).description('启用百度翻译缓存')
65
- }).description('指令基本配置'),
66
- koishi_1.Schema.object({
67
- queryShowAvatarEnable: koishi_1.Schema.boolean().default(false).description('查询指令展示头像,部分玩家的擦边头像可能导致封号'),
68
- tmpTrafficType: koishi_1.Schema.union([
69
- koishi_1.Schema.const(1).description('文字'),
70
- koishi_1.Schema.const(2).description('热力图')
71
- ]).default(1).description('路况信息展示方式'),
72
- tmpQueryType: koishi_1.Schema.union([
73
- koishi_1.Schema.const(1).description('文字'),
74
- koishi_1.Schema.const(2).description('图片')
75
- ]).default(1).description('玩家信息展示方式'),
76
- }).description('指令名称配置'),
62
+ debugMode: koishi_1.Schema.boolean().default(false).description('启用调试模式(输出详细日志)')
63
+ }).description('基本配置'),
77
64
  koishi_1.Schema.object({
65
+ commands: koishi_1.Schema.object({
66
+ tmpQuery: koishi_1.Schema.boolean().default(true).description('是否启用查询功能'),
67
+ tmpTraffic: koishi_1.Schema.boolean().default(true).description('是否启用路况查询'),
68
+ tmpServer: koishi_1.Schema.boolean().default(true).description('是否启用服务器查询'),
69
+ tmpBind: koishi_1.Schema.boolean().default(true).description('是否启用绑定功能'),
70
+ tmpPosition: koishi_1.Schema.boolean().default(true).description('是否启用定位功能'),
71
+ tmpVersion: koishi_1.Schema.boolean().default(true).description('是否启用版本查询'),
72
+ tmpDlcMap: koishi_1.Schema.boolean().default(true).description('是否启用DLC地图查询'),
73
+ tmpMileageRanking: koishi_1.Schema.boolean().default(true).description('是否启用里程排行榜'),
74
+ tmpVtc: koishi_1.Schema.boolean().default(true).description('是否启用VTC查询'),
75
+ mainSettings: koishi_1.Schema.boolean().default(false).description('是否启用车队平台功能'),
76
+ resetPassword: koishi_1.Schema.boolean().default(false).description('是否启用重置密码功能'),
77
+ tmpActivityService: koishi_1.Schema.boolean().default(false).description('是否启用活动查询')
78
+ }).description('指令配置'),
79
+ baiduTranslate: koishi_1.Schema.object({
80
+ enable: koishi_1.Schema.boolean().default(false).description('是否启用百度翻译'),
81
+ appId: koishi_1.Schema.string().description('百度翻译APP ID'),
82
+ key: koishi_1.Schema.string().description('百度翻译秘钥'),
83
+ enableCache: koishi_1.Schema.boolean().default(false).description('是否启用翻译缓存')
84
+ }).description('百度翻译配置'),
85
+ tmpQuery: koishi_1.Schema.object({
86
+ showAvatar: koishi_1.Schema.boolean().default(false).description('是否显示玩家头像(部分玩家的擦边头像可能导致封号)'),
87
+ type: koishi_1.Schema.union([
88
+ koishi_1.Schema.const(1).description('文字'),
89
+ koishi_1.Schema.const(2).description('图片')
90
+ ]).default(1).description('玩家信息展示方式'),
91
+ }).description('玩家查询配置'),
92
+ tmpTraffic: koishi_1.Schema.object({
93
+ type: koishi_1.Schema.union([
94
+ koishi_1.Schema.const(1).description('文字'),
95
+ koishi_1.Schema.const(2).description('热力图')
96
+ ]).default(1).description('路况信息展示方式'),
97
+ }).description('路况查询配置'),
78
98
  mainSettings: koishi_1.Schema.object({
79
- url: koishi_1.Schema.string().description("API服务器地址").required(),
80
- token: koishi_1.Schema.string().description("API认证令牌").required(),
81
- logOutput: koishi_1.Schema.boolean().description("是否输出日志").default(true)
82
- }).description("车队平台设置")
83
- }),
84
- koishi_1.Schema.object({
99
+ settings: koishi_1.Schema.object({
100
+ url: koishi_1.Schema.string().description("API服务器地址"),
101
+ token: koishi_1.Schema.string().description("API认证令牌"),
102
+ logOutput: koishi_1.Schema.boolean().description("是否输出日志").default(true)
103
+ })
104
+ }).description("车队平台配置"),
85
105
  resetPassword: koishi_1.Schema.object({
86
- adminUsers: koishi_1.Schema.array(koishi_1.Schema.string()).description("管理员用户ID(拥有重置任意teamId权限)").default([])
87
- }).description("重置密码指令设置")
88
- }),
89
- koishi_1.Schema.object({
90
- activityQuertEnable: koishi_1.Schema.boolean().default(false).description('是否启用活动查询'),
91
- }).description("活动查询 - 开关"),
92
- koishi_1.Schema.object({
93
- adminUseHttps: koishi_1.Schema.boolean().description("使用HTTPS协议").default(true),
94
- adminApiUrl: koishi_1.Schema.string().required().description("车队平台URL(不包含协议)").default(""),
95
- adminApiToken: koishi_1.Schema.string().required().description("车队平台TOKEN").default(""),
96
- adminVtcId: koishi_1.Schema.string().required().description("VTC ID(用于TMP API").default("")
97
- }).description("活动查询 - API配置"),
98
- koishi_1.Schema.object({
99
- adminCheckTimes: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("活动检查时间(HH:mm格式)").default(["08:00", "12:00", "14:00", "20:00"]),
100
- adminSendTimes: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("信息发送时间(HH:mm格式)").default(["08:05", "12:05", "14:05", "20:05"]),
101
- adminGroups: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("管理群组ID列表").default([])
102
- }).description("活动查询 - 管理群配置"),
103
- koishi_1.Schema.object({
104
- adminServerSource: koishi_1.Schema.union([
105
- koishi_1.Schema.const("platform").description("车队平台API"),
106
- koishi_1.Schema.const("tmp").description("TMP API")
107
- ]).description("服务器信息来源").default("tmp"),
108
- adminStartPointSource: koishi_1.Schema.union([
109
- koishi_1.Schema.const("platform").description("车队平台API"),
110
- koishi_1.Schema.const("tmp").description("TMP API")
111
- ]).description("起点信息来源").default("tmp"),
112
- adminEndPointSource: koishi_1.Schema.union([
113
- koishi_1.Schema.const("platform").description("车队平台API"),
114
- koishi_1.Schema.const("tmp").description("TMP API")
115
- ]).description("终点信息来源").default("tmp"),
116
- adminShowBanner: koishi_1.Schema.boolean().description("是否显示活动横幅").default(false)
117
- }).description("活动查询 - 数据源配置"),
118
- koishi_1.Schema.object({
119
- adminProfileUploadedMessage: koishi_1.Schema.string().description("活动档已上传时的消息").default("今日活动档已做/上传"),
120
- adminProfileNotUploadedMessage: koishi_1.Schema.string().description("活动档未上传时的消息").default("今日活动档还没做,请负责的管理注意!")
121
- }).description("活动查询 - 管理群消息配置"),
122
- koishi_1.Schema.object({
123
- adminNoActivityNotification: koishi_1.Schema.boolean().description("启用今日无活动通知").default(false),
124
- adminNoActivityTime: koishi_1.Schema.string().description("今日无活动通知发送时间(HH:mm格式)").default("09:00"),
125
- adminNoActivityMessage: koishi_1.Schema.string().description("今日无活动通知消息").default("今日没活动")
126
- }).description("活动查询 - 无活动通知配置"),
127
- koishi_1.Schema.object({
128
- mainGroups: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("主群群号列表").default([]),
129
- mainActivityReminderMessage: koishi_1.Schema.string().description("活动提醒消息模板,支持变量:{name}, {server}, {startingPoint}, {terminalPoint}, {distance}, {banner}, {timeLeft}").default("活动 {name} 还有 {timeLeft} 分钟就要开始啦!\n服务器: {server}\n起点: {startingPoint}\n终点: {terminalPoint}\n距离: {distance}KM"),
130
- mainActivityStartReminderMessage: koishi_1.Schema.string().description("活动开始提醒消息模板,支持变量:{name}, {server}, {startingPoint}, {terminalPoint}, {distance}, {banner}").default("活动 {name} 现在开始集合啦!\n服务器: {server}\n起点: {startingPoint}\n终点: {terminalPoint}\n距离: {distance}KM\n活动将于20:30分开始!"),
131
- mainActivityReminderTimes: koishi_1.Schema.array(koishi_1.Schema.number()).role("table").description("活动开始前提醒时间(分钟)").default([60, 30, 15])
132
- }).description("活动查询 - 主群配置"),
133
- koishi_1.Schema.object({
134
- debugMode: koishi_1.Schema.boolean().description("启用调试模式(输出详细日志)").default(false),
135
- logApiResponses: koishi_1.Schema.boolean().description("记录API响应详情").default(false),
136
- logTimingDetails: koishi_1.Schema.boolean().description("记录定时任务执行详情").default(false),
137
- logActivityMatching: koishi_1.Schema.boolean().description("记录活动匹配过程").default(false),
138
- logMessageSending: koishi_1.Schema.boolean().description("记录消息发送详情").default(false)
139
- }).description("活动查询 - 开发者选项")
106
+ settings: koishi_1.Schema.object({
107
+ adminUsers: koishi_1.Schema.array(koishi_1.Schema.string()).description("管理员用户ID(拥有重置任意teamId权限)").default([])
108
+ })
109
+ }).description("重置密码功能配置"),
110
+ tmpActivityService: koishi_1.Schema.object({
111
+ api: koishi_1.Schema.object({
112
+ useHttps: koishi_1.Schema.boolean().description("使用HTTPS协议").default(true),
113
+ url: koishi_1.Schema.string().description("车队平台URL(不包含协议)").default(""),
114
+ token: koishi_1.Schema.string().description("车队平台TOKEN").default(""),
115
+ vtcId: koishi_1.Schema.string().description("VTC ID(用于TMP API)").default("")
116
+ }).description("API配置"),
117
+ admin: koishi_1.Schema.object({
118
+ checkTimes: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("活动检查时间(HH:mm格式)").default(["08:00", "12:00", "14:00", "20:00"]),
119
+ sendTimes: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("信息发送时间(HH:mm格式)").default(["08:05", "12:05", "14:05", "20:05"]),
120
+ groups: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("管理群组ID列表").default([])
121
+ }).description("管理群配置"),
122
+ dataSource: koishi_1.Schema.object({
123
+ serverSource: koishi_1.Schema.union([
124
+ koishi_1.Schema.const("platform").description("车队平台API"),
125
+ koishi_1.Schema.const("tmp").description("TMP API")
126
+ ]).description("服务器信息来源").default("tmp"),
127
+ startPointSource: koishi_1.Schema.union([
128
+ koishi_1.Schema.const("platform").description("车队平台API"),
129
+ koishi_1.Schema.const("tmp").description("TMP API")
130
+ ]).description("起点信息来源").default("tmp"),
131
+ endPointSource: koishi_1.Schema.union([
132
+ koishi_1.Schema.const("platform").description("车队平台API"),
133
+ koishi_1.Schema.const("tmp").description("TMP API")
134
+ ]).description("终点信息来源").default("tmp"),
135
+ showBanner: koishi_1.Schema.boolean().description("是否显示活动横幅").default(false)
136
+ }).description("数据源配置"),
137
+ messages: koishi_1.Schema.object({
138
+ profileUploaded: koishi_1.Schema.string().description("活动档已上传时的消息").default("今日活动档已做/上传"),
139
+ profileNotUploaded: koishi_1.Schema.string().description("活动档未上传时的消息").default("今日活动档还没做,请负责的管理注意!")
140
+ }).description("管理群消息配置"),
141
+ noActivity: koishi_1.Schema.object({
142
+ enable: koishi_1.Schema.boolean().description("启用今日无活动通知").default(false),
143
+ time: koishi_1.Schema.string().description("今日无活动通知发送时间(HH:mm格式)").default("09:00"),
144
+ message: koishi_1.Schema.string().description("今日无活动通知消息").default("今日没活动")
145
+ }).description("无活动通知配置"),
146
+ mainGroup: koishi_1.Schema.object({
147
+ groups: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("主群群号列表").default([]),
148
+ activityReminderMessage: koishi_1.Schema.string().description("活动提醒消息模板,支持变量:{name}, {server}, {startingPoint}, {terminalPoint}, {distance}, {banner}, {timeLeft}").default("活动 {name} 还有 {timeLeft} 分钟就要开始啦!\n服务器: {server}\n起点: {startingPoint}\n终点: {terminalPoint}\n距离: {distance}KM"),
149
+ activityStartReminderMessage: koishi_1.Schema.string().description("活动开始提醒消息模板,支持变量:{name}, {server}, {startingPoint}, {terminalPoint}, {distance}, {banner}").default("活动 {name} 现在开始集合啦!\n服务器: {server}\n起点: {startingPoint}\n终点: {terminalPoint}\n距离: {distance}KM\n活动将于20:30分开始!"),
150
+ activityReminderTimes: koishi_1.Schema.array(koishi_1.Schema.number()).role("table").description("活动开始前提醒时间(分钟)").default([60, 30, 15])
151
+ }).description("主群配置"),
152
+ debug: koishi_1.Schema.object({
153
+ debugMode: koishi_1.Schema.boolean().description("启用调试模式").default(false),
154
+ logApiResponses: koishi_1.Schema.boolean().description("记录API响应详情").default(false),
155
+ logTimingDetails: koishi_1.Schema.boolean().description("记录定时任务执行详情").default(false),
156
+ logActivityMatching: koishi_1.Schema.boolean().description("记录活动匹配过程").default(false),
157
+ logMessageSending: koishi_1.Schema.boolean().description("记录消息发送详情").default(false)
158
+ }).description("开发者选项")
159
+ }).description("活动查询配置")
160
+ }).description('功能配置')
140
161
  ]);
141
162
 
142
- class ActivityService {
143
- constructor(ctx, config) {
144
- this.ctx = ctx;
145
- this.cfg = config;
146
- this.todayActivities = [];
147
- this.todayTMPEvents = [];
148
- this.sentReminders = new Set();
149
- this.sentNoActivityNotification = false;
150
- this.timers = [];
151
- this.logger = this.initLogger();
152
- }
153
-
154
- initLogger() {
155
- return {
156
- debug: (message, ...args) => {
157
- if (this.cfg.debugMode) {
158
- this.ctx.logger.debug(`[TMP-BOT DEBUG] ${message}`, ...args);
159
- }
160
- },
161
- info: (message, ...args) => {
162
- this.ctx.logger.info(`[TMP-BOT] ${message}`, ...args);
163
- },
164
- warn: (message, ...args) => {
165
- this.ctx.logger.warn(`[TMP-BOT WARN] ${message}`, ...args);
166
- },
167
- error: (message, ...args) => {
168
- this.ctx.logger.error(`[TMP-BOT ERROR] ${message}`, ...args);
169
- },
170
- api: (message, data) => {
171
- if (this.cfg.logApiResponses) {
172
- this.ctx.logger.info(`[TMP-BOT API] ${message}`, data ? JSON.stringify(data, null, 2) : "");
173
- }
174
- },
175
- timing: (message, data) => {
176
- if (this.cfg.logTimingDetails) {
177
- this.ctx.logger.info(`[TMP-BOT TIMING] ${message}`, data || "");
178
- }
179
- },
180
- matching: (message, data) => {
181
- if (this.cfg.logActivityMatching) {
182
- this.ctx.logger.info(`[TMP-BOT MATCHING] ${message}`, data || "");
183
- }
184
- },
185
- message: (message, data) => {
186
- if (this.cfg.logMessageSending) {
187
- this.ctx.logger.info(`[TMP-BOT MESSAGE] ${message}`, data || "");
188
- }
189
- }
190
- };
191
- }
192
-
193
- start() {
194
- this.setupDailyTasks();
195
- this.registerAdminCommands();
196
- this.ctx.on("dispose", () => this.cleanup());
197
- }
198
-
199
- registerAdminCommands() {
200
- this.ctx.command("活动查询", "手动检查今日活动")
201
- .action(async () => {
202
- this.logger.debug("手动执行活动检查命令");
203
- await this.updateActivityData();
204
- return `检查完成!\n车队平台今日活动: ${this.todayActivities.length} 个\nTMP今日参与活动: ${this.todayTMPEvents.length} 个`;
205
- });
206
-
207
- this.ctx.command("重置数据", "手动重置今日活动数据")
208
- .action(() => {
209
- this.logger.debug("手动执行数据重置命令");
210
- this.resetDailyData();
211
- return "✅ 今日活动数据已重置完成!";
212
- });
163
+ function registerBaseCommands(ctx, cfg) {
164
+ if (cfg.commands?.tmpQuery) {
165
+ ctx.command('查询 <tmpId>')
166
+ .usage("查询TMP玩家信息")
167
+ .action(async ({ session }, tmpId) => await commands.tmpQuery(ctx, cfg, session, tmpId));
213
168
  }
214
169
 
215
- setupDailyTasks() {
216
- const now = new Date();
217
- const localTime = now.toLocaleString();
218
- const localDate = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
219
- const utcDate = now.toISOString().split("T")[0];
220
-
221
- this.logger.timing(`开始设置每日定时任务,本地时间: ${localTime}, 本地日期: ${localDate}, UTC日期: ${utcDate}`);
222
-
223
- const resetHour = 2;
224
- const resetMinute = 0;
225
- const resetDelay = this.getNextTime(resetHour, resetMinute);
226
- const resetTimer = setTimeout(() => {
227
- this.logger.timing("执行每日数据重置");
228
- this.resetDailyData();
229
- const dailyResetTimer = setInterval(() => {
230
- this.logger.timing("执行每日数据重置");
231
- this.resetDailyData();
232
- }, koishi_1.Time.day);
233
- this.timers.push(dailyResetTimer);
234
- }, resetDelay);
235
- this.timers.push(resetTimer);
236
- this.logger.timing(`设置数据重置定时器: ${resetHour}:${resetMinute.toString().padStart(2, "0")}, 延迟: ${resetDelay}ms`);
237
-
238
- this.cfg.adminCheckTimes.forEach((timeStr, index) => {
239
- const [hours, minutes] = timeStr.split(":").map(Number);
240
- this.setupTimer(hours, minutes, async () => {
241
- this.logger.timing(`执行定时检查任务 #${index + 1} (${timeStr})`);
242
- await this.updateActivityData();
243
- await this.checkActivityStatusChange();
244
- }, `检查定时器 #${index + 1}: ${timeStr}`);
245
- });
246
-
247
- this.cfg.adminSendTimes.forEach((timeStr, index) => {
248
- const [hours, minutes] = timeStr.split(":").map(Number);
249
- this.setupTimer(hours, minutes, async () => {
250
- this.logger.timing(`执行定时发送任务 #${index + 1} (${timeStr})`);
251
- await this.checkAndSendProfileReminders();
252
- }, `发送定时器 #${index + 1}: ${timeStr}`);
253
- });
170
+ if (cfg.commands?.tmpServer) {
171
+ ctx.command('美卡服务器')
172
+ .usage("查询美国卡车模拟器TMP服务器信息")
173
+ .action(async () => await commands.tmpServer(ctx, cfg, 'ATS'));
254
174
 
255
- if (this.cfg.adminNoActivityNotification) {
256
- const [noActivityHours, noActivityMinutes] = this.cfg.adminNoActivityTime.split(":").map(Number);
257
- this.setupTimer(noActivityHours, noActivityMinutes, () => {
258
- this.logger.timing(`执行今日无活动通知任务 (${this.cfg.adminNoActivityTime})`);
259
- this.checkAndSendNoActivityNotification();
260
- }, `无活动通知定时器: ${this.cfg.adminNoActivityTime}`);
261
- }
262
-
263
- const minuteTimer = setInterval(async () => {
264
- await this.checkAndSendActivityReminders();
265
- }, koishi_1.Time.minute);
266
- this.timers.push(minuteTimer);
267
- this.logger.timing("设置每分钟检查定时器");
268
- this.logger.debug("启动时立即更新活动数据");
269
- this.updateActivityData();
175
+ ctx.command('欧卡服务器')
176
+ .usage("查询欧洲卡车模拟2TMP服务器信息")
177
+ .action(async () => await commands.tmpServer(ctx, cfg, 'ETS2'));
270
178
  }
271
179
 
272
- setupTimer(hours, minutes, callback, name) {
273
- const delay = this.getNextTime(hours, minutes);
274
- const timer = setTimeout(() => {
275
- callback();
276
- const dailyTimer = setInterval(callback, koishi_1.Time.day);
277
- this.timers.push(dailyTimer);
278
- }, delay);
279
- this.timers.push(timer);
280
- this.logger.timing(`${name}, 延迟: ${delay}ms`);
180
+ if (cfg.commands?.tmpBind) {
181
+ ctx.command('绑定 <tmpId>')
182
+ .usage("绑定TmpId")
183
+ .action(async ({ session }, tmpId) => await commands.tmpBind(ctx, cfg, session, tmpId));
281
184
  }
282
185
 
283
- getNextTime(hours, minutes) {
284
- const now = new Date();
285
- const target = new Date(
286
- now.getFullYear(),
287
- now.getMonth(),
288
- now.getDate(),
289
- hours,
290
- minutes,
291
- 0,
292
- 0
293
- );
294
- if (target.getTime() <= now.getTime()) {
295
- target.setDate(target.getDate() + 1);
296
- }
297
- return target.getTime() - now.getTime();
186
+ if (cfg.commands?.tmpTraffic) {
187
+ ctx.command('路况 <serverName>')
188
+ .usage("查询欧洲卡车模拟2服务器路况")
189
+ .example("路况 - s1")
190
+ .action(async ({ session }, serverName) => await commands.tmpTraffic(ctx, cfg, serverName));
298
191
  }
299
192
 
300
- resetDailyData() {
301
- const now = new Date();
302
- const localTime = now.toLocaleString();
303
- const localDate = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
304
- const utcDate = now.toISOString().split("T")[0];
305
-
306
- const previousActivityCount = this.todayActivities.length;
307
- const previousTMPCount = this.todayTMPEvents.length;
308
- const previousReminderCount = this.sentReminders.size;
309
- const previousNoActivityNotification = this.sentNoActivityNotification;
310
-
311
- this.logger.info(`[数据重置] 开始重置数据,本地时间: ${localTime}, 本地日期: ${localDate}, UTC日期: ${utcDate}`);
312
- this.logger.info(`[数据重置] 重置前数据: 活动${previousActivityCount}个, TMP${previousTMPCount}个, 提醒${previousReminderCount}个, 无活动通知${previousNoActivityNotification ? "已发送" : "未发送"}`);
313
-
314
- this.todayActivities = [];
315
- this.todayTMPEvents = [];
316
- this.sentReminders.clear();
317
- this.sentNoActivityNotification = false;
318
-
319
- this.logger.info(`[数据重置] 每日数据已重置: 活动${previousActivityCount}→0, TMP${previousTMPCount}→0, 提醒${previousReminderCount}→0, 无活动通知${previousNoActivityNotification ? "已发送" : "未发送"}→未发送`);
320
-
321
- this.updateActivityData().then(() => {
322
- this.logger.info(`[数据重置] 重置后数据更新完成: 活动${this.todayActivities.length}个, TMP${this.todayTMPEvents.length}个`);
323
- }).catch(error => {
324
- this.logger.error(`[数据重置] 重置后数据更新失败:`, error.message);
325
- });
193
+ if (cfg.commands?.tmpPosition) {
194
+ ctx.command('定位 <tmpId>')
195
+ .usage("定位玩家线上位置")
196
+ .action(async ({ session }, tmpId) => await commands.tmpPosition(ctx, cfg, session, tmpId));
326
197
  }
327
198
 
328
- async updateActivityData() {
329
- try {
330
- this.logger.debug("开始更新活动数据");
331
- const startTime = Date.now();
332
- await Promise.all([
333
- this.updateTodayActivities(),
334
- this.updateTodayTMPEvents()
335
- ]);
336
-
337
- const duration = Date.now() - startTime;
338
- this.logger.info(`活动数据更新完成,耗时: ${duration}ms`);
339
- this.logger.debug(`今日活动数量: ${this.todayActivities.length}, TMP活动数量: ${this.todayTMPEvents.length}`);
340
- } catch (error) {
341
- this.logger.error("更新活动数据失败:", error.message);
342
- }
199
+ if (cfg.commands?.tmpVersion) {
200
+ ctx.command('tmp版本')
201
+ .usage("查询TruckersMP支持的游戏版本")
202
+ .action(async () => await commands.tmpVersion(ctx));
343
203
  }
344
204
 
345
- async updateTodayActivities() {
346
- try {
347
- this.todayActivities = [];
348
-
349
- const protocol = this.cfg.adminUseHttps ? "https://" : "http://";
350
- const fullUrl = `${protocol}${this.cfg.adminApiUrl}/api/activity/info/list?token=${this.cfg.adminApiToken}&page=1&limit=50&themeName=`;
351
- this.logger.api(`请求车队平台API: ${fullUrl.replace(this.cfg.adminApiToken, "***")}`);
352
-
353
- const startTime = Date.now();
354
- const response = await this.ctx.http.get(fullUrl, { timeout: 10000 });
355
- const duration = Date.now() - startTime;
356
- this.logger.api(`车队平台API响应耗时: ${duration}ms, 状态码: ${response.code}`);
357
-
358
- if (this.cfg.logApiResponses) {
359
- this.logger.api("车队平台API响应详情:", {
360
- code: response.code,
361
- totalCount: response.data?.totalCount,
362
- listCount: response.data?.list?.length
363
- });
364
- }
365
-
366
- if (response.code === 0 && response.data?.list) {
367
- const now = new Date();
368
- const today = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
369
- this.logger.debug(`[活动更新] 当前本地日期: ${today}, UTC日期: ${new Date().toISOString().split("T")[0]}`);
370
-
371
- const originalCount = response.data.list.length;
372
- this.logger.debug(`[活动更新] API返回活动总数: ${originalCount}`);
373
- if (this.cfg.debugMode && originalCount > 0) {
374
- const activityDates = response.data.list.map(a => `${a.themeName}: ${a.startTime?.split(" ")[0]}`);
375
- this.logger.debug(`[活动更新] 所有活动日期:`, activityDates);
376
- }
377
-
378
- this.todayActivities = response.data.list.filter((activity) => {
379
- const activityDate = activity.startTime?.split(" ")[0];
380
- const isToday = activityDate === today;
381
- if (!isToday && this.cfg.debugMode) {
382
- this.logger.debug(`[活动更新] 跳过非今日活动: ${activity.themeName}, 日期: ${activityDate}, 当前日期: ${today}`);
383
- }
384
- return isToday;
385
- });
386
-
387
- this.logger.info(`[活动更新] 从车队平台找到 ${this.todayActivities.length}/${originalCount} 个今日活动`);
388
- if (this.cfg.debugMode && this.todayActivities.length > 0) {
389
- const todayActivityNames = this.todayActivities.map(a => `${a.themeName}: ${a.startTime}`);
390
- this.logger.debug(`[活动更新] 今日活动详情:`, todayActivityNames);
391
- }
392
- } else {
393
- this.logger.error(`[活动更新] 车队平台API返回错误: ${response.msg || '未知错误'} (代码: ${response.code || '无'})`);
394
- this.todayActivities = [];
395
- }
396
- } catch (error) {
397
- this.logger.error("[活动更新] 获取车队平台活动列表失败:", error.message);
398
- this.todayActivities = [];
399
- }
205
+ if (cfg.commands?.tmpDlcMap) {
206
+ ctx.command('地图dlc价格')
207
+ .usage("查询欧洲卡车模拟2地图dlc价格")
208
+ .action(async ({ session }) => await commands.tmpDlcMap(ctx, session));
400
209
  }
401
210
 
402
- async updateTodayTMPEvents() {
403
- try {
404
- this.todayTMPEvents = [];
405
-
406
- if (!this.cfg.adminVtcId) {
407
- this.logger.warn("[TMP活动更新] TMP API请求失败:未配置adminVtcId");
408
- return;
409
- }
211
+ if (cfg.commands?.tmpMileageRanking) {
212
+ ctx.command('里程排行榜')
213
+ .usage("查询欧洲卡车模拟2里程排行榜")
214
+ .action(async ({ session }) => await commands.tmpMileageRanking(ctx, session, MileageRankingType.total));
410
215
 
411
- const tmpApiUrl = `https://api.truckersmp.com/v2/vtc/${this.cfg.adminVtcId}/events/attending/`;
412
- this.logger.api(`[TMP活动更新] 请求TMP API: ${tmpApiUrl}`);
413
-
414
- const startTime = Date.now();
415
- const response = await this.ctx.http.get(tmpApiUrl, { timeout: 10000 });
416
- const duration = Date.now() - startTime;
417
- this.logger.api(`[TMP活动更新] TMP API响应耗时: ${duration}ms, 错误状态: ${response.error}`);
418
-
419
- if (!response.error && Array.isArray(response.response)) {
420
- const now = new Date();
421
- const today = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
422
- this.logger.debug(`[TMP活动更新] 当前本地日期: ${today}, UTC日期: ${new Date().toISOString().split("T")[0]}`);
423
-
424
- const originalCount = response.response.length;
425
- this.logger.debug(`[TMP活动更新] API返回活动总数: ${originalCount}`);
426
-
427
- if (this.cfg.debugMode && originalCount > 0) {
428
- const eventDates = response.response.map(e => `${e.name}: ${e.start_at?.split(" ")[0]}`);
429
- this.logger.debug(`[TMP活动更新] 所有活动日期:`, eventDates);
430
- }
431
-
432
- this.todayTMPEvents = response.response.filter((event) => {
433
- const eventDate = event.start_at?.split(" ")[0];
434
- const isToday = eventDate === today;
435
- if (!isToday && this.cfg.debugMode) {
436
- this.logger.debug(`[TMP活动更新] 跳过非今日活动: ${event.name}, 日期: ${eventDate}, 当前日期: ${today}`);
437
- }
438
- return isToday;
439
- });
440
-
441
- this.logger.info(`[TMP活动更新] 从TMP找到 ${this.todayTMPEvents.length}/${originalCount} 个今日活动`);
442
-
443
- if (this.cfg.debugMode && this.todayTMPEvents.length > 0) {
444
- const todayEventNames = this.todayTMPEvents.map(e => `${e.name}: ${e.start_at}`);
445
- this.logger.debug(`[TMP活动更新] 今日活动详情:`, todayEventNames);
446
- }
447
- } else {
448
- this.logger.error(`[TMP活动更新] TMP API返回错误: ${response.message || '未知错误'}`);
449
- }
450
- } catch (error) {
451
- this.logger.error("[TMP活动更新] 获取TMP活动失败:", error.message);
452
- }
216
+ ctx.command('今日里程排行榜')
217
+ .usage("查询欧洲卡车模拟2今日里程排行榜")
218
+ .action(async ({ session }) => await commands.tmpMileageRanking(ctx, session, MileageRankingType.today));
453
219
  }
454
220
 
455
- async checkAndSendProfileReminders() {
456
- await this.updateActivityData();
457
-
458
- if (this.todayActivities.length === 0) {
459
- this.logger.debug("今日没有活动,跳过档位检查");
460
- return;
461
- }
462
-
463
- this.logger.debug(`开始检查 ${this.todayActivities.length} 个活动的档位状态`);
464
-
465
- for (const activity of this.todayActivities) {
466
- const hasProfile = !!activity.profileFile;
467
- const message = hasProfile ? this.cfg.adminProfileUploadedMessage : this.cfg.adminProfileNotUploadedMessage;
468
- const fullMessage = `活动 "${activity.themeName || '未知活动'}" - ${message}`;
469
- this.logger.message(`活动档位检查: "${activity.themeName || '未知活动'}" - ${hasProfile ? "已上传" : "未上传"}`);
470
-
471
- for (const groupId of this.cfg.adminGroups) {
472
- try {
473
- await this.sendToGroup(groupId, fullMessage, "管理群组");
474
- this.logger.message(`已发送档位提醒到管理群组 ${groupId}: ${activity.themeName || '未知活动'}`);
475
- } catch (error) {
476
- this.logger.error(`发送消息到管理群组 ${groupId} 失败:`, error.message);
477
- }
478
- }
479
- }
221
+ if (cfg.commands?.tmpVtc) {
222
+ ctx.command('vtc查询 <vtcid>')
223
+ .usage("查询TruckersMP VTC信息")
224
+ .action(async ({ session }, vtcid) => await commands.tmpVtc(ctx, cfg, session, vtcid));
480
225
  }
481
226
 
482
- async checkAndSendNoActivityNotification(manualTest = false) {
483
- if (!manualTest && this.sentNoActivityNotification) {
484
- this.logger.debug("今日已发送过无活动通知,跳过");
485
- return;
486
- }
487
-
488
- if (this.todayActivities.length > 0 || this.todayTMPEvents.length > 0) {
489
- this.logger.debug(`今日有活动(车队平台: ${this.todayActivities.length}个, TMP: ${this.todayTMPEvents.length}个),不发送无活动通知`);
490
- return;
491
- }
492
-
493
- this.logger.info(`${manualTest ? "手动测试" : "自动"}今日无活动,发送通知到管理群`);
494
-
495
- for (const groupId of this.cfg.adminGroups) {
496
- try {
497
- await this.sendToGroup(groupId, this.cfg.adminNoActivityMessage, "管理群组");
498
- this.logger.message(`已发送无活动通知到管理群组 ${groupId}`);
499
- } catch (error) {
500
- this.logger.error(`发送无活动通知到管理群组 ${groupId} 失败:`, error.message);
501
- }
502
- }
503
-
504
- if (!manualTest) {
505
- this.sentNoActivityNotification = true;
506
- this.logger.debug("已标记今日无活动通知为已发送");
507
- }
227
+ if (cfg.commands?.resetPassword) {
228
+ ctx.command(`重置密码 [targetTeamId:string]`, "重置欧卡车队平台密码")
229
+ .usage("重置自己的密码,或管理员重置指定teamId的密码")
230
+ .example(`重置密码 - 重置自己的密码`)
231
+ .example(`重置密码 - 管理员重置指定teamId的密码`)
232
+ .action(async ({ session }, targetTeamId) => await commands.resetPassword(ctx, cfg, session, targetTeamId));
508
233
  }
509
234
 
510
- async checkActivityStatusChange() {
511
- await this.updateActivityData();
512
- if (this.sentNoActivityNotification && (this.todayActivities.length > 0 || this.todayTMPEvents.length > 0)) {
513
- this.logger.info(`检测到活动状态变化:之前无活动,现在有活动(车队平台: ${this.todayActivities.length}个, TMP: ${this.todayTMPEvents.length}个)`);
514
- this.sentNoActivityNotification = false;
515
- await this.checkAndSendProfileReminders();
516
- }
235
+ if (cfg.commands?.mainSettings) {
236
+ ctx.command(`查询积分 [targetQQ:string]`, "查询欧卡车队平台积分")
237
+ .usage("查询自己或指定QQ号的积分,在群聊中可@他人查询")
238
+ .example(`查询积分 - 查询自己的积分`)
239
+ .example(`查询积分 123456 - 查询指定QQ号的积分`)
240
+ .action(async ({ session }, targetQQ) => await commands.queryPoint(ctx, cfg, session, targetQQ));
517
241
  }
518
242
 
519
- async checkAndSendActivityReminders() {
520
- const now = new Date();
521
- const today = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
522
- const todayUTC = now.toISOString().split("T")[0];
523
- let remindersSent = 0;
524
- this.logger.debug(`检查 ${this.todayActivities.length} 个活动的提醒时间,当前本地日期: ${today}, UTC日期: ${todayUTC}`);
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
-
532
- for (const activity of this.todayActivities) {
533
- try {
534
- const activityDate = activity.startTime?.split(" ")[0];
535
- if (activityDate !== today) {
536
- this.logger.debug(`跳过非今日活动 "${activity.themeName}",活动日期: ${activityDate},当前本地日期: ${today}`);
537
- continue;
538
- }
539
-
540
- const activityStartTime = new Date(activity.startTime);
541
- if (isNaN(activityStartTime.getTime())) {
542
- this.logger.warn(`活动 "${activity.themeName}" 开始时间格式错误,跳过提醒`);
543
- continue;
544
- }
545
-
546
- const timeDiff = activityStartTime.getTime() - now.getTime();
547
- const totalSecondsLeft = Math.floor(timeDiff / 1000);
548
- const minutesLeft = Math.floor(totalSecondsLeft / 60);
549
- const secondsLeft = totalSecondsLeft % 60;
550
- this.logger.debug(`活动 "${activity.themeName}" 剩余时间: ${minutesLeft} 分 ${secondsLeft} 秒`);
551
- this.logger.debug(`活动 "${activity.themeName}" 时间检查: totalSecondsLeft=${totalSecondsLeft}, 触发条件: -300 <= ${totalSecondsLeft} <= 0`);
552
-
553
- if (totalSecondsLeft >= -300 && totalSecondsLeft <= 0) {
554
- const startReminderKey = `${activity.id}_started`;
555
- if (!this.sentReminders.has(startReminderKey)) {
556
- this.logger.info(`触发活动开始提醒: ${activity.themeName}`);
557
- await this.sendActivityStartReminder(activity);
558
- this.sentReminders.add(startReminderKey);
559
- remindersSent++;
560
- } else {
561
- this.logger.debug(`活动 "${activity.themeName}" 开始提醒已发送过,跳过`);
562
- }
563
- } else {
564
- this.logger.debug(`活动 "${activity.themeName}" 未满足开始提醒条件,当前剩余 ${totalSecondsLeft} 秒`);
565
- }
566
-
567
- if (totalSecondsLeft < 0) continue;
568
- for (const reminderTime of this.cfg.mainActivityReminderTimes) {
569
- const reminderTimeSeconds = reminderTime * 60;
570
- this.logger.debug(`活动 "${activity.themeName}" ${reminderTime}分钟前提醒检查: totalSecondsLeft=${totalSecondsLeft}, reminderTimeSeconds=${reminderTimeSeconds}, 条件: ${reminderTimeSeconds - 60} <= ${totalSecondsLeft} <= ${reminderTimeSeconds}`);
571
- if (totalSecondsLeft <= reminderTimeSeconds && totalSecondsLeft > reminderTimeSeconds - 60) {
572
- const reminderKey = `${activity.id}_${reminderTime}`;
573
- if (!this.sentReminders.has(reminderKey)) {
574
- this.logger.info(`触发活动前提醒: ${activity.themeName} - ${reminderTime} 分钟前`);
575
- await this.sendActivityReminder(activity, reminderTime);
576
- this.sentReminders.add(reminderKey);
577
- remindersSent++;
578
- } else {
579
- this.logger.debug(`活动 "${activity.themeName}" ${reminderTime}分钟前提醒已发送过,跳过`);
580
- }
581
- }
582
- }
583
- } catch (error) {
584
- this.logger.error(`处理活动 "${activity.themeName}" 提醒失败:`, error.message);
585
- }
586
- }
587
-
588
- if (remindersSent > 0) {
589
- this.logger.info(`本轮发送了 ${remindersSent} 个活动提醒`);
590
- } else {
591
- this.logger.debug(`本轮未发送任何活动提醒`);
592
- }
593
- }
594
-
595
- createActivityReplacements(activity, tmpEvent, minutesLeft) {
596
- const replacements = {
597
- name: activity.themeName || '未知活动',
598
- distance: activity.distance?.toString() || '未知'
599
- };
600
-
601
- if (minutesLeft !== undefined) {
602
- replacements.timeLeft = minutesLeft.toString();
603
- }
604
-
605
- if (this.cfg.adminServerSource === "tmp" && tmpEvent) {
606
- replacements.server = tmpEvent.server?.name || '未知服务器';
607
- } else {
608
- replacements.server = activity.serverName || '未知服务器';
609
- }
610
-
611
- if (this.cfg.adminStartPointSource === "tmp" && tmpEvent) {
612
- replacements.startingPoint = `${tmpEvent.departure?.location || ''} - ${tmpEvent.departure?.city || ''}`.trim() || '未知起点';
613
- } else {
614
- replacements.startingPoint = activity.startingPoint || '未知起点';
615
- }
616
-
617
- if (this.cfg.adminEndPointSource === "tmp" && tmpEvent) {
618
- replacements.terminalPoint = `${tmpEvent.arrive?.location || ''} - ${tmpEvent.arrive?.city || ''}`.trim() || '未知终点';
619
- } else {
620
- replacements.terminalPoint = activity.terminalPoint || '未知终点';
621
- }
622
-
623
- if (this.cfg.adminShowBanner && tmpEvent && tmpEvent.banner) {
624
- replacements.banner = tmpEvent.banner;
625
- } else {
626
- replacements.banner = "无";
627
- }
628
-
629
- return replacements;
630
- }
631
-
632
- async sendActivityStartReminder(activity) {
633
- try {
634
- const tmpEvent = this.todayTMPEvents.find(
635
- (event) => event.name.includes(activity.themeName) || activity.themeName.includes(event.name)
636
- );
637
- this.logger.matching(`活动匹配: "${activity.themeName}" - 找到TMP匹配: ${!!tmpEvent}`);
638
-
639
- const replacements = this.createActivityReplacements(activity, tmpEvent);
640
-
641
- let message = this.cfg.mainActivityStartReminderMessage;
642
- for (const [key, value] of Object.entries(replacements)) {
643
- message = message.replace(new RegExp(`{${key}}`, "g"), value);
644
- }
645
-
646
- if (!this.cfg.adminShowBanner) {
647
- message = message.replace(/活动横幅:.*?\n?/, "");
648
- }
649
-
650
- message = message.replace(/\\n/g, "\n").trim();
651
- const fullMessage = `@全体成员\n${message}`;
652
-
653
- await this.sendToMainGroups(fullMessage, activity.themeName, "开始提醒");
654
- } catch (error) {
655
- this.logger.error(`发送活动开始提醒失败:`, error.message);
656
- }
657
- }
658
-
659
- async sendActivityReminder(activity, minutesLeft) {
660
- try {
661
- const tmpEvent = this.todayTMPEvents.find(
662
- (event) => event.name.includes(activity.themeName) || activity.themeName.includes(event.name)
663
- );
664
- this.logger.matching(`活动匹配: "${activity.themeName}" - 找到TMP匹配: ${!!tmpEvent}`);
665
-
666
- const replacements = this.createActivityReplacements(activity, tmpEvent, minutesLeft);
667
-
668
- let message = this.cfg.mainActivityReminderMessage;
669
- for (const [key, value] of Object.entries(replacements)) {
670
- message = message.replace(new RegExp(`{${key}}`, "g"), value);
671
- }
672
-
673
- if (!this.cfg.adminShowBanner) {
674
- message = message.replace(/活动横幅:.*?\n?/, "");
675
- }
676
-
677
- message = message.replace(/\\n/g, "\n").trim();
678
- const fullMessage = `@全体成员\n${message}`;
679
-
680
- await this.sendToMainGroups(fullMessage, activity.themeName, `${minutesLeft}分钟前提醒`);
681
- } catch (error) {
682
- this.logger.error(`发送活动提醒失败:`, error.message);
683
- }
684
- }
685
-
686
- async sendToMainGroups(message, activityName, reminderType) {
687
- for (const groupId of this.cfg.mainGroups) {
688
- try {
689
- await this.sendToGroup(groupId, message, "主群组");
690
- this.logger.message(`已发送${reminderType}到主群组 ${groupId}: ${activityName}`);
691
- } catch (error) {
692
- this.logger.error(`发送${reminderType}到主群组 ${groupId} 失败:`, error.message);
693
- }
694
- }
695
- }
696
-
697
- async sendToGroup(groupId, message, groupType) {
698
- const availableBots = this.ctx.bots.filter((bot) => {
699
- const unsupportedPlatforms = ["mail", "telegram", "discord", "qq", "wechat-official"];
700
- return !unsupportedPlatforms.includes(bot.platform);
701
- });
702
-
703
- if (availableBots.length === 0) {
704
- throw new Error(`没有可用的聊天平台适配器(当前不支持邮件/电报/Discord/QQ/微信公众号)`);
705
- }
706
-
707
- let lastError = null;
708
- this.logger.debug(`尝试通过 ${availableBots.length} 个适配器发送消息到${groupType} ${groupId}`);
709
-
710
- for (const bot of availableBots) {
711
- try {
712
- await bot.sendMessage(groupId, message);
713
- this.logger.debug(`已通过 ${bot.platform} 适配器发送消息到${groupType} ${groupId}`);
714
- return;
715
- } catch (error) {
716
- lastError = error;
717
- this.logger.warn(`通过 ${bot.platform} 适配器发送消息失败: ${error.message}`);
718
- }
719
- }
720
-
721
- throw lastError || new Error(`所有适配器都无法发送消息到${groupType} ${groupId}`);
722
- }
723
-
724
- cleanup() {
725
- this.logger.debug("插件卸载,开始清理资源");
726
- this.todayActivities = [];
727
- this.todayTMPEvents = [];
728
- this.sentReminders.clear();
729
- this.timers.forEach((timer) => {
730
- clearTimeout(timer);
731
- clearInterval(timer);
732
- });
733
- this.timers.length = 0;
734
- this.logger.debug("资源清理完成");
735
- }
736
- }
737
-
738
- function registerBaseCommands(ctx, cfg) {
739
- ctx.command('查询 <tmpId>')
740
- .usage("查询TMP玩家信息")
741
- .action(async ({ session }, tmpId) => await commands.tmpQuery(ctx, cfg, session, tmpId));
742
-
743
- ctx.command('美卡服务器')
744
- .usage("查询美国卡车模拟器TMP服务器信息")
745
- .action(async () => await commands.tmpServer(ctx, cfg, 'ATS'));
746
-
747
- ctx.command('欧卡服务器')
748
- .usage("查询欧洲卡车模拟2TMP服务器信息")
749
- .action(async () => await commands.tmpServer(ctx, cfg, 'ETS2'));
750
-
751
- ctx.command('绑定 <tmpId>')
752
- .usage("绑定TmpId")
753
- .action(async ({ session }, tmpId) => await commands.tmpBind(ctx, cfg, session, tmpId));
754
-
755
- ctx.command('路况 <serverName>')
756
- .usage("查询欧洲卡车模拟2服务器路况")
757
- .example("路况 - s1")
758
- .action(async ({ session }, serverName) => await commands.tmpTraffic(ctx, cfg, serverName));
759
-
760
- ctx.command('定位 <tmpId>')
761
- .usage("定位玩家线上位置")
762
- .action(async ({ session }, tmpId) => await commands.tmpPosition(ctx, cfg, session, tmpId));
763
-
764
- ctx.command('tmp版本')
765
- .usage("查询TruckersMP支持的游戏版本")
766
- .action(async () => await commands.tmpVersion(ctx));
767
-
768
- ctx.command('地图dlc价格')
769
- .usage("查询欧洲卡车模拟2地图dlc价格")
770
- .action(async ({ session }) => await commands.tmpDlcMap(ctx, session));
771
-
772
- ctx.command('里程排行榜')
773
- .usage("查询欧洲卡车模拟2里程排行榜")
774
- .action(async ({ session }) => await commands.tmpMileageRanking(ctx, session, MileageRankingType.total));
775
-
776
- ctx.command('今日里程排行榜')
777
- .usage("查询欧洲卡车模拟2今日里程排行榜")
778
- .action(async ({ session }) => await commands.tmpMileageRanking(ctx, session, MileageRankingType.today));
779
-
780
- ctx.command('vtc查询 <vtcid>')
781
- .usage("查询TruckersMP VTC信息")
782
- .action(async ({ session }, vtcid) => await commands.tmpVtc(ctx, cfg, session, vtcid));
783
-
784
- ctx.command(`重置密码 [targetTeamId:string]`, "重置欧卡车队平台密码")
785
- .usage("重置自己的密码,或管理员重置指定teamId的密码")
786
- .example(`重置密码 - 重置自己的密码`)
787
- .example(`重置密码 - 管理员重置指定teamId的密码`)
788
- .action(async ({ session }, targetTeamId) => await commands.resetPassword(ctx, cfg, session, targetTeamId));
789
-
790
- ctx.command(`查询积分 [targetQQ:string]`, "查询欧卡车队平台积分")
791
- .usage("查询自己或指定QQ号的积分,在群聊中可@他人查询")
792
- .example(`查询积分 - 查询自己的积分`)
793
- .example(`查询积分 123456 - 查询指定QQ号的积分`)
794
- .action(async ({ session }, targetQQ) => await commands.queryPoint(ctx, cfg, session, targetQQ));
795
-
796
243
  ctx.command('规则查询')
797
244
  .action(async () => 'TruckersMP官方规则链接:https://truckersmp.com/knowledge-base/article/746');
798
245
  }
@@ -810,8 +257,13 @@ function apply(ctx, cfg) {
810
257
 
811
258
  registerBaseCommands(ctx, cfg);
812
259
 
813
- if (cfg.activityQuertEnable) {
814
- const activityService = new ActivityService(ctx, cfg);
260
+ if (cfg.commands?.tmpActivityService) {
261
+ const activityConfig = {
262
+ ...cfg.tmpActivityService,
263
+ debugMode: cfg.debugMode,
264
+ debug: cfg.tmpActivityService.debug
265
+ };
266
+ const activityService = new ActivityService(ctx, activityConfig);
815
267
  activityService.start();
816
268
  } else if (cfg.debugMode) {
817
269
  ctx.logger.debug("[TMP-BOT] 活动查询功能已禁用");