koishi-plugin-minecraft-search 1.3.9 → 2.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/index.d.ts CHANGED
@@ -2,20 +2,33 @@ import { Context, Schema } from 'koishi';
2
2
  export declare const name = "minecraft-search";
3
3
  export interface ServerConfig {
4
4
  id: number;
5
+ userId: string;
6
+ groupId: string;
5
7
  name: string;
6
8
  host: string;
9
+ port: number;
10
+ serverType: 'java' | 'bedrock';
11
+ timeout: number;
7
12
  minekuaiInstanceId?: string;
8
- timeout?: number;
9
- serverType?: 'java' | 'bedrock';
13
+ }
14
+ export interface ApiKeyConfig {
15
+ id: number;
16
+ userId: string;
17
+ groupId: string;
18
+ apiKey: string;
10
19
  }
11
20
  export interface Config {
12
- servers: ServerConfig[];
13
- minekuaiSettings: MinekuaiSettings;
21
+ minekuaiApiUrl: string;
14
22
  showIpInDetail: boolean;
15
23
  }
16
- export interface MinekuaiSettings {
17
- apiUrl: string;
18
- apiKey: string;
19
- }
20
24
  export declare const Config: Schema<Config>;
25
+ export declare const inject: {
26
+ required: string[];
27
+ };
28
+ declare module 'koishi' {
29
+ interface Tables {
30
+ minecraft_server: ServerConfig;
31
+ minecraft_api_key: ApiKeyConfig;
32
+ }
33
+ }
21
34
  export declare function apply(ctx: Context, config: Config): void;
package/lib/index.js CHANGED
@@ -32,6 +32,7 @@ var src_exports = {};
32
32
  __export(src_exports, {
33
33
  Config: () => Config,
34
34
  apply: () => apply,
35
+ inject: () => inject,
35
36
  name: () => name
36
37
  });
37
38
  module.exports = __toCommonJS(src_exports);
@@ -43,26 +44,39 @@ import("mc-server-util").then((m) => {
43
44
  var name = "minecraft-search";
44
45
  var Config = import_koishi.Schema.intersect([
45
46
  import_koishi.Schema.object({
46
- servers: import_koishi.Schema.array(import_koishi.Schema.object({
47
- id: import_koishi.Schema.number().required().description("服务器ID"),
48
- name: import_koishi.Schema.string().required().description("服务器名称"),
49
- host: import_koishi.Schema.string().required().description("服务器地址"),
50
- serverType: import_koishi.Schema.union(["java", "bedrock"]).default("java").description("服务器类型"),
51
- timeout: import_koishi.Schema.number().default(5).description("查询超时时间(秒)"),
52
- minekuaiInstanceId: import_koishi.Schema.string().description("麦块实例ID (可选)")
53
- })).description("服务器列表").role("table").required()
54
- }).description("服务器配置"),
55
- import_koishi.Schema.object({
56
- minekuaiSettings: import_koishi.Schema.object({
57
- apiUrl: import_koishi.Schema.string().description("麦块API地址").default("https://minekuai.com/api/client"),
58
- apiKey: import_koishi.Schema.string().description("麦块API密钥")
59
- })
60
- }).description("麦块联机配置(可选)"),
47
+ minekuaiApiUrl: import_koishi.Schema.string().description("麦块API地址").default("https://minekuai.com/api/client")
48
+ }).description("麦块联机配置"),
61
49
  import_koishi.Schema.object({
62
50
  showIpInDetail: import_koishi.Schema.boolean().default(true).description("在查询详细状态时显示服务器IP地址")
63
51
  }).description("显示配置")
64
52
  ]);
53
+ var inject = {
54
+ required: ["database"]
55
+ };
65
56
  function apply(ctx, config) {
57
+ ctx.model.extend("minecraft_server", {
58
+ id: "unsigned",
59
+ userId: "string",
60
+ groupId: "string",
61
+ name: "string",
62
+ host: "string",
63
+ port: "integer",
64
+ serverType: "string",
65
+ timeout: "float",
66
+ minekuaiInstanceId: "string"
67
+ }, {
68
+ autoInc: true,
69
+ primary: "id"
70
+ });
71
+ ctx.model.extend("minecraft_api_key", {
72
+ id: "unsigned",
73
+ userId: "string",
74
+ groupId: "string",
75
+ apiKey: "string"
76
+ }, {
77
+ autoInc: true,
78
+ primary: "id"
79
+ });
66
80
  function parseServerAddress(hostString, defaultPort) {
67
81
  if (hostString.includes(":")) {
68
82
  const [host, portStr] = hostString.split(":");
@@ -78,14 +92,16 @@ function apply(ctx, config) {
78
92
  };
79
93
  }
80
94
  __name(parseServerAddress, "parseServerAddress");
81
- async function minekuaiApiRequest(instanceId, operation, maxRetries = 3) {
82
- const { apiUrl, apiKey } = config.minekuaiSettings;
83
- if (!apiKey) throw new Error("麦块API密钥未配置");
84
- if (!apiUrl) throw new Error("麦块API地址未配置");
85
- const baseUrl = apiUrl.replace(/\/+$/, "");
95
+ async function minekuaiApiRequest(instanceId, operation, groupId, maxRetries = 3) {
96
+ const apiKeys = await ctx.database.get("minecraft_api_key", { groupId });
97
+ if (!apiKeys || apiKeys.length === 0) {
98
+ throw new Error("本群未配置麦块API密钥,请先使用 绑定密钥 指令");
99
+ }
100
+ const apiKeyRecord = apiKeys[0];
101
+ const baseUrl = config.minekuaiApiUrl.replace(/\/+$/, "");
86
102
  const url = `${baseUrl}/servers/${instanceId}/power`;
87
103
  const headers = {
88
- "Authorization": `Bearer ${apiKey}`,
104
+ "Authorization": `Bearer ${apiKeyRecord.apiKey}`,
89
105
  "Content-Type": "application/json",
90
106
  "Accept": "application/json"
91
107
  };
@@ -112,8 +128,7 @@ function apply(ctx, config) {
112
128
  if (!getMinecraftServerStatus) {
113
129
  throw new Error("mc-server-util 模块未正确加载");
114
130
  }
115
- const defaultPort = server.serverType === "bedrock" ? 19132 : 25565;
116
- const { host, port } = parseServerAddress(server.host, defaultPort);
131
+ const { host, port } = parseServerAddress(server.host, server.port || 25565);
117
132
  const timeout = (server.timeout || 5) * 1e3;
118
133
  let result;
119
134
  if (server.serverType === "bedrock") {
@@ -145,21 +160,27 @@ function apply(ctx, config) {
145
160
  }
146
161
  }
147
162
  __name(queryServerStatus, "queryServerStatus");
163
+ function getServerName(server) {
164
+ return server.name || "Minecraft 服务器";
165
+ }
166
+ __name(getServerName, "getServerName");
148
167
  function formatShortStatus(result, server) {
168
+ const displayName = getServerName(server);
149
169
  if (!result.online) {
150
- return `🔴 ${server.name} - 离线`;
170
+ return `🔴 ${displayName} - 离线`;
151
171
  }
152
172
  const players = result.players ? `${result.players.online}/${result.players.max}` : "N/A";
153
173
  const version = result.version ? result.version.name : "N/A";
154
- return `🟢 ${server.name} - 在线 | 玩家: ${players} | 版本: ${version}`;
174
+ return `🟢 ${displayName} - 在线 | 玩家: ${players} | 版本: ${version}`;
155
175
  }
156
176
  __name(formatShortStatus, "formatShortStatus");
157
177
  function formatDetailedStatus(result, server, showIp) {
178
+ const displayName = getServerName(server);
158
179
  if (!result.online) {
159
180
  if (showIp) {
160
- return `🔴 服务器 ${server.name} (${server.host}) 当前离线`;
181
+ return `🔴 ${displayName} (${server.host}) 当前离线`;
161
182
  } else {
162
- return `🔴 服务器 ${server.name} 当前离线`;
183
+ return `🔴 ${displayName} 当前离线`;
163
184
  }
164
185
  }
165
186
  let motdText = "暂无描述";
@@ -179,11 +200,10 @@ function apply(ctx, config) {
179
200
  descriptionStr = descriptionStr.replace(/§[0-9a-fk-or]/gi, "");
180
201
  motdText = descriptionStr.replace(/\n/g, " ").replace(/\s+/g, " ").trim();
181
202
  }
182
- let message = `🟢 ${server.name} 状态信息
203
+ let message = `🟢 ${displayName} 状态信息
183
204
  `;
184
205
  if (showIp) {
185
- const defaultPort = server.serverType === "bedrock" ? 19132 : 25565;
186
- const { host, port } = parseServerAddress(server.host, defaultPort);
206
+ const { host, port } = parseServerAddress(server.host, server.port || 25565);
187
207
  message += `📡 地址: ${host}:${port}
188
208
  `;
189
209
  }
@@ -208,12 +228,13 @@ function apply(ctx, config) {
208
228
  return message;
209
229
  }
210
230
  __name(formatDetailedStatus, "formatDetailedStatus");
211
- ctx.command("mc/查服 [id:number]", "查询Minecraft服务器状态").action(async ({ session }, id) => {
212
- if (id === void 0) {
213
- if (config.servers.length === 0) {
214
- return "❌ 未配置任何服务器";
231
+ ctx.command("mc/查服 [target:text]", "查询Minecraft服务器状态").action(async ({ session }, target) => {
232
+ const servers = await ctx.database.get("minecraft_server", {});
233
+ if (target === void 0) {
234
+ if (servers.length === 0) {
235
+ return "❌ 本群未绑定任何服务器,请先使用 绑定 指令";
215
236
  }
216
- const queries = config.servers.map((server2) => queryServerStatus(server2));
237
+ const queries = servers.map((server) => queryServerStatus(server));
217
238
  const results = await Promise.all(queries);
218
239
  const onlineCount = results.filter((r) => r.success && r.data && r.data.online).length;
219
240
  let message = `📊 服务器状态汇总 (当前在线${onlineCount}/${results.length}台)
@@ -226,77 +247,203 @@ function apply(ctx, config) {
226
247
  message += `[ID:${serverId}] ${originalStatus}
227
248
  `;
228
249
  } else {
229
- message += `[ID:${serverId}] 🔴 ${result2.server.name} - 离线 | 原因:${result2.error}
250
+ message += `[ID:${serverId}] 🔴 ${getServerName(result2.server)} - 离线 | 原因:${result2.error}
230
251
  `;
231
252
  }
232
253
  });
233
254
  message += `
234
- 💡 输入"查服+服务器ID"即可查询详细状态,例如:查服 ${config.servers[0]?.id || 1}`;
255
+ 💡 输入"查服+服务器ID"即可查询详细状态,例如:查服 ${servers[0]?.id || 1}`;
256
+ message += `
257
+ 💡 也可以直接输入IP地址查询`;
235
258
  return message;
236
259
  }
237
- const server = config.servers.find((s) => s.id === id);
260
+ const id = parseInt(target);
261
+ if (!isNaN(id)) {
262
+ const server = servers.find((s) => s.id === id);
263
+ if (server) {
264
+ const result2 = await queryServerStatus(server);
265
+ if (!result2.success) {
266
+ return `🔴 ${getServerName(server)} - 离线 | 原因:${result2.error}`;
267
+ }
268
+ return formatDetailedStatus(result2.data, server, config.showIpInDetail);
269
+ }
270
+ }
271
+ const host = String(target);
272
+ const defaultPort = 25565;
273
+ const { host: parsedHost, port: parsedPort } = parseServerAddress(host, defaultPort);
274
+ const tempServer = {
275
+ id: 0,
276
+ userId: session.userId,
277
+ groupId: session.guildId || "",
278
+ name: parsedHost,
279
+ host: parsedHost,
280
+ port: parsedPort,
281
+ serverType: "java",
282
+ timeout: 5
283
+ };
284
+ const result = await queryServerStatus(tempServer);
285
+ if (!result.success) {
286
+ return `🔴 服务器 ${parsedHost}:${parsedPort} - 离线 | 原因:${result.error}`;
287
+ }
288
+ return formatDetailedStatus(result.data, tempServer, config.showIpInDetail);
289
+ });
290
+ ctx.guild().command("mc/绑定 <host:string>", "绑定Minecraft服务器").option("name", "-n <name:string>", { fallback: "" }).option("timeout", "-t <timeout:number>", { fallback: 5 }).action(async ({ session, options }, host) => {
291
+ if (!host) {
292
+ return "请提供服务器地址,例如:绑定+IP地址(不带端口时默认为25565)";
293
+ }
294
+ const groupId = session.guildId;
295
+ const userId = session.userId;
296
+ const defaultPort = 25565;
297
+ const { host: parsedHost, port: parsedPort } = parseServerAddress(host, defaultPort);
298
+ const existingServers = await ctx.database.get("minecraft_server", {
299
+ groupId,
300
+ host: parsedHost,
301
+ port: parsedPort
302
+ });
303
+ if (existingServers.length > 0) {
304
+ return `该服务器 (${parsedHost}:${parsedPort}) 已在本群绑定,服务器ID为: ${existingServers[0].id}`;
305
+ }
306
+ const createData = {
307
+ userId,
308
+ groupId,
309
+ host: parsedHost,
310
+ port: parsedPort,
311
+ serverType: "java",
312
+ timeout: options.timeout,
313
+ minekuaiInstanceId: ""
314
+ };
315
+ if (options.name) {
316
+ createData.name = options.name;
317
+ }
318
+ await ctx.database.create("minecraft_server", createData);
319
+ const servers = await ctx.database.get("minecraft_server", { groupId });
320
+ const newServer = servers[servers.length - 1];
321
+ return `✅ 服务器绑定成功!
322
+ 服务器ID: ${newServer.id}
323
+ 名称: ${newServer.name || "Minecraft 服务器"}
324
+ 地址: ${parsedHost}:${parsedPort}`;
325
+ });
326
+ ctx.guild().command("mc/绑定密钥 <apiKey:string>", "绑定麦块API密钥").action(async ({ session }, apiKey) => {
327
+ if (!apiKey) {
328
+ return "请提供API密钥";
329
+ }
330
+ const groupId = session.guildId;
331
+ const userId = session.userId;
332
+ const existingKeys = await ctx.database.get("minecraft_api_key", { groupId });
333
+ if (existingKeys.length > 0) {
334
+ await ctx.database.set("minecraft_api_key", { groupId }, { apiKey });
335
+ return "✅ API密钥更新成功!";
336
+ }
337
+ await ctx.database.create("minecraft_api_key", {
338
+ userId,
339
+ groupId,
340
+ apiKey
341
+ });
342
+ return "✅ API密钥绑定成功!";
343
+ });
344
+ ctx.guild().command("mc/解绑 <id:number>", "解绑Minecraft服务器").action(async ({ session }, id) => {
345
+ if (!id) {
346
+ return "请提供服务器ID,例如:解绑 1";
347
+ }
348
+ const groupId = session.guildId;
349
+ const servers = await ctx.database.get("minecraft_server", { groupId });
350
+ const server = servers.find((s) => s.id === id);
238
351
  if (!server) {
239
352
  return `❌ 未找到ID为 ${id} 的服务器`;
240
353
  }
241
- const result = await queryServerStatus(server);
242
- if (!result.success) {
243
- return `🔴 服务器 ${server.name} - 离线 | 原因:${result.error}`;
354
+ await ctx.database.remove("minecraft_server", { id });
355
+ return `✅ 服务器 ${server.name} 已解绑`;
356
+ });
357
+ ctx.guild().command("mc/修改 <id:number>", "修改Minecraft服务器信息").option("name", "-n <name:string>", { fallback: "" }).option("timeout", "-t <timeout:number>", { fallback: 0 }).action(async ({ session, options }, id) => {
358
+ if (!id) {
359
+ return "请提供服务器ID,例如:修改 1";
360
+ }
361
+ const groupId = session.guildId;
362
+ const servers = await ctx.database.get("minecraft_server", { groupId });
363
+ const server = servers.find((s) => s.id === id);
364
+ if (!server) {
365
+ return `❌ 未找到ID为 ${id} 的服务器`;
366
+ }
367
+ const updates = {};
368
+ if (options.name) {
369
+ updates.name = options.name;
244
370
  }
245
- return formatDetailedStatus(result.data, server, config.showIpInDetail);
371
+ if (options.timeout > 0) {
372
+ updates.timeout = options.timeout;
373
+ }
374
+ if (Object.keys(updates).length === 0) {
375
+ return "请提供要修改的参数,使用 -n 指定新名称,-t 指定新超时时间";
376
+ }
377
+ await ctx.database.set("minecraft_server", { id }, updates);
378
+ const parts = [];
379
+ if (updates.name) parts.push(`名称: ${updates.name}`);
380
+ if (updates.timeout) parts.push(`超时: ${updates.timeout}秒`);
381
+ return `✅ 服务器信息已更新!
382
+ ${parts.join("\n")}`;
246
383
  });
247
- ctx.command("mc/开服 <id:number>", "启动麦块服务器").action(async ({ session }, id) => {
384
+ ctx.guild().command("mc/开服 <id:number>", "启动麦块服务器").action(async ({ session }, id) => {
248
385
  if (!id) return "请提供服务器ID,例如:开服 1";
249
- const server = config.servers.find((s) => s.id === id);
250
- if (!server) return `未找到ID为 ${id} 的服务器`;
386
+ const groupId = session.guildId;
387
+ const servers = await ctx.database.get("minecraft_server", { groupId });
388
+ const server = servers.find((s) => s.id === id);
389
+ if (!server) return `❌ 未找到ID为 ${id} 的服务器,请确保操作的是本群绑定的服务器`;
251
390
  if (!server.minekuaiInstanceId) return `服务器 ${server.name} 未配置麦块实例ID`;
252
391
  try {
253
- await minekuaiApiRequest(server.minekuaiInstanceId, "start", 3);
392
+ await minekuaiApiRequest(server.minekuaiInstanceId, "start", groupId, 3);
254
393
  return `✅ 已发送启动指令到服务器 ${server.name} (ID: ${id})`;
255
394
  } catch (error) {
256
395
  return `❌ 启动服务器 ${server.name} 失败: ${error.message}`;
257
396
  }
258
397
  });
259
- ctx.command("mc/重启 <id:number>", "重启麦块服务器").action(async ({ session }, id) => {
398
+ ctx.guild().command("mc/重启 <id:number>", "重启麦块服务器").action(async ({ session }, id) => {
260
399
  if (!id) return "请提供服务器ID,例如:重启 1";
261
- const server = config.servers.find((s) => s.id === id);
262
- if (!server) return `未找到ID为 ${id} 的服务器`;
400
+ const groupId = session.guildId;
401
+ const servers = await ctx.database.get("minecraft_server", { groupId });
402
+ const server = servers.find((s) => s.id === id);
403
+ if (!server) return `❌ 未找到ID为 ${id} 的服务器,请确保操作的是本群绑定的服务器`;
263
404
  if (!server.minekuaiInstanceId) return `服务器 ${server.name} 未配置麦块实例ID`;
264
405
  try {
265
- await minekuaiApiRequest(server.minekuaiInstanceId, "restart", 3);
406
+ await minekuaiApiRequest(server.minekuaiInstanceId, "restart", groupId, 3);
266
407
  return `✅ 服务器 ${server.name} 重启指令已发送完成,请稍后检查服务器状态`;
267
408
  } catch (error) {
268
409
  return `❌ 重启服务器 ${server.name} 失败: ${error.message}`;
269
410
  }
270
411
  });
271
- ctx.command("mc/强制重启 <id:number>", "强制重启麦块服务器").action(async ({ session }, id) => {
412
+ ctx.guild().command("mc/强制重启 <id:number>", "强制重启麦块服务器").action(async ({ session }, id) => {
272
413
  if (!id) return "请提供服务器ID,例如:强制重启 1";
273
- const server = config.servers.find((s) => s.id === id);
274
- if (!server) return `未找到ID为 ${id} 的服务器`;
414
+ const groupId = session.guildId;
415
+ const servers = await ctx.database.get("minecraft_server", { groupId });
416
+ const server = servers.find((s) => s.id === id);
417
+ if (!server) return `❌ 未找到ID为 ${id} 的服务器,请确保操作的是本群绑定的服务器`;
275
418
  if (!server.minekuaiInstanceId) return `服务器 ${server.name} 未配置麦块实例ID`;
276
419
  try {
277
- await minekuaiApiRequest(server.minekuaiInstanceId, "stop", 3);
420
+ await minekuaiApiRequest(server.minekuaiInstanceId, "stop", groupId, 3);
278
421
  await new Promise((resolve) => setTimeout(resolve, 1e3));
279
- await minekuaiApiRequest(server.minekuaiInstanceId, "kill", 3);
422
+ await minekuaiApiRequest(server.minekuaiInstanceId, "kill", groupId, 3);
280
423
  await new Promise((resolve) => setTimeout(resolve, 3e3));
281
- await minekuaiApiRequest(server.minekuaiInstanceId, "start", 3);
424
+ await minekuaiApiRequest(server.minekuaiInstanceId, "start", groupId, 3);
282
425
  return `✅ 服务器 ${server.name} 强制重启指令已发送完成,请稍后检查服务器状态`;
283
426
  } catch (error) {
284
427
  return `❌ 强制重启服务器 ${server.name} 失败: ${error.message}`;
285
428
  }
286
429
  });
287
- ctx.command("mc/资源 <id:number>", "查看麦块服务器资源使用情况").action(async ({ session }, id) => {
430
+ ctx.guild().command("mc/资源 <id:number>", "查看麦块服务器资源使用情况").action(async ({ session }, id) => {
288
431
  if (!id) return "请提供服务器ID,例如:资源 1";
289
- const server = config.servers.find((s) => s.id === id);
290
- if (!server) return `未找到ID为 ${id} 的服务器`;
432
+ const groupId = session.guildId;
433
+ const servers = await ctx.database.get("minecraft_server", { groupId });
434
+ const server = servers.find((s) => s.id === id);
435
+ if (!server) return `❌ 未找到ID为 ${id} 的服务器,请确保操作的是本群绑定的服务器`;
291
436
  if (!server.minekuaiInstanceId) return `服务器 ${server.name} 未配置麦块实例ID`;
292
437
  try {
293
- const { apiUrl, apiKey } = config.minekuaiSettings;
294
- if (!apiKey) throw new Error("麦块API密钥未配置");
295
- if (!apiUrl) throw new Error("麦块API地址未配置");
296
- const baseUrl = apiUrl.replace(/\/+$/, "");
438
+ const apiKeys = await ctx.database.get("minecraft_api_key", { groupId });
439
+ if (!apiKeys || apiKeys.length === 0) {
440
+ throw new Error("本群未配置麦块API密钥,请先使用 绑定密钥 指令");
441
+ }
442
+ const apiKeyRecord = apiKeys[0];
443
+ const baseUrl = config.minekuaiApiUrl.replace(/\/+$/, "");
297
444
  const url = `${baseUrl}/servers/${server.minekuaiInstanceId}/resources`;
298
445
  const headers = {
299
- "Authorization": `Bearer ${apiKey}`,
446
+ "Authorization": `Bearer ${apiKeyRecord.apiKey}`,
300
447
  "Content-Type": "application/json",
301
448
  "Accept": "application/json"
302
449
  };
@@ -339,11 +486,49 @@ function apply(ctx, config) {
339
486
  return `❌ 查询服务器 ${server.name} 资源使用情况失败: ${error.message}`;
340
487
  }
341
488
  });
489
+ ctx.guild().command("mc/服务器列表", "查看已绑定的服务器列表").action(async ({ session }) => {
490
+ const groupId = session.guildId;
491
+ const servers = await ctx.database.get("minecraft_server", { groupId });
492
+ if (servers.length === 0) {
493
+ return "本群暂未绑定任何服务器";
494
+ }
495
+ let message = `📋 本群已绑定 ${servers.length} 台服务器:
496
+
497
+ `;
498
+ servers.forEach((server) => {
499
+ message += `[ID:${server.id}] ${server.name}
500
+ `;
501
+ message += ` 地址: ${server.host}:${server.port}
502
+ `;
503
+ message += ` 类型: ${server.serverType} | 超时: ${server.timeout}秒
504
+ `;
505
+ if (server.minekuaiInstanceId) {
506
+ message += ` 麦块实例: ${server.minekuaiInstanceId}
507
+ `;
508
+ }
509
+ message += "\n";
510
+ });
511
+ return message.trim();
512
+ });
513
+ ctx.guild().command("mc/设置实例 <id:number> <instanceId:string>", "设置服务器的麦块实例ID").action(async ({ session }, id, instanceId) => {
514
+ if (!id || !instanceId) {
515
+ return "请提供服务器ID和实例ID,例如:设置实例 1 abc123";
516
+ }
517
+ const groupId = session.guildId;
518
+ const servers = await ctx.database.get("minecraft_server", { groupId });
519
+ const server = servers.find((s) => s.id === id);
520
+ if (!server) {
521
+ return `❌ 未找到ID为 ${id} 的服务器`;
522
+ }
523
+ await ctx.database.set("minecraft_server", { id }, { minekuaiInstanceId: instanceId });
524
+ return `✅ 服务器 ${server.name} 的麦块实例ID已设置为: ${instanceId}`;
525
+ });
342
526
  }
343
527
  __name(apply, "apply");
344
528
  // Annotate the CommonJS export names for ESM import in node:
345
529
  0 && (module.exports = {
346
530
  Config,
347
531
  apply,
532
+ inject,
348
533
  name
349
534
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-minecraft-search",
3
3
  "description": "使用API查询基础的mc服务器信息",
4
- "version": "1.3.9",
4
+ "version": "2.0.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/readme.md CHANGED
@@ -16,6 +16,7 @@
16
16
  ### ⚡ 服务器电源控制
17
17
  - 支持通过麦块联机 API 启动服务器
18
18
  - 支持通过麦块联机 API 重启服务器
19
+ - 支持通过麦块联机 API 强制重启服务器
19
20
  - 自动重试机制,提高操作成功率
20
21
 
21
22
  ### 📊 服务器资源查询
@@ -25,6 +26,18 @@
25
26
  - 显示服务器运行时间
26
27
  - 显示服务器状态和暂停状态
27
28
 
29
+ ### 🗄️ 数据库存储
30
+ - 使用数据库存储服务器配置,支持多群组管理
31
+ - 支持按群组绑定服务器,每个群组只能管理自己的服务器
32
+ - 支持 API 密钥按群组存储
33
+
34
+ ### 🔧 服务器管理
35
+ - 支持绑定服务器(自动解析地址和端口)
36
+ - 支持解绑服务器
37
+ - 支持修改服务器信息(名称、超时时间)
38
+ - 支持设置麦块实例ID
39
+ - 支持查看服务器列表
40
+
28
41
  ## 安装
29
42
 
30
43
  1. 安装插件:
@@ -36,34 +49,30 @@ npm install koishi-plugin-minecraft-search
36
49
 
37
50
  ## 配置说明
38
51
 
39
- ### 服务器配置
40
- ```typescript
41
- servers: [
42
- {
43
- id: 1, // 服务器ID(数字)
44
- name: "主服务器", // 服务器名称
45
- host: "play.example.com:25565", // 服务器地址(支持带端口)
46
- serverType: "java", // 服务器类型:java/bedrock
47
- timeout: 5.0, // 查询超时时间(秒)
48
- minekuaiInstanceId: "xxx" // 麦块实例ID(可选,用于电源控制)
49
- }
50
- ]
51
- ```
52
-
53
- ### 麦块联机配置(可选)
52
+ ### 基础配置
54
53
  ```typescript
55
- minekuaiSettings: {
56
- apiUrl: "https://minekuai.com/api/client", // 麦块API地址
57
- apiKey: "your-api-key" // 麦块API密钥
54
+ {
55
+ "minekuaiApiUrl": "https://minekuai.com/api/client", // 麦块API地址
56
+ "showIpInDetail": true // 是否在详细状态中显示IP地址
58
57
  }
59
58
  ```
60
59
 
61
60
  ## 使用指令
62
61
 
62
+ ### 服务器管理
63
+ ```
64
+ mc/绑定 <host> [-n <name>] [-t <timeout>] # 绑定服务器,支持指定名称和超时时间
65
+ mc/解绑 <id> # 解绑服务器
66
+ mc/修改 <id> [-n <name>] [-t <timeout>] # 修改服务器信息
67
+ mc/服务器列表 # 查看已绑定的服务器列表
68
+ mc/设置实例 <id> <instanceId> # 设置服务器的麦块实例ID
69
+ mc/绑定API密钥 <apiKey> # 绑定麦块API密钥
70
+ ```
71
+
63
72
  ### 查询服务器状态
64
73
  ```
65
- 查服 # 查询全部服务器状态(简短信息)
66
- 查服 1 # 查询ID为1的服务器的详细信息
74
+ mc/查服 # 查询全部服务器状态(简短信息)
75
+ mc/查服 1 # 查询ID为1的服务器的详细信息
67
76
  ```
68
77
 
69
78
  **输出示例:**
@@ -79,14 +88,14 @@ minekuaiSettings: {
79
88
 
80
89
  ### 服务器电源控制
81
90
  ```
82
- 开服 1 # 启动ID为1的麦块服务器
83
- 重启 1 # 重启ID为1的麦块服务器
84
- 强制重启 1 # 强制重启ID为1的麦块服务器
91
+ mc/开服 1 # 启动ID为1的麦块服务器
92
+ mc/重启 1 # 重启ID为1的麦块服务器
93
+ mc/强制重启 1 # 强制重启ID为1的麦块服务器
85
94
  ```
86
95
 
87
96
  ### 服务器资源查询
88
97
  ```
89
- 资源 1 # 查看ID为1的麦块服务器资源使用情况
98
+ mc/资源 1 # 查看ID为1的麦块服务器资源使用情况
90
99
  ```
91
100
 
92
101
  **输出示例:**
@@ -103,15 +112,35 @@ minekuaiSettings: {
103
112
  ⏰ 查询时间: 2026-03-13 12:00:00
104
113
  ```
105
114
 
106
- ## 配置选项说明
107
-
108
- ### 服务器类型 (serverType)
109
- - `java`:Java 版服务器(默认)
110
- - `bedrock`:基岩版服务器(暂不支持)
111
-
112
- ### 超时时间 (timeout)
113
- - 默认值:5.0 秒
114
- - 设置查询超时时间,避免长时间等待
115
+ ## 指令说明
116
+
117
+ ### 绑定服务器
118
+ - **命令**:`mc/绑定 <host> [-n <name>] [-t <timeout>]`
119
+ - **参数**:
120
+ - `<host>`:服务器地址,支持带端口格式(如:`play.example.com:25565`)
121
+ - `-n <name>`:服务器名称(可选,默认使用地址作为名称)
122
+ - `-t <timeout>`:查询超时时间(可选,默认5秒)
123
+ - **示例**:
124
+ - `mc/绑定 s3.ungc.com.cn` - 绑定默认端口的服务器
125
+ - `mc/绑定 s3.ungc.com.cn:37095 -n 测试服 -t 10` - 绑定指定端口、名称和超时的服务器
126
+
127
+ ### 绑定API密钥
128
+ - **命令**:`mc/绑定API密钥 <apiKey>`
129
+ - **参数**:
130
+ - `<apiKey>`:麦块联机平台的API密钥
131
+ - **说明**:每个群组只需绑定一次,后续会自动使用该密钥
132
+
133
+ ### 服务器管理指令
134
+ - **`mc/解绑 <id>`**:解绑指定ID的服务器
135
+ - **`mc/修改 <id> [-n <name>] [-t <timeout>]`**:修改服务器名称或超时时间
136
+ - **`mc/设置实例 <id> <instanceId>`**:为服务器设置麦块实例ID,用于电源控制
137
+ - **`mc/服务器列表`**:查看当前群组已绑定的所有服务器
138
+
139
+ ### 服务器控制指令
140
+ - **`mc/开服 <id>`**:启动指定服务器
141
+ - **`mc/重启 <id>`**:重启指定服务器
142
+ - **`mc/强制重启 <id>`**:强制停止并重启指定服务器
143
+ - **`mc/资源 <id>`**:查询服务器资源使用情况
115
144
 
116
145
  ## 技术特性
117
146
 
@@ -120,19 +149,22 @@ minekuaiSettings: {
120
149
  - 📱 **友好输出格式**:使用 emoji 和清晰排版,信息易读
121
150
  - ⚡ **高性能查询**:支持并行查询多个服务器
122
151
  - 🛡️ **错误处理**:完善的错误处理和用户提示
152
+ - 🗄️ **数据库存储**:使用数据库存储服务器配置,支持多群组管理
153
+ - 🔒 **权限控制**:每个群组只能管理自己绑定的服务器
123
154
 
124
155
  ## 依赖说明
125
156
 
126
157
  - 使用 https://www.npmjs.com/package/mc-server-util 库进行服务器状态查询
127
158
  - 支持麦块联机平台的 API 集成
128
- - 基于 Koishi 框架开发
159
+ - 基于 Koishi 框架开发,依赖数据库插件
129
160
 
130
161
  ## 注意事项
131
162
 
132
163
  1. 麦块联机功能需要配置正确的 API 地址和密钥
133
- 2. Query 查询可能会增加查询时间,建议按需开启
134
- 3. 服务器地址支持带端口格式(如:`play.example.com:25565`)
135
- 4. 插件会自动处理 MOTD 中的换行符,确保输出整洁
164
+ 2. 服务器地址支持带端口格式(如:`play.example.com:25565`)
165
+ 3. 插件会自动处理 MOTD 中的换行符,确保输出整洁
166
+ 4. 所有服务器操作指令均限制为群组指令,只能操作本群绑定的服务器
167
+ 5. API 密钥按群组存储,每个群组需要单独绑定
136
168
 
137
169
  ## 故障排除
138
170
 
@@ -141,11 +173,20 @@ minekuaiSettings: {
141
173
  - 网络连接是否正常
142
174
  - 防火墙是否阻止了查询请求
143
175
  - 麦块 API 配置是否正确
176
+ - 服务器是否为本群绑定的服务器
144
177
 
145
178
  ## 更新日志
146
179
  <details>
147
180
  <summary>点我查看更新日志详情</summary>
148
181
 
182
+ ### v2.0.0
183
+ - 全新数据库存储架构,支持多群组管理
184
+ - 新增服务器绑定、解绑、修改等管理指令
185
+ - 支持按群组存储 API 密钥
186
+ - 增加服务器列表查看功能
187
+ - 优化错误提示,明确权限限制
188
+ - 移除配置文件中的服务器列表,改为数据库存储
189
+
149
190
  ### v1.3.6
150
191
  - 新增服务器资源使用情况查询功能
151
192
  - 支持查看 CPU、内存、磁盘使用情况
@@ -176,4 +217,4 @@ minekuaiSettings: {
176
217
 
177
218
  ## 支持与反馈
178
219
 
179
- 如有问题或建议,请通过相关渠道联系开发者。
220
+ 如有问题或建议,请通过相关渠道联系开发者。