koishi-plugin-minecraft-search 0.1.2 → 1.0.1
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.d.ts +8 -0
- package/lib/index.js +168 -24
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface Config {
|
|
|
10
10
|
servers: ServerConfig[];
|
|
11
11
|
querySettings: QuerySettings;
|
|
12
12
|
minekuaiSettings: MinekuaiSettings;
|
|
13
|
+
apiSettings: ApiSettings;
|
|
13
14
|
}
|
|
14
15
|
export interface QuerySettings {
|
|
15
16
|
defaultTimeout: number;
|
|
@@ -24,5 +25,12 @@ export interface MinekuaiSettings {
|
|
|
24
25
|
apiUrl: string;
|
|
25
26
|
apiKey: string;
|
|
26
27
|
}
|
|
28
|
+
export interface ApiSettings {
|
|
29
|
+
apiProvider: 'mcstatus' | 'lazy';
|
|
30
|
+
lazyApiUrl: string;
|
|
31
|
+
useBackup: boolean;
|
|
32
|
+
returnType: 'json' | 'image' | 'html';
|
|
33
|
+
autoDetectBedrock: boolean;
|
|
34
|
+
}
|
|
27
35
|
export declare const Config: Schema<Config>;
|
|
28
36
|
export declare function apply(ctx: Context, config: Config): void;
|
package/lib/index.js
CHANGED
|
@@ -28,6 +28,23 @@ module.exports = __toCommonJS(src_exports);
|
|
|
28
28
|
var import_koishi = require("koishi");
|
|
29
29
|
var name = "minecraft-status";
|
|
30
30
|
var Config = import_koishi.Schema.intersect([
|
|
31
|
+
// 新增:API配置分类
|
|
32
|
+
import_koishi.Schema.object({
|
|
33
|
+
apiSettings: import_koishi.Schema.object({
|
|
34
|
+
apiProvider: import_koishi.Schema.union([
|
|
35
|
+
import_koishi.Schema.const("mcstatus").description("mcstatus.io API (默认)"),
|
|
36
|
+
import_koishi.Schema.const("lazy").description("Lazy Minecraft API")
|
|
37
|
+
]).description("API提供商选择").default("mcstatus"),
|
|
38
|
+
lazyApiUrl: import_koishi.Schema.string().description("Lazy API地址").default("https://api.imlazy.ink/mcapi"),
|
|
39
|
+
useBackup: import_koishi.Schema.boolean().description("使用备用API地址").default(false),
|
|
40
|
+
returnType: import_koishi.Schema.union([
|
|
41
|
+
import_koishi.Schema.const("json").description("JSON格式"),
|
|
42
|
+
import_koishi.Schema.const("image").description("图片格式"),
|
|
43
|
+
import_koishi.Schema.const("html").description("网页格式")
|
|
44
|
+
]).description("返回类型 (仅Lazy API)").default("json"),
|
|
45
|
+
autoDetectBedrock: import_koishi.Schema.boolean().description("自动检测基岩版服务器").default(true)
|
|
46
|
+
})
|
|
47
|
+
}).description("API设置"),
|
|
31
48
|
import_koishi.Schema.object({
|
|
32
49
|
servers: import_koishi.Schema.array(import_koishi.Schema.object({
|
|
33
50
|
id: import_koishi.Schema.number().required().description("服务器ID (数字)"),
|
|
@@ -131,7 +148,25 @@ function apply(ctx, config) {
|
|
|
131
148
|
return `❌ 重启服务器 ${server.name} 失败: ${error.message}`;
|
|
132
149
|
}
|
|
133
150
|
});
|
|
134
|
-
ctx.command("mcstatus [server]", "查询 Minecraft 服务器状态").alias("服务器状态", "查服").option("list", "-l 查看服务器列表").option("info", "-i <id> 查看服务器详细信息", { type: "number" }).option("timeout", "-t <seconds> 设置超时时间", { type: "number" }).option("force", "-f 强制刷新缓存").action(async ({ session, options }, server) => {
|
|
151
|
+
ctx.command("mcstatus [server]", "查询 Minecraft 服务器状态").alias("服务器状态", "查服").option("list", "-l 查看服务器列表").option("info", "-i <id> 查看服务器详细信息", { type: "number" }).option("timeout", "-t <seconds> 设置超时时间", { type: "number" }).option("force", "-f 强制刷新缓存").option("api", "-a <provider> 临时切换API提供商", { type: "string" }).action(async ({ session, options }, server) => {
|
|
152
|
+
if (options.api) {
|
|
153
|
+
const tempProvider = options.api.toLowerCase();
|
|
154
|
+
if (["mcstatus", "lazy"].includes(tempProvider)) {
|
|
155
|
+
const originalProvider = config.apiSettings.apiProvider;
|
|
156
|
+
config.apiSettings.apiProvider = tempProvider;
|
|
157
|
+
try {
|
|
158
|
+
const result = await handleMcStatusCommand(server, options);
|
|
159
|
+
return result;
|
|
160
|
+
} finally {
|
|
161
|
+
config.apiSettings.apiProvider = originalProvider;
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
return "❌ 无效的API提供商,可选: mcstatus, lazy";
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return await handleMcStatusCommand(server, options);
|
|
168
|
+
});
|
|
169
|
+
async function handleMcStatusCommand(server, options) {
|
|
135
170
|
if (options.list) {
|
|
136
171
|
return getServerList(config.servers);
|
|
137
172
|
}
|
|
@@ -150,7 +185,8 @@ function apply(ctx, config) {
|
|
|
150
185
|
return getServerInfo(serverConfig, config, options.force, options.timeout || config.querySettings.defaultTimeout);
|
|
151
186
|
}
|
|
152
187
|
return getDirectServerStatus(server, config, options.force, options.timeout || config.querySettings.defaultTimeout);
|
|
153
|
-
}
|
|
188
|
+
}
|
|
189
|
+
__name(handleMcStatusCommand, "handleMcStatusCommand");
|
|
154
190
|
function getServerList(servers) {
|
|
155
191
|
if (servers.length === 0) {
|
|
156
192
|
return "暂无服务器配置,请在插件配置中添加服务器。";
|
|
@@ -231,12 +267,18 @@ function apply(ctx, config) {
|
|
|
231
267
|
iconElement ? (0, import_koishi.h)("span", [iconElement, " "]) : "",
|
|
232
268
|
`🟢 ${server.name}`
|
|
233
269
|
]),
|
|
234
|
-
(0, import_koishi.h)("p", `📍 地址: ${server.host}`)
|
|
235
|
-
|
|
270
|
+
(0, import_koishi.h)("p", `📍 地址: ${server.host}`)
|
|
271
|
+
);
|
|
272
|
+
let versionDisplay = `🎮 版本: ${status.version.name_clean}`;
|
|
273
|
+
if (status.version.protocol && status.version.protocol !== 0) {
|
|
274
|
+
versionDisplay += ` (协议: ${status.version.protocol})`;
|
|
275
|
+
}
|
|
276
|
+
message.children.push((0, import_koishi.h)("p", versionDisplay));
|
|
277
|
+
message.children.push(
|
|
236
278
|
(0, import_koishi.h)("p", `📅 状态获取时间: ${new Date(status.retrieved_at).toLocaleString("zh-CN")}`)
|
|
237
279
|
);
|
|
238
280
|
if (status.motd) {
|
|
239
|
-
|
|
281
|
+
let cleanMotd = status.motd.clean.replace(/\n/g, " ").replace(/\s+/g, " ").trim().replace(/§./g, "");
|
|
240
282
|
if (cleanMotd) {
|
|
241
283
|
message.children.push(
|
|
242
284
|
(0, import_koishi.h)("p", "📋 MOTD: " + cleanMotd.substring(0, 100) + (cleanMotd.length > 100 ? "..." : ""))
|
|
@@ -254,11 +296,6 @@ function apply(ctx, config) {
|
|
|
254
296
|
);
|
|
255
297
|
}
|
|
256
298
|
}
|
|
257
|
-
if (status.software) {
|
|
258
|
-
message.children.push(
|
|
259
|
-
(0, import_koishi.h)("p", `💻 核心: ${status.software}`)
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
299
|
if (config2.querySettings.showPlugins && status.plugins && status.plugins.length > 0) {
|
|
263
300
|
const pluginCount = status.plugins.length;
|
|
264
301
|
const pluginList = status.plugins.slice(0, 5).map((p) => p.version ? `${p.name} v${p.version}` : p.name).join(", ");
|
|
@@ -273,11 +310,6 @@ function apply(ctx, config) {
|
|
|
273
310
|
(0, import_koishi.h)("p", `⚙️ 模组 (${modCount}个): ${modList}`)
|
|
274
311
|
);
|
|
275
312
|
}
|
|
276
|
-
if (status.srv_record) {
|
|
277
|
-
message.children.push(
|
|
278
|
-
(0, import_koishi.h)("p", `🔗 SRV记录: ${status.srv_record.host}:${status.srv_record.port}`)
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
313
|
if (status.expires_at) {
|
|
282
314
|
const cacheTime = Math.max(0, Math.floor((status.expires_at - Date.now()) / 1e3));
|
|
283
315
|
message.children.push(
|
|
@@ -322,31 +354,143 @@ function apply(ctx, config) {
|
|
|
322
354
|
if (!address || address.trim() === "") {
|
|
323
355
|
throw new Error("服务器地址不能为空");
|
|
324
356
|
}
|
|
325
|
-
const cacheKey = `mcstatus:${address}:${enableQuery}`;
|
|
357
|
+
const cacheKey = `mcstatus:${address}:${enableQuery}:${config.apiSettings.apiProvider}`;
|
|
326
358
|
if (!force) {
|
|
327
359
|
const cached = cache.get(cacheKey);
|
|
328
360
|
if (cached && Date.now() - cached.timestamp < config.querySettings.cacheTime * 1e3) {
|
|
329
361
|
return cached.data;
|
|
330
362
|
}
|
|
331
363
|
}
|
|
332
|
-
|
|
333
|
-
const
|
|
334
|
-
query: enableQuery.toString(),
|
|
335
|
-
timeout: timeout.toString()
|
|
336
|
-
};
|
|
364
|
+
let response;
|
|
365
|
+
const { apiProvider } = config.apiSettings;
|
|
337
366
|
try {
|
|
338
|
-
|
|
367
|
+
if (apiProvider === "lazy") {
|
|
368
|
+
response = await queryWithLazyApi(address, timeout);
|
|
369
|
+
} else {
|
|
370
|
+
const url = `https://api.mcstatus.io/v2/status/java/${encodeURIComponent(address)}`;
|
|
371
|
+
const params = {
|
|
372
|
+
query: enableQuery.toString()
|
|
373
|
+
};
|
|
374
|
+
response = await ctx.http.get(url, {
|
|
375
|
+
params,
|
|
376
|
+
timeout: timeout * 1e3 + 5e3
|
|
377
|
+
});
|
|
378
|
+
}
|
|
339
379
|
cache.set(cacheKey, {
|
|
340
380
|
data: response,
|
|
341
381
|
timestamp: Date.now()
|
|
342
382
|
});
|
|
383
|
+
ctx.logger.debug(`${apiProvider.toUpperCase()} API查询成功: ${address}`);
|
|
343
384
|
return response;
|
|
344
385
|
} catch (error) {
|
|
345
|
-
ctx.logger.error(
|
|
346
|
-
throw new Error(`查询服务器状态失败: ${address}`);
|
|
386
|
+
ctx.logger.error(`${apiProvider.toUpperCase()} API查询失败: ${address}`, error);
|
|
387
|
+
throw new Error(`查询服务器状态失败: ${address} (${error.message})`);
|
|
347
388
|
}
|
|
348
389
|
}
|
|
349
390
|
__name(getServerStatus, "getServerStatus");
|
|
391
|
+
async function queryWithLazyApi(host, timeout) {
|
|
392
|
+
const { lazyApiUrl, useBackup, returnType, autoDetectBedrock } = config.apiSettings;
|
|
393
|
+
const baseUrl = useBackup ? "https://api.lazy.ink/mcapi" : lazyApiUrl;
|
|
394
|
+
const params = new URLSearchParams({
|
|
395
|
+
type: returnType,
|
|
396
|
+
host
|
|
397
|
+
});
|
|
398
|
+
if (autoDetectBedrock) {
|
|
399
|
+
params.append("be", "false");
|
|
400
|
+
}
|
|
401
|
+
const url = `${baseUrl}?${params.toString()}`;
|
|
402
|
+
try {
|
|
403
|
+
const response = await ctx.http.get(url, { timeout: timeout * 1e3 });
|
|
404
|
+
return transformLazyResponse(response, host);
|
|
405
|
+
} catch (error) {
|
|
406
|
+
ctx.logger.error("Lazy API查询失败:", error);
|
|
407
|
+
throw new Error(`Lazy API查询失败: ${error.message}`);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
__name(queryWithLazyApi, "queryWithLazyApi");
|
|
411
|
+
function transformLazyResponse(lazyData, host) {
|
|
412
|
+
let cleanMotd = "";
|
|
413
|
+
if (lazyData.motd && lazyData.motd.extra) {
|
|
414
|
+
cleanMotd = lazyData.motd.extra.map((item) => item.text).join("");
|
|
415
|
+
cleanMotd = cleanMotd.replace(/§./g, "");
|
|
416
|
+
}
|
|
417
|
+
let versionName = lazyData.version || "Unknown";
|
|
418
|
+
if (versionName === "Unknown" || !versionName) {
|
|
419
|
+
versionName = "未知";
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
online: lazyData.status === "在线",
|
|
423
|
+
host: lazyData.host || host,
|
|
424
|
+
version: {
|
|
425
|
+
name_clean: versionName,
|
|
426
|
+
protocol: lazyData.protocol || 0
|
|
427
|
+
},
|
|
428
|
+
players: {
|
|
429
|
+
online: lazyData.players_online || 0,
|
|
430
|
+
max: lazyData.players_max || 0,
|
|
431
|
+
list: (lazyData.players || []).map((p) => ({
|
|
432
|
+
name_clean: p.name
|
|
433
|
+
}))
|
|
434
|
+
},
|
|
435
|
+
motd: {
|
|
436
|
+
clean: cleanMotd || lazyData.motd?.text || "A Minecraft Server"
|
|
437
|
+
},
|
|
438
|
+
icon: lazyData.favicon || null,
|
|
439
|
+
software: lazyData.software || "",
|
|
440
|
+
plugins: lazyData.plugins || [],
|
|
441
|
+
mods: lazyData.mods || [],
|
|
442
|
+
retrieved_at: Date.now(),
|
|
443
|
+
expires_at: Date.now() + config.querySettings.cacheTime * 1e3
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
__name(transformLazyResponse, "transformLazyResponse");
|
|
447
|
+
ctx.command("mcstatus.api", "检查API状态").option("switch", "-s <provider> 切换API提供商", { type: "string" }).option("test", "-t 测试所有API").action(async ({ session, options }) => {
|
|
448
|
+
if (options.switch) {
|
|
449
|
+
if (["mcstatus", "lazy"].includes(options.switch.toLowerCase())) {
|
|
450
|
+
config.apiSettings.apiProvider = options.switch.toLowerCase();
|
|
451
|
+
return `✅ 已切换API提供商为: ${options.switch.toUpperCase()}`;
|
|
452
|
+
} else {
|
|
453
|
+
return "❌ 无效的API提供商,可选: mcstatus, lazy";
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
if (options.test) {
|
|
457
|
+
const testServers = [
|
|
458
|
+
{ name: "Hypixel", host: "mc.hypixel.net" },
|
|
459
|
+
{ name: "演示服务器", host: "demo.mcstatus.io" }
|
|
460
|
+
];
|
|
461
|
+
const results = [];
|
|
462
|
+
for (const server of testServers) {
|
|
463
|
+
try {
|
|
464
|
+
const startTime = Date.now();
|
|
465
|
+
await getServerStatus(server.host, 5, false, true);
|
|
466
|
+
const responseTime = Date.now() - startTime;
|
|
467
|
+
results.push(`🟢 ${server.name}: ${responseTime}ms`);
|
|
468
|
+
} catch (error) {
|
|
469
|
+
results.push(`🔴 ${server.name}: 失败`);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return (0, import_koishi.h)("message", [
|
|
473
|
+
(0, import_koishi.h)("p", `当前API提供商: ${config.apiSettings.apiProvider.toUpperCase()}`),
|
|
474
|
+
(0, import_koishi.h)("p", "API测试结果:"),
|
|
475
|
+
...results.map((r) => (0, import_koishi.h)("p", r)),
|
|
476
|
+
(0, import_koishi.h)(
|
|
477
|
+
"p",
|
|
478
|
+
{ style: { fontSize: "12px", color: "#888" } },
|
|
479
|
+
'使用 "mcstatus.api -s <provider>" 切换API'
|
|
480
|
+
)
|
|
481
|
+
]);
|
|
482
|
+
}
|
|
483
|
+
return (0, import_koishi.h)("message", [
|
|
484
|
+
(0, import_koishi.h)("p", `当前API提供商: ${config.apiSettings.apiProvider.toUpperCase()}`),
|
|
485
|
+
(0, import_koishi.h)("p", `Lazy API地址: ${config.apiSettings.useBackup ? "备用地址" : config.apiSettings.lazyApiUrl}`),
|
|
486
|
+
(0, import_koishi.h)("p", `返回类型: ${config.apiSettings.returnType.toUpperCase()}`),
|
|
487
|
+
(0, import_koishi.h)(
|
|
488
|
+
"p",
|
|
489
|
+
{ style: { fontSize: "12px", color: "#888" } },
|
|
490
|
+
'使用 "mcstatus.api -t" 测试API或 "mcstatus.api -s <provider>" 切换'
|
|
491
|
+
)
|
|
492
|
+
]);
|
|
493
|
+
});
|
|
350
494
|
setInterval(() => {
|
|
351
495
|
const now = Date.now();
|
|
352
496
|
for (const [key, value] of cache.entries()) {
|