koishi-plugin-lutu 1.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.
- package/lib/api/evmOpenApi.d.ts +33 -0
- package/lib/api/evmOpenApi.js +114 -0
- package/lib/api/truckersMpApi.d.ts +34 -0
- package/lib/api/truckersMpApi.js +133 -0
- package/lib/api/truckersMpMapApi.d.ts +6 -0
- package/lib/api/truckersMpMapApi.js +25 -0
- package/lib/api/truckyAppApi.d.ts +12 -0
- package/lib/api/truckyAppApi.js +48 -0
- package/lib/command/ets-app/queryPoint.js +74 -0
- package/lib/command/ets-app/resetPassword.js +111 -0
- package/lib/command/tmpActivityService.js +603 -0
- package/lib/command/tmpBind.d.ts +2 -0
- package/lib/command/tmpBind.js +18 -0
- package/lib/command/tmpDlcMap.d.ts +3 -0
- package/lib/command/tmpDlcMap.js +33 -0
- package/lib/command/tmpMileageRanking.d.ts +3 -0
- package/lib/command/tmpMileageRanking.js +55 -0
- package/lib/command/tmpPosition.d.ts +3 -0
- package/lib/command/tmpPosition.js +107 -0
- package/lib/command/tmpQuery/tmpQuery.d.ts +2 -0
- package/lib/command/tmpQuery/tmpQuery.js +12 -0
- package/lib/command/tmpQuery/tmpQueryImg.d.ts +3 -0
- package/lib/command/tmpQuery/tmpQueryImg.js +103 -0
- package/lib/command/tmpQuery/tmpQueryText.d.ts +2 -0
- package/lib/command/tmpQuery/tmpQueryText.js +175 -0
- package/lib/command/tmpServer.d.ts +2 -0
- package/lib/command/tmpServer.js +41 -0
- package/lib/command/tmpTraffic/tmpTraffic.d.ts +2 -0
- package/lib/command/tmpTraffic/tmpTraffic.js +15 -0
- package/lib/command/tmpTraffic/tmpTrafficMap.d.ts +3 -0
- package/lib/command/tmpTraffic/tmpTrafficMap.js +163 -0
- package/lib/command/tmpTraffic/tmpTrafficText.d.ts +2 -0
- package/lib/command/tmpTraffic/tmpTrafficText.js +60 -0
- package/lib/command/tmpVersion.d.ts +2 -0
- package/lib/command/tmpVersion.js +14 -0
- package/lib/command/tmpVtc.js +29 -0
- package/lib/database/guildBind.d.ts +15 -0
- package/lib/database/guildBind.js +41 -0
- package/lib/database/model.d.ts +2 -0
- package/lib/database/model.js +65 -0
- package/lib/database/translateCache.d.ts +14 -0
- package/lib/database/translateCache.js +31 -0
- package/lib/index.d.ts +35 -0
- package/lib/index.js +276 -0
- package/lib/resource/dlc.html +115 -0
- package/lib/resource/mileage-leaderboard.html +363 -0
- package/lib/resource/package/SEGUIEMJ.TTF +0 -0
- package/lib/resource/package/leaflet/heatmap.min.js +9 -0
- package/lib/resource/package/leaflet/leaflet-heatmap.js +246 -0
- package/lib/resource/package/leaflet/leaflet.min.css +1 -0
- package/lib/resource/package/leaflet/leaflet.min.js +1 -0
- package/lib/resource/position.html +223 -0
- package/lib/resource/query.html +363 -0
- package/lib/resource/traffic.html +207 -0
- package/lib/util/baiduTranslate.d.ts +2 -0
- package/lib/util/baiduTranslate.js +30 -0
- package/lib/util/common.d.ts +1 -0
- package/lib/util/common.js +5 -0
- package/lib/util/constant.d.ts +8 -0
- package/lib/util/constant.js +16 -0
- package/package.json +41 -0
- package/readme.md +143 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 查询服务器列表
|
|
3
|
+
*/
|
|
4
|
+
export function serverList(http: any): Promise<{
|
|
5
|
+
error: boolean;
|
|
6
|
+
}>;
|
|
7
|
+
/**
|
|
8
|
+
* 查询在线玩家
|
|
9
|
+
*/
|
|
10
|
+
export function mapPlayerList(http: any, serverId: any, ax: any, ay: any, bx: any, by: any): Promise<{
|
|
11
|
+
error: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* 查询玩家信息
|
|
15
|
+
*/
|
|
16
|
+
export function playerInfo(http: any, tmpId: any): Promise<{
|
|
17
|
+
code: any;
|
|
18
|
+
error: boolean;
|
|
19
|
+
} | {
|
|
20
|
+
error: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* DLC列表
|
|
24
|
+
*/
|
|
25
|
+
export function dlcList(http: any, type: any): Promise<{
|
|
26
|
+
error: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* 玩家里程排行
|
|
30
|
+
*/
|
|
31
|
+
export function mileageRankingList(http: any, rankingType: any, tmpId: any): Promise<{
|
|
32
|
+
error: boolean;
|
|
33
|
+
}>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const BASE_API = 'https://da.vtcm.link';
|
|
2
|
+
module.exports = {
|
|
3
|
+
/**
|
|
4
|
+
* 查询服务器列表
|
|
5
|
+
*/
|
|
6
|
+
async serverList(http) {
|
|
7
|
+
let result = null;
|
|
8
|
+
try {
|
|
9
|
+
result = await http.get(`${BASE_API}/server/list`);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return {
|
|
13
|
+
error: true
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
// 拼接返回数据
|
|
17
|
+
let data = {
|
|
18
|
+
error: result.code !== 200
|
|
19
|
+
};
|
|
20
|
+
if (!data.error) {
|
|
21
|
+
data.data = result.data;
|
|
22
|
+
}
|
|
23
|
+
return data;
|
|
24
|
+
},
|
|
25
|
+
/**
|
|
26
|
+
* 查询在线玩家
|
|
27
|
+
*/
|
|
28
|
+
async mapPlayerList(http, serverId, ax, ay, bx, by) {
|
|
29
|
+
let result = null;
|
|
30
|
+
try {
|
|
31
|
+
result = await http.get(`${BASE_API}/map/playerList?aAxisX=${ax}&aAxisY=${ay}&bAxisX=${bx}&bAxisY=${by}&serverId=${serverId}`);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return {
|
|
35
|
+
error: true
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// 拼接返回数据
|
|
39
|
+
let data = {
|
|
40
|
+
error: result.code !== 200
|
|
41
|
+
};
|
|
42
|
+
if (!data.error) {
|
|
43
|
+
data.data = result.data;
|
|
44
|
+
}
|
|
45
|
+
return data;
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* 查询玩家信息
|
|
49
|
+
*/
|
|
50
|
+
async playerInfo(http, tmpId) {
|
|
51
|
+
let result = null;
|
|
52
|
+
try {
|
|
53
|
+
result = await http.get(`https://da.vtcm.link/player/info?tmpId=${tmpId}`);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return {
|
|
57
|
+
error: true
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// 拼接返回数据
|
|
61
|
+
let data = {
|
|
62
|
+
code: result.code,
|
|
63
|
+
error: result.code !== 200
|
|
64
|
+
};
|
|
65
|
+
if (!data.error) {
|
|
66
|
+
data.data = result.data;
|
|
67
|
+
}
|
|
68
|
+
return data;
|
|
69
|
+
},
|
|
70
|
+
/**
|
|
71
|
+
* DLC列表
|
|
72
|
+
*/
|
|
73
|
+
async dlcList(http, type) {
|
|
74
|
+
let result = null;
|
|
75
|
+
try {
|
|
76
|
+
result = await http.get(`${BASE_API}/dlc/list?type=${type}`);
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
return {
|
|
80
|
+
error: true
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// 拼接返回数据
|
|
84
|
+
let data = {
|
|
85
|
+
error: result.code !== 200
|
|
86
|
+
};
|
|
87
|
+
if (!data.error) {
|
|
88
|
+
data.data = result.data;
|
|
89
|
+
}
|
|
90
|
+
return data;
|
|
91
|
+
},
|
|
92
|
+
/**
|
|
93
|
+
* 玩家里程排行
|
|
94
|
+
*/
|
|
95
|
+
async mileageRankingList(http, rankingType, tmpId) {
|
|
96
|
+
let result = null;
|
|
97
|
+
try {
|
|
98
|
+
result = await http.get(`${BASE_API}/statistics/mileageRankingList?rankingType=${rankingType}&tmpId=${tmpId || ''}&rankingCount=10`);
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
return {
|
|
102
|
+
error: true
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// 拼接返回数据
|
|
106
|
+
let data = {
|
|
107
|
+
error: result.code !== 200
|
|
108
|
+
};
|
|
109
|
+
if (!data.error) {
|
|
110
|
+
data.data = result.data;
|
|
111
|
+
}
|
|
112
|
+
return data;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 查询玩家信息
|
|
3
|
+
*/
|
|
4
|
+
export function player(http: any, tmpId: any): Promise<{
|
|
5
|
+
error: any;
|
|
6
|
+
}>;
|
|
7
|
+
/**
|
|
8
|
+
* 查询服务器列表
|
|
9
|
+
*/
|
|
10
|
+
export function servers(http: any): Promise<{
|
|
11
|
+
error: any;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* 查询玩家封禁信息
|
|
15
|
+
*/
|
|
16
|
+
export function bans(http: any, tmpId: any): Promise<{
|
|
17
|
+
error: any;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* 游戏版本
|
|
21
|
+
*/
|
|
22
|
+
export function version(http: any): Promise<{
|
|
23
|
+
error: boolean;
|
|
24
|
+
data?: undefined;
|
|
25
|
+
} | {
|
|
26
|
+
error: boolean;
|
|
27
|
+
data: any;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* 查询车队成员信息
|
|
31
|
+
*/
|
|
32
|
+
export function vtcMember(http: any, vtcId: any, memberId: any): Promise<{
|
|
33
|
+
error: any;
|
|
34
|
+
}>;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const BASE_API = 'https://api.truckersmp.com/v2';
|
|
2
|
+
module.exports = {
|
|
3
|
+
/**
|
|
4
|
+
* 查询玩家信息
|
|
5
|
+
*/
|
|
6
|
+
async player(http, tmpId) {
|
|
7
|
+
let result = null;
|
|
8
|
+
try {
|
|
9
|
+
result = await http.get(`${BASE_API}/player/${tmpId}`);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return {
|
|
13
|
+
error: true
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
// 拼接返回数据
|
|
17
|
+
let data = {
|
|
18
|
+
error: JSON.parse(result.error)
|
|
19
|
+
};
|
|
20
|
+
if (!data.error) {
|
|
21
|
+
data.data = result.response;
|
|
22
|
+
}
|
|
23
|
+
return data;
|
|
24
|
+
},
|
|
25
|
+
/**
|
|
26
|
+
* 查询服务器列表
|
|
27
|
+
*/
|
|
28
|
+
async servers(http) {
|
|
29
|
+
let result = null;
|
|
30
|
+
try {
|
|
31
|
+
result = await http.get(`${BASE_API}/servers`);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return {
|
|
35
|
+
error: true
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// 拼接返回数据
|
|
39
|
+
let data = {
|
|
40
|
+
error: JSON.parse(result.error)
|
|
41
|
+
};
|
|
42
|
+
if (!data.error) {
|
|
43
|
+
data.data = result.response;
|
|
44
|
+
}
|
|
45
|
+
return data;
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* 查询玩家封禁信息
|
|
49
|
+
*/
|
|
50
|
+
async bans(http, tmpId) {
|
|
51
|
+
let result = null;
|
|
52
|
+
try {
|
|
53
|
+
result = await http.get(`${BASE_API}/bans/${tmpId}`);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return {
|
|
57
|
+
error: true
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// 拼接返回数据
|
|
61
|
+
let data = {
|
|
62
|
+
error: JSON.parse(result.error)
|
|
63
|
+
};
|
|
64
|
+
if (!data.error) {
|
|
65
|
+
data.data = result.response;
|
|
66
|
+
}
|
|
67
|
+
return data;
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* 游戏版本
|
|
71
|
+
*/
|
|
72
|
+
async version(http) {
|
|
73
|
+
let result = null;
|
|
74
|
+
try {
|
|
75
|
+
result = await http.get(`${BASE_API}/version`);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return {
|
|
79
|
+
error: true
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// 拼接返回数据
|
|
83
|
+
return {
|
|
84
|
+
error: false,
|
|
85
|
+
data: result
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
/**
|
|
89
|
+
* 查询车队成员信息
|
|
90
|
+
*/
|
|
91
|
+
async vtcMember(http, vtcId, memberId) {
|
|
92
|
+
let result = null;
|
|
93
|
+
try {
|
|
94
|
+
result = await http.get(`${BASE_API}/vtc/${vtcId}/member/${memberId}`);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return {
|
|
98
|
+
error: true
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// 拼接返回数据
|
|
102
|
+
let data = {
|
|
103
|
+
error: JSON.parse(result.error)
|
|
104
|
+
};
|
|
105
|
+
if (!data.error) {
|
|
106
|
+
data.data = result.response;
|
|
107
|
+
}
|
|
108
|
+
return data;
|
|
109
|
+
},
|
|
110
|
+
/*
|
|
111
|
+
* 查询vtc信息
|
|
112
|
+
*/
|
|
113
|
+
async vtc(http, vtcId) {
|
|
114
|
+
let result = null
|
|
115
|
+
try {
|
|
116
|
+
result = await http.get(`${BASE_API}/vtc/${vtcId}`)
|
|
117
|
+
} catch {
|
|
118
|
+
return {
|
|
119
|
+
error: true
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 拼接返回数据
|
|
124
|
+
let data = {
|
|
125
|
+
error: JSON.parse(result.error)
|
|
126
|
+
}
|
|
127
|
+
if (!data.error) {
|
|
128
|
+
data.data = result.response
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return data
|
|
132
|
+
}
|
|
133
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const BASE_API = 'https://tracker.ets2map.com';
|
|
2
|
+
module.exports = {
|
|
3
|
+
/**
|
|
4
|
+
* 区域查询玩家
|
|
5
|
+
*/
|
|
6
|
+
async area(http, serverId, x1, y1, x2, y2) {
|
|
7
|
+
let result = null;
|
|
8
|
+
try {
|
|
9
|
+
result = await http.get(`${BASE_API}/v3/area?x1=${x1}&y1=${y1}&x2=${x2}&y2=${y2}&server=${serverId}`);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return {
|
|
13
|
+
error: true
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
// 拼接返回数据
|
|
17
|
+
let data = {
|
|
18
|
+
error: !result || !result.Success
|
|
19
|
+
};
|
|
20
|
+
if (!data.error) {
|
|
21
|
+
data.data = result.Data;
|
|
22
|
+
}
|
|
23
|
+
return data;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const BASE_API = 'https://api.codetabs.com/v1/proxy/?quest=https://api.truckyapp.com'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
/**
|
|
5
|
+
* 查询线上信息
|
|
6
|
+
*/
|
|
7
|
+
async online (http, tmpId) {
|
|
8
|
+
let result = null
|
|
9
|
+
try {
|
|
10
|
+
result = await http.get(`${BASE_API}/v3/map/online?playerID=${tmpId}`)
|
|
11
|
+
} catch {
|
|
12
|
+
return {
|
|
13
|
+
error: true
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 拼接返回数据
|
|
18
|
+
let data = {
|
|
19
|
+
error: !result || !result.response || result.response.error
|
|
20
|
+
}
|
|
21
|
+
if (!data.error) {
|
|
22
|
+
data.data = result.response
|
|
23
|
+
}
|
|
24
|
+
return data
|
|
25
|
+
},
|
|
26
|
+
/**
|
|
27
|
+
* 查询热门交通数据
|
|
28
|
+
*/
|
|
29
|
+
async trafficTop (http, serverName) {
|
|
30
|
+
let result = null
|
|
31
|
+
try {
|
|
32
|
+
result = await http.get(`${BASE_API}/v2/traffic/top?game=ets2&server=${serverName}`)
|
|
33
|
+
} catch {
|
|
34
|
+
return {
|
|
35
|
+
error: true
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 拼接返回数据
|
|
40
|
+
let data = {
|
|
41
|
+
error: !result || !result.response || result.response.length <= 0
|
|
42
|
+
}
|
|
43
|
+
if (!data.error) {
|
|
44
|
+
data.data = result.response
|
|
45
|
+
}
|
|
46
|
+
return data
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module.exports = async (ctx, cfg, session, targetQQ) => {
|
|
2
|
+
const { url, token, logOutput } = cfg.mainSettings?.settings || {};
|
|
3
|
+
let queryQQ = targetQQ;
|
|
4
|
+
if (!queryQQ) {
|
|
5
|
+
queryQQ = session.userId;
|
|
6
|
+
} else {
|
|
7
|
+
if (queryQQ.startsWith("<at ")) {
|
|
8
|
+
if (queryQQ.startsWith('<at ')) {
|
|
9
|
+
queryQQ = queryQQ.replace('<at ', '');
|
|
10
|
+
}
|
|
11
|
+
let id = '';
|
|
12
|
+
const idStart = queryQQ.indexOf('id="');
|
|
13
|
+
if (idStart !== -1) {
|
|
14
|
+
const valueStart = idStart + 4;
|
|
15
|
+
const valueEnd = queryQQ.indexOf('"', valueStart);
|
|
16
|
+
if (valueEnd !== -1) {
|
|
17
|
+
id = queryQQ.substring(valueStart, valueEnd);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
queryQQ = id;
|
|
21
|
+
}
|
|
22
|
+
if (!/^\d+$/.test(queryQQ)) {
|
|
23
|
+
return "QQ号格式不正确,请输入纯数字QQ号";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
if (logOutput) {
|
|
28
|
+
ctx.logger.info(`开始查询用户 ${queryQQ} 的积分`);
|
|
29
|
+
}
|
|
30
|
+
const userInfoUrl = `https://${url}/api/user/info/list?token=${token}&page=0&limit=7&tmpId=&tmpName=&teamId=&qq=${queryQQ}&state=0&teamRole=`;
|
|
31
|
+
if (logOutput) {
|
|
32
|
+
ctx.logger.info(`请求用户信息: ${userInfoUrl}`);
|
|
33
|
+
}
|
|
34
|
+
const userInfoResponse = await ctx.http.post(userInfoUrl);
|
|
35
|
+
if (logOutput) {
|
|
36
|
+
ctx.logger.info(`用户信息响应: ${JSON.stringify(userInfoResponse)}`);
|
|
37
|
+
}
|
|
38
|
+
if (userInfoResponse.code !== 0) {
|
|
39
|
+
return `获取用户信息失败: ${userInfoResponse.msg || "未知错误"}`;
|
|
40
|
+
}
|
|
41
|
+
const userList = userInfoResponse.page?.list || [];
|
|
42
|
+
if (userList.length === 0) {
|
|
43
|
+
return `未找到QQ号 ${queryQQ} 关联的用户信息`;
|
|
44
|
+
}
|
|
45
|
+
const userInfo = userList[0];
|
|
46
|
+
const rewardPoints = userInfo.rewardPoints || 0;
|
|
47
|
+
const tmpName = userInfo.tmpName || "未知用户";
|
|
48
|
+
const teamRole = userInfo.teamRole || "未知职位";
|
|
49
|
+
const teamId = userInfo.teamId || "未知编号";
|
|
50
|
+
let message = `🚛 晚风车队平台 - 积分查询🚚
|
|
51
|
+
`;
|
|
52
|
+
message += `👤 用户: ${tmpName}
|
|
53
|
+
`;
|
|
54
|
+
message += `🆔 车队编号: ${teamId}
|
|
55
|
+
`;
|
|
56
|
+
message += `📧 QQ: ${queryQQ}
|
|
57
|
+
`;
|
|
58
|
+
message += `🏆 职位: ${teamRole}
|
|
59
|
+
`;
|
|
60
|
+
message += `⭐ 当前积分: ${rewardPoints}
|
|
61
|
+
`;
|
|
62
|
+
message += `📅 加入日期: ${userInfo.joinDate || "未知"}`;
|
|
63
|
+
return message;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
ctx.logger.error(`积分查询过程出错: ${error}`);
|
|
66
|
+
if (error.response) {
|
|
67
|
+
return `请求失败: ${error.response.status} ${error.response.statusText}`;
|
|
68
|
+
} else if (error.code) {
|
|
69
|
+
return `网络错误: ${error.code}`;
|
|
70
|
+
} else {
|
|
71
|
+
return "系统错误,请稍后重试";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
module.exports = async (ctx, cfg, session, targetTeamId) => {
|
|
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
|
+
// 日志工具函数
|
|
9
|
+
const log = (msg) => logOutput && ctx.logger.info(msg);
|
|
10
|
+
|
|
11
|
+
// 通用HTTP请求函数
|
|
12
|
+
const fetchData = async (apiUrl) => {
|
|
13
|
+
try {
|
|
14
|
+
const response = await ctx.http.post(apiUrl);
|
|
15
|
+
log(`请求响应: ${JSON.stringify(response)}`);
|
|
16
|
+
return response;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
log(`请求错误: ${error}`);
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// 获取用户信息
|
|
24
|
+
const getUserInfo = async (params) => {
|
|
25
|
+
const query = new URLSearchParams({ token, page: 0, limit: 1, ...params }).toString();
|
|
26
|
+
const userInfoUrl = `https://${url}/api/user/info/list?${query}`;
|
|
27
|
+
log(`获取用户信息: ${userInfoUrl}`);
|
|
28
|
+
const response = await fetchData(userInfoUrl);
|
|
29
|
+
|
|
30
|
+
if (response.code !== 0 || !response.page?.list?.length) {
|
|
31
|
+
throw new Error(`未找到用户信息`);
|
|
32
|
+
}
|
|
33
|
+
return response.page.list[0];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// 重置密码
|
|
37
|
+
const resetPassword = async (teamId) => {
|
|
38
|
+
const resetUrl = `https://${url}/api/user/info/resetPasswordWithTeamId?token=${token}&teamId=${teamId}`;
|
|
39
|
+
log(`重置密码请求: ${resetUrl}`);
|
|
40
|
+
const response = await fetchData(resetUrl);
|
|
41
|
+
|
|
42
|
+
if (response.code !== 0) {
|
|
43
|
+
throw new Error(response.msg || "未知错误");
|
|
44
|
+
}
|
|
45
|
+
return teamId;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
let teamId, targetQQ;
|
|
50
|
+
|
|
51
|
+
// 处理@提及的QQ号
|
|
52
|
+
if (targetTeamId?.startsWith("<at ")) {
|
|
53
|
+
if (!isAdmin) return "您没有权限重置其他用户的密码,请联系管理员";
|
|
54
|
+
|
|
55
|
+
// 提取QQ号
|
|
56
|
+
const idStart = targetTeamId.indexOf('id="');
|
|
57
|
+
if (idStart === -1) return "获取QQ号错误,请使用车队编号重置";
|
|
58
|
+
|
|
59
|
+
targetQQ = targetTeamId.substring(idStart + 4, targetTeamId.indexOf('"', idStart + 4));
|
|
60
|
+
if (!/^\d+$/.test(targetQQ)) return "获取QQ号错误,请使用车队编号重置";
|
|
61
|
+
|
|
62
|
+
log(`管理员 ${currentUserQQ} 重置QQ: ${targetQQ} 密码`);
|
|
63
|
+
const userInfo = await getUserInfo({ qq: targetQQ });
|
|
64
|
+
teamId = userInfo.teamId;
|
|
65
|
+
}
|
|
66
|
+
// 处理车队编号或私聊场景
|
|
67
|
+
else {
|
|
68
|
+
if (isPrivateChat) {
|
|
69
|
+
// 私聊场景
|
|
70
|
+
if (!targetTeamId) {
|
|
71
|
+
// 无目标编号时用当前用户QQ查询
|
|
72
|
+
log(`用户 ${currentUserQQ} 发起密码重置`);
|
|
73
|
+
const userInfo = await getUserInfo({ qq: currentUserQQ });
|
|
74
|
+
teamId = userInfo.teamId;
|
|
75
|
+
if (!teamId) return "未找到您的信息,请联系管理员";
|
|
76
|
+
} else {
|
|
77
|
+
// 有目标编号时验证权限
|
|
78
|
+
const userInfo = await getUserInfo({ teamId: targetTeamId });
|
|
79
|
+
if (!isAdmin && userInfo.qq !== currentUserQQ) {
|
|
80
|
+
return "您没有权限重置其他成员的密码,请联系管理员";
|
|
81
|
+
}
|
|
82
|
+
teamId = targetTeamId;
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
// 非私聊场景(仅管理员可操作)
|
|
86
|
+
if (!isAdmin) return "您没有权限重置其他用户的密码,请联系管理员重置,或私聊机器人重置";
|
|
87
|
+
|
|
88
|
+
teamId = targetTeamId;
|
|
89
|
+
log(`管理员 ${currentUserQQ} 重置车队: ${teamId} 密码`);
|
|
90
|
+
await getUserInfo({ teamId }); // 验证车队存在性
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 执行密码重置
|
|
95
|
+
const resetTeamId = await resetPassword(teamId);
|
|
96
|
+
const isAdminOp = isAdmin && (targetTeamId || targetQQ);
|
|
97
|
+
return isAdminOp
|
|
98
|
+
? `管理员操作:车队编号 ${resetTeamId} 的密码重置成功!新密码已发送到用户邮箱。`
|
|
99
|
+
: "密码重置成功!新密码已发送到您的邮箱,请查收。";
|
|
100
|
+
|
|
101
|
+
} catch (error) {
|
|
102
|
+
ctx.logger.error(`密码重置错误: ${error.message}`);
|
|
103
|
+
if (error.response) {
|
|
104
|
+
return `请求失败: ${error.response.status} ${error.response.statusText}`;
|
|
105
|
+
} else if (error.code) {
|
|
106
|
+
return `网络错误: ${error.code}`;
|
|
107
|
+
} else {
|
|
108
|
+
return error.message.includes("未找到") ? error.message : "系统错误,请稍后重试";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|