mioku-plugin-terraria 1.0.0 → 2.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/README.md +4 -8
- package/index.ts +80 -62
- package/package.json +6 -55
- package/utils/command-router.ts +0 -21
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# mioku-plugin-terraria
|
|
2
2
|
|
|
3
|
-
为 Mioku 提供 Terraria(TShock)服务器与 QQ 群消息互通能力,使用 [TianSuo](https://github.com/
|
|
3
|
+
为 Mioku 提供 Terraria(TShock)服务器与 QQ 群消息互通能力,使用 [TianSuo](https://github.com/Jerryplusy/TianSuo) 协议(JSON over WebSocket)。
|
|
4
4
|
|
|
5
5
|
## 功能特性
|
|
6
6
|
|
|
@@ -9,13 +9,9 @@
|
|
|
9
9
|
- **多服务器支持**:可同时连接多台 Terraria 服务器,每台独立配置
|
|
10
10
|
- **自动重连**:连接断开后按指数退避自动重连,可配置最大重试次数
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## 服务端要求
|
|
13
13
|
|
|
14
|
-
Terraria 服务器需安装 [TianSuo](https://github.com/
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
bun install
|
|
18
|
-
```
|
|
14
|
+
Terraria 服务器需安装 [TianSuo](https://github.com/Jerryplusy/TianSuo) TShock 插件
|
|
19
15
|
|
|
20
16
|
## 配置
|
|
21
17
|
|
|
@@ -32,6 +28,6 @@ bun install
|
|
|
32
28
|
|
|
33
29
|
## 鸣谢
|
|
34
30
|
|
|
35
|
-
- [TianSuo](https://github.com/
|
|
31
|
+
- [TianSuo](https://github.com/Jerryplusy/TianSuo):Terraria WebSocket 桥
|
|
36
32
|
- [TShock](https://github.com/TShock/TShock) 与 [Pryaxis](https://github.com/Pryaxis):Terraria 服务端框架与插件 API
|
|
37
33
|
- [Re-Logic](https://www.terraria.org/):Terraria
|
package/index.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { definePlugin, getService, Services, type
|
|
1
|
+
import { definePlugin, getService, Services, type MiokuContext } from "mioku";
|
|
2
2
|
import { handleStatus } from "./handlers/status";
|
|
3
3
|
import { handleSync } from "./handlers/sync";
|
|
4
4
|
import { handleReconnect } from "./handlers/reconnect";
|
|
5
|
-
import { parseTsCommand } from "./utils/command-router";
|
|
6
5
|
import { createConfigHandler } from "./utils/config-handler";
|
|
7
6
|
import {
|
|
8
7
|
formatQqToTerraria,
|
|
@@ -19,10 +18,8 @@ import { PROTOCOL, type TerrariaConfig, type TerrariaEvent } from "./types";
|
|
|
19
18
|
|
|
20
19
|
export default definePlugin({
|
|
21
20
|
name: "terraria",
|
|
22
|
-
version: "1.0.0",
|
|
23
|
-
description: "Terraria 服务器与 QQ 群消息互通插件,基于 TianSuo 协议",
|
|
24
21
|
|
|
25
|
-
async setup(ctx:
|
|
22
|
+
async setup(ctx: MiokuContext) {
|
|
26
23
|
const configService = getService(ctx, Services.Config);
|
|
27
24
|
|
|
28
25
|
const configHandler = createConfigHandler(configService);
|
|
@@ -42,65 +39,86 @@ export default definePlugin({
|
|
|
42
39
|
serverManager.startServers(config);
|
|
43
40
|
ctx.logger.info("Terraria 插件已就绪");
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
const text = ctx.text(event).trim();
|
|
42
|
+
const requireGroup = (event: any): number | undefined => {
|
|
47
43
|
const groupId =
|
|
48
44
|
"group_id" in event && typeof event.group_id === "number"
|
|
49
45
|
? event.group_id
|
|
50
46
|
: undefined;
|
|
47
|
+
return groupId;
|
|
48
|
+
};
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
50
|
+
ctx.command({
|
|
51
|
+
name: "/ts 状态",
|
|
52
|
+
match: /^\/ts\s*状态(?:\s|$)/,
|
|
53
|
+
prefixes: false,
|
|
54
|
+
permission: "master",
|
|
55
|
+
description: "查看所有已配置服务器的 WebSocket 连接状态",
|
|
56
|
+
handler: async ({ event }) => {
|
|
57
|
+
if (!requireGroup(event)) return;
|
|
58
|
+
await handleStatus(serverManager, config, async (msg) => {
|
|
59
|
+
await event.reply(msg);
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
ctx.command({
|
|
64
|
+
name: "/ts 开启同步",
|
|
65
|
+
match: /^\/ts\s*开启同步(?:\s|$)/,
|
|
66
|
+
prefixes: false,
|
|
67
|
+
permission: "master",
|
|
68
|
+
description: "开启指定服务器的群聊消息同步功能",
|
|
69
|
+
usage: "/ts 开启同步 <服务器名称>",
|
|
70
|
+
handler: async ({ event, args }) => {
|
|
71
|
+
if (!requireGroup(event)) return;
|
|
72
|
+
await handleSync(
|
|
73
|
+
args[0],
|
|
74
|
+
true,
|
|
75
|
+
configHandler,
|
|
76
|
+
config,
|
|
77
|
+
async (msg) => {
|
|
78
|
+
await event.reply(msg);
|
|
79
|
+
},
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
ctx.command({
|
|
84
|
+
name: "/ts 关闭同步",
|
|
85
|
+
match: /^\/ts\s*关闭同步(?:\s|$)/,
|
|
86
|
+
prefixes: false,
|
|
87
|
+
permission: "master",
|
|
88
|
+
description: "关闭指定服务器的群聊消息同步功能",
|
|
89
|
+
usage: "/ts 关闭同步 <服务器名称>",
|
|
90
|
+
handler: async ({ event, args }) => {
|
|
91
|
+
if (!requireGroup(event)) return;
|
|
92
|
+
await handleSync(
|
|
93
|
+
args[0],
|
|
94
|
+
false,
|
|
95
|
+
configHandler,
|
|
96
|
+
config,
|
|
97
|
+
async (msg) => {
|
|
98
|
+
await event.reply(msg);
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
ctx.command({
|
|
104
|
+
name: "/ts 重连",
|
|
105
|
+
match: /^\/ts\s*重连(?:\s|$)/,
|
|
106
|
+
prefixes: false,
|
|
107
|
+
permission: "master",
|
|
108
|
+
description: "断开并重新建立所有服务器的 WebSocket 连接",
|
|
109
|
+
handler: async ({ event }) => {
|
|
110
|
+
if (!requireGroup(event)) return;
|
|
111
|
+
await handleReconnect(serverManager, async (msg) => {
|
|
112
|
+
await event.reply(msg);
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
});
|
|
102
116
|
|
|
117
|
+
ctx.handle("message", async (event) => {
|
|
118
|
+
const groupId = requireGroup(event);
|
|
103
119
|
if (!groupId) return;
|
|
120
|
+
const text = ctx.text(event)?.trim();
|
|
121
|
+
if (text?.startsWith("/ts")) return;
|
|
104
122
|
await forwardToTerraria(ctx, event, config, configHandler, serverManager);
|
|
105
123
|
});
|
|
106
124
|
|
|
@@ -112,7 +130,7 @@ export default definePlugin({
|
|
|
112
130
|
});
|
|
113
131
|
|
|
114
132
|
async function handleTerrariaEvent(
|
|
115
|
-
ctx:
|
|
133
|
+
ctx: MiokuContext,
|
|
116
134
|
raw: { serverName: string; name: string; data: Record<string, unknown> },
|
|
117
135
|
config: TerrariaConfig,
|
|
118
136
|
configHandler: ReturnType<typeof createConfigHandler>,
|
|
@@ -152,11 +170,11 @@ async function handleTerrariaEvent(
|
|
|
152
170
|
const groups = serverItem.group_list ? [serverItem.group_list] : [];
|
|
153
171
|
|
|
154
172
|
for (const botId of bots) {
|
|
155
|
-
const bot = ctx.pickBot(
|
|
173
|
+
const bot = ctx.pickBot(botId);
|
|
156
174
|
if (!bot) continue;
|
|
157
175
|
for (const groupId of groups) {
|
|
158
176
|
try {
|
|
159
|
-
await bot.
|
|
177
|
+
await bot.sendMessage({ type: "group", group_id: groupId}, messageText);
|
|
160
178
|
} catch (err) {
|
|
161
179
|
ctx.logger.error(
|
|
162
180
|
`[Terraria] 发送消息到群 ${groupId} 失败: ${err}`,
|
|
@@ -167,7 +185,7 @@ async function handleTerrariaEvent(
|
|
|
167
185
|
}
|
|
168
186
|
|
|
169
187
|
async function forwardToTerraria(
|
|
170
|
-
ctx:
|
|
188
|
+
ctx: MiokuContext,
|
|
171
189
|
event: any,
|
|
172
190
|
config: TerrariaConfig,
|
|
173
191
|
configHandler: ReturnType<typeof createConfigHandler>,
|
|
@@ -195,7 +213,7 @@ async function forwardToTerraria(
|
|
|
195
213
|
const isAllowed = isCommandAllowed(
|
|
196
214
|
commandText,
|
|
197
215
|
server,
|
|
198
|
-
ctx.
|
|
216
|
+
ctx.isMaster?.(event) ?? false,
|
|
199
217
|
event.user_id,
|
|
200
218
|
);
|
|
201
219
|
if (!isAllowed) continue;
|
package/package.json
CHANGED
|
@@ -1,78 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mioku-plugin-terraria",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Terraria 服务器与 QQ 群消息互通插件,基于 TianSuo 协议",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [
|
|
8
|
-
"mioku"
|
|
9
|
-
"terraria",
|
|
10
|
-
"tshock",
|
|
11
|
-
"tiansuo"
|
|
8
|
+
"mioku"
|
|
12
9
|
],
|
|
13
10
|
"repository": {
|
|
14
11
|
"type": "git",
|
|
15
12
|
"url": "https://github.com/mioku-lab/mioku-plugin-terraria.git"
|
|
16
13
|
},
|
|
17
14
|
"mioku": {
|
|
18
|
-
"services": [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"id": "/ts 状态",
|
|
22
|
-
"match": "/^\\/ts\\s*状态/"
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"id": "/ts 开启同步",
|
|
26
|
-
"match": "/^\\/ts\\s*开启同步/"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"id": "/ts 关闭同步",
|
|
30
|
-
"match": "/^\\/ts\\s*关闭同步/"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"id": "/ts 重连",
|
|
34
|
-
"match": "/^\\/ts\\s*重连/"
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
"help": {
|
|
38
|
-
"title": "Terraria",
|
|
39
|
-
"description": "Terraria 服务器与 QQ 群消息互通插件,基于 TianSuo 协议",
|
|
40
|
-
"commands": [
|
|
41
|
-
{
|
|
42
|
-
"cmd": "/ts 状态",
|
|
43
|
-
"desc": "查看所有已配置服务器的 WebSocket 连接状态",
|
|
44
|
-
"role": "master"
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"cmd": "/ts 开启同步 <服务器名称>",
|
|
48
|
-
"desc": "开启指定服务器的群聊消息同步功能",
|
|
49
|
-
"usage": "/ts 开启同步 <服务器名称>",
|
|
50
|
-
"role": "master"
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"cmd": "/ts 关闭同步 <服务器名称>",
|
|
54
|
-
"desc": "关闭指定服务器的群聊消息同步功能",
|
|
55
|
-
"usage": "/ts 关闭同步 <服务器名称>",
|
|
56
|
-
"role": "master"
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
"cmd": "/ts 重连",
|
|
60
|
-
"desc": "断开并重新建立所有服务器的 WebSocket 连接",
|
|
61
|
-
"role": "master"
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
}
|
|
15
|
+
"services": [
|
|
16
|
+
"config"
|
|
17
|
+
]
|
|
65
18
|
},
|
|
66
19
|
"dependencies": {
|
|
67
20
|
"ws": "^8.18.0"
|
|
68
21
|
},
|
|
69
22
|
"peerDependencies": {
|
|
70
|
-
"mioku": "^0.
|
|
71
|
-
"mioki": "^0.16.0"
|
|
23
|
+
"mioku": "^1.0.0"
|
|
72
24
|
},
|
|
73
25
|
"devDependencies": {
|
|
74
26
|
"mioku": "workspace:*",
|
|
75
|
-
"mioki": "^0.16.0",
|
|
76
27
|
"@types/ws": "^8.5.13"
|
|
77
28
|
}
|
|
78
29
|
}
|
package/utils/command-router.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export interface ParsedCommand {
|
|
2
|
-
action: string;
|
|
3
|
-
args: string[];
|
|
4
|
-
raw: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function parseTsCommand(text: string): ParsedCommand | null {
|
|
8
|
-
const trimmed = text.trim();
|
|
9
|
-
if (!trimmed.startsWith("/ts")) return null;
|
|
10
|
-
|
|
11
|
-
const remainder = trimmed.slice(3).trim();
|
|
12
|
-
if (!remainder) {
|
|
13
|
-
return { action: "", args: [], raw: "" };
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const parts = remainder.split(/\s+/);
|
|
17
|
-
const action = parts[0] || "";
|
|
18
|
-
const args = parts.slice(1);
|
|
19
|
-
|
|
20
|
-
return { action, args, raw: remainder };
|
|
21
|
-
}
|