news 2026/10/14 17:28:32

Wechatferry room-kick 插件:微信机器人实现 BAN/KICK 命令式与关键字自动踢人

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Wechatferry room-kick 插件:微信机器人实现 BAN/KICK 命令式与关键字自动踢人
  • 即时通讯
  • 后端
  • AI 应用

【免费下载链接】wechatferry

-

项目地址:https://gitcode.com/gh_mirrors/wec/wechatferry
点击查看免费下载

wechatferry 提供了@wechatferry/plugins插件包,其中wechatyPluginRoomKick让 Wechaty 机器人获得群聊踢人能力:管理员在群里 @ 某人并发送BAN或KICK即可将其移出群聊,机器人还可按blackListMessage匹配器自动踢掉发送敏感内容的成员。读完本文,你将掌握该插件的完整安装、配置与使用方式,并能从源码层面理解"命令识别 → @ 成员解析 → 底层协议踢人"的完整调用链。

插件做什么

尽管微信本身支持踢人操作,但手动操作比较麻烦。room-kick 插件把这个动作自动化为两种模式(见 docs/plugins/room-kick.md):

  1. 命令式踢人:被配置为管理员(admin)的用户在启用的群聊中 @ 一个或多个成员,并发送BAN(或KICK),机器人会先发一条警告消息,再把目标移出群聊;
  2. 关键字匹配踢人:普通成员发送命中blackListMessage匹配器的消息时,机器人自动警告并将其移出群聊。

该插件由 packages/plugins 包导出,包名@wechatferry/plugins,与safe-mode、room-mute、room-limit等插件共同发布。

安装与快速上手

安装

参考 docs/plugins/index.md,安装插件包的方式为:

# pnpm pnpm add -D @wechatferry/plugins # yarn yarn add -D @wechatferry/plugins # npm npm install -D @wechatferry/plugins

基本用法

官方文档给出的最小示例如下(注意room与admin是必填项,blackListMessage可选):

import { WechatyBuilder } from 'wechaty' import { wechatyPluginRoomKick } from '@wechatferry/plugins' const bot = WechatyBuilder.build() bot .use(wechatyPluginRoomKick({ admin: [], room: [], // blackListMessage: [/fuck/i] })) bot.start()

使用效果如下(摘自文档):

RoomName Admin: BAN @User Bot: @User 你违反了群规,管理员现将你移出群聊 System: 你将"User"移出了群聊

除了BAN踢人外,设置的管理员还可以使用KICK来踢人。

选项说明

wechatyPluginRoomKick的配置类型为RoomKickOptions,定义在 room-kick.ts,完整字段如下:

选项类型必填说明
roommatchers.RoomMatcherOptions是启用踢人的群聊范围,支持字符串、正则或群名称列表等wechaty-plugin-contrib提供的匹配器写法;未命中的群完全不受插件影响
adminmatchers.ContactMatcherOptions是管理员列表,只有管理员的BAN/KICK命令会被执行;管理员之间不能互踢
blackListMessagematchers.MessageMatcherOptions否黑名单消息匹配器(如正则/fuck/i),非管理员成员命中该匹配器的消息将触发自动踢人;不传则不启用关键字踢人

三个字段最终都会被wechaty-plugin-contrib的matchers.roomMatcher/contactMatcher/messageMatcher编译成谓词函数,因此既支持单个名称,也支持数组、正则等匹配器惯用写法。

两种踢人路径的判定逻辑

插件在 room-kick.ts 中通过defineWechatyPlugin定义(该工具函数见 utils.ts,作用仅是给工厂函数标注配置类型T),并注册bot.on('message')监听,判定流程为:

  1. 过滤自身消息:message.self()为真直接返回,机器人自己的发言不会触发任何逻辑;
  2. 过滤非群聊:message.room()为空(单聊)直接返回;
  3. 群范围过滤:isManagedRoom(room)不命中配置的room匹配器则返回;
  4. 管理员分支:isAdmin(talker)命中时,要求消息是文本类型(types.Message.Text),且mentionList非空,再取mentionText()(即去掉 @ 之后的文本)与KICK/BAN做精确相等比较。满足后先调用talkAdminKickWarn发送你违反了群规,管理员现将你移出群聊 ✈️,bot.sleep(1000)等待 1 秒后,遍历mentionList逐个执行room.remove(member),其中对每个成员再做一次isAdmin检查——踢人列表里混入管理员会被静默跳过;
  5. 关键字分支(else if):非管理员的消息若命中isBlackListMessage,则发送你发表了不当言论,现将你移出群聊✈️ \n欢迎再次进来。,等待 1 秒后room.remove(talker)。

两条路径的提示语均由talkers.roomTalker生成(来自wechaty-plugin-contrib),会自动带上被 @ 成员的提及。

底层原理:从 mention 解析到 wcf 协议踢人

"谁被 @ 了"是怎么识别的

message.mentionList()的数据来自 wechatferry 的 puppet 实现。群聊文本消息的 XML 里带有<msgsource>的atuserlist字段,puppet 侧的 room-parser.ts 会把message.xml解析为 JSON,将逗号分隔的atuserlist切分成 wxid 数组并写入消息 payload 的mentionIdList,Wechaty 层的mentionList()便由此而来。

发送方向上也有对应的 mention 处理:puppet.ts 中的messageSendText支持@[mention:wxid]语法,由 mentionTextParser 解析出被 @ 的 wxid 列表并替换为显示名后发送。因此插件里roomTalker发出的警告消息确实会 @ 到被踢者本人。

踢人如何落到微信协议

room.remove(member)在 wechatferry puppet 中对应roomDel()(puppet.ts):

override async roomDel( roomId: string, contactId: string, ): Promise<void> { log.verbose('WechatferryPuppet', 'roomDel(%s, %s)', roomId, contactId) this.agent.removeChatRoomMembers(roomId, contactId) }

agent 层的removeChatRoomMembers(agent.ts)把单个 wxid 归一化为数组后调用this.wcf.delRoomMembers;core 层的 client.ts 最终构造 protobuf 请求,函数号为wcf.Functions.FUNC_DEL_ROOM_MEMBERS,把wxids以逗号拼接(并去掉空格)发给 wcf 服务:

delRoomMembers(roomId: string, wxidList: string[]) { const req = new wcf.Request({ func: wcf.Functions.FUNC_DEL_ROOM_MEMBERS, m: new wcf.MemberMgmt({ roomid: roomId, wxids: wxidList.join(',').replaceAll(' ', ''), }), }) const { status } = this.send(req) return status }

也就是说,room-kick 插件的room.remove()调用链是:Room.remove → WechatferryPuppet.roomDel → WechatferryAgent.removeChatRoomMembers → WcfClient.delRoomMembers → FUNC_DEL_ROOM_MEMBERS协议请求。

使用注意与限制

  • 命令是精确匹配:源码中判断为text === 'KICK' || text === 'BAN'(room-kick.ts),mentionText()返回的是去掉 @ 之后的文本,因此必须形如BAN @User;写成ban @user或BAN@User之外的变体不会生效;
  • 必须带 @:管理员分支要求mentionList.length > 0,不带 @ 的BAN会被忽略,无法"踢最近发言者";
  • 管理员不可被踢:命令分支内对每个被 @ 成员再次做isAdmin判断,blackListMessage分支只作用于非管理员(else if结构),因此管理员发言命中黑名单也不会被自动踢出——从源码结构看,这是有意避免机器人误伤管理者的设计;
  • 警告与踢人之间有 1 秒延迟:bot.sleep(1000)保证警告消息先于"移出群聊"的系统提示出现,群成员能看到因果;
  • 仅监听 message 事件:插件不处理图片、文件等消息类型的黑名单匹配(matchers.messageMatcher对文本以外的消息按匹配器自身语义判定),BAN/KICK命令则只接受纯文本;
  • 群成员数量较多时注意执行节奏:BAN多人时是串行 for 循环逐个room.remove,没有额外节流。

相关能力

同一个插件包内还有语义相近的wechatyPluginRoomMute(禁言/解封,见 room-mute.ts),它复用了相同的"管理员 @ + 命令"模式(MUTE/UNMUTE命令、unstorage 持久化封禁时长、禁言期内再发言自动移出群聊),可作为 room-kick 的进阶或组合方案:先禁言警告、违规再实踢。

小结

wechatyPluginRoomKick用不到 60 行代码实现了"命令式 + 关键字"双模式群管:room/admin/blackListMessage三个匹配器决定作用范围,BAN/KICK命令与黑名单匹配分别覆盖人工管理与自动执法两类场景,底层则复用 wechatferry puppet 的roomDel → wcf FUNC_DEL_ROOM_MEMBERS协议链路完成真正的移出群聊动作。所有实现均可在 packages/plugins/src/room-kick/room-kick.ts 中直接核对。

  • 即时通讯
  • 后端
  • AI 应用

【免费下载链接】wechatferry

-

项目地址:https://gitcode.com/gh_mirrors/wec/wechatferry
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 17:28:01

2024 CSP-J初赛真题拆解:考点分布、常见陷阱与备考攻略

简介&#xff1a;2024年信息学奥赛CSP-J初赛真题详细分析&#xff0c;面向备战入门组第一轮的中学生与少儿编程学员&#xff0c;旨在帮助读者把握初赛题型与核心考点。文档内容以真题为线索&#xff0c;按基础知识理解、算法与数据结构、数学逻辑思维、编程语言知识四部分展开&…

作者头像 李华
网站建设 2026/10/14 17:27:42

轻量人脸检测1MB模型结构拆解与部署实践

很多朋友第一次听到“Ultra-Light-Fast-Generic-Face-Detector-1MB”这个名字&#xff0c;第一反应多半是&#xff1a;1MB的网络&#xff0c;真能做人脸检测&#xff1f;我一开始也不信&#xff0c;直到在一台资源很紧的嵌入式板子上把它的网络结构跑通&#xff0c;才发现这个轻…

作者头像 李华
网站建设 2026/10/14 17:27:12

高数值孔径(NA)如何决定显微镜成像分辨率与荧光信号质量

1. 高数值孔径不是玄学——它定义了显微镜的天花板1.1 数值孔径到底在描述什么搞过显微镜的人都知道&#xff0c;做成像实验就像撮合“光学”“样品”“探测器”三方的默契。很多时候换了高级样品&#xff0c;用了最新款相机&#xff0c;图像依然不理想&#xff0c;最后查下来&…

作者头像 李华
网站建设 2026/10/14 17:25:19

企业培训系统如何接入业务流程?拆解EduSoho的AI应用与集成思路

企业上线培训系统&#xff0c;通常希望解决三件事&#xff1a;让员工快速找到岗位知识&#xff0c;让培训任务能够持续执行&#xff0c;让管理者知道接下来应该辅导谁、改进什么。从系统建设角度看&#xff0c;这涉及内容管理、组织人员、学习任务、业务练习和数据分析。只把课…

作者头像 李华