mioku-plugin-mc 3.0.1 → 4.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/index.ts +66 -68
- package/package.json +4 -52
- package/play/actions/registry.ts +1 -1
- package/play/context.ts +2 -2
- package/play/debug/commands.ts +2 -2
- package/play/index.ts +3 -3
- package/play/missions/registry.ts +1 -1
- package/play/session.ts +2 -2
- package/utils/command-router.ts +0 -51
package/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { definePlugin, type
|
|
1
|
+
import { definePlugin, type MiokuContext } from "mioku";
|
|
2
2
|
import { getService, Services } from "mioku";
|
|
3
3
|
import { createConfigHandler } from "./utils/config-handler";
|
|
4
4
|
import { createPlayConfigHandler } from "./play/config";
|
|
@@ -6,7 +6,6 @@ import { createPlayManager } from "./play";
|
|
|
6
6
|
import { createMcSkill } from "./skills/mc";
|
|
7
7
|
import { handleDebugCommand } from "./play/debug/commands";
|
|
8
8
|
import { createServerManager } from "./utils/server-manager";
|
|
9
|
-
import { parseMcCommand } from "./utils/command-router";
|
|
10
9
|
import { handleStatus } from "./handlers/status";
|
|
11
10
|
import { handleSync } from "./handlers/sync";
|
|
12
11
|
import { handleReconnect } from "./handlers/reconnect";
|
|
@@ -21,10 +20,8 @@ import type { McConfig } from "./types";
|
|
|
21
20
|
|
|
22
21
|
export default definePlugin({
|
|
23
22
|
name: "mc",
|
|
24
|
-
version: "1.0.0",
|
|
25
|
-
description: "Minecraft服务器与QQ群消息互通插件",
|
|
26
23
|
|
|
27
|
-
async setup(ctx:
|
|
24
|
+
async setup(ctx: MiokuContext) {
|
|
28
25
|
const configService = getService(ctx, Services.Config);
|
|
29
26
|
|
|
30
27
|
const configHandler = createConfigHandler(configService);
|
|
@@ -74,7 +71,7 @@ export default definePlugin({
|
|
|
74
71
|
if (groupId) {
|
|
75
72
|
const reply = await handleDebugCommand({
|
|
76
73
|
text,
|
|
77
|
-
|
|
74
|
+
isMaster: ctx.isMaster?.(event) ?? false,
|
|
78
75
|
debugEnabled: playConfigHandler.getConfig().debug.enabled,
|
|
79
76
|
playManager,
|
|
80
77
|
groupId: Number(groupId),
|
|
@@ -85,60 +82,64 @@ export default definePlugin({
|
|
|
85
82
|
}
|
|
86
83
|
}
|
|
87
84
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (!parsed || parsed.action === "") {
|
|
91
|
-
if (groupId) {
|
|
92
|
-
playManager.onQqMessage(event);
|
|
93
|
-
await forwardToMc(ctx, event, config, configHandler, serverManager);
|
|
94
|
-
}
|
|
95
|
-
return;
|
|
85
|
+
if (groupId) {
|
|
86
|
+
await forwardToMc(ctx, event, config, configHandler, serverManager);
|
|
96
87
|
}
|
|
88
|
+
});
|
|
97
89
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
90
|
+
const replyWithEvent = (event: import("mioku").MessageEvent) =>
|
|
91
|
+
async (msg: string) => {
|
|
92
|
+
await event.reply(msg);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
ctx.command({
|
|
96
|
+
id: "mc-status",
|
|
97
|
+
name: "mc-status",
|
|
98
|
+
match: /^\/mc\s+状态\s*$/,
|
|
99
|
+
prefixes: ["/"],
|
|
100
|
+
permission: "master",
|
|
101
|
+
description: "查看所有已配置服务器的WebSocket连接状态,包括连接中、已断开等",
|
|
102
|
+
async handler({ event }) {
|
|
103
|
+
await handleStatus(serverManager, config, replyWithEvent(event));
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
ctx.command({
|
|
108
|
+
id: "mc-sync-on",
|
|
109
|
+
name: "mc-sync-on",
|
|
110
|
+
match: /^\/mc\s+开启同步(?:\s+(.+))?$/,
|
|
111
|
+
prefixes: ["/"],
|
|
112
|
+
description: "开启指定服务器的群聊消息同步功能,开启后该服务器可接收和发送群聊消息",
|
|
113
|
+
usage: "/mc 开启同步 <服务器名称>",
|
|
114
|
+
permission: "master",
|
|
115
|
+
async handler({ event, args }) {
|
|
116
|
+
await handleSync(args[0], true, serverManager, configHandler, config, replyWithEvent(event));
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
ctx.command({
|
|
121
|
+
id: "mc-sync-off",
|
|
122
|
+
name: "mc-sync-off",
|
|
123
|
+
match: /^\/mc\s+关闭同步(?:\s+(.+))?$/,
|
|
124
|
+
prefixes: ["/"],
|
|
125
|
+
description: "关闭指定服务器的群聊消息同步功能,关闭后该服务器不再接收和发送群聊消息",
|
|
126
|
+
usage: "/mc 关闭同步 <服务器名称>",
|
|
127
|
+
permission: "master",
|
|
128
|
+
async handler({ event, args }) {
|
|
129
|
+
await handleSync(args[0], false, serverManager, configHandler, config, replyWithEvent(event));
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
ctx.command({
|
|
134
|
+
id: "mc-reconnect",
|
|
135
|
+
name: "mc-reconnect",
|
|
136
|
+
match: /^\/mc\s+重连\s*$/,
|
|
137
|
+
prefixes: ["/"],
|
|
138
|
+
permission: "master",
|
|
139
|
+
description: "断开并重新建立所有服务器的WebSocket连接,用于连接异常时手动恢复",
|
|
140
|
+
async handler({ event }) {
|
|
141
|
+
await handleReconnect(serverManager, replyWithEvent(event));
|
|
142
|
+
},
|
|
142
143
|
});
|
|
143
144
|
|
|
144
145
|
ctx.logger.info("Minecraft插件加载成功");
|
|
@@ -153,7 +154,7 @@ export default definePlugin({
|
|
|
153
154
|
});
|
|
154
155
|
|
|
155
156
|
async function handleMcEvent(
|
|
156
|
-
ctx:
|
|
157
|
+
ctx: MiokuContext,
|
|
157
158
|
event: McEvent,
|
|
158
159
|
config: McConfig,
|
|
159
160
|
configHandler: ReturnType<typeof createConfigHandler>,
|
|
@@ -174,12 +175,12 @@ async function handleMcEvent(
|
|
|
174
175
|
const groups = groupList ? [groupList] : [];
|
|
175
176
|
|
|
176
177
|
for (const botId of bots) {
|
|
177
|
-
const bot = ctx.pickBot(
|
|
178
|
+
const bot = ctx.pickBot(botId);
|
|
178
179
|
if (!bot) continue;
|
|
179
180
|
|
|
180
181
|
for (const groupId of groups) {
|
|
181
182
|
try {
|
|
182
|
-
await bot.
|
|
183
|
+
await bot.sendMessage({ type: "group", group_id: groupId}, messageText);
|
|
183
184
|
} catch (err) {
|
|
184
185
|
ctx.logger.error(`[MC] 发送消息到群 ${groupId} 失败: ${err}`);
|
|
185
186
|
}
|
|
@@ -188,7 +189,7 @@ async function handleMcEvent(
|
|
|
188
189
|
}
|
|
189
190
|
|
|
190
191
|
async function forwardToMc(
|
|
191
|
-
ctx:
|
|
192
|
+
ctx: MiokuContext,
|
|
192
193
|
event: any,
|
|
193
194
|
config: McConfig,
|
|
194
195
|
configHandler: ReturnType<typeof createConfigHandler>,
|
|
@@ -197,10 +198,7 @@ async function forwardToMc(
|
|
|
197
198
|
const text = ctx.text(event);
|
|
198
199
|
ctx.logger.debug(`[MC] 收到群消息 group=${event.group_id} text=${text}`);
|
|
199
200
|
|
|
200
|
-
|
|
201
|
-
if (!event.group_id) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
201
|
+
if (!event.group_id) return;
|
|
204
202
|
|
|
205
203
|
const servers = configHandler.getServersForGroup(event.group_id);
|
|
206
204
|
if (servers.length === 0) return;
|
|
@@ -219,7 +217,7 @@ async function forwardToMc(
|
|
|
219
217
|
const isAllowed = isCommandAllowed(
|
|
220
218
|
commandText,
|
|
221
219
|
server,
|
|
222
|
-
ctx.
|
|
220
|
+
ctx.isMaster?.(event) ?? false,
|
|
223
221
|
event.user_id ?? "",
|
|
224
222
|
);
|
|
225
223
|
|
|
@@ -252,4 +250,4 @@ async function forwardToMc(
|
|
|
252
250
|
ctx.logger.error(`[MC] 发送到服务器 ${server.server_name} 失败: ${err}`);
|
|
253
251
|
}
|
|
254
252
|
}
|
|
255
|
-
}
|
|
253
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mioku-plugin-mc",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Minecraft与QQ群消息互通插件,支持服务器状态监控与RCON命令",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -15,53 +15,7 @@
|
|
|
15
15
|
"services": [
|
|
16
16
|
"config",
|
|
17
17
|
"ai"
|
|
18
|
-
]
|
|
19
|
-
"accessHooks": [
|
|
20
|
-
{
|
|
21
|
-
"id": "/mc 状态",
|
|
22
|
-
"match": "/^\\/mc\\s*状态/"
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"id": "/mc 开启同步",
|
|
26
|
-
"match": "/^\\/mc\\s*开启同步/"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"id": "/mc 关闭同步",
|
|
30
|
-
"match": "/^\\/mc\\s*关闭同步/"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"id": "/mc 重连",
|
|
34
|
-
"match": "/^\\/mc\\s*重连/"
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
"help": {
|
|
38
|
-
"title": "Minecraft",
|
|
39
|
-
"description": "Minecraft服务器与QQ群消息互通插件,支持服务器状态监控与RCON命令",
|
|
40
|
-
"commands": [
|
|
41
|
-
{
|
|
42
|
-
"cmd": "/mc 状态",
|
|
43
|
-
"desc": "查看所有已配置服务器的WebSocket连接状态,包括连接中、已断开等",
|
|
44
|
-
"role": "master"
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"cmd": "/mc 开启同步",
|
|
48
|
-
"desc": "开启指定服务器的群聊消息同步功能,开启后该服务器可接收和发送群聊消息",
|
|
49
|
-
"usage": "/mc 开启同步 <服务器名称>",
|
|
50
|
-
"role": "master"
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"cmd": "/mc 关闭同步",
|
|
54
|
-
"desc": "关闭指定服务器的群聊消息同步功能,关闭后该服务器不再接收和发送群聊消息",
|
|
55
|
-
"usage": "/mc 关闭同步 <服务器名称>",
|
|
56
|
-
"role": "master"
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
"cmd": "/mc 重连",
|
|
60
|
-
"desc": "断开并重新建立所有服务器的WebSocket连接,用于连接异常时手动恢复",
|
|
61
|
-
"role": "master"
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
}
|
|
18
|
+
]
|
|
65
19
|
},
|
|
66
20
|
"dependencies": {
|
|
67
21
|
"@cikeyqi/queqiao-node-sdk": "^0.1.3",
|
|
@@ -71,11 +25,9 @@
|
|
|
71
25
|
"zod": "^3.24.1"
|
|
72
26
|
},
|
|
73
27
|
"peerDependencies": {
|
|
74
|
-
"mioku": "^0.
|
|
75
|
-
"mioki": "^0.16.0"
|
|
28
|
+
"mioku": "^1.0.0"
|
|
76
29
|
},
|
|
77
30
|
"devDependencies": {
|
|
78
|
-
"mioku": "workspace:*"
|
|
79
|
-
"mioki": "^0.16.0"
|
|
31
|
+
"mioku": "workspace:*"
|
|
80
32
|
}
|
|
81
33
|
}
|
package/play/actions/registry.ts
CHANGED
package/play/context.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MiokuContext } from "mioku";
|
|
2
2
|
import type { AIService, AIInstance, ConfigService } from "mioku";
|
|
3
3
|
import type { PlayConfig } from "./types";
|
|
4
4
|
import type { ConfigHandler } from "../utils/config-handler";
|
|
@@ -6,7 +6,7 @@ import type { WorkSubroutine, WorkTerminator } from "./ai/work-subroutine";
|
|
|
6
6
|
import type { PlaySession } from "./session";
|
|
7
7
|
|
|
8
8
|
export interface PlayPluginContext {
|
|
9
|
-
ctx:
|
|
9
|
+
ctx: MiokuContext;
|
|
10
10
|
config: PlayConfig;
|
|
11
11
|
aiService: AIService | undefined;
|
|
12
12
|
configService: ConfigService | undefined;
|
package/play/debug/commands.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { PlayManager } from "../index";
|
|
|
2
2
|
|
|
3
3
|
export interface DebugCommandContext {
|
|
4
4
|
text: string;
|
|
5
|
-
|
|
5
|
+
isMaster: boolean;
|
|
6
6
|
debugEnabled: boolean;
|
|
7
7
|
playManager: PlayManager;
|
|
8
8
|
groupId: number;
|
|
@@ -78,7 +78,7 @@ function parseBundleArgs(arg: string): ParsedBundleArgs | null {
|
|
|
78
78
|
export async function handleDebugCommand(
|
|
79
79
|
ctx: DebugCommandContext,
|
|
80
80
|
): Promise<string | null> {
|
|
81
|
-
if (!ctx.debugEnabled || !ctx.
|
|
81
|
+
if (!ctx.debugEnabled || !ctx.isMaster) return null;
|
|
82
82
|
const text = ctx.text.trim();
|
|
83
83
|
if (!text.startsWith("/")) return null;
|
|
84
84
|
const head = text.split(/\s+/)[0]?.toLowerCase();
|
package/play/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MiokuContext } from "mioku";
|
|
2
2
|
import type { AIService, AIInstance, ConfigService } from "mioku";
|
|
3
3
|
import type { ConfigHandler } from "../utils/config-handler";
|
|
4
4
|
import type { PlayPluginContext } from "./context";
|
|
@@ -17,7 +17,7 @@ import { SelfDefenseBehavior } from "./behavior/catalog/defend";
|
|
|
17
17
|
import type { GroupBinding, PlayServerConfig } from "./types";
|
|
18
18
|
|
|
19
19
|
export interface PlayManagerOptions {
|
|
20
|
-
ctx:
|
|
20
|
+
ctx: MiokuContext;
|
|
21
21
|
aiService: AIService | undefined;
|
|
22
22
|
configService: ConfigService | undefined;
|
|
23
23
|
playConfigHandler: PlayConfigHandler;
|
|
@@ -36,7 +36,7 @@ export interface PlayExitResult {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export class PlayManager {
|
|
39
|
-
private readonly ctx:
|
|
39
|
+
private readonly ctx: MiokuContext;
|
|
40
40
|
private readonly aiService: AIService | undefined;
|
|
41
41
|
private readonly configService: ConfigService | undefined;
|
|
42
42
|
private readonly playConfigHandler: PlayConfigHandler;
|
package/play/session.ts
CHANGED
|
@@ -242,7 +242,7 @@ export class PlaySession {
|
|
|
242
242
|
const bot = ctx.ctx.pickBot(this.binding.botSelfId);
|
|
243
243
|
if (!bot) return;
|
|
244
244
|
try {
|
|
245
|
-
await bot.
|
|
245
|
+
await bot.sendMessage({ type: "group", group_id: this.binding.groupId}, message);
|
|
246
246
|
} catch (err) {
|
|
247
247
|
ctx.ctx.logger.error(`[MC/play] 发送 QQ 通知失败: ${err}`);
|
|
248
248
|
}
|
|
@@ -264,7 +264,7 @@ export class PlaySession {
|
|
|
264
264
|
const bot = ctx.ctx.pickBot(this.binding.botSelfId);
|
|
265
265
|
if (!bot) return false;
|
|
266
266
|
try {
|
|
267
|
-
await bot.
|
|
267
|
+
await bot.sendMessage({ type: "group", group_id: this.binding.groupId}, message);
|
|
268
268
|
return true;
|
|
269
269
|
} catch (err) {
|
|
270
270
|
ctx.ctx.logger.error(`[MC/play] 发送 QQ 消息失败: ${err}`);
|
package/utils/command-router.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
export interface ParsedCommand {
|
|
2
|
-
action: string;
|
|
3
|
-
args: string[];
|
|
4
|
-
raw: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function parseMcCommand(text: string): ParsedCommand | null {
|
|
8
|
-
const trimmed = text.trim();
|
|
9
|
-
if (!trimmed.startsWith("/mc")) return null;
|
|
10
|
-
|
|
11
|
-
const remainder = trimmed.slice(3).trim();
|
|
12
|
-
if (!remainder) {
|
|
13
|
-
return { action: "", args: [], raw: "" };
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// split into action and args
|
|
17
|
-
const parts = remainder.split(/\s+/);
|
|
18
|
-
const action = parts[0] || "";
|
|
19
|
-
const args = parts.slice(1);
|
|
20
|
-
|
|
21
|
-
return { action, args, raw: remainder };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function matchMcCommand(
|
|
25
|
-
text: string,
|
|
26
|
-
pattern: RegExp
|
|
27
|
-
): RegExpMatchArray | null {
|
|
28
|
-
const parsed = parseMcCommand(text);
|
|
29
|
-
if (!parsed) return null;
|
|
30
|
-
return parsed.raw.match(pattern);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function buildStatusReply(
|
|
34
|
-
serverName: string,
|
|
35
|
-
status: string,
|
|
36
|
-
displayName?: string
|
|
37
|
-
): string {
|
|
38
|
-
const name = displayName || serverName;
|
|
39
|
-
const icon = status === "connected" ? "在线" : status === "connecting" ? "连接中" : "离线";
|
|
40
|
-
return `[${name}] ${icon}`;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function buildSyncReply(
|
|
44
|
-
serverName: string,
|
|
45
|
-
enabled: boolean,
|
|
46
|
-
displayName?: string
|
|
47
|
-
): string {
|
|
48
|
-
const name = displayName || serverName;
|
|
49
|
-
const action = enabled ? "开启" : "关闭";
|
|
50
|
-
return `${action}了服务器 ${name} 的同步`;
|
|
51
|
-
}
|