---
name: feishu-group-msg-sync
description: 定期同步飞书群聊消息到MySQL数据库或飞书电子表格。以Bot身份拉取群消息（文本/图片/视频/音频/文件），非文本媒体上传到腾讯COS生成可访问链接，所有记录写入MySQL数据库（支持引用回复关系）或追加到飞书电子表格。支持crontab定时执行。触发场景：群消息记录、群聊同步到表格、群聊数据采集、群反馈收集。
---

# 飞书群聊消息同步

定期将飞书群聊消息同步到MySQL数据库或飞书电子表格，非文本媒体上传到COS。

## 存储方案

### 方案一：MySQL数据库（推荐）

将消息存储到 `vala_test.feishu_group_message` 表，支持：
- 完整的消息元数据（message_id、parent_id、root_id）
- 引用回复关系（quote_message_id）
- 高效的查询和统计
- 与微信反馈数据统一管理

### 方案二：飞书电子表格

将消息追加到飞书电子表格，适合简单场景和快速查看。

## 工作流程

1. 以Bot身份从飞书群拉取增量消息（基于上次同步时间）
2. 提取消息元数据（message_id、parent_id、root_id、quote_message_id）
3. 文本消息直接记录内容
4. 媒体消息（图片/视频/音频/文件）下载后上传到腾讯COS，记录可访问URL
5. 所有记录写入MySQL数据库或追加到飞书电子表格

## 数据库表结构

`feishu_group_message` 表字段说明：

| 字段 | 类型 | 说明 |
|------|------|------|
| id | bigint | 自增主键 |
| chat_id | varchar(128) | 群聊ID（如 oc_xxx） |
| chat_name | varchar(255) | 群聊名称 |
| sender_id | varchar(128) | 发送者ID（open_id或user_id） |
| sender_name | varchar(255) | 发送者显示名称 |
| msg_type | varchar(32) | 消息类型（text/post/image/media/audio/file/sticker/system/merge_forward） |
| content | text | 消息文本内容或描述 |
| forward_detail | longtext | merge_forward转发详情（媒体已替换为COS链接） |
| media_url | varchar(1024) | 媒体文件COS URL |
| message_id | varchar(128) | 飞书消息ID（om_xxx） |
| parent_id | varchar(128) | 父消息ID（thread根消息） |
| root_id | varchar(128) | 根消息ID（thread根消息） |
| quote_message_id | varchar(128) | **引用消息ID（reply引用的消息）** |
| msg_time | datetime | 消息发送时间 |
| msg_timestamp | bigint | 消息时间戳（毫秒） |
| collected_at | datetime | 采集入库时间 |

### 引用回复关系

通过 `quote_message_id` 字段记录引用回复关系：
- 当用户在飞书中"回复"某条消息时，lark-cli 返回的消息数据包含 `reply_to` 字段（字符串类型，值为被引用消息的 `message_id`）
- 同步脚本自动提取 `reply_to` 并存入数据库的 `quote_message_id` 字段
- 可通过此字段查询某条消息的所有回复，构建完整对话链

**引用关系识别优先级**（脚本内 `extract_quote_message_id` 函数）：
1. `msg.reply_to` — lark-cli 格式（字符串，直接是 message_id）
2. `msg.parent_id` — 飞书原始API格式
3. `msg.body.quote.message_id` — 事件推送格式

**查询示例：**
```sql
-- 查询某条消息的所有回复
SELECT * FROM lark_group_message 
WHERE quote_message_id = 'om_xxx' 
ORDER BY msg_timestamp;

-- 查询完整对话链（原消息 + 所有回复）
SELECT * FROM lark_group_message 
WHERE message_id = 'om_xxx' OR quote_message_id = 'om_xxx'
ORDER BY msg_timestamp;
```

> 更多查询示例见 `references/query_examples.md`

## 前置条件

- Bot已加入目标飞书群
- Bot有权读取群消息（`im:message` / `im:message.group_at_msg` scope）
- Bot有权写入目标电子表格（已被添加为协作者）
- 腾讯COS凭证可用（参考 `tencent-cos-upload` skill）
- Python依赖：`cos-python-sdk-v5`、`lark-cli`

## 使用方式

### 方案一：同步到MySQL数据库（推荐）

1. 确保数据库表已创建：
```bash
mysql -h bj-cdb-8frbdwju.sql.tencentcdb.com -P 25413 -u chatbot -p'xhuBx7d@uT2gUVv' vala_test < scripts/create_feishu_group_message_table.sql
```

2. 修改脚本配置：
```bash
# 编辑 scripts/sync_group_to_mysql.py 顶部的配置区域
CHAT_ID = "oc_xxx"                    # 目标群ID
CHAT_NAME = "群名称"                   # 群名称
LARK_CLI_CONFIG = "/root/.openclaw/credentials/<agent>"  # Bot凭证目录
```

3. 设置crontab定时任务：
```bash
# 每4小时执行
0 */4 * * * /usr/bin/python3 /root/.openclaw/workspace-xiaokui/skills/feishu-group-msg-sync/scripts/sync_group_to_mysql.py >> /var/log/feishu_sync.log 2>&1
```

### 方案二：同步到飞书电子表格

1. 复制脚本模板并修改配置：
```bash
cp scripts/sync_group_to_sheet.py /path/to/your/scripts/
# 编辑脚本顶部的配置区域
```

2. 修改脚本中的配置常量：
```python
CHAT_ID = "oc_xxx"                    # 目标群ID
SPREADSHEET_TOKEN = "xxx"             # 电子表格token
SHEET_ID = "xxx"                      # sheet页ID
LARK_CLI_CONFIG = "/root/.openclaw/credentials/<agent>"  # Bot凭证目录
```

3. 设置crontab：
```bash
# 每小时执行
0 * * * * /usr/bin/python3 /path/to/sync_group_to_sheet.py >> /var/log/sync.log 2>&1
```

### 关键配置说明

#### 获取群ID
搜索群或从群设置中获取 `chat_id`（格式 `oc_xxx`）。

#### 获取电子表格信息
```bash
# 如果是wiki下的表格，先获取obj_token
LARKSUITE_CLI_CONFIG_DIR=<credentials> lark-cli wiki spaces get_node \
    --params '{"token":"<wiki_token>"}' --as bot

# 获取sheet_id
LARKSUITE_CLI_CONFIG_DIR=<credentials> lark-cli sheets +info \
    --spreadsheet-token <token> --as bot
```

#### 电子表格列结构

脚本默认写入4列，在表格首行设置表头：

| 列 | 内容 | 示例 |
|----|------|------|
| A | 时间 | 2026-04-10 15:30 |
| B | 反馈人 | 张三 |
| C | 信息类型 | 文本/图片/视频(15s)/语音/文件 |
| D | 信息内容(或地址) | 文本内容 或 https://domain/path/file.png |

## COS目录结构

媒体文件按类型和日期组织：
```
{cos_base_path}/
├── image/{date}/{msgid}.png
├── video/{date}/{msgid}.mp4
├── audio/{date}/{msgid}.ogg
└── file/{date}/{msgid}.ext
```

## 增量同步机制

- 同步时间记录在 `LAST_SYNC_FILE`（默认 `/tmp/last_feedback_sync_time`）
- 每次同步拉取 `上次同步时间 → 当前时间` 的消息
- 仅在写入成功后更新同步时间，确保不丢消息
- 首次运行自动从1小时前开始

## 消息类型处理

| 消息类型 | 处理方式 | quote_message_id |
|----------|---------|------------------|
| text/post | 直接记录文本内容 | 如有引用则记录 |
| image | 下载 → 上传COS → 记录URL | 如有引用则记录 |
| media(视频) | 下载 → 上传COS → 记录URL，类型含时长 | 如有引用则记录 |
| audio | 下载 → 上传COS → 记录URL | 如有引用则记录 |
| file | 下载 → 上传COS → 记录URL | 如有引用则记录 |
| sticker | 记录为"表情包" | 如有引用则记录 |
| merge_forward | 解析子消息、下载媒体→COS、生成forward_detail | 如有引用则记录 |
| system | 跳过（入群退群等系统消息） | - |
| 已删除 | 跳过 | - |

## 自定义扩展

### 同步多个群到数据库

复制 `sync_group_to_mysql.py` 并修改 `CHAT_ID` 和 `CHAT_NAME`，或改造为从配置文件读取多群列表。

### 修改表格列结构

如需修改电子表格列结构、增加字段，编辑 `sync_group_to_sheet.py` 中的 `process_message()` 函数返回的行数据。
