koishi-plugin-cs2-server-query 2.6.5 → 2.6.7
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 +99 -8
- package/package.json +1 -2
package/lib/index.js
CHANGED
|
@@ -154,6 +154,45 @@ function apply(ctx, config) {
|
|
|
154
154
|
saveMapStats();
|
|
155
155
|
}
|
|
156
156
|
__name(cleanupOldEntries, "cleanupOldEntries");
|
|
157
|
+
function resolveGroupNameByCommand(rawCommand) {
|
|
158
|
+
if (commandMappings[rawCommand]) return commandMappings[rawCommand];
|
|
159
|
+
const lowerCommand = rawCommand.toLowerCase();
|
|
160
|
+
const matched = Object.entries(commandMappings).find(
|
|
161
|
+
([cmd]) => cmd.toLowerCase() === lowerCommand
|
|
162
|
+
);
|
|
163
|
+
return matched ? matched[1] : null;
|
|
164
|
+
}
|
|
165
|
+
__name(resolveGroupNameByCommand, "resolveGroupNameByCommand");
|
|
166
|
+
function buildWeeklyZEMapReport(groupName) {
|
|
167
|
+
const groupStats = mapStats[groupName];
|
|
168
|
+
if (!groupStats) {
|
|
169
|
+
return `社区 "${groupName}" 最近7天暂无地图统计数据。`;
|
|
170
|
+
}
|
|
171
|
+
const now = Date.now();
|
|
172
|
+
const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1e3;
|
|
173
|
+
const topMaps = Object.entries(groupStats).filter(([mapName]) => /^ze/i.test(mapName)).map(([mapName, timestamps]) => ({
|
|
174
|
+
mapName,
|
|
175
|
+
count: timestamps.filter((ts) => ts >= sevenDaysAgo).length
|
|
176
|
+
})).filter((item) => item.count > 0).sort((a, b) => b.count - a.count || a.mapName.localeCompare(b.mapName)).slice(0, 10);
|
|
177
|
+
if (!topMaps.length) {
|
|
178
|
+
return `社区 "${groupName}" 最近7天暂无 ze 开头地图记录。`;
|
|
179
|
+
}
|
|
180
|
+
const totalCount = topMaps.reduce((sum, item) => sum + item.count, 0);
|
|
181
|
+
const dateRange = `${new Date(sevenDaysAgo).toLocaleDateString("zh-CN")} - ${new Date(now).toLocaleDateString("zh-CN")}`;
|
|
182
|
+
return [
|
|
183
|
+
`${groupName} 地图周报(ZEmap Top10)`,
|
|
184
|
+
`统计周期:${dateRange}`,
|
|
185
|
+
"",
|
|
186
|
+
...topMaps.map((item, index) => {
|
|
187
|
+
const translation = mapTranslations[item.mapName]?.translation;
|
|
188
|
+
const translated = translation ? ` (${translation})` : "";
|
|
189
|
+
return `${index + 1}. ${item.mapName}${translated} - ${item.count} 次`;
|
|
190
|
+
}),
|
|
191
|
+
"",
|
|
192
|
+
`Top10 合计出现次数:${totalCount} 次`
|
|
193
|
+
].join("\n");
|
|
194
|
+
}
|
|
195
|
+
__name(buildWeeklyZEMapReport, "buildWeeklyZEMapReport");
|
|
157
196
|
ctx.setInterval(() => {
|
|
158
197
|
cleanupOldEntries();
|
|
159
198
|
}, 24 * 60 * 60 * 1e3);
|
|
@@ -197,8 +236,22 @@ function apply(ctx, config) {
|
|
|
197
236
|
async function generateServerImage(group, mapTranslations2) {
|
|
198
237
|
const browser = await import_puppeteer.default.launch({ args: ["--no-sandbox", "--disable-setuid-sandbox"] });
|
|
199
238
|
const page = await browser.newPage();
|
|
200
|
-
const totalPlayers = group.servers.reduce((sum, server) =>
|
|
201
|
-
|
|
239
|
+
const totalPlayers = group.servers.reduce((sum, server) => {
|
|
240
|
+
if (server.status !== "在线") return sum;
|
|
241
|
+
let players = server.players;
|
|
242
|
+
if (server.name.includes("PVE") || server.name.includes("pve")) {
|
|
243
|
+
players = Math.min(players, 32);
|
|
244
|
+
}
|
|
245
|
+
return sum + players;
|
|
246
|
+
}, 0);
|
|
247
|
+
const totalMaxPlayers = group.servers.reduce((sum, server) => {
|
|
248
|
+
if (server.status !== "在线") return sum;
|
|
249
|
+
let maxPlayers = server.maxPlayers;
|
|
250
|
+
if (server.name.includes("PVE") || server.name.includes("pve")) {
|
|
251
|
+
maxPlayers = Math.min(maxPlayers, 32);
|
|
252
|
+
}
|
|
253
|
+
return sum + maxPlayers;
|
|
254
|
+
}, 0);
|
|
202
255
|
const onlineServers = group.servers.filter((server) => server.status === "在线").length;
|
|
203
256
|
const baseHeight = 150;
|
|
204
257
|
const rowHeight = 50;
|
|
@@ -307,6 +360,12 @@ function apply(ctx, config) {
|
|
|
307
360
|
const translation = mapTranslations2[server.map];
|
|
308
361
|
const difficulty = translation?.difficulty;
|
|
309
362
|
const difficultyColor = difficulty ? difficultyColors[difficulty] : "#000000";
|
|
363
|
+
let displayPlayers = server.players;
|
|
364
|
+
let displayMaxPlayers = server.maxPlayers;
|
|
365
|
+
if (server.name.includes("PVE") || server.name.includes("pve")) {
|
|
366
|
+
displayPlayers = Math.min(displayPlayers, 32);
|
|
367
|
+
displayMaxPlayers = Math.min(displayMaxPlayers, 32);
|
|
368
|
+
}
|
|
310
369
|
const mapDuration = server.status === "在线" ? Math.floor((Date.now() - server.mapChangeTime) / 6e4) : 0;
|
|
311
370
|
const recentCount = (mapStats[group.name]?.[server.map] || []).filter(
|
|
312
371
|
(ts) => Date.now() - ts <= 7 * 24 * 60 * 60 * 1e3
|
|
@@ -325,11 +384,11 @@ function apply(ctx, config) {
|
|
|
325
384
|
</td>
|
|
326
385
|
<td style="color: ${(() => {
|
|
327
386
|
if (server.status !== "在线") return "#888";
|
|
328
|
-
const ratio =
|
|
387
|
+
const ratio = displayPlayers / displayMaxPlayers;
|
|
329
388
|
if (ratio <= 0.5) return "#33cc00";
|
|
330
389
|
if (ratio <= 0.8) return "#ffcc00";
|
|
331
390
|
return "#ff4444";
|
|
332
|
-
})()}">${server.status === "在线" ? `${
|
|
391
|
+
})()}">${server.status === "在线" ? `${displayPlayers}/${displayMaxPlayers}` : "-"}</td>
|
|
333
392
|
<td>${server.status === "在线" ? `${mapDuration}分钟` : "-"}</td>
|
|
334
393
|
<td class="status-${server.status === "在线" ? "online" : "offline"}">${server.status}</td>
|
|
335
394
|
<td><code>${server.ip}</code></td>
|
|
@@ -353,6 +412,12 @@ function apply(ctx, config) {
|
|
|
353
412
|
}
|
|
354
413
|
__name(generateServerImage, "generateServerImage");
|
|
355
414
|
async function generatePushImage(server, mapTranslations2) {
|
|
415
|
+
let displayPlayers = server.players;
|
|
416
|
+
let displayMaxPlayers = server.maxPlayers;
|
|
417
|
+
if (server.name.includes("PVE") || server.name.includes("pve")) {
|
|
418
|
+
displayPlayers = Math.min(server.players, 32);
|
|
419
|
+
displayMaxPlayers = Math.min(server.maxPlayers, 32);
|
|
420
|
+
}
|
|
356
421
|
const browser = await import_puppeteer.default.launch({ args: ["--no-sandbox", "--disable-setuid-sandbox"] });
|
|
357
422
|
const page = await browser.newPage();
|
|
358
423
|
const html = `
|
|
@@ -404,12 +469,12 @@ function apply(ctx, config) {
|
|
|
404
469
|
<p>地图: <span class="map-name">${server.map}</span> (${mapTranslations2[server.map]?.translation || "无翻译"})</p>
|
|
405
470
|
<p>当前人数:
|
|
406
471
|
<span class="player-count" style="color: ${(() => {
|
|
407
|
-
const ratio =
|
|
472
|
+
const ratio = displayPlayers / displayMaxPlayers;
|
|
408
473
|
if (ratio <= 0.5) return "#33cc00";
|
|
409
474
|
if (ratio <= 0.9) return "#ffcc00";
|
|
410
475
|
return "#ff4444";
|
|
411
476
|
})()}">
|
|
412
|
-
${
|
|
477
|
+
${displayPlayers}/${displayMaxPlayers}
|
|
413
478
|
</span>
|
|
414
479
|
</p>
|
|
415
480
|
</div>
|
|
@@ -509,6 +574,13 @@ function apply(ctx, config) {
|
|
|
509
574
|
__name(handleOfflineServers, "handleOfflineServers");
|
|
510
575
|
ctx.middleware(async (session, next) => {
|
|
511
576
|
const content = session.content.trim();
|
|
577
|
+
const weeklyReportMatch = content.match(/^(.+?)周报$/);
|
|
578
|
+
if (weeklyReportMatch) {
|
|
579
|
+
const reportCommand = weeklyReportMatch[1].trim();
|
|
580
|
+
const groupName2 = resolveGroupNameByCommand(reportCommand);
|
|
581
|
+
if (!groupName2) return next();
|
|
582
|
+
return buildWeeklyZEMapReport(groupName2);
|
|
583
|
+
}
|
|
512
584
|
const commandMatch = content.match(/^(.+?)(\s+(\d+))?$/);
|
|
513
585
|
if (!commandMatch) return next();
|
|
514
586
|
const command = commandMatch[1];
|
|
@@ -675,6 +747,12 @@ connect ${server.ip}`;
|
|
|
675
747
|
if (Object.keys(commandMappings).length === 0) return "未找到任何指令映射。";
|
|
676
748
|
return `指令映射列表:${Object.entries(commandMappings).map(([command, groupName]) => `${command} -> ${groupName}`).join(", ")}`;
|
|
677
749
|
});
|
|
750
|
+
ctx.command("cs2周报 <groupCommand>", "查看指定社区最近7天 ze 地图出现次数 Top10(例:cs2周报 exg)").action((_, groupCommand) => {
|
|
751
|
+
if (!groupCommand) return "请提供社区指令,例如:cs2周报 exg";
|
|
752
|
+
const groupName = resolveGroupNameByCommand(groupCommand.trim());
|
|
753
|
+
if (!groupName) return `未找到指令 "${groupCommand}" 对应的社区。`;
|
|
754
|
+
return buildWeeklyZEMapReport(groupName);
|
|
755
|
+
});
|
|
678
756
|
function fuzzyMatchMap(input) {
|
|
679
757
|
const lowerInput = input.toLowerCase();
|
|
680
758
|
const maps = Object.keys(mapTranslations);
|
|
@@ -1184,7 +1262,14 @@ ${mapList}
|
|
|
1184
1262
|
server.status = "离线";
|
|
1185
1263
|
}
|
|
1186
1264
|
}
|
|
1187
|
-
const totalPlayers = group.servers.reduce((sum, server) =>
|
|
1265
|
+
const totalPlayers = group.servers.reduce((sum, server) => {
|
|
1266
|
+
if (server.status !== "在线") return sum;
|
|
1267
|
+
let players = server.players;
|
|
1268
|
+
if (server.name.includes("PVE") || server.name.includes("pve")) {
|
|
1269
|
+
players = Math.min(players, 32);
|
|
1270
|
+
}
|
|
1271
|
+
return sum + players;
|
|
1272
|
+
}, 0);
|
|
1188
1273
|
if (!communityStats[group.name]) {
|
|
1189
1274
|
communityStats[group.name] = [];
|
|
1190
1275
|
}
|
|
@@ -1198,7 +1283,13 @@ ${mapList}
|
|
|
1198
1283
|
const zeServers = group.servers.filter(
|
|
1199
1284
|
(server) => server.status === "在线" && (server.name.includes("僵尸逃跑") || server.name.includes("ZE") || server.name.includes("Zombie") || server.name.includes("ZOMBIE"))
|
|
1200
1285
|
);
|
|
1201
|
-
const zeTotalPlayers = zeServers.reduce((sum, server) =>
|
|
1286
|
+
const zeTotalPlayers = zeServers.reduce((sum, server) => {
|
|
1287
|
+
let players = server.players;
|
|
1288
|
+
if (server.name.includes("PVE") || server.name.includes("pve")) {
|
|
1289
|
+
players = Math.min(players, 32);
|
|
1290
|
+
}
|
|
1291
|
+
return sum + players;
|
|
1292
|
+
}, 0);
|
|
1202
1293
|
if (zeServers.length > 0) {
|
|
1203
1294
|
if (!zeStats[group.name]) {
|
|
1204
1295
|
zeStats[group.name] = [];
|