koishi-plugin-ets2-tools-tmp 3.0.5 → 3.1.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/api/evmOpenApi.js +1 -1
- package/lib/command/ets-app/pointRanking/pointRanking.js +159 -0
- package/lib/command/tmpActivityService/tmpActivityServiceV1.js +14 -4
- package/lib/command/tmpActivityService/tmpActivityServiceV2.js +14 -4
- package/lib/command/tmpActivityService.js +10 -5
- package/lib/command/tmpFootprint.js +3 -3
- package/lib/command/tmpQuery/tmpQueryImg.js +92 -2
- package/lib/command/tmpQuery/tmpQueryText.js +8 -1
- package/lib/index.js +17 -8
- package/lib/resource/point-leaderboard.html +581 -0
- package/lib/resource/query.html +651 -244
- package/package.json +1 -1
package/lib/api/evmOpenApi.js
CHANGED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
const { segment } = require('koishi');
|
|
2
|
+
const { resolve } = require('path');
|
|
3
|
+
const common = require('../../../util/common');
|
|
4
|
+
|
|
5
|
+
module.exports = async (ctx, cfg, session) => {
|
|
6
|
+
// 群组限制检查
|
|
7
|
+
const mainGroups = cfg.tmpActivityService?.mainGroup?.groups || [];
|
|
8
|
+
const adminGroups = cfg.tmpActivityService?.admin?.groups || [];
|
|
9
|
+
const allowedGroups = [...new Set([...mainGroups, ...adminGroups])];
|
|
10
|
+
|
|
11
|
+
if (allowedGroups.length === 0) {
|
|
12
|
+
return '未配置允许使用此指令的群组';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// 当前会话的群号(onebot 平台格式为 group:xxx)
|
|
16
|
+
const currentGroupId = session.channelId;
|
|
17
|
+
const isAllowed = allowedGroups.some(g => currentGroupId.includes(g));
|
|
18
|
+
|
|
19
|
+
if (!isAllowed) {
|
|
20
|
+
return '该指令在本群聊不可用';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!ctx.puppeteer) {
|
|
24
|
+
return '未启用 Puppeteer 功能';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const settings = cfg.mainSettings?.settings || {};
|
|
28
|
+
const baseUrl = settings.url || "open.vtcm.link";
|
|
29
|
+
const token = settings.token || "";
|
|
30
|
+
const logOutput = settings.logOutput;
|
|
31
|
+
|
|
32
|
+
const log = (msg) => logOutput && ctx.logger.info(msg);
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
log('[积分排行] 开始查询车队成员积分信息');
|
|
36
|
+
|
|
37
|
+
// 分页获取全部成员数据(API page 参数为 1-indexed)
|
|
38
|
+
const allMembers = [];
|
|
39
|
+
let currentPage = 1;
|
|
40
|
+
let totalPage = 1;
|
|
41
|
+
|
|
42
|
+
while (currentPage <= totalPage) {
|
|
43
|
+
const queryUrl = `https://${baseUrl}/api/user/info/list?page=${currentPage}&limit=100&tmpId=&tmpName=&teamId=&qq=&state=0&teamRole=&token=${token}`;
|
|
44
|
+
log(`[积分排行] 请求第 ${currentPage} 页: ${queryUrl.replace(token, "***")}`);
|
|
45
|
+
|
|
46
|
+
const response = await ctx.http.get(queryUrl, { timeout: 10000 });
|
|
47
|
+
|
|
48
|
+
if (response.code !== 0) {
|
|
49
|
+
log(`[积分排行] 第 ${currentPage} 页请求失败: ${response.msg || '未知错误'}`);
|
|
50
|
+
return response.msg || '查询成员信息失败';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!response.page?.list) {
|
|
54
|
+
log(`[积分排行] 第 ${currentPage} 页数据为空`);
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
allMembers.push(...response.page.list);
|
|
59
|
+
totalPage = response.page.totalPage || 1;
|
|
60
|
+
currentPage++;
|
|
61
|
+
|
|
62
|
+
log(`[积分排行] 已获取 ${allMembers.length}/${response.page.totalCount} 条记录, 总页数: ${totalPage}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (allMembers.length === 0) {
|
|
66
|
+
return '暂无成员数据';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 按 id 去重(防止分页返回重复数据)
|
|
70
|
+
const uniqueMembers = [];
|
|
71
|
+
const seenIds = new Set();
|
|
72
|
+
for (const m of allMembers) {
|
|
73
|
+
if (m.id && !seenIds.has(m.id)) {
|
|
74
|
+
seenIds.add(m.id);
|
|
75
|
+
uniqueMembers.push(m);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
log(`[积分排行] 去重前: ${allMembers.length}, 去重后: ${uniqueMembers.length}`);
|
|
79
|
+
|
|
80
|
+
// 按 rewardPoints 降序排序
|
|
81
|
+
const sortedMembers = uniqueMembers
|
|
82
|
+
.filter(m => typeof m.rewardPoints === 'number')
|
|
83
|
+
.sort((a, b) => b.rewardPoints - a.rewardPoints);
|
|
84
|
+
|
|
85
|
+
// 取前10
|
|
86
|
+
const top10 = sortedMembers
|
|
87
|
+
.slice(0, 10)
|
|
88
|
+
.map((player, index) => ({
|
|
89
|
+
rank: index + 1,
|
|
90
|
+
tmpName: player.tmpName || '未知',
|
|
91
|
+
tmpId: player.tmpId,
|
|
92
|
+
teamId: player.teamId,
|
|
93
|
+
rewardPoints: player.rewardPoints || 0,
|
|
94
|
+
teamRole: player.teamRole || '',
|
|
95
|
+
avatarUrl: player.avatarUrl || ''
|
|
96
|
+
}));
|
|
97
|
+
|
|
98
|
+
log(`[积分排行] 排行榜前10名已生成, 第一名: ${top10[0]?.tmpName} (${top10[0]?.rewardPoints}积分)`);
|
|
99
|
+
|
|
100
|
+
// 查询当前用户的排名
|
|
101
|
+
let currentPlayer = null;
|
|
102
|
+
const currentUserQQ = String(session.userId || '');
|
|
103
|
+
if (currentUserQQ) {
|
|
104
|
+
const playerIndex = sortedMembers.findIndex(m => String(m.qq) === currentUserQQ);
|
|
105
|
+
if (playerIndex !== -1) {
|
|
106
|
+
const player = sortedMembers[playerIndex];
|
|
107
|
+
currentPlayer = {
|
|
108
|
+
rank: playerIndex + 1,
|
|
109
|
+
tmpName: player.tmpName || '未知',
|
|
110
|
+
tmpId: player.tmpId,
|
|
111
|
+
teamId: player.teamId,
|
|
112
|
+
rewardPoints: player.rewardPoints || 0,
|
|
113
|
+
avatarUrl: player.avatarUrl || ''
|
|
114
|
+
};
|
|
115
|
+
log(`[积分排行] 找到当前用户: ${currentPlayer.tmpName}, 排名: ${currentPlayer.rank}, 积分: ${currentPlayer.rewardPoints}`);
|
|
116
|
+
} else {
|
|
117
|
+
log(`[积分排行] 未在车队成员中找到当前用户QQ: ${currentUserQQ}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 拼接页面数据
|
|
122
|
+
const data = {
|
|
123
|
+
top10: top10,
|
|
124
|
+
totalCount: uniqueMembers.length,
|
|
125
|
+
currentPlayer: currentPlayer,
|
|
126
|
+
updateTime: new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// 渲染图片
|
|
130
|
+
let page;
|
|
131
|
+
try {
|
|
132
|
+
page = await ctx.puppeteer.page();
|
|
133
|
+
await page.setViewport({ width: 800, height: 1200, deviceScaleFactor: 2 });
|
|
134
|
+
await page.goto(`file:///${resolve(__dirname, '../../../resource/point-leaderboard.html')}`);
|
|
135
|
+
await page.evaluate(`setData(${JSON.stringify(data)})`);
|
|
136
|
+
await page.waitForNetworkIdle();
|
|
137
|
+
await common.sleep(800);
|
|
138
|
+
const element = await page.$("#container");
|
|
139
|
+
return segment.image(await element.screenshot({
|
|
140
|
+
encoding: "binary"
|
|
141
|
+
}), "image/jpg");
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
log(`[积分排行] 渲染异常: ${e.message}`);
|
|
145
|
+
return '渲染异常,请重试';
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
if (page) {
|
|
149
|
+
await page.close();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
} catch (error) {
|
|
153
|
+
log(`[积分排行] 系统错误: ${error.message}`);
|
|
154
|
+
if (error.response) {
|
|
155
|
+
return `请求失败: ${error.response.status} ${error.response.statusText}`;
|
|
156
|
+
}
|
|
157
|
+
return '系统错误,请稍后重试';
|
|
158
|
+
}
|
|
159
|
+
};
|
|
@@ -57,15 +57,25 @@ module.exports = {
|
|
|
57
57
|
|
|
58
58
|
if (response.code === 0 && response.data) {
|
|
59
59
|
const enableAutoClock = response.data.enableAutoClock;
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
74
|
+
return { status: 'not_set', message: '今日活动打卡未设置' };
|
|
65
75
|
}
|
|
66
76
|
} catch (error) {
|
|
67
77
|
this.logger.error(`检查V1活动 "${activity.themeName}" 自动打卡状态失败:`, error.message);
|
|
68
|
-
return
|
|
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
|
-
|
|
75
|
-
|
|
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
|
|
88
|
+
return { status: 'not_set', message: '今日活动打卡未设置' };
|
|
79
89
|
}
|
|
80
90
|
} catch (error) {
|
|
81
91
|
this.logger.error(`检查V2活动 "${activity.themeName}" 自动打卡状态失败:`, error.message);
|
|
82
|
-
return
|
|
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
|
|
623
|
+
const autoClockResult = await this.checkAutoClock(activity);
|
|
624
624
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
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 || '未知活动'}" - ${
|
|
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(
|
|
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 === '
|
|
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,6 +25,7 @@ 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
|
}
|
|
@@ -50,27 +55,36 @@ module.exports = async (ctx, cfg, session, tmpId) => {
|
|
|
50
55
|
data.tmpId = playerInfo.data.tmpId;
|
|
51
56
|
data.name = playerInfo.data.name;
|
|
52
57
|
data.steamId = playerInfo.data.steamId;
|
|
53
|
-
|
|
58
|
+
let registerDate = dayjs(playerInfo.data.registerTime);
|
|
59
|
+
data.registerDate = registerDate.format('YYYY年MM月DD日');
|
|
60
|
+
data.registerDays = dayjs().diff(registerDate, 'day');
|
|
54
61
|
data.avatarUrl = playerInfo.data.avatarUrl;
|
|
55
62
|
data.groupColor = playerInfo.data.groupColor;
|
|
56
63
|
data.groupName = (userGroup[playerInfo.data.groupName] || playerInfo.data.groupName);
|
|
57
64
|
data.isJoinVtc = playerInfo.data.isJoinVtc;
|
|
58
65
|
data.vtcName = playerInfo.data.vtcName;
|
|
59
66
|
data.vtcRole = playerInfo.data.vtcRole;
|
|
67
|
+
data.vtcHistory = playerInfo.data.vtcHistory || [];
|
|
60
68
|
data.isSponsor = playerInfo.data.isSponsor;
|
|
61
69
|
data.sponsorAmount = playerInfo.data.sponsorAmount;
|
|
62
70
|
data.sponsorCumulativeAmount = playerInfo.data.sponsorCumulativeAmount;
|
|
63
71
|
data.sponsorHide = playerInfo.data.sponsorHide;
|
|
72
|
+
data.mileage = playerInfo.data.mileage;
|
|
73
|
+
data.todayMileage = playerInfo.data.todayMileage;
|
|
64
74
|
data.isOnline = false;
|
|
75
|
+
data.onlineStatus = '离线';
|
|
65
76
|
if (playerMapInfo && !playerMapInfo.error) {
|
|
66
77
|
data.isOnline = playerMapInfo.data.online;
|
|
67
78
|
if (data.isOnline) {
|
|
79
|
+
data.onlineStatus = '在线';
|
|
68
80
|
data.onlineServerName = playerMapInfo.data.serverDetails.name;
|
|
69
81
|
data.onlineCountry = await baiduTranslate(ctx, cfg, playerMapInfo.data.location.poi.country);
|
|
70
82
|
data.onlineCity = await baiduTranslate(ctx, cfg, playerMapInfo.data.location.poi.realName);
|
|
71
83
|
data.onlineX = playerMapInfo.data.x;
|
|
72
84
|
data.onlineY = playerMapInfo.data.y;
|
|
73
85
|
data.onlineMapType = playerMapInfo.data.serverDetails.id === 50 ? 'promods' : 'ets';
|
|
86
|
+
} else if (playerInfo.data.lastOnlineTime) {
|
|
87
|
+
data.lastOnlineTime = dayjs(playerInfo.data.lastOnlineTime).fromNow(false);
|
|
74
88
|
}
|
|
75
89
|
}
|
|
76
90
|
data.isBan = playerInfo.data.isBan;
|
|
@@ -79,10 +93,86 @@ module.exports = async (ctx, cfg, session, tmpId) => {
|
|
|
79
93
|
data.banReasonZh = playerInfo.data.banReasonZh;
|
|
80
94
|
data.banCount = playerInfo.data.banCount;
|
|
81
95
|
data.banHide = playerInfo.data.banHide;
|
|
96
|
+
// 查询VTC积分(仅主群/管理群显示)
|
|
97
|
+
data.rewardPoints = 0;
|
|
98
|
+
if (playerInfo.data.isJoinVtc && cfg.commands?.mainSettings) {
|
|
99
|
+
const mainGroups = cfg.tmpActivityService?.mainGroup?.groups || [];
|
|
100
|
+
const adminGroups = cfg.tmpActivityService?.admin?.groups || [];
|
|
101
|
+
const allowedGroups = [...new Set([...mainGroups, ...adminGroups])];
|
|
102
|
+
const currentGroupId = session.channelId || '';
|
|
103
|
+
const isInAllowedGroup = allowedGroups.some(g => currentGroupId.includes(g));
|
|
104
|
+
|
|
105
|
+
if (isInAllowedGroup && playerInfo.data.vtcId == vtcId) {
|
|
106
|
+
const { url, token, logOutput, platformVersion } = cfg.mainSettings?.settings || {};
|
|
107
|
+
const platform = (platformVersion || "v1").toLowerCase();
|
|
108
|
+
try {
|
|
109
|
+
if (platform === "v2") {
|
|
110
|
+
const baseUrl = url;
|
|
111
|
+
const userInfoUrl = `https://${baseUrl}/members/get?token=${token}&tmpId=${tmpId}`;
|
|
112
|
+
if (logOutput) {
|
|
113
|
+
ctx.logger.info(`[TMP_BOT] tmpQueryImg:开始查询TmpID ${tmpId} 的V2.0积分`);
|
|
114
|
+
ctx.logger.info(`[TMP_BOT] 请求V2.0用户信息: ${userInfoUrl}`);
|
|
115
|
+
}
|
|
116
|
+
const userInfoResponse = await ctx.http.get(userInfoUrl);
|
|
117
|
+
if (logOutput) {
|
|
118
|
+
ctx.logger.info(`[TMP_BOT] V2.0用户信息响应: ${JSON.stringify(userInfoResponse)}`);
|
|
119
|
+
}
|
|
120
|
+
if (userInfoResponse.code === 200 && userInfoResponse.data) {
|
|
121
|
+
data.rewardPoints = userInfoResponse.data.point || 0;
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
if (logOutput) {
|
|
125
|
+
ctx.logger.info(`[TMP_BOT] tmpQueryImg:开始查询TmpID ${tmpId} 的V1.0积分`);
|
|
126
|
+
}
|
|
127
|
+
const userInfoUrl = `https://${url}/api/user/info/list?token=${token}&page=0&limit=7&tmpId=${tmpId}&tmpName=&teamId=&qq=&state=0&teamRole=`;
|
|
128
|
+
if (logOutput) {
|
|
129
|
+
ctx.logger.info(`[TMP_BOT] 请求V1.0用户信息: ${userInfoUrl}`);
|
|
130
|
+
}
|
|
131
|
+
const userInfoResponse = await ctx.http.post(userInfoUrl);
|
|
132
|
+
if (logOutput) {
|
|
133
|
+
ctx.logger.info(`[TMP_BOT] V1.0用户信息响应: ${JSON.stringify(userInfoResponse)}`);
|
|
134
|
+
}
|
|
135
|
+
const userList = userInfoResponse.page?.list || [];
|
|
136
|
+
const userInfo = userList[0];
|
|
137
|
+
data.rewardPoints = userInfo.rewardPoints || 0;
|
|
138
|
+
}
|
|
139
|
+
} catch (error) {
|
|
140
|
+
ctx.logger.error(`积分查询过程出错: ${error}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// 查询Steam游戏时长
|
|
145
|
+
data.ets2GameTime = null;
|
|
146
|
+
data.atsGameTime = null;
|
|
147
|
+
if (cfg.commands?.tmpQueryGameTime) {
|
|
148
|
+
try {
|
|
149
|
+
const steamApiKey = cfg.steamApi?.key;
|
|
150
|
+
if (steamApiKey) {
|
|
151
|
+
const steamId = playerInfo.data.steamId;
|
|
152
|
+
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`;
|
|
153
|
+
const response = await ctx.http.get(url);
|
|
154
|
+
if (response.response && response.response.game_count > 0) {
|
|
155
|
+
for (const game of response.response.games) {
|
|
156
|
+
const playtimeMinutes = game.playtime_forever;
|
|
157
|
+
const hours = Math.floor(playtimeMinutes / 60);
|
|
158
|
+
const minutes = playtimeMinutes % 60;
|
|
159
|
+
const playtime = `${hours}小时${minutes}分钟`;
|
|
160
|
+
if (game.appid === 227300) {
|
|
161
|
+
data.ets2GameTime = playtime;
|
|
162
|
+
} else if (game.appid === 270880) {
|
|
163
|
+
data.atsGameTime = playtime;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
ctx.logger.error(`查询Steam游戏时长出错: ${error}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
82
172
|
let page;
|
|
83
173
|
try {
|
|
84
174
|
page = await ctx.puppeteer.page();
|
|
85
|
-
await page.setViewport({ width:
|
|
175
|
+
await page.setViewport({ width: 520, height: 1000 });
|
|
86
176
|
await page.goto(`file:///${resolve(__dirname, '../../resource/query.html')}`);
|
|
87
177
|
await page.evaluate(`init(${JSON.stringify(data)})`);
|
|
88
178
|
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
|
-
|
|
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
|
@@ -21,6 +21,7 @@ const commands = {
|
|
|
21
21
|
queryPoint: require('./command/ets-app/queryPoint/queryPoint'),
|
|
22
22
|
changePoint: require('./command/ets-app/changePoint/changePoint'),
|
|
23
23
|
addMember: require('./command/ets-app/addMember/addMemberV2'),
|
|
24
|
+
pointRanking: require('./command/ets-app/pointRanking/pointRanking'),
|
|
24
25
|
tmpVtc: require('./command/tmpVtc'),
|
|
25
26
|
tmpFootprint: require('./command/tmpFootprint')
|
|
26
27
|
};
|
|
@@ -75,6 +76,7 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
75
76
|
tmpVersion: koishi_1.Schema.boolean().default(true).description('是否启用版本查询'),
|
|
76
77
|
tmpDlcMap: koishi_1.Schema.boolean().default(true).description('是否启用DLC地图查询'),
|
|
77
78
|
tmpMileageRanking: koishi_1.Schema.boolean().default(true).description('是否启用里程排行榜'),
|
|
79
|
+
pointRanking: koishi_1.Schema.boolean().default(false).description('是否启用积分排行榜'),
|
|
78
80
|
tmpVtc: koishi_1.Schema.boolean().default(true).description('是否启用VTC查询'),
|
|
79
81
|
tmpFootprint: koishi_1.Schema.boolean().default(true).description('是否启用足迹查询'),
|
|
80
82
|
mainSettings: koishi_1.Schema.boolean().default(false).description('是否启用车队平台积分查询功能'),
|
|
@@ -189,7 +191,7 @@ exports.Config = koishi_1.Schema.intersect([
|
|
|
189
191
|
onlineCheck: koishi_1.Schema.object({
|
|
190
192
|
enable: koishi_1.Schema.boolean().description("启用今日有活动时的在线成员检查").default(false),
|
|
191
193
|
time: koishi_1.Schema.string().description("在线成员检查发送时间(HH:mm格式)").default("20:30"),
|
|
192
|
-
apiUrl: koishi_1.Schema.string().description("在线成员查询API地址(含vtcId参数)")
|
|
194
|
+
apiUrl: koishi_1.Schema.string().description("在线成员查询API地址(含vtcId参数)")
|
|
193
195
|
}).description("在线成员检查配置"),
|
|
194
196
|
mainGroup: koishi_1.Schema.object({
|
|
195
197
|
groups: koishi_1.Schema.array(koishi_1.Schema.string()).role("table").description("主群群号列表").default([]),
|
|
@@ -220,6 +222,7 @@ function logDisabledCommands(ctx, cfg) {
|
|
|
220
222
|
{ key: 'tmpVersion', label: 'tmp版本' },
|
|
221
223
|
{ key: 'tmpDlcMap', label: '地图dlc价格' },
|
|
222
224
|
{ key: 'tmpMileageRanking', label: '里程排行榜/今日里程排行榜' },
|
|
225
|
+
{ key: 'pointRanking', label: '积分排行榜' },
|
|
223
226
|
{ key: 'tmpVtc', label: 'vtc查询' },
|
|
224
227
|
{ key: 'tmpFootprint', label: '足迹查询' },
|
|
225
228
|
{ key: 'resetPassword', label: '重置密码' },
|
|
@@ -294,6 +297,12 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
294
297
|
.action(async ({ session }) => await commands.tmpMileageRanking(ctx, session, MileageRankingType.today));
|
|
295
298
|
}
|
|
296
299
|
|
|
300
|
+
if (cfg.commands?.pointRanking) {
|
|
301
|
+
ctx.command('积分排行')
|
|
302
|
+
.usage("查询车队积分排行榜(仅限总群和管理群使用)")
|
|
303
|
+
.action(async ({ session }) => await commands.pointRanking(ctx, cfg, session));
|
|
304
|
+
}
|
|
305
|
+
|
|
297
306
|
if (cfg.commands?.tmpVtc) {
|
|
298
307
|
ctx.command('vtc查询 <vtcid>')
|
|
299
308
|
.usage("查询TruckersMP VTC信息")
|
|
@@ -303,15 +312,15 @@ function registerBaseCommands(ctx, cfg) {
|
|
|
303
312
|
if (cfg.commands?.tmpFootprint) {
|
|
304
313
|
ctx.command('近十日足迹 [tmpId:string]')
|
|
305
314
|
.usage("查询ETS服务器今日足迹")
|
|
306
|
-
.example("
|
|
307
|
-
.example("
|
|
308
|
-
.action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.ets, tmpId, '
|
|
315
|
+
.example("近七日足迹")
|
|
316
|
+
.example("近七日足迹 12345")
|
|
317
|
+
.action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.ets, tmpId, 'sevenday'));
|
|
309
318
|
|
|
310
|
-
ctx.command('
|
|
319
|
+
ctx.command('近七日足迹p [tmpId:string]')
|
|
311
320
|
.usage("查询Promods服务器今日足迹")
|
|
312
|
-
.example("
|
|
313
|
-
.example("
|
|
314
|
-
.action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.promods, tmpId, '
|
|
321
|
+
.example("近七日足迹p")
|
|
322
|
+
.example("近七日足迹p 12345")
|
|
323
|
+
.action(async ({ session }, tmpId) => await commands.tmpFootprint(ctx, session, ServerType.promods, tmpId, 'sevenday'));
|
|
315
324
|
|
|
316
325
|
ctx.command('昨日足迹 [tmpId:string]')
|
|
317
326
|
.usage("查询ETS服务器今日足迹")
|