# lark2lark - 飞书群聊自动跨群转发机器人 基于飞书企业自建应用 + WebSocket 长连接,实现 7x24 小时无人值守的消息自动转发。 ## 架构 ``` 源群 ──┐ ├─ WebSocket 事件 ──> 白名单过滤 ──> 防死循环 ──> 去重 ──> 限流队列 ──> Forward API ──> 目标群 源群 ──┘ (匀速 <5 QPS) ``` | 模块 | 职责 | |------|------| | `config.py` | 加载 YAML / 环境变量配置 | | `dedup.py` | message_id LRU 去重(飞书重发保护) | | `ratelimit.py` | asyncio.Queue + 单 Worker 匀速消费(<5 QPS) | | `forwarder.py` | 事件处理 + 白名单 + sender_type=bot 过滤 + Forward API 调用 | | `bot.py` | Bot 子进程入口:WebSocket 长连接 + 限流 Worker | | `main.py` | 入口,启动 Web 面板(含 Bot 子进程管理) | | `web/supervisor.py` | FastAPI 面板后端:配置/状态/日志 API + 子进程管理 | | `web/auth.py` | 面板密码登录 + Cookie 签名鉴权 | | `web/index.html` | 单文件前端:配置/状态/日志三 Tab | ## 快速开始 ### 1. 创建飞书自建应用 1. 登录 [飞书开放平台](https://open.feishu.cn/) → 创建企业自建应用 2. **凭证与基础信息**:获取 `App ID` 和 `App Secret` 3. **权限管理**:申请以下 Scopes - `im:message.group_msg`(获取群组所有消息) - `im:message:send_as_bot`(以机器人身份发消息) - `im:resource`(可选,建议申请) 4. **事件与回调** → 事件配置 → 订阅方式选 **使用长连接接收事件** 5. 订阅事件:`im.message.receive_v1` 6. **机器人** 菜单:启用机器人 7. 发布版本 → 管理员审批 ### 2. 把机器人加入源群和目标群 在每个群设置 → 群机器人 → 添加机器人 → 选你的应用。 ### 3. 获取 chat_id ```bash # 可用飞书开放平台调试台,或调用获取群列表 API # https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/chat/list ``` ### 4. 配置 ```bash cp config.example.yaml config.yaml # 编辑 config.yaml 填入 app_id / app_secret / source_chat_ids / target_chat_ids ``` ### 5. 设置面板密码(重要) ```bash # Linux export LARK_PANEL_PASSWORD="your-strong-password" # Windows PowerShell $env:LARK_PANEL_PASSWORD="your-strong-password" ``` ### 6. 运行 ```bash pip install -r requirements.txt python main.py ``` 启动后访问 `http://服务器IP:8080`,用密码登录面板。 > 首次启动可只用面板配置:把 `config.example.yaml` 复制为 `config.yaml`(不必填真实凭据),启动后通过面板的"配置"页填入并保存即可,Bot 会自动重连。 ## Web 管理面板 面板提供三个功能页: - **配置**:在线编辑 app_id / app_secret / 源群 / 目标群 / QPS 等参数,保存后 Bot 自动重启生效(无需手动重启进程) - **状态**:实时显示 Bot 进程存活、WebSocket 连接状态、队列积压、去重缓存、运行时长(每 3 秒刷新) - **日志**:SSE 实时推送 Bot 日志,支持级别过滤,最多保留 500 条历史 面板密码通过环境变量 `LARK_PANEL_PASSWORD` 设置(推荐),或在 `config.yaml` 的 `panel.password` 配置(仅本地调试用)。 ## Docker 部署 ```bash docker build -t lark2lark . docker run -d --name lark2lark \ -p 8080:8080 \ -e LARK_PANEL_PASSWORD="your-strong-password" \ -v $(pwd)/config.yaml:/app/config.yaml \ --restart unless-stopped \ lark2lark ``` ## 设计要点 - **WebSocket 长连接**:免公网 IP / 域名 / Webhook,SDK 自动心跳保活 - **防死循环**:丢弃 `sender_type == "bot"` 的消息,避免双向转发风暴 - **幂等去重**:本地 LRU 缓存 message_id(不依赖 event_id),防止网络重发 - **限流缓冲**:asyncio.Queue 单 Worker 匀速消费,间隔 `1/max_qps` 秒,保守默认 4 QPS - **重试退避**:单条失败按指数退避重试,最终失败仅告警不阻塞队列 - **原生 Forward API**:无需下载二进制再上传,支持图片/文件/富文本无损转发 - **Web 面板**:FastAPI 后端 + 单文件前端,在线配置/状态/日志,密码登录保护 - **子进程隔离**:Bot 运行在子进程中,配置变更自动重启,崩溃自动恢复 ## 约束(飞书官方限制) 1. 不支持转发:红包、投票、语音、日程转让、端到端加密消息 2. 源消息被设置"禁止转发"时 API 无法越权转发 3. "合并转发"消息包无法二次拆分转发