koishi-plugin-ets2-tools-tmp 3.0.6 → 3.1.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.
@@ -57,15 +57,25 @@ module.exports = {
57
57
 
58
58
  if (response.code === 0 && response.data) {
59
59
  const enableAutoClock = response.data.enableAutoClock;
60
- this.logger.debug(`活动 "${activity.themeName}" V1自动打卡状态: ${enableAutoClock}`);
61
- return enableAutoClock === 1;
60
+ const serverId = response.data.serverId;
61
+ this.logger.debug(`活动 "${activity.themeName}" V1自动打卡状态: ${enableAutoClock}, serverId: ${serverId}`);
62
+
63
+ if (enableAutoClock === 1) {
64
+ if (serverId != null) {
65
+ return { status: 'set', message: '今日活动自动打卡已设置' };
66
+ } else {
67
+ return { status: 'no_server', message: '今日活动打卡服务器未设置' };
68
+ }
69
+ } else {
70
+ return { status: 'not_set', message: '今日活动打卡未设置' };
71
+ }
62
72
  } else {
63
73
  this.logger.error(`V1活动详情API返回错误: ${response.msg || '未知错误'} (代码: ${response.code || '无'})`);
64
- return false;
74
+ return { status: 'not_set', message: '今日活动打卡未设置' };
65
75
  }
66
76
  } catch (error) {
67
77
  this.logger.error(`检查V1活动 "${activity.themeName}" 自动打卡状态失败:`, error.message);
68
- return false;
78
+ return { status: 'not_set', message: '今日活动打卡未设置' };
69
79
  }
70
80
  }
71
81
  };
@@ -71,15 +71,25 @@ module.exports = {
71
71
 
72
72
  if (response.code === 200 && response.data) {
73
73
  const autoCheckInEnable = response.data.autoCheckInEnable;
74
- this.logger.debug(`活动 "${activity.themeName}" V2自动打卡状态: ${autoCheckInEnable}`);
75
- return autoCheckInEnable === 1;
74
+ const serverId = response.data.serverId;
75
+ this.logger.debug(`活动 "${activity.themeName}" V2自动打卡状态: ${autoCheckInEnable}, serverId: ${serverId}`);
76
+
77
+ if (autoCheckInEnable === 1) {
78
+ if (serverId != null) {
79
+ return { status: 'set', message: '今日活动自动打卡已设置' };
80
+ } else {
81
+ return { status: 'no_server', message: '今日活动打卡服务器未设置' };
82
+ }
83
+ } else {
84
+ return { status: 'not_set', message: '今日活动打卡未设置' };
85
+ }
76
86
  } else {
77
87
  this.logger.error(`V2活动详情API返回错误: ${response.msg || '未知错误'} (代码: ${response.code || '无'})`);
78
- return false;
88
+ return { status: 'not_set', message: '今日活动打卡未设置' };
79
89
  }
80
90
  } catch (error) {
81
91
  this.logger.error(`检查V2活动 "${activity.themeName}" 自动打卡状态失败:`, error.message);
82
- return false;
92
+ return { status: 'not_set', message: '今日活动打卡未设置' };
83
93
  }
84
94
  }
85
95
  };
@@ -620,13 +620,18 @@ class ActivityService {
620
620
 
621
621
  for (const activity of this.todayActivities) {
622
622
  try {
623
- const autoClockEnabled = await this.checkAutoClock(activity);
623
+ const autoClockResult = await this.checkAutoClock(activity);
624
624
 
625
- const message = autoClockEnabled
626
- ? `今日活动自动打卡已设置`
627
- : `请注意,今日活动打卡未设置。\n 活动名称: ${activity.themeName || '未知活动'}`;
625
+ let message;
626
+ if (autoClockResult.status === 'set') {
627
+ message = `今日活动自动打卡已设置`;
628
+ } else if (autoClockResult.status === 'no_server') {
629
+ message = `请注意,今日活动打卡服务器未设置。\n 活动名称: ${activity.themeName || '未知活动'}`;
630
+ } else {
631
+ message = `请注意,今日活动打卡未设置。\n 活动名称: ${activity.themeName || '未知活动'}`;
632
+ }
628
633
 
629
- this.logger.message(`自动打卡检查: "${activity.themeName || '未知活动'}" - ${autoClockEnabled ? "已设置" : "未设置"}`);
634
+ this.logger.message(`自动打卡检查: "${activity.themeName || '未知活动'}" - ${autoClockResult.message}`);
630
635
 
631
636
  for (const groupId of this.cfg.admin.groups) {
632
637
  try {
@@ -68,7 +68,7 @@ module.exports = async (ctx, session, serverType, tmpId, date) => {
68
68
  }
69
69
 
70
70
  if (date === 'tenday') {
71
- startTime = dayjs().subtract(10, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss');
71
+ startTime = dayjs().subtract(7, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss');
72
72
  endTime = dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss');
73
73
  }
74
74
 
@@ -98,8 +98,8 @@ module.exports = async (ctx, session, serverType, tmpId, date) => {
98
98
  if (date === 'today') {
99
99
  return `今日暂无数据`;
100
100
  }
101
- if (date === 'tenday') {
102
- return `近十天暂无数据`;
101
+ if (date === 'sevenday') {
102
+ return `近七日暂无数据`;
103
103
  }
104
104
  if (date === 'lastMonth') {
105
105
  return `上月暂无数据`;
@@ -1,4 +1,6 @@
1
1
  const dayjs = require('dayjs');
2
+ const dayjsRelativeTime = require('dayjs/plugin/relativeTime');
3
+ const dayjsLocaleZhCn = require('dayjs/locale/zh-cn');
2
4
  const guildBind = require('../../database/guildBind');
3
5
  const truckyAppApi = require('../../api/truckyAppApi');
4
6
  const evmOpenApi = require('../../api/evmOpenApi');
@@ -6,6 +8,8 @@ const baiduTranslate = require('../../util/baiduTranslate');
6
8
  const { resolve } = require("path");
7
9
  const common = require("../../util/common");
8
10
  const { segment } = require("koishi");
11
+ dayjs.extend(dayjsRelativeTime);
12
+ dayjs.locale(dayjsLocaleZhCn);
9
13
  /**
10
14
  * 用户组
11
15
  */
@@ -21,11 +25,27 @@ const userGroup = {
21
25
  * 查询玩家信息
22
26
  */
23
27
  module.exports = async (ctx, cfg, session, tmpId) => {
28
+ const { vtcId } = cfg.tmpActivityService?.api || {};
24
29
  if (!ctx.puppeteer) {
25
30
  return '未启用 puppeteer 服务';
26
31
  }
27
- if (tmpId && isNaN(tmpId)) {
28
- return `请输入正确的玩家编号`;
32
+ if (tmpId && tmpId.startsWith("<at ")) {
33
+ let queryQQ = tmpId.replace('<at ', '');
34
+ let id = '';
35
+ const idStart = queryQQ.indexOf('id="');
36
+ if (idStart !== -1) {
37
+ const valueStart = idStart + 4;
38
+ const valueEnd = queryQQ.indexOf('"', valueStart);
39
+ if (valueEnd !== -1) {
40
+ id = queryQQ.substring(valueStart, valueEnd);
41
+ }
42
+ }
43
+ queryQQ = id;
44
+ let guildBindData = await guildBind.get(ctx.database, session.platform, queryQQ);
45
+ if (!guildBindData) {
46
+ return `该用户没有绑定玩家编号`;
47
+ }
48
+ tmpId = guildBindData.tmp_id;
29
49
  }
30
50
  // 如果没有传入tmpId,尝试从数据库查询绑定信息
31
51
  if (!tmpId) {
@@ -50,27 +70,36 @@ module.exports = async (ctx, cfg, session, tmpId) => {
50
70
  data.tmpId = playerInfo.data.tmpId;
51
71
  data.name = playerInfo.data.name;
52
72
  data.steamId = playerInfo.data.steamId;
53
- data.registerDate = dayjs(playerInfo.data.registerTime).format('YYYY年MM月DD日');
73
+ let registerDate = dayjs(playerInfo.data.registerTime);
74
+ data.registerDate = registerDate.format('YYYY年MM月DD日');
75
+ data.registerDays = dayjs().diff(registerDate, 'day');
54
76
  data.avatarUrl = playerInfo.data.avatarUrl;
55
77
  data.groupColor = playerInfo.data.groupColor;
56
78
  data.groupName = (userGroup[playerInfo.data.groupName] || playerInfo.data.groupName);
57
79
  data.isJoinVtc = playerInfo.data.isJoinVtc;
58
80
  data.vtcName = playerInfo.data.vtcName;
59
81
  data.vtcRole = playerInfo.data.vtcRole;
82
+ data.vtcHistory = playerInfo.data.vtcHistory || [];
60
83
  data.isSponsor = playerInfo.data.isSponsor;
61
84
  data.sponsorAmount = playerInfo.data.sponsorAmount;
62
85
  data.sponsorCumulativeAmount = playerInfo.data.sponsorCumulativeAmount;
63
86
  data.sponsorHide = playerInfo.data.sponsorHide;
87
+ data.mileage = playerInfo.data.mileage;
88
+ data.todayMileage = playerInfo.data.todayMileage;
64
89
  data.isOnline = false;
90
+ data.onlineStatus = '离线';
65
91
  if (playerMapInfo && !playerMapInfo.error) {
66
92
  data.isOnline = playerMapInfo.data.online;
67
93
  if (data.isOnline) {
94
+ data.onlineStatus = '在线';
68
95
  data.onlineServerName = playerMapInfo.data.serverDetails.name;
69
96
  data.onlineCountry = await baiduTranslate(ctx, cfg, playerMapInfo.data.location.poi.country);
70
97
  data.onlineCity = await baiduTranslate(ctx, cfg, playerMapInfo.data.location.poi.realName);
71
98
  data.onlineX = playerMapInfo.data.x;
72
99
  data.onlineY = playerMapInfo.data.y;
73
100
  data.onlineMapType = playerMapInfo.data.serverDetails.id === 50 ? 'promods' : 'ets';
101
+ } else if (playerInfo.data.lastOnlineTime) {
102
+ data.lastOnlineTime = dayjs(playerInfo.data.lastOnlineTime).fromNow(false);
74
103
  }
75
104
  }
76
105
  data.isBan = playerInfo.data.isBan;
@@ -79,10 +108,86 @@ module.exports = async (ctx, cfg, session, tmpId) => {
79
108
  data.banReasonZh = playerInfo.data.banReasonZh;
80
109
  data.banCount = playerInfo.data.banCount;
81
110
  data.banHide = playerInfo.data.banHide;
111
+ // 查询VTC积分(仅主群/管理群显示)
112
+ data.rewardPoints = 0;
113
+ if (playerInfo.data.isJoinVtc && cfg.commands?.mainSettings) {
114
+ const mainGroups = cfg.tmpActivityService?.mainGroup?.groups || [];
115
+ const adminGroups = cfg.tmpActivityService?.admin?.groups || [];
116
+ const allowedGroups = [...new Set([...mainGroups, ...adminGroups])];
117
+ const currentGroupId = session.channelId || '';
118
+ const isInAllowedGroup = allowedGroups.some(g => currentGroupId.includes(g));
119
+
120
+ if (isInAllowedGroup && playerInfo.data.vtcId == vtcId) {
121
+ const { url, token, logOutput, platformVersion } = cfg.mainSettings?.settings || {};
122
+ const platform = (platformVersion || "v1").toLowerCase();
123
+ try {
124
+ if (platform === "v2") {
125
+ const baseUrl = url;
126
+ const userInfoUrl = `https://${baseUrl}/members/get?token=${token}&tmpId=${tmpId}`;
127
+ if (logOutput) {
128
+ ctx.logger.info(`[TMP_BOT] tmpQueryImg:开始查询TmpID ${tmpId} 的V2.0积分`);
129
+ ctx.logger.info(`[TMP_BOT] 请求V2.0用户信息: ${userInfoUrl}`);
130
+ }
131
+ const userInfoResponse = await ctx.http.get(userInfoUrl);
132
+ if (logOutput) {
133
+ ctx.logger.info(`[TMP_BOT] V2.0用户信息响应: ${JSON.stringify(userInfoResponse)}`);
134
+ }
135
+ if (userInfoResponse.code === 200 && userInfoResponse.data) {
136
+ data.rewardPoints = userInfoResponse.data.point || 0;
137
+ }
138
+ } else {
139
+ if (logOutput) {
140
+ ctx.logger.info(`[TMP_BOT] tmpQueryImg:开始查询TmpID ${tmpId} 的V1.0积分`);
141
+ }
142
+ const userInfoUrl = `https://${url}/api/user/info/list?token=${token}&page=0&limit=7&tmpId=${tmpId}&tmpName=&teamId=&qq=&state=0&teamRole=`;
143
+ if (logOutput) {
144
+ ctx.logger.info(`[TMP_BOT] 请求V1.0用户信息: ${userInfoUrl}`);
145
+ }
146
+ const userInfoResponse = await ctx.http.post(userInfoUrl);
147
+ if (logOutput) {
148
+ ctx.logger.info(`[TMP_BOT] V1.0用户信息响应: ${JSON.stringify(userInfoResponse)}`);
149
+ }
150
+ const userList = userInfoResponse.page?.list || [];
151
+ const userInfo = userList[0];
152
+ data.rewardPoints = userInfo.rewardPoints || 0;
153
+ }
154
+ } catch (error) {
155
+ ctx.logger.error(`积分查询过程出错: ${error}`);
156
+ }
157
+ }
158
+ }
159
+ // 查询Steam游戏时长
160
+ data.ets2GameTime = null;
161
+ data.atsGameTime = null;
162
+ if (cfg.commands?.tmpQueryGameTime) {
163
+ try {
164
+ const steamApiKey = cfg.steamApi?.key;
165
+ if (steamApiKey) {
166
+ const steamId = playerInfo.data.steamId;
167
+ const url = `https://api.114512.xyz/steam/IPlayerService/GetOwnedGames/v1?key=${steamApiKey}&steamid=${steamId}&appids_filter[0]=227300&appids_filter[1]=270880&include_played_free_games=1`;
168
+ const response = await ctx.http.get(url);
169
+ if (response.response && response.response.game_count > 0) {
170
+ for (const game of response.response.games) {
171
+ const playtimeMinutes = game.playtime_forever;
172
+ const hours = Math.floor(playtimeMinutes / 60);
173
+ const minutes = playtimeMinutes % 60;
174
+ const playtime = `${hours}小时${minutes}分钟`;
175
+ if (game.appid === 227300) {
176
+ data.ets2GameTime = playtime;
177
+ } else if (game.appid === 270880) {
178
+ data.atsGameTime = playtime;
179
+ }
180
+ }
181
+ }
182
+ }
183
+ } catch (error) {
184
+ ctx.logger.error(`查询Steam游戏时长出错: ${error}`);
185
+ }
186
+ }
82
187
  let page;
83
188
  try {
84
189
  page = await ctx.puppeteer.page();
85
- await page.setViewport({ width: 1000, height: 1000 });
190
+ await page.setViewport({ width: 520, height: 1000 });
86
191
  await page.goto(`file:///${resolve(__dirname, '../../resource/query.html')}`);
87
192
  await page.evaluate(`init(${JSON.stringify(data)})`);
88
193
  await common.sleep(100);
@@ -81,7 +81,14 @@ module.exports = async (ctx, cfg, session, tmpId) => {
81
81
  }
82
82
  message += '\n🚚车队角色: ' + playerInfo.data.vtcRole;
83
83
  if (cfg.commands?.mainSettings) {
84
- if (playerInfo.data.vtcId == vtcId) {
84
+ // 仅在主群或管理群中显示车队积分
85
+ const mainGroups = cfg.tmpActivityService?.mainGroup?.groups || [];
86
+ const adminGroups = cfg.tmpActivityService?.admin?.groups || [];
87
+ const allowedGroups = [...new Set([...mainGroups, ...adminGroups])];
88
+ const currentGroupId = session.channelId || '';
89
+ const isInAllowedGroup = allowedGroups.some(g => currentGroupId.includes(g));
90
+
91
+ if (isInAllowedGroup && playerInfo.data.vtcId == vtcId) {
85
92
  const { url, token, logOutput, platformVersion } = cfg.mainSettings?.settings || {};
86
93
  const platform = (platformVersion || "v1").toLowerCase();
87
94
  try {
package/lib/index.js CHANGED
@@ -312,15 +312,15 @@ function registerBaseCommands(ctx, cfg) {
312
312
  if (cfg.commands?.tmpFootprint) {
313
313
  ctx.command('近十日足迹 [tmpId:string]')
314
314
  .usage("查询ETS服务器今日足迹")
315
- .example("近十日足迹")
316
- .example("近十日足迹 12345")
317
- .action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.ets, tmpId, 'tenday'));
315
+ .example("近七日足迹")
316
+ .example("近七日足迹 12345")
317
+ .action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.ets, tmpId, 'sevenday'));
318
318
 
319
- ctx.command('近十日足迹p [tmpId:string]')
319
+ ctx.command('近七日足迹p [tmpId:string]')
320
320
  .usage("查询Promods服务器今日足迹")
321
- .example("近十日足迹p")
322
- .example("近十日足迹p 12345")
323
- .action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.promods, tmpId, 'tenday'));
321
+ .example("近七日足迹p")
322
+ .example("近七日足迹p 12345")
323
+ .action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.promods, tmpId, 'sevenday'));
324
324
 
325
325
  ctx.command('昨日足迹 [tmpId:string]')
326
326
  .usage("查询ETS服务器今日足迹")