@zhin.js/plugin-group-admin 0.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 +2 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +139 -0
- package/lib/index.js.map +1 -0
- package/package.json +32 -0
- package/src/index.ts +154 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zhin.js/plugin-group-admin
|
|
3
|
+
*
|
|
4
|
+
* 群管理插件 —— 入群欢迎、关键词回复、撤回提示、AI 群公告工具
|
|
5
|
+
*
|
|
6
|
+
* 功能:
|
|
7
|
+
* - 入群欢迎:监听 notice.receive 中的成员加入事件,发送可自定义欢迎语
|
|
8
|
+
* - 关键词回复:中间件匹配消息关键词并自动回复,支持增删查命令管理
|
|
9
|
+
* - 撤回提示:监听 notice.receive 中的群消息撤回事件,通知群内
|
|
10
|
+
* - AI 工具:group_announce,AI 可调用发送群公告
|
|
11
|
+
*
|
|
12
|
+
* 命令:
|
|
13
|
+
* 添加关键词 <keyword:text> <reply:text> 添加关键词回复对
|
|
14
|
+
* 删除关键词 <keyword:text> 删除关键词
|
|
15
|
+
* 关键词列表 查看所有关键词
|
|
16
|
+
*/
|
|
17
|
+
import { usePlugin, MessageCommand, ZhinTool } from 'zhin.js';
|
|
18
|
+
const plugin = usePlugin();
|
|
19
|
+
const { addCommand, addMiddleware, addTool, logger } = plugin;
|
|
20
|
+
// ─── 入群欢迎 ───────────────────────────────────────────────────────────────
|
|
21
|
+
const WELCOME_TEMPLATE = '欢迎新成员加入本群!';
|
|
22
|
+
plugin.on('notice.receive', async (notice) => {
|
|
23
|
+
if (notice.$type !== 'group_member_increase')
|
|
24
|
+
return;
|
|
25
|
+
if (notice.$channel.type !== 'group')
|
|
26
|
+
return;
|
|
27
|
+
const targetName = notice.$target?.name || notice.$target?.id || '新成员';
|
|
28
|
+
const welcomeMsg = `🎉 ${targetName},${WELCOME_TEMPLATE}`;
|
|
29
|
+
try {
|
|
30
|
+
const adapter = plugin.inject(notice.$adapter);
|
|
31
|
+
if (!adapter)
|
|
32
|
+
return;
|
|
33
|
+
const bot = adapter.bots?.find((b) => b.$config?.name === notice.$bot || b.$id === notice.$bot);
|
|
34
|
+
if (!bot)
|
|
35
|
+
return;
|
|
36
|
+
await bot.$sendMessage({
|
|
37
|
+
context: notice.$adapter,
|
|
38
|
+
bot: notice.$bot,
|
|
39
|
+
content: welcomeMsg,
|
|
40
|
+
id: notice.$channel.id,
|
|
41
|
+
type: notice.$channel.type,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
logger.warn(`发送入群欢迎消息失败: ${e.message}`);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
// ─── 关键词回复 ──────────────────────────────────────────────────────────────
|
|
49
|
+
const keywords = new Map();
|
|
50
|
+
// 中间件:匹配关键词自动回复
|
|
51
|
+
addMiddleware(async (message, next) => {
|
|
52
|
+
if (message.$channel.type !== 'group') {
|
|
53
|
+
await next();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const raw = message.$raw?.trim();
|
|
57
|
+
if (!raw) {
|
|
58
|
+
await next();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for (const [keyword, reply] of keywords) {
|
|
62
|
+
if (raw.includes(keyword)) {
|
|
63
|
+
await message.$reply(reply);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await next();
|
|
68
|
+
});
|
|
69
|
+
// 命令:添加关键词
|
|
70
|
+
addCommand(new MessageCommand('添加关键词 <keyword:text> <reply:text>')
|
|
71
|
+
.desc('添加一个关键词自动回复对')
|
|
72
|
+
.action(async (_message, result) => {
|
|
73
|
+
const { keyword, reply } = result.params;
|
|
74
|
+
if (!keyword || !reply)
|
|
75
|
+
return '请提供关键词和回复内容';
|
|
76
|
+
keywords.set(keyword, reply);
|
|
77
|
+
return `已添加关键词「${keyword}」→「${reply}」`;
|
|
78
|
+
}));
|
|
79
|
+
// 命令:删除关键词
|
|
80
|
+
addCommand(new MessageCommand('删除关键词 <keyword:text>')
|
|
81
|
+
.desc('删除一个关键词')
|
|
82
|
+
.action(async (_message, result) => {
|
|
83
|
+
const { keyword } = result.params;
|
|
84
|
+
if (!keyword)
|
|
85
|
+
return '请提供要删除的关键词';
|
|
86
|
+
if (!keywords.has(keyword))
|
|
87
|
+
return `关键词「${keyword}」不存在`;
|
|
88
|
+
keywords.delete(keyword);
|
|
89
|
+
return `已删除关键词「${keyword}」`;
|
|
90
|
+
}));
|
|
91
|
+
// 命令:关键词列表
|
|
92
|
+
addCommand(new MessageCommand('关键词列表')
|
|
93
|
+
.desc('查看所有关键词回复对')
|
|
94
|
+
.action(async () => {
|
|
95
|
+
if (keywords.size === 0)
|
|
96
|
+
return '当前没有设置任何关键词';
|
|
97
|
+
const lines = Array.from(keywords.entries()).map(([k, v], i) => `${i + 1}. 「${k}」→「${v}」`);
|
|
98
|
+
return `关键词列表(共 ${keywords.size} 条):\n${lines.join('\n')}`;
|
|
99
|
+
}));
|
|
100
|
+
// ─── 撤回提示 ───────────────────────────────────────────────────────────────
|
|
101
|
+
plugin.on('notice.receive', async (notice) => {
|
|
102
|
+
if (notice.$type !== 'group_recall')
|
|
103
|
+
return;
|
|
104
|
+
if (notice.$channel.type !== 'group')
|
|
105
|
+
return;
|
|
106
|
+
const operatorName = notice.$operator?.name || notice.$operator?.id || '某人';
|
|
107
|
+
const msg = `⚠️ ${operatorName} 撤回了一条消息`;
|
|
108
|
+
try {
|
|
109
|
+
const adapter = plugin.inject(notice.$adapter);
|
|
110
|
+
if (!adapter)
|
|
111
|
+
return;
|
|
112
|
+
const bot = adapter.bots?.find((b) => b.$config?.name === notice.$bot || b.$id === notice.$bot);
|
|
113
|
+
if (!bot)
|
|
114
|
+
return;
|
|
115
|
+
await bot.$sendMessage({
|
|
116
|
+
context: notice.$adapter,
|
|
117
|
+
bot: notice.$bot,
|
|
118
|
+
content: msg,
|
|
119
|
+
id: notice.$channel.id,
|
|
120
|
+
type: notice.$channel.type,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
logger.warn(`发送撤回提示失败: ${e.message}`);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// ─── AI 工具:群公告 ─────────────────────────────────────────────────────────
|
|
128
|
+
addTool(new ZhinTool('group_announce')
|
|
129
|
+
.desc('向群聊发送公告/通知消息')
|
|
130
|
+
.keyword('群公告', '通知', 'announce')
|
|
131
|
+
.param('message', { type: 'string', description: '要发送的公告内容' }, true)
|
|
132
|
+
.execute(async (args) => {
|
|
133
|
+
const content = args.message;
|
|
134
|
+
if (!content?.trim())
|
|
135
|
+
return '公告内容不能为空';
|
|
136
|
+
return `📢 群公告:\n${content}`;
|
|
137
|
+
})
|
|
138
|
+
.toTool());
|
|
139
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zhin.js/plugin-group-admin",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Group management plugin for Zhin.js — welcome, keyword reply, recall detection",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./lib/index.js",
|
|
7
|
+
"types": "./lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"development": "./src/index.ts",
|
|
12
|
+
"import": "./lib/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"files": ["src", "lib", "README.md"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc --build",
|
|
19
|
+
"clean": "rimraf lib"
|
|
20
|
+
},
|
|
21
|
+
"keywords": ["zhin", "zhin.js", "bot", "plugin", "group", "admin", "welcome", "keyword-reply"],
|
|
22
|
+
"author": { "name": "lc-cn", "email": "admin@liucl.cn", "url": "https://github.com/lc-cn" },
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {},
|
|
25
|
+
"devDependencies": { "typescript": "^5.9.3", "zhin.js": "workspace:*" },
|
|
26
|
+
"peerDependencies": { "zhin.js": ">=1.0.60" },
|
|
27
|
+
"repository": { "type": "git", "url": "git+https://github.com/zhinjs/zhin.git", "directory": "plugins/utils/group-admin" },
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public",
|
|
30
|
+
"registry": "https://registry.npmjs.org"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zhin.js/plugin-group-admin
|
|
3
|
+
*
|
|
4
|
+
* 群管理插件 —— 入群欢迎、关键词回复、撤回提示、AI 群公告工具
|
|
5
|
+
*
|
|
6
|
+
* 功能:
|
|
7
|
+
* - 入群欢迎:监听 notice.receive 中的成员加入事件,发送可自定义欢迎语
|
|
8
|
+
* - 关键词回复:中间件匹配消息关键词并自动回复,支持增删查命令管理
|
|
9
|
+
* - 撤回提示:监听 notice.receive 中的群消息撤回事件,通知群内
|
|
10
|
+
* - AI 工具:group_announce,AI 可调用发送群公告
|
|
11
|
+
*
|
|
12
|
+
* 命令:
|
|
13
|
+
* 添加关键词 <keyword:text> <reply:text> 添加关键词回复对
|
|
14
|
+
* 删除关键词 <keyword:text> 删除关键词
|
|
15
|
+
* 关键词列表 查看所有关键词
|
|
16
|
+
*/
|
|
17
|
+
import { usePlugin, MessageCommand, ZhinTool } from 'zhin.js'
|
|
18
|
+
|
|
19
|
+
const plugin = usePlugin()
|
|
20
|
+
const { addCommand, addMiddleware, addTool, logger } = plugin
|
|
21
|
+
|
|
22
|
+
// ─── 入群欢迎 ───────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
const WELCOME_TEMPLATE = '欢迎新成员加入本群!'
|
|
25
|
+
|
|
26
|
+
plugin.on('notice.receive', async (notice) => {
|
|
27
|
+
if (notice.$type !== 'group_member_increase') return
|
|
28
|
+
if (notice.$channel.type !== 'group') return
|
|
29
|
+
|
|
30
|
+
const targetName = notice.$target?.name || notice.$target?.id || '新成员'
|
|
31
|
+
const welcomeMsg = `🎉 ${targetName},${WELCOME_TEMPLATE}`
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const adapter = plugin.inject(notice.$adapter as any) as any
|
|
35
|
+
if (!adapter) return
|
|
36
|
+
const bot = adapter.bots?.find((b: any) => b.$config?.name === notice.$bot || b.$id === notice.$bot)
|
|
37
|
+
if (!bot) return
|
|
38
|
+
await bot.$sendMessage({
|
|
39
|
+
context: notice.$adapter,
|
|
40
|
+
bot: notice.$bot,
|
|
41
|
+
content: welcomeMsg,
|
|
42
|
+
id: notice.$channel.id,
|
|
43
|
+
type: notice.$channel.type,
|
|
44
|
+
})
|
|
45
|
+
} catch (e: any) {
|
|
46
|
+
logger.warn(`发送入群欢迎消息失败: ${e.message}`)
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
// ─── 关键词回复 ──────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
const keywords = new Map<string, string>()
|
|
53
|
+
|
|
54
|
+
// 中间件:匹配关键词自动回复
|
|
55
|
+
addMiddleware(async (message, next) => {
|
|
56
|
+
if (message.$channel.type !== 'group') {
|
|
57
|
+
await next()
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const raw = message.$raw?.trim()
|
|
62
|
+
if (!raw) {
|
|
63
|
+
await next()
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (const [keyword, reply] of keywords) {
|
|
68
|
+
if (raw.includes(keyword)) {
|
|
69
|
+
await message.$reply(reply)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await next()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
// 命令:添加关键词
|
|
78
|
+
addCommand(
|
|
79
|
+
new MessageCommand('添加关键词 <keyword:text> <reply:text>')
|
|
80
|
+
.desc('添加一个关键词自动回复对')
|
|
81
|
+
.action(async (_message, result) => {
|
|
82
|
+
const { keyword, reply } = result.params as { keyword: string; reply: string }
|
|
83
|
+
if (!keyword || !reply) return '请提供关键词和回复内容'
|
|
84
|
+
keywords.set(keyword, reply)
|
|
85
|
+
return `已添加关键词「${keyword}」→「${reply}」`
|
|
86
|
+
}),
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
// 命令:删除关键词
|
|
90
|
+
addCommand(
|
|
91
|
+
new MessageCommand('删除关键词 <keyword:text>')
|
|
92
|
+
.desc('删除一个关键词')
|
|
93
|
+
.action(async (_message, result) => {
|
|
94
|
+
const { keyword } = result.params as { keyword: string }
|
|
95
|
+
if (!keyword) return '请提供要删除的关键词'
|
|
96
|
+
if (!keywords.has(keyword)) return `关键词「${keyword}」不存在`
|
|
97
|
+
keywords.delete(keyword)
|
|
98
|
+
return `已删除关键词「${keyword}」`
|
|
99
|
+
}),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
// 命令:关键词列表
|
|
103
|
+
addCommand(
|
|
104
|
+
new MessageCommand('关键词列表')
|
|
105
|
+
.desc('查看所有关键词回复对')
|
|
106
|
+
.action(async () => {
|
|
107
|
+
if (keywords.size === 0) return '当前没有设置任何关键词'
|
|
108
|
+
const lines = Array.from(keywords.entries()).map(
|
|
109
|
+
([k, v], i) => `${i + 1}. 「${k}」→「${v}」`,
|
|
110
|
+
)
|
|
111
|
+
return `关键词列表(共 ${keywords.size} 条):\n${lines.join('\n')}`
|
|
112
|
+
}),
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
// ─── 撤回提示 ───────────────────────────────────────────────────────────────
|
|
116
|
+
|
|
117
|
+
plugin.on('notice.receive', async (notice) => {
|
|
118
|
+
if (notice.$type !== 'group_recall') return
|
|
119
|
+
if (notice.$channel.type !== 'group') return
|
|
120
|
+
|
|
121
|
+
const operatorName = notice.$operator?.name || notice.$operator?.id || '某人'
|
|
122
|
+
const msg = `⚠️ ${operatorName} 撤回了一条消息`
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const adapter = plugin.inject(notice.$adapter as any) as any
|
|
126
|
+
if (!adapter) return
|
|
127
|
+
const bot = adapter.bots?.find((b: any) => b.$config?.name === notice.$bot || b.$id === notice.$bot)
|
|
128
|
+
if (!bot) return
|
|
129
|
+
await bot.$sendMessage({
|
|
130
|
+
context: notice.$adapter,
|
|
131
|
+
bot: notice.$bot,
|
|
132
|
+
content: msg,
|
|
133
|
+
id: notice.$channel.id,
|
|
134
|
+
type: notice.$channel.type,
|
|
135
|
+
})
|
|
136
|
+
} catch (e: any) {
|
|
137
|
+
logger.warn(`发送撤回提示失败: ${e.message}`)
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// ─── AI 工具:群公告 ─────────────────────────────────────────────────────────
|
|
142
|
+
|
|
143
|
+
addTool(
|
|
144
|
+
new ZhinTool('group_announce')
|
|
145
|
+
.desc('向群聊发送公告/通知消息')
|
|
146
|
+
.keyword('群公告', '通知', 'announce')
|
|
147
|
+
.param('message', { type: 'string', description: '要发送的公告内容' }, true)
|
|
148
|
+
.execute(async (args) => {
|
|
149
|
+
const content = args.message as string
|
|
150
|
+
if (!content?.trim()) return '公告内容不能为空'
|
|
151
|
+
return `📢 群公告:\n${content}`
|
|
152
|
+
})
|
|
153
|
+
.toTool(),
|
|
154
|
+
)
|