koishi-plugin-cs2-server-query 2.4.0 → 2.6.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/index.js +282 -25
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -40,6 +40,7 @@ var import_steam_server_query = require("steam-server-query");
|
|
|
40
40
|
var import_fs = __toESM(require("fs"));
|
|
41
41
|
var import_path = __toESM(require("path"));
|
|
42
42
|
var import_puppeteer = __toESM(require("puppeteer"));
|
|
43
|
+
var zeStats = {};
|
|
43
44
|
var name = "cs2-server-query";
|
|
44
45
|
var Config = import_koishi.Schema.object({
|
|
45
46
|
mapTranslationFile: import_koishi.Schema.string().default("map-translation.json"),
|
|
@@ -170,6 +171,14 @@ function apply(ctx, config) {
|
|
|
170
171
|
if (import_fs.default.existsSync(communityStatsFilePath)) {
|
|
171
172
|
communityStats = JSON.parse(import_fs.default.readFileSync(communityStatsFilePath, "utf-8"));
|
|
172
173
|
}
|
|
174
|
+
const zeStatsFilePath = import_path.default.resolve(__dirname, "ze-stats.json");
|
|
175
|
+
if (import_fs.default.existsSync(zeStatsFilePath)) {
|
|
176
|
+
zeStats = JSON.parse(import_fs.default.readFileSync(zeStatsFilePath, "utf-8"));
|
|
177
|
+
}
|
|
178
|
+
function saveZEStats() {
|
|
179
|
+
import_fs.default.writeFileSync(zeStatsFilePath, JSON.stringify(zeStats, null, 2));
|
|
180
|
+
}
|
|
181
|
+
__name(saveZEStats, "saveZEStats");
|
|
173
182
|
function saveCommunityStats() {
|
|
174
183
|
import_fs.default.writeFileSync(communityStatsFilePath, JSON.stringify(communityStats, null, 2));
|
|
175
184
|
}
|
|
@@ -282,7 +291,7 @@ function apply(ctx, config) {
|
|
|
282
291
|
</head>
|
|
283
292
|
<body>
|
|
284
293
|
<div class="overlay">
|
|
285
|
-
<h2>${group.name} -
|
|
294
|
+
<h2>${group.name} - 服务器列表(输入help查指令,快速发送进服IP例如"exg 1")</h2>
|
|
286
295
|
<p class="total-players">总玩家数: ${totalPlayers}/${totalMaxPlayers} | 在线服务器: ${onlineServers}/${group.servers.length}</p> <!-- 显示在线服务器数量 -->
|
|
287
296
|
<table>
|
|
288
297
|
<tr>
|
|
@@ -290,7 +299,7 @@ function apply(ctx, config) {
|
|
|
290
299
|
<th>服务器名称</th>
|
|
291
300
|
<th>地图</th>
|
|
292
301
|
<th>玩家</th>
|
|
293
|
-
<th
|
|
302
|
+
<th>地图运行时间</th>
|
|
294
303
|
<th>状态</th>
|
|
295
304
|
<th>IP 地址</th>
|
|
296
305
|
</tr>
|
|
@@ -1167,14 +1176,31 @@ ${mapList}
|
|
|
1167
1176
|
communityStats[group.name] = communityStats[group.name].filter(
|
|
1168
1177
|
(stat) => now - stat.time <= 12 * 60 * 60 * 1e3
|
|
1169
1178
|
);
|
|
1179
|
+
const zeServers = group.servers.filter(
|
|
1180
|
+
(server) => server.status === "在线" && (server.name.includes("僵尸逃跑") || server.name.includes("ZE") || server.name.includes("Zombie") || server.name.includes("ZOMBIE"))
|
|
1181
|
+
);
|
|
1182
|
+
const zeTotalPlayers = zeServers.reduce((sum, server) => sum + server.players, 0);
|
|
1183
|
+
if (zeServers.length > 0) {
|
|
1184
|
+
if (!zeStats[group.name]) {
|
|
1185
|
+
zeStats[group.name] = [];
|
|
1186
|
+
}
|
|
1187
|
+
zeStats[group.name].push({
|
|
1188
|
+
time: Date.now(),
|
|
1189
|
+
players: zeTotalPlayers
|
|
1190
|
+
});
|
|
1191
|
+
zeStats[group.name] = zeStats[group.name].filter(
|
|
1192
|
+
(stat) => now - stat.time <= 12 * 60 * 60 * 1e3
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1170
1195
|
}
|
|
1171
1196
|
saveCommunityStats();
|
|
1197
|
+
saveZEStats();
|
|
1172
1198
|
}, 10 * 60 * 1e3);
|
|
1173
|
-
ctx.command("cs2统计", "
|
|
1199
|
+
ctx.command("cs2统计", "生成并发送CS2社区服总人数统计折线图").action(async ({ session }) => {
|
|
1174
1200
|
const browser = await import_puppeteer.default.launch({ args: ["--no-sandbox", "--disable-setuid-sandbox"] });
|
|
1175
1201
|
const page = await browser.newPage();
|
|
1176
1202
|
const colors = ["#FF0000", "#00FF00", "#0000FF", "#FF00FF", "#00FFFF", "#FFFF00", "#FFA500", "#800080", "#008000", "#000080"];
|
|
1177
|
-
const margin = { top:
|
|
1203
|
+
const margin = { top: 45, right: 30, bottom: 50, left: 50 };
|
|
1178
1204
|
const width = 1200 - margin.left - margin.right;
|
|
1179
1205
|
const height = 600 - margin.top - margin.bottom;
|
|
1180
1206
|
const generateSVG = /* @__PURE__ */ __name((statsData) => {
|
|
@@ -1237,31 +1263,65 @@ ${mapList}
|
|
|
1237
1263
|
`;
|
|
1238
1264
|
}).join("")}
|
|
1239
1265
|
`;
|
|
1240
|
-
const legend = groups2.map(([groupName], i) =>
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1266
|
+
const legend = groups2.map(([groupName, dataPoints], i) => {
|
|
1267
|
+
const latest = dataPoints[dataPoints.length - 1];
|
|
1268
|
+
const latestPlayers = latest ? latest.players : 0;
|
|
1269
|
+
const playerRatio = latestPlayers / maxPlayers;
|
|
1270
|
+
const playerColor = playerRatio <= 0.5 ? "#33cc00" : playerRatio <= 0.8 ? "#ffcc00" : "#ff4444";
|
|
1271
|
+
return `
|
|
1272
|
+
<g transform="translate(${width - 250}, ${20 + i * 35})">
|
|
1273
|
+
<!-- 社区标识 -->
|
|
1274
|
+
<rect x="0" y="-14" width="28" height="28" rx="6" fill="rgba(0,0,0,0.5)"/>
|
|
1275
|
+
<path d="M6 -4 L22 -4" stroke="${colors[i % colors.length]}" stroke-width="4"/>
|
|
1276
|
+
<circle cx="14" cy="-4" r="5" fill="${colors[i % colors.length]}"/>
|
|
1277
|
+
|
|
1278
|
+
<!-- 社区名称 -->
|
|
1279
|
+
<text x="35" y="0" fill="#fff" font-size="18" font-weight="bold" dominant-baseline="middle">
|
|
1280
|
+
${groupName}
|
|
1281
|
+
</text>
|
|
1282
|
+
|
|
1283
|
+
<!-- 人数显示 - 使用动态颜色 -->
|
|
1284
|
+
<g transform="translate(180, 0)">
|
|
1285
|
+
<rect x="-15" y="-15" width="70" height="30" rx="8" fill="rgba(0,0,0,0.5)" stroke="${playerColor}" stroke-width="1.5"/>
|
|
1286
|
+
<text x="20" y="0" fill="${playerColor}" font-size="18" font-weight="bold" text-anchor="middle" dominant-baseline="middle">
|
|
1287
|
+
${latestPlayers}
|
|
1288
|
+
</text>
|
|
1289
|
+
<text x="35" y="0" fill="#aaa" font-size="14" dominant-baseline="middle">人</text>
|
|
1290
|
+
</g>
|
|
1291
|
+
</g>
|
|
1292
|
+
`;
|
|
1293
|
+
}).join("");
|
|
1248
1294
|
return `
|
|
1249
1295
|
<svg viewBox="0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}">
|
|
1250
1296
|
<style>
|
|
1251
|
-
.title {
|
|
1252
|
-
|
|
1297
|
+
.title {
|
|
1298
|
+
font: bold 28px 'Microsoft YaHei', sans-serif;
|
|
1299
|
+
fill: #fff;
|
|
1300
|
+
text-anchor: middle;
|
|
1301
|
+
text-shadow: 0 0 8px rgba(255, 255, 255, 0.3);
|
|
1302
|
+
}
|
|
1303
|
+
.axis-label {
|
|
1304
|
+
font: 18px 'Microsoft YaHei', sans-serif;
|
|
1305
|
+
fill: #fff;
|
|
1306
|
+
}
|
|
1307
|
+
.latest-title {
|
|
1308
|
+
font: bold 22px 'Microsoft YaHei', sans-serif;
|
|
1309
|
+
fill: #FFD700;
|
|
1310
|
+
text-anchor: end;
|
|
1311
|
+
}
|
|
1253
1312
|
</style>
|
|
1254
1313
|
<g transform="translate(${margin.left}, ${margin.top})">
|
|
1255
|
-
|
|
1314
|
+
<!-- 主标题 -->
|
|
1315
|
+
<text x="${width / 2}" y="-15" class="title">
|
|
1316
|
+
CS2社区总人数统计(12小时)
|
|
1317
|
+
</text>
|
|
1256
1318
|
|
|
1257
|
-
<!--
|
|
1258
|
-
<
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
<stop offset="100%" stop-color="rgba(255,255,255,0)"/>
|
|
1262
|
-
</linearGradient>
|
|
1263
|
-
</defs>
|
|
1319
|
+
<!-- 右上角标题 -->
|
|
1320
|
+
<text x="${width - 10}" y="-15" class="latest-title" text-anchor="end">
|
|
1321
|
+
最新在线人数
|
|
1322
|
+
</text>
|
|
1264
1323
|
|
|
1324
|
+
<!-- 图表内容 -->
|
|
1265
1325
|
${xAxis}
|
|
1266
1326
|
${yAxis}
|
|
1267
1327
|
<rect width="${width}" height="${height}" fill="url(#grid-gradient)"/>
|
|
@@ -1270,10 +1330,14 @@ ${mapList}
|
|
|
1270
1330
|
([_, stats], i) => createPath(stats, colors[i % colors.length])
|
|
1271
1331
|
).join("")}
|
|
1272
1332
|
|
|
1273
|
-
|
|
1333
|
+
<!-- 图例 -->
|
|
1334
|
+
<g transform="translate(0, 0)">
|
|
1335
|
+
${legend}
|
|
1336
|
+
</g>
|
|
1274
1337
|
|
|
1275
|
-
|
|
1276
|
-
<text x="
|
|
1338
|
+
<!-- 坐标轴标签 -->
|
|
1339
|
+
<text x="${width / 2}" y="${height + 45}" class="axis-label" text-anchor="middle">时间</text>
|
|
1340
|
+
<text x="-70" y="${height / 2}" transform="rotate(-90)" class="axis-label" text-anchor="middle">玩家数量</text>
|
|
1277
1341
|
</g>
|
|
1278
1342
|
</svg>
|
|
1279
1343
|
`;
|
|
@@ -1305,6 +1369,199 @@ ${mapList}
|
|
|
1305
1369
|
</div>
|
|
1306
1370
|
</body>
|
|
1307
1371
|
</html>
|
|
1372
|
+
`;
|
|
1373
|
+
await page.setContent(html);
|
|
1374
|
+
await page.setViewport({ width: 1280, height: 720 });
|
|
1375
|
+
const screenshot = await page.screenshot({
|
|
1376
|
+
type: "png",
|
|
1377
|
+
fullPage: true,
|
|
1378
|
+
encoding: "binary"
|
|
1379
|
+
});
|
|
1380
|
+
await browser.close();
|
|
1381
|
+
return import_koishi.h.image(screenshot, "image/png");
|
|
1382
|
+
});
|
|
1383
|
+
ctx.command("ze统计", "生成并发送各社区ZE服务器总人数统计折线图").action(async ({ session }) => {
|
|
1384
|
+
const browser = await import_puppeteer.default.launch({ args: ["--no-sandbox", "--disable-setuid-sandbox"] });
|
|
1385
|
+
const page = await browser.newPage();
|
|
1386
|
+
const colors = ["#FF0000", "#00FF00", "#0000FF", "#FF00FF", "#00FFFF", "#FFFF00", "#FFA500", "#800080", "#008000", "#000080"];
|
|
1387
|
+
const margin = { top: 45, right: 30, bottom: 50, left: 50 };
|
|
1388
|
+
const width = 1200 - margin.left - margin.right;
|
|
1389
|
+
const height = 600 - margin.top - margin.bottom;
|
|
1390
|
+
const generateSVG = /* @__PURE__ */ __name((statsData) => {
|
|
1391
|
+
const communities = Object.entries(statsData);
|
|
1392
|
+
if (communities.length === 0) return "";
|
|
1393
|
+
const allPoints = communities.flatMap(([_, stats]) => stats);
|
|
1394
|
+
const minTime = Math.min(...allPoints.map((p) => p.time));
|
|
1395
|
+
const maxTime = Math.max(...allPoints.map((p) => p.time));
|
|
1396
|
+
const maxPlayers = Math.max(...allPoints.map((p) => p.players)) || 1;
|
|
1397
|
+
const xScale = /* @__PURE__ */ __name((time) => (time - minTime) / (maxTime - minTime) * width, "xScale");
|
|
1398
|
+
const yScale = /* @__PURE__ */ __name((players) => height - players / maxPlayers * height, "yScale");
|
|
1399
|
+
const createPath = /* @__PURE__ */ __name((points, color) => {
|
|
1400
|
+
if (points.length < 2) return "";
|
|
1401
|
+
const first = points[0];
|
|
1402
|
+
let path2 = `M ${xScale(first.time)} ${yScale(first.players)}`;
|
|
1403
|
+
for (let i = 1; i < points.length; i++) {
|
|
1404
|
+
const p = points[i];
|
|
1405
|
+
const prev = points[i - 1];
|
|
1406
|
+
const cp1x = (prev.time + p.time) / 2;
|
|
1407
|
+
const cp1y = prev.players;
|
|
1408
|
+
const cp2x = cp1x;
|
|
1409
|
+
const cp2y = p.players;
|
|
1410
|
+
path2 += ` C ${xScale(cp1x)} ${yScale(cp1y)}, ${xScale(cp2x)} ${yScale(cp2y)}, ${xScale(p.time)} ${yScale(p.players)}`;
|
|
1411
|
+
}
|
|
1412
|
+
return `
|
|
1413
|
+
<path d="${path2}" fill="none" stroke="${color}" stroke-width="3" stroke-linejoin="round" stroke-linecap="round"/>
|
|
1414
|
+
${points.map((p) => `
|
|
1415
|
+
<circle cx="${xScale(p.time)}" cy="${yScale(p.players)}" r="4" fill="${color}"/>
|
|
1416
|
+
<circle cx="${xScale(p.time)}" cy="${yScale(p.players)}" r="6" fill="${color}" fill-opacity="0.2"/>
|
|
1417
|
+
`).join("")}
|
|
1418
|
+
`;
|
|
1419
|
+
}, "createPath");
|
|
1420
|
+
const xAxis = `
|
|
1421
|
+
<path d="M0 ${height} H${width}" stroke="#fff" stroke-width="2"/>
|
|
1422
|
+
${Array.from({ length: 12 }).map((_, i) => {
|
|
1423
|
+
const x = width * i / 11;
|
|
1424
|
+
const date = new Date(minTime + (maxTime - minTime) * (i / 11));
|
|
1425
|
+
return `
|
|
1426
|
+
<g transform="translate(${x}, ${height})">
|
|
1427
|
+
<path d="M0 0 v5" stroke="#fff" stroke-width="1"/>
|
|
1428
|
+
<text x="0" y="25" fill="#fff" font-size="14" text-anchor="middle">
|
|
1429
|
+
${date.toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" })}
|
|
1430
|
+
</text>
|
|
1431
|
+
</g>
|
|
1432
|
+
`;
|
|
1433
|
+
}).join("")}
|
|
1434
|
+
`;
|
|
1435
|
+
const yAxis = `
|
|
1436
|
+
<path d="M0 0 V${height}" stroke="#fff" stroke-width="2"/>
|
|
1437
|
+
${Array.from({ length: 6 }).map((_, i) => {
|
|
1438
|
+
const y = height - height * i / 5;
|
|
1439
|
+
return `
|
|
1440
|
+
<g transform="translate(0, ${y})">
|
|
1441
|
+
<path d="M-5 0 h5" stroke="#fff" stroke-width="1"/>
|
|
1442
|
+
<text x="-15" y="5" fill="#fff" font-size="14" text-anchor="end">
|
|
1443
|
+
${Math.round(maxPlayers * i / 5)}
|
|
1444
|
+
</text>
|
|
1445
|
+
<path d="M0 0 H${width}" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>
|
|
1446
|
+
</g>
|
|
1447
|
+
`;
|
|
1448
|
+
}).join("")}
|
|
1449
|
+
`;
|
|
1450
|
+
const legend = communities.map(([communityName, dataPoints], i) => {
|
|
1451
|
+
const latest = dataPoints[dataPoints.length - 1];
|
|
1452
|
+
const latestPlayers = latest ? latest.players : 0;
|
|
1453
|
+
const playerRatio = latestPlayers / maxPlayers;
|
|
1454
|
+
const playerColor = playerRatio <= 0.5 ? "#33cc00" : playerRatio <= 0.8 ? "#ffcc00" : "#ff4444";
|
|
1455
|
+
return `
|
|
1456
|
+
<g transform="translate(${width - 250}, ${20 + i * 35})">
|
|
1457
|
+
<!-- 社区标识 -->
|
|
1458
|
+
<rect x="0" y="-14" width="28" height="28" rx="6" fill="rgba(0,0,0,0.5)"/>
|
|
1459
|
+
<path d="M6 -4 L22 -4" stroke="${colors[i % colors.length]}" stroke-width="4"/>
|
|
1460
|
+
<circle cx="14" cy="-4" r="5" fill="${colors[i % colors.length]}"/>
|
|
1461
|
+
|
|
1462
|
+
<!-- 社区名称 -->
|
|
1463
|
+
<text x="35" y="0" fill="#fff" font-size="18" font-weight="bold" dominant-baseline="middle">
|
|
1464
|
+
${communityName}
|
|
1465
|
+
</text>
|
|
1466
|
+
|
|
1467
|
+
<!-- 人数显示 -->
|
|
1468
|
+
<g transform="translate(180, 0)">
|
|
1469
|
+
<rect x="-15" y="-15" width="70" height="30" rx="8" fill="rgba(0,0,0,0.5)" stroke="${playerColor}" stroke-width="1.5"/>
|
|
1470
|
+
<text x="20" y="0" fill="${playerColor}" font-size="18" font-weight="bold" text-anchor="middle" dominant-baseline="middle">
|
|
1471
|
+
${latestPlayers}
|
|
1472
|
+
</text>
|
|
1473
|
+
<text x="35" y="0" fill="#aaa" font-size="14" dominant-baseline="middle">人</text>
|
|
1474
|
+
</g>
|
|
1475
|
+
</g>
|
|
1476
|
+
`;
|
|
1477
|
+
}).join("");
|
|
1478
|
+
return `
|
|
1479
|
+
<svg viewBox="0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}">
|
|
1480
|
+
<style>
|
|
1481
|
+
.title {
|
|
1482
|
+
font: bold 28px 'Microsoft YaHei', sans-serif;
|
|
1483
|
+
fill: #fff;
|
|
1484
|
+
text-anchor: middle;
|
|
1485
|
+
text-shadow: 0 0 8px rgba(255, 255, 255, 0.3);
|
|
1486
|
+
}
|
|
1487
|
+
.axis-label {
|
|
1488
|
+
font: 18px 'Microsoft YaHei', sans-serif;
|
|
1489
|
+
fill: #fff;
|
|
1490
|
+
}
|
|
1491
|
+
.latest-title {
|
|
1492
|
+
font: bold 22px 'Microsoft YaHei', sans-serif;
|
|
1493
|
+
fill: #FFD700;
|
|
1494
|
+
text-anchor: end;
|
|
1495
|
+
}
|
|
1496
|
+
</style>
|
|
1497
|
+
<g transform="translate(${margin.left}, ${margin.top})">
|
|
1498
|
+
<!-- 主标题 -->
|
|
1499
|
+
<text x="${width / 2}" y="-15" class="title">
|
|
1500
|
+
ZE服务器总人数统计(12小时)
|
|
1501
|
+
</text>
|
|
1502
|
+
|
|
1503
|
+
<!-- 右上角标题 -->
|
|
1504
|
+
<text x="${width - 10}" y="-15" class="latest-title" text-anchor="end">
|
|
1505
|
+
最新在线人数
|
|
1506
|
+
</text>
|
|
1507
|
+
|
|
1508
|
+
<!-- 图表内容 -->
|
|
1509
|
+
${xAxis}
|
|
1510
|
+
${yAxis}
|
|
1511
|
+
|
|
1512
|
+
${communities.map(
|
|
1513
|
+
([_, stats], i) => createPath(stats, colors[i % colors.length])
|
|
1514
|
+
).join("")}
|
|
1515
|
+
|
|
1516
|
+
<!-- 图例 -->
|
|
1517
|
+
<g transform="translate(0, 0)">
|
|
1518
|
+
${legend}
|
|
1519
|
+
</g>
|
|
1520
|
+
|
|
1521
|
+
<!-- 坐标轴标签 -->
|
|
1522
|
+
<text x="${width / 2}" y="${height + 45}" class="axis-label" text-anchor="middle">时间</text>
|
|
1523
|
+
<text x="-70" y="${height / 2}" transform="rotate(-90)" class="axis-label" text-anchor="middle">玩家数量</text>
|
|
1524
|
+
</g>
|
|
1525
|
+
</svg>
|
|
1526
|
+
`;
|
|
1527
|
+
}, "generateSVG");
|
|
1528
|
+
if (Object.keys(zeStats).length === 0) {
|
|
1529
|
+
await browser.close();
|
|
1530
|
+
return "暂无ZE服务器统计数据,请等待数据收集(每10分钟更新一次)。";
|
|
1531
|
+
}
|
|
1532
|
+
const html = `
|
|
1533
|
+
<!DOCTYPE html>
|
|
1534
|
+
<html>
|
|
1535
|
+
<head>
|
|
1536
|
+
<style>
|
|
1537
|
+
body {
|
|
1538
|
+
margin: 0;
|
|
1539
|
+
padding: 40px;
|
|
1540
|
+
background: url('${config.statsBackgroundImage}') no-repeat center center/cover;
|
|
1541
|
+
color: white;
|
|
1542
|
+
font-family: 'Arial', sans-serif;
|
|
1543
|
+
}
|
|
1544
|
+
.chart-container {
|
|
1545
|
+
background: rgba(0, 0, 0, 0.8);
|
|
1546
|
+
border-radius: 20px;
|
|
1547
|
+
padding: 30px;
|
|
1548
|
+
box-shadow: 0 0 30px rgba(0,0,0,0.5);
|
|
1549
|
+
backdrop-filter: blur(5px);
|
|
1550
|
+
}
|
|
1551
|
+
.no-data {
|
|
1552
|
+
text-align: center;
|
|
1553
|
+
font-size: 24px;
|
|
1554
|
+
color: #fff;
|
|
1555
|
+
padding: 100px 0;
|
|
1556
|
+
}
|
|
1557
|
+
</style>
|
|
1558
|
+
</head>
|
|
1559
|
+
<body>
|
|
1560
|
+
<div class="chart-container">
|
|
1561
|
+
${Object.keys(zeStats).length > 0 ? generateSVG(zeStats) : '<div class="no-data">暂无ZE服务器统计数据</div>'}
|
|
1562
|
+
</div>
|
|
1563
|
+
</body>
|
|
1564
|
+
</html>
|
|
1308
1565
|
`;
|
|
1309
1566
|
await page.setContent(html);
|
|
1310
1567
|
await page.setViewport({ width: 1280, height: 720 });
|