一个基于 napcat-sdk 的 QQ 私聊客服催回复机器人。
它的目标很简单:客户发来私聊消息后,如果客服迟迟没有回复,机器人就把消息整理后推送到内部群里提醒;如果超时更久,再按里程碑继续催办;客服处理完成后,再自动结束监控。
- QQ 私聊作为客服入口
- 需要把未回复客户集中提醒到内部群
- 希望减少人工盯聊天窗口的成本
- 希望用“贴表情”或“戳一戳”做快捷收尾
- 自动通过好友申请,并同步通知到内部群
- 监听非白名单用户的私聊消息
- 对新消息做 1 分钟防抖,避免客户连续补充消息时频繁提醒
- 将待处理客户消息以合并转发形式发送到内部群
- 按里程碑进行超时催办
- 客服私聊回复后自动移出监控队列
- 支持在内部群对提醒消息贴表情,自动给客户发送结束语
- 支持在通知群通过戳一戳,输出运行统计信息
- 支持在通知群引用合并转发消息后执行
.say/.more/.bye/.close/.list指令 - 支持在私聊窗口通过戳一戳,自动给客户发送结束语
- 夜间免打扰模式:夜间时段自动延后提醒,并在次日汇总发送
- 状态持久化:程序重启后自动恢复待回复客户和监听队列
- 会话存档:每次会话结束后自动保存聊天记录到本地 JSON 文件
- 客户发送私聊消息,机器人将其加入待回复队列。
- 如果客户在 1 分钟内继续发消息,计时会重置。
- 超过 1 分钟仍未回复时,机器人向内部群发送“新客户提醒”。
- 超过配置的里程碑时间后,机器人继续发送“超时催办”。
- 客服回复后,该客户会从监控队列中移除。
- 客服也可以通过在内部群提醒消息上贴表情,或在私聊窗口戳一戳来结束会话。
- 若开启夜间模式,夜间时段的所有提醒会暂存,并在次日指定时间统一汇总发送。
所有命令均需 引用(回复) 一条由机器人发送的合并转发消息,才能正确识别对应的客户。
| 指令 | 用途 | 示例 | 是否需要引用消息 |
|---|---|---|---|
.say <内容> |
向客户发送私聊消息 | .say 您好,请问有什么可以帮您? |
是 |
.more |
获取客户最近 100 条历史消息(以合并转发形式返回) | .more |
是 |
.bye |
向客户发送结束语并关闭会话 | .bye |
是 |
.close |
关闭会话(不发送结束语) | .close |
是 |
.list |
列出所有未回复客户及其等待时间 | .list |
否 |
.help |
显示帮助信息 | .help |
否 |
附加操作:
- 在内部群对机器人发送的合并转发消息贴表情(任何表情),机器人会自动向该客户发送结束语并关闭会话(仅支持单客户消息)。
- 在内部群戳一戳机器人,机器人会发送状态统计面板。
- 客户发消息后自动进入队列(白名单用户除外)。
- 客服直接私聊回复客户,会话自动结束。
- 客户在私聊窗口戳一戳机器人,机器人会自动发送结束语并关闭会话(无论是否在队列中)。
在配置文件中可以设定夜间时段(例如 22:00 至 08:00)。夜间时段内:
- 所有新客户提醒和超时催办不会立即发送,而是暂存在内存中。
- 到达设定的汇总时间(如
08:00)时,机器人会在内部群发送一条汇总消息,列出夜间所有待回复客户的数量,并清空暂存队列。
项目使用 config.yaml 作为配置文件(示例见下文)。首次运行前请根据实际情况修改。
# WebSocket 连接
ws_url: "ws://127.0.0.1:8080"
ws_token: "your_token"
# 内部通知群号
internal_group_id: 123456789
# 白名单(不监控的 QQ 号)
whitelist:
- 100000
- 100001
# 超时里程碑(单位:分钟)
milestones:
- 5
- 15
- 30
- 60
- 120
- 180
- 360
- 720
- 1440
- 2880
- 4320
# 最多同时监听多少条可快捷处理的合并转发消息
monitored_forward_limit: 100
# 结束语内容
closing_message: "您好,本次服务已结束,感谢您的咨询。"
# 各命令的防抖时间(秒)
debounce_seconds:
say: 5
bye: 5
more: 10
list: 5
close: 5
# 好友申请去重缓存过期时间(秒)
processed_friend_requests_expire: 300
# 回复耗时记录最大数量
reply_duration_maxlen: 1000
# 客服可用时间段(星期几 -> 时间段列表)
# 用于 .list 等命令中随机 @ 可用成员
availability:
123456789: # 客服 QQ 号
monday:
- ["09:00", "12:00"]
- ["13:00", "18:00"]
tuesday:
- ["09:00", "12:00"]
# ... 其他日期
# 存档目录
archive_dir: "archives"
# 状态文件路径
state_file: "archives/state.json"
# 获取客户历史消息时,仅拉取最近多少秒内的消息
recent_message_max_age: 86400 # 24小时
# 监听合并转发的最大存活时间(秒)
max_listen_age: 86400
# 夜间模式配置
night_mode:
start: "22:00"
end: "08:00"
summary_time: "08:00"| 配置项 | 说明 |
|---|---|
ws_url / ws_token |
NapCat WebSocket 地址和 Token |
internal_group_id |
接收提醒的内部群号 |
whitelist |
不参与监控的 QQ 号列表 |
milestones |
超时催办时间点(分钟),每个客户每个里程碑只提醒一次 |
availability |
客服的在线时间段,用于随机 @ 提醒 |
night_mode |
夜间免打扰时段和汇总时间 |
archive_dir |
会话记录存档目录 |
state_file |
状态持久化文件路径 |
- Python
3.10+(代码使用了match语句,需要 3.10 及以上) - 可用的 NapCat / OneBot WebSocket 服务
- 一个用于接收提醒的内部 QQ 群
使用 uv 管理依赖(推荐):
uv sync或手动安装:
pip install napcat-sdk pyyamluv run python main.py启动后程序会:
- 建立到 NapCat 的 WebSocket 连接
- 加载历史状态(如果存在
state.json) - 后台每 60 秒执行一次巡检
- 在连接断开后自动重连
如果你用的是 Claude Code、Codex 或其他编码代理,建议在开始修改代码前,先让 AI 阅读这份 napcat-sdk 专用技能说明:
这样 AI 通常能更快理解:
napcat-sdk的核心心智模型- 应该优先使用哪些文档查询方式
NapCatClient、事件类型、消息段的大致用法- 常见坑点,比如
user_id/group_id的类型差异
如果你要直接给 AI 一句提示词,可以这样写:
在修改这个项目之前,请先阅读 https://raw.githubusercontent.com/faithleysath/napcat-sdk/refs/heads/main/skills/use-napcat-sdk/SKILL.md,并按照其中的 napcat-sdk 使用约定、文档查询路径和常见注意事项来理解与修改代码。
- 客户首次发消息后,不会立刻提醒
- 只有当“距离最后一条消息已满 1 分钟”时,才会推送到内部群
- 这样可以避免客户连续发多条消息时刷屏
默认里程碑如下:
5, 15, 30, 60, 120, 180, 360, 720, 1440, 2880, 4320 分钟
每个客户每个里程碑只提醒一次;如果客户中途又发新消息,计时和里程碑记录都会重置。
以下行为会让客户从待回复队列中移除:
- 客服直接私聊回复客户
- 通过内部群提醒消息触发自动结束语,并成功发出私聊
- 其他触发了机器人主动私聊发送消息的收尾动作
- 合并转发中如果包含多个客户,暂不支持一键结束(机器人会提示手动处理)。
- 夜间延后的通知仅保留客户数量,不保留具体消息内容。
- 状态文件 (
state.json) 和存档目录 (archives/) 会随时间增长,需要定期清理。
.
├── main.py # 主程序,事件监听与巡检逻辑
├── config.yaml # 配置文件(需自行创建)
├── pyproject.toml # 项目元信息与依赖
├── uv.lock # uv 锁文件
├── archives/ # 会话存档目录(自动生成)
│ └── state.json # 运行时状态(自动生成)
└── README.md
- 支持多客服分组和更细粒度的权限控制
- 将夜间延后的通知改为可配置的汇总粒度(如按小时汇总)
- 增加 Web 管理界面查看会话记录
- 支持将存档数据导出为 CSV 或数据库
暂未声明。