koishi-plugin-ets2-tools-tmp 2.5.91 → 3.0.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.
Files changed (31) hide show
  1. package/lib/command/ets-app/addMember/addMemberV2.js +93 -0
  2. package/lib/command/ets-app/changePoint/changePoint.js +14 -0
  3. package/lib/command/ets-app/changePoint/changePointV1.js +3 -0
  4. package/lib/command/ets-app/changePoint/changePointV2.js +91 -0
  5. package/lib/command/ets-app/queryPoint/queryPoint.js +38 -0
  6. package/lib/command/ets-app/queryPoint/queryPointV1.js +51 -0
  7. package/lib/command/ets-app/queryPoint/queryPointV2.js +51 -0
  8. package/lib/command/ets-app/resetPassword/resetPassword.js +20 -0
  9. package/lib/command/ets-app/resetPassword/resetPasswordV1.js +115 -0
  10. package/lib/command/ets-app/resetPassword/resetPasswordV2.js +71 -0
  11. package/lib/command/tmpActivityService/tmpActivityServiceV1.js +71 -0
  12. package/lib/command/tmpActivityService/tmpActivityServiceV2.js +85 -0
  13. package/lib/command/tmpActivityService.js +13 -120
  14. package/lib/command/tmpDlcMap.js +1 -1
  15. package/lib/command/tmpFootprint.js +1 -1
  16. package/lib/command/tmpMileageRanking.js +1 -1
  17. package/lib/command/tmpPosition.js +1 -1
  18. package/lib/command/tmpServer/tmpServer.d.ts +2 -0
  19. package/lib/command/tmpServer/tmpServer.js +15 -0
  20. package/lib/command/tmpServer/tmpServerImg.d.ts +3 -0
  21. package/lib/command/tmpServer/tmpServerImg.js +35 -0
  22. package/lib/command/tmpServer/tmpServerText.d.ts +2 -0
  23. package/lib/command/tmpServer/tmpServerText.js +33 -0
  24. package/lib/command/tmpTraffic/tmpTrafficMap.js +1 -1
  25. package/lib/index.js +50 -15
  26. package/lib/resource/dlc.html +1 -1
  27. package/lib/resource/footprint.html +2 -2
  28. package/lib/resource/position.html +1 -1
  29. package/lib/resource/server-list.html +298 -0
  30. package/lib/resource/traffic.html +1 -1
  31. package/package.json +1 -1
@@ -0,0 +1,93 @@
1
+ const dayjs = require("dayjs");
2
+
3
+ module.exports = async (ctx, cfg, session, tmpId, qq, teamNumber) => {
4
+ const { url, token, logOutput } = cfg.mainSettings?.settings || {};
5
+ const { adminUsers, teamNumberGenerateEnable } = cfg.addMember?.settings || {};
6
+ const currentUserQQ = session.userId;
7
+ const isAdmin = adminUsers.includes(currentUserQQ);
8
+
9
+ const log = (msg) => logOutput && ctx.logger.info(msg);
10
+
11
+ const parseAtQQ = (raw) => {
12
+ if (!raw?.startsWith("<at ")) return raw;
13
+ const idStart = raw.indexOf('id="');
14
+ if (idStart === -1) return "";
15
+ const idEnd = raw.indexOf('"', idStart + 4);
16
+ if (idEnd === -1) return "";
17
+ return raw.substring(idStart + 4, idEnd);
18
+ };
19
+
20
+ try {
21
+ if (!isAdmin) {
22
+ return "您没有权限使用新增成员功能,请联系管理员";
23
+ }
24
+
25
+ if (!token) return "未配置车队平台V2.0 API认证令牌";
26
+
27
+ if (!tmpId) {
28
+ return "请输入TMP ID";
29
+ }
30
+
31
+ if (!qq) {
32
+ return "请输入QQ号或@群成员";
33
+ }
34
+
35
+ const parsedQQ = parseAtQQ(qq) || qq;
36
+ if (!/^\d+$/.test(parsedQQ)) {
37
+ return "QQ号格式不正确,请输入纯数字QQ号";
38
+ }
39
+
40
+ const autoGenerate = teamNumberGenerateEnable !== false;
41
+ if (!autoGenerate && !teamNumber) {
42
+ return "自动生成车队编号已关闭,请输入车队编号";
43
+ }
44
+
45
+ const baseUrl = url || "open.vtcm.link";
46
+ const email = `${parsedQQ}@qq.com`;
47
+ const joinDate = dayjs().format("YYYY-MM-DD");
48
+
49
+ const requestBody = {
50
+ tmpId: Number(tmpId),
51
+ teamNumberGenerateEnable: autoGenerate ? 1 : 0,
52
+ qq: parsedQQ,
53
+ email,
54
+ joinDate,
55
+ state: 1
56
+ };
57
+
58
+ if (!autoGenerate) {
59
+ requestBody.teamNumber = Number(teamNumber);
60
+ }
61
+
62
+ const saveUrl = `https://${baseUrl}/members/save`;
63
+ log(`[V2] 新增成员请求: ${saveUrl}, body: ${JSON.stringify(requestBody)}`);
64
+ const response = await ctx.http.post(saveUrl, requestBody, { headers: { token } });
65
+ log(`[V2] 新增成员响应: ${JSON.stringify(response)}`);
66
+
67
+ if (response.code !== 200) {
68
+ return response.msg || "新增成员失败";
69
+ }
70
+
71
+ let result = `新增成员成功!\n`;
72
+ result += `TMP ID: ${tmpId}\n`;
73
+ result += `QQ: ${parsedQQ}\n`;
74
+ result += `邮箱: ${email}\n`;
75
+ result += `加入日期: ${joinDate}\n`;
76
+ if (!autoGenerate) {
77
+ result += `车队编号: ${teamNumber}\n`;
78
+ } else {
79
+ result += `车队编号: 自动生成\n`;
80
+ }
81
+ return result;
82
+
83
+ } catch (error) {
84
+ ctx.logger.error(`[V2] 新增成员错误: ${error.message}`);
85
+ if (error.response) {
86
+ return `请求失败: ${error.response.status} ${error.response.statusText}`;
87
+ } else if (error.code) {
88
+ return `网络错误: ${error.code}`;
89
+ } else {
90
+ return "系统错误,请稍后重试";
91
+ }
92
+ }
93
+ };
@@ -0,0 +1,14 @@
1
+ const changePointV1 = require("./changePointV1");
2
+ const changePointV2 = require("./changePointV2");
3
+
4
+ module.exports = async (ctx, cfg, session, target, changeType, quantity) => {
5
+ const { platformVersion } = cfg.mainSettings?.settings || {};
6
+ const platform = (platformVersion || "v1").toLowerCase();
7
+
8
+ switch (platform) {
9
+ case "v2":
10
+ return await changePointV2(ctx, cfg, session, target, changeType, quantity);
11
+ default:
12
+ return await changePointV1(ctx, cfg, session, target, changeType, quantity);
13
+ }
14
+ };
@@ -0,0 +1,3 @@
1
+ module.exports = async (ctx, cfg, session, target, changeType, quantity) => {
2
+ return "V1.0平台暂不支持积分修改功能";
3
+ };
@@ -0,0 +1,91 @@
1
+ module.exports = async (ctx, cfg, session, target, changeType, quantity) => {
2
+ const { url, token, logOutput } = cfg.mainSettings?.settings || {};
3
+ const { adminUsers } = cfg.changePoint?.settings || {};
4
+ const currentUserQQ = session.userId;
5
+ const isPrivateChat = session.channelId === `private:${currentUserQQ}`;
6
+ const isAdmin = adminUsers.includes(currentUserQQ);
7
+
8
+ const log = (msg) => logOutput && ctx.logger.info(msg);
9
+
10
+ const parseAtQQ = (raw) => {
11
+ if (!raw?.startsWith("<at ")) return raw;
12
+ const idStart = raw.indexOf('id="');
13
+ if (idStart === -1) return "";
14
+ const idEnd = raw.indexOf('"', idStart + 4);
15
+ if (idEnd === -1) return "";
16
+ return raw.substring(idStart + 4, idEnd);
17
+ };
18
+
19
+ try {
20
+ if (isPrivateChat) {
21
+ return "积分修改功能仅支持群聊使用";
22
+ }
23
+
24
+ if (!isAdmin) {
25
+ return "您没有权限使用积分修改功能,请联系管理员";
26
+ }
27
+
28
+ if (!token) return "未配置车队平台V2.0 API认证令牌";
29
+
30
+ if (!changeType || !["增加", "减少"].includes(changeType)) {
31
+ return "请指定操作类型:增加 或 减少";
32
+ }
33
+
34
+ if (!quantity || isNaN(Number(quantity)) || Number(quantity) <= 0) {
35
+ return "请输入有效的积分数量(正整数)";
36
+ }
37
+
38
+ const baseUrl = url || "open.vtcm.link";
39
+ let uid;
40
+
41
+ if (target) {
42
+ const parsedQQ = parseAtQQ(target);
43
+ if (parsedQQ && /^\d+$/.test(parsedQQ)) {
44
+ const memberUrl = `https://${baseUrl}/members/get?qq=${encodeURIComponent(parsedQQ)}`;
45
+ log(`[V2] 获取成员信息: ${memberUrl}`);
46
+ const memberResponse = await ctx.http.get(memberUrl, { headers: { token } });
47
+ log(`[V2] 成员信息响应: ${JSON.stringify(memberResponse)}`);
48
+
49
+ if (memberResponse.code !== 200 || !memberResponse.data?.uid) {
50
+ return memberResponse.msg || `未找到QQ号 ${parsedQQ} 关联的用户信息`;
51
+ }
52
+ uid = memberResponse.data.uid;
53
+ } else if (/^\d+$/.test(target)) {
54
+ uid = target;
55
+ } else {
56
+ return "目标用户格式不正确,请输入UID或@群成员";
57
+ }
58
+ } else {
59
+ return "请指定目标用户(UID或@群成员)";
60
+ }
61
+
62
+ const changeTypeNum = changeType === "增加" ? 1 : 2;
63
+ const quantityNum = Number(quantity);
64
+
65
+ const changeUrl = `https://${baseUrl}/members/point/change`;
66
+ const requestBody = {
67
+ uid: Number(uid),
68
+ changeType: changeTypeNum,
69
+ quantity: quantityNum
70
+ };
71
+ log(`[V2] 积分修改请求: ${changeUrl}, body: ${JSON.stringify(requestBody)}`);
72
+ const changeResponse = await ctx.http.post(changeUrl, requestBody, { headers: { token } });
73
+ log(`[V2] 积分修改响应: ${JSON.stringify(changeResponse)}`);
74
+
75
+ if (changeResponse.code !== 200) {
76
+ return changeResponse.msg || "积分修改失败";
77
+ }
78
+
79
+ return `积分修改成功!\n目标UID: ${uid}\n操作: ${changeType} ${quantityNum} 积分`;
80
+
81
+ } catch (error) {
82
+ ctx.logger.error(`[V2] 积分修改错误: ${error.message}`);
83
+ if (error.response) {
84
+ return `请求失败: ${error.response.status} ${error.response.statusText}`;
85
+ } else if (error.code) {
86
+ return `网络错误: ${error.code}`;
87
+ } else {
88
+ return "系统错误,请稍后重试";
89
+ }
90
+ }
91
+ };
@@ -0,0 +1,38 @@
1
+ const queryPointV1 = require("./queryPointV1");
2
+ const queryPointV2 = require("./queryPointV2");
3
+
4
+ module.exports = async (ctx, cfg, session, targetQQ) => {
5
+ const { platformVersion } = cfg.mainSettings?.settings || {};
6
+ const platform = (platformVersion || "v1").toLowerCase();
7
+
8
+ let queryQQ = targetQQ;
9
+ if (!queryQQ) {
10
+ queryQQ = session.userId;
11
+ } else {
12
+ if (queryQQ.startsWith("<at ")) {
13
+ if (queryQQ.startsWith('<at ')) {
14
+ queryQQ = queryQQ.replace('<at ', '');
15
+ }
16
+ let id = '';
17
+ const idStart = queryQQ.indexOf('id="');
18
+ if (idStart !== -1) {
19
+ const valueStart = idStart + 4;
20
+ const valueEnd = queryQQ.indexOf('"', valueStart);
21
+ if (valueEnd !== -1) {
22
+ id = queryQQ.substring(valueStart, valueEnd);
23
+ }
24
+ }
25
+ queryQQ = id;
26
+ }
27
+ if (!/^\d+$/.test(queryQQ)) {
28
+ return "QQ号格式不正确,请输入纯数字QQ号";
29
+ }
30
+ }
31
+
32
+ switch (platform) {
33
+ case "v2":
34
+ return await queryPointV2(ctx, cfg, queryQQ);
35
+ default:
36
+ return await queryPointV1(ctx, cfg, queryQQ);
37
+ }
38
+ };
@@ -0,0 +1,51 @@
1
+ module.exports = async (ctx, cfg, queryQQ) => {
2
+ const { Name, url, token, logOutput } = cfg.mainSettings?.settings || {};
3
+
4
+ try {
5
+ if (logOutput) {
6
+ ctx.logger.info(`开始查询用户 ${queryQQ} 的积分`);
7
+ }
8
+
9
+ const userInfoUrl = `https://${url}/api/user/info/list?token=${token}&page=0&limit=7&tmpId=&tmpName=&teamId=&qq=${queryQQ}&state=0&teamRole=`;
10
+ if (logOutput) {
11
+ ctx.logger.info(`请求V1.0用户信息: ${userInfoUrl}`);
12
+ }
13
+ const userInfoResponse = await ctx.http.post(userInfoUrl);
14
+ if (logOutput) {
15
+ ctx.logger.info(`V1.0用户信息响应: ${JSON.stringify(userInfoResponse)}`);
16
+ }
17
+
18
+ if (userInfoResponse.code !== 0) {
19
+ return `获取用户信息失败: ${userInfoResponse.msg || "未知错误"}`;
20
+ }
21
+ const userList = userInfoResponse.page?.list || [];
22
+ if (userList.length === 0) {
23
+ return `未找到QQ号 ${queryQQ} 关联的用户信息`;
24
+ }
25
+
26
+ const userInfo = userList[0];
27
+ const tmpName = userInfo.tmpName || "未知用户";
28
+ const teamRole = userInfo.teamRole || userInfo.tmpRole || "未知职位";
29
+ const teamId = userInfo.teamId || userInfo.uid || "未知编号";
30
+ const rewardPoints = userInfo.rewardPoints || userInfo.point || 0;
31
+ const joinDate = userInfo.joinDate || "未知";
32
+
33
+ let message = `🚛 ${Name}平台 - 积分查询🚚\n`;
34
+ message += `👤 用户: ${tmpName}\n`;
35
+ message += `🆔 车队编号: ${teamId}\n`;
36
+ message += `📧 QQ: ${queryQQ}\n`;
37
+ message += `🏆 职位: ${teamRole}\n`;
38
+ message += `⭐ 当前积分: ${rewardPoints}\n`;
39
+ message += `📅 加入日期: ${joinDate}`;
40
+ return message;
41
+ } catch (error) {
42
+ ctx.logger.error(`积分查询过程出错: ${error}`);
43
+ if (error.response) {
44
+ return `请求失败: ${error.response.status} ${error.response.statusText}`;
45
+ } else if (error.code) {
46
+ return `网络错误: ${error.code}`;
47
+ } else {
48
+ return "系统错误,请稍后重试";
49
+ }
50
+ }
51
+ };
@@ -0,0 +1,51 @@
1
+ module.exports = async (ctx, cfg, queryQQ) => {
2
+ const { Name, url, token, logOutput } = cfg.mainSettings?.settings || {};
3
+
4
+ try {
5
+ if (logOutput) {
6
+ ctx.logger.info(`开始查询用户 ${queryQQ} 的积分`);
7
+ }
8
+
9
+ const baseUrl = url || "open.vtcm.link";
10
+ const userInfoUrl = `https://${baseUrl}/members/get?token=${token}&qq=${queryQQ}`;
11
+ if (logOutput) {
12
+ ctx.logger.info(`请求V2.0用户信息: ${userInfoUrl}`);
13
+ }
14
+ const userInfoResponse = await ctx.http.get(userInfoUrl);
15
+ if (logOutput) {
16
+ ctx.logger.info(`V2.0用户信息响应: ${JSON.stringify(userInfoResponse)}`);
17
+ }
18
+
19
+ if (userInfoResponse.code !== 200) {
20
+ return `获取用户信息失败: ${userInfoResponse.msg || "未知错误"}`;
21
+ }
22
+ if (!userInfoResponse.data) {
23
+ return `未找到QQ号 ${queryQQ} 关联的用户信息`;
24
+ }
25
+
26
+ const userInfo = userInfoResponse.data;
27
+ const tmpName = userInfo.tmpName || "未知用户";
28
+ const teamRole = userInfo.teamRole || userInfo.tmpRole || "未知职位";
29
+ const teamId = userInfo.teamId || userInfo.uid || "未知编号";
30
+ const rewardPoints = userInfo.rewardPoints || userInfo.point || 0;
31
+ const joinDate = userInfo.joinDate || "未知";
32
+
33
+ let message = `🚛 ${Name}平台 - 积分查询🚚\n`;
34
+ message += `👤 用户: ${tmpName}\n`;
35
+ message += `🆔 车队编号: ${teamId}\n`;
36
+ message += `📧 QQ: ${queryQQ}\n`;
37
+ message += `🏆 职位: ${teamRole}\n`;
38
+ message += `⭐ 当前积分: ${rewardPoints}\n`;
39
+ message += `📅 加入日期: ${joinDate}`;
40
+ return message;
41
+ } catch (error) {
42
+ ctx.logger.error(`积分查询过程出错: ${error}`);
43
+ if (error.response) {
44
+ return `请求失败: ${error.response.status} ${error.response.statusText}`;
45
+ } else if (error.code) {
46
+ return `网络错误: ${error.code}`;
47
+ } else {
48
+ return "系统错误,请稍后重试";
49
+ }
50
+ }
51
+ };
@@ -0,0 +1,20 @@
1
+ const resetPasswordV1 = require("./resetPasswordV1");
2
+ const resetPasswordV2 = require("./resetPasswordV2");
3
+
4
+ module.exports = async (ctx, cfg, session, targetTeamId, password) => {
5
+ const { platformVersion } = cfg.mainSettings?.settings || {};
6
+ const platform = (platformVersion || "v1").toLowerCase();
7
+
8
+ switch (platform) {
9
+ case "v2": {
10
+ let actualPassword = password;
11
+ if (targetTeamId && !password && !/^\d+$/.test(targetTeamId)) {
12
+ actualPassword = targetTeamId;
13
+ targetTeamId = undefined;
14
+ }
15
+ return await resetPasswordV2(ctx, cfg, session, actualPassword);
16
+ }
17
+ default:
18
+ return await resetPasswordV1(ctx, cfg, session, targetTeamId, password);
19
+ }
20
+ };
@@ -0,0 +1,115 @@
1
+ module.exports = async (ctx, cfg, session, targetTeamId, password) => {
2
+ const { url, token, logOutput } = cfg.mainSettings?.settings || {};
3
+ const { adminUsers } = cfg.resetPassword?.settings || {};
4
+ const currentUserQQ = session.userId;
5
+ const isAdmin = adminUsers.includes(currentUserQQ);
6
+ const isPrivateChat = session.channelId === `private:${currentUserQQ}`;
7
+
8
+ const log = (msg) => logOutput && ctx.logger.info(msg);
9
+
10
+ const parseAtQQ = (raw) => {
11
+ if (!raw?.startsWith("<at ")) return raw;
12
+ const idStart = raw.indexOf('id="');
13
+ if (idStart === -1) return "";
14
+ const idEnd = raw.indexOf('"', idStart + 4);
15
+ if (idEnd === -1) return "";
16
+ return raw.substring(idStart + 4, idEnd);
17
+ };
18
+
19
+ const fetchData = async (apiUrl) => {
20
+ try {
21
+ const response = await ctx.http.post(apiUrl);
22
+ log(`请求响应: ${JSON.stringify(response)}`);
23
+ return response;
24
+ } catch (error) {
25
+ log(`请求错误: ${error}`);
26
+ throw error;
27
+ }
28
+ };
29
+
30
+ const getUserInfo = async (params) => {
31
+ const query = new URLSearchParams({ token, page: 0, limit: 1, ...params }).toString();
32
+ const userInfoUrl = `https://${url}/api/user/info/list?${query}`;
33
+ log(`获取用户信息: ${userInfoUrl}`);
34
+ const response = await fetchData(userInfoUrl);
35
+
36
+ if (response.code !== 0 || !response.page?.list?.length) {
37
+ throw new Error(`未找到用户信息`);
38
+ }
39
+ return response.page.list[0];
40
+ };
41
+
42
+ const resetPasswordApi = async (teamId) => {
43
+ const resetUrl = `https://${url}/api/user/info/resetPasswordWithTeamId?token=${token}&teamId=${teamId}`;
44
+ log(`重置密码请求: ${resetUrl}`);
45
+ const response = await fetchData(resetUrl);
46
+
47
+ if (response.code !== 0) {
48
+ throw new Error(response.msg || "未知错误");
49
+ }
50
+ return teamId;
51
+ };
52
+
53
+ try {
54
+ let teamId, targetQQ;
55
+
56
+ if (targetTeamId?.startsWith("<at ")) {
57
+ if (!isAdmin) return "您没有权限重置其他用户的密码,请联系管理员";
58
+
59
+ const idStart = targetTeamId.indexOf('id="');
60
+ if (idStart === -1) return "获取QQ号错误,请使用车队编号重置";
61
+
62
+ targetQQ = targetTeamId.substring(idStart + 4, targetTeamId.indexOf('"', idStart + 4));
63
+ if (!/^\d+$/.test(targetQQ)) return "获取QQ号错误,请使用车队编号重置";
64
+
65
+ log(`管理员 ${currentUserQQ} 重置QQ: ${targetQQ} 密码`);
66
+ const userInfo = await getUserInfo({ qq: targetQQ });
67
+ teamId = userInfo.teamId;
68
+ } else {
69
+ if (isPrivateChat) {
70
+ if (!targetTeamId) {
71
+ log(`用户 ${currentUserQQ} 发起密码重置`);
72
+ const userInfo = await getUserInfo({ qq: currentUserQQ });
73
+ teamId = userInfo.teamId;
74
+ if (!teamId) return "未找到您的信息,请联系管理员";
75
+ } else {
76
+ log(`用户 ${currentUserQQ} 尝试重置车队编号 ${targetTeamId} 的密码`);
77
+ const userInfo = await getUserInfo({ teamId: targetTeamId });
78
+
79
+ if (!isAdmin && String(userInfo.qq) !== String(currentUserQQ)) {
80
+ return "您没有权限重置其他成员的密码,请联系管理员";
81
+ }
82
+
83
+ teamId = targetTeamId;
84
+ if (isAdmin) {
85
+ log(`管理员 ${currentUserQQ} 重置车队编号 ${targetTeamId} 的密码`);
86
+ } else {
87
+ log(`验证通过,车队编号 ${targetTeamId} 对应的QQ ${userInfo.qq} 与当前用户QQ ${currentUserQQ} 一致`);
88
+ }
89
+ }
90
+ } else {
91
+ if (!isAdmin) return "您没有权限重置其他用户的密码,请联系管理员重置,或私聊机器人重置";
92
+
93
+ teamId = targetTeamId;
94
+ log(`管理员 ${currentUserQQ} 重置车队: ${teamId} 密码`);
95
+ await getUserInfo({ teamId });
96
+ }
97
+ }
98
+
99
+ const resetTeamId = await resetPasswordApi(teamId);
100
+ const isAdminOp = isAdmin && (targetTeamId || targetQQ);
101
+ return isAdminOp
102
+ ? `管理员操作:车队编号 ${resetTeamId} 的密码重置成功!新密码已发送到用户邮箱。`
103
+ : "密码重置成功!新密码已发送到您的邮箱,请查收。";
104
+
105
+ } catch (error) {
106
+ ctx.logger.error(`密码重置错误: ${error.message}`);
107
+ if (error.response) {
108
+ return `请求失败: ${error.response.status} ${error.response.statusText}`;
109
+ } else if (error.code) {
110
+ return `网络错误: ${error.code}`;
111
+ } else {
112
+ return error.message.includes("未找到") ? error.message : "系统错误,请稍后重试";
113
+ }
114
+ }
115
+ };
@@ -0,0 +1,71 @@
1
+ module.exports = async (ctx, cfg, session, password) => {
2
+ const { url, token, logOutput } = cfg.mainSettings?.settings || {};
3
+ const currentUserQQ = session.userId;
4
+ const isPrivateChat = session.channelId === `private:${currentUserQQ}`;
5
+
6
+ const log = (msg) => logOutput && ctx.logger.info(msg);
7
+
8
+ const randomChar = (chars) => chars[Math.floor(Math.random() * chars.length)];
9
+ const generatePassword = () => {
10
+ const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
11
+ const digits = "0123456789";
12
+ const all = letters + digits;
13
+ const chars = [randomChar(letters), randomChar(digits)];
14
+ for (let i = 0; i < 8; i++) {
15
+ chars.push(randomChar(all));
16
+ }
17
+ for (let i = chars.length - 1; i > 0; i--) {
18
+ const j = Math.floor(Math.random() * (i + 1));
19
+ [chars[i], chars[j]] = [chars[j], chars[i]];
20
+ }
21
+ return chars.join("");
22
+ };
23
+
24
+ try {
25
+ if (!isPrivateChat) {
26
+ return "V2.0平台密码重置仅支持私聊使用,请私聊机器人进行操作";
27
+ }
28
+
29
+ if (!token) return "未配置车队平台V2.0 API认证令牌";
30
+
31
+ const baseUrl = url || "open.vtcm.link";
32
+ const queryQQ = currentUserQQ;
33
+
34
+ const memberUrl = `https://${baseUrl}/members/get?qq=${encodeURIComponent(queryQQ)}`;
35
+ log(`[V2] 获取成员信息: ${memberUrl}`);
36
+ const memberResponse = await ctx.http.get(memberUrl, { headers: { token } });
37
+ log(`[V2] 成员信息响应: ${JSON.stringify(memberResponse)}`);
38
+
39
+ if (memberResponse.code !== 200 || !memberResponse.data?.uid) {
40
+ return memberResponse.msg || "未找到与您QQ号关联的用户信息";
41
+ }
42
+
43
+ const memberUid = memberResponse.data.uid;
44
+ const newPassword = password?.trim() || generatePassword();
45
+
46
+ if (newPassword.length < 6 || newPassword.length > 16) {
47
+ return "密码长度需为6-16位";
48
+ }
49
+
50
+ const resetUrl = `https://${baseUrl}/members/${memberUid}/password`;
51
+ log(`[V2] 重置密码请求: ${resetUrl}`);
52
+ const resetResponse = await ctx.http.post(resetUrl, { password: newPassword }, { headers: { token } });
53
+ log(`[V2] 重置密码响应: ${JSON.stringify(resetResponse)}`);
54
+
55
+ if (resetResponse.code !== 200) {
56
+ return resetResponse.msg || "密码重置失败";
57
+ }
58
+
59
+ return `密码重置成功!\n您的UID: ${memberUid}\n新密码: ${newPassword}\n请妥善保管好您的密码,以防泄露`;
60
+
61
+ } catch (error) {
62
+ ctx.logger.error(`[V2] 密码重置错误: ${error.message}`);
63
+ if (error.response) {
64
+ return `请求失败: ${error.response.status} ${error.response.statusText}`;
65
+ } else if (error.code) {
66
+ return `网络错误: ${error.code}`;
67
+ } else {
68
+ return "系统错误,请稍后重试";
69
+ }
70
+ }
71
+ };
@@ -0,0 +1,71 @@
1
+ module.exports = {
2
+ async updateTodayActivities() {
3
+ try {
4
+ this.todayActivities = [];
5
+
6
+ const baseUrl = this.cfg.mainSettings?.url || "open.vtcm.link";
7
+ const token = this.cfg.mainSettings?.token || "";
8
+ const fullUrl = `https://${baseUrl}/api/activity/info/list?token=${token}&page=1&limit=100&themeName=`;
9
+ this.logger.api(`请求V1车队平台API: ${fullUrl.replace(token, "***")}`);
10
+
11
+ const startTime = Date.now();
12
+ const response = await this.ctx.http.get(fullUrl, { timeout: 10000 });
13
+ const duration = Date.now() - startTime;
14
+ this.logger.api(`V1车队平台API响应耗时: ${duration}ms, 状态码: ${response.code}`);
15
+
16
+ if (this.cfg.debug?.logApiResponses) {
17
+ this.logger.api("V1车队平台API响应详情:", {
18
+ code: response.code,
19
+ totalCount: response.data?.totalCount,
20
+ listCount: response.data?.list?.length
21
+ });
22
+ }
23
+
24
+ if (response.code === 0 && response.data?.list) {
25
+ const now = new Date();
26
+ const today = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`;
27
+ this.logger.debug(`[V1活动更新] 当前本地日期: ${today}, UTC日期: ${new Date().toISOString().split("T")[0]}`);
28
+
29
+ const originalCount = response.data.list.length;
30
+ this.logger.debug(`[V1活动更新] API返回活动总数: ${originalCount}`);
31
+
32
+ this.todayActivities = response.data.list.filter((activity) => {
33
+ const activityDate = activity.startTime?.split(" ")[0];
34
+ return activityDate === today;
35
+ });
36
+
37
+ this.logger.info(`[V1活动更新] 从车队平台找到 ${this.todayActivities.length}/${originalCount} 个今日活动`);
38
+ } else {
39
+ this.logger.error(`[V1活动更新] 车队平台API返回错误: ${response.msg || '未知错误'} (代码: ${response.code || '无'})`);
40
+ this.todayActivities = [];
41
+ }
42
+ } catch (error) {
43
+ this.logger.error("[V1活动更新] 获取车队平台活动列表失败:", error.message);
44
+ this.todayActivities = [];
45
+ }
46
+ },
47
+
48
+ async checkAutoClock(activity) {
49
+ try {
50
+ const baseUrl = this.cfg.mainSettings?.url || "open.vtcm.link";
51
+ const token = this.cfg.mainSettings?.token || "";
52
+ const fullUrl = `https://${baseUrl}/api/activity/info/info/${activity.id}?token=${token}`;
53
+ this.logger.api(`请求V1活动详情API: ${fullUrl.replace(token, "***")}`);
54
+
55
+ const response = await this.ctx.http.get(fullUrl, { timeout: 10000 });
56
+ this.logger.api(`V1活动详情API响应:`, response);
57
+
58
+ if (response.code === 0 && response.data) {
59
+ const enableAutoClock = response.data.enableAutoClock;
60
+ this.logger.debug(`活动 "${activity.themeName}" V1自动打卡状态: ${enableAutoClock}`);
61
+ return enableAutoClock === 1;
62
+ } else {
63
+ this.logger.error(`V1活动详情API返回错误: ${response.msg || '未知错误'} (代码: ${response.code || '无'})`);
64
+ return false;
65
+ }
66
+ } catch (error) {
67
+ this.logger.error(`检查V1活动 "${activity.themeName}" 自动打卡状态失败:`, error.message);
68
+ return false;
69
+ }
70
+ }
71
+ };