SKILL.md 11.7 KB

name: feishu-lark description: > 飞书 Lark 官方 CLI 封装。支持消息发送、文档操作、 日历管理、云盘文件、联系人查询等核心功能。 基于 larksuite/cli 工具,适配 Android/Termux 环境。 category: productivity tags: [feishu, lark, messaging, productivity, cli] author: Hermes Agent version: 1.0.0

requires: [lark-cli]

Feishu/Lark Skill

飞书官方 CLI 工具的封装,适配 Android/Termux 环境。

前置要求

  1. 安装 lark-cli:

    curl -L -o /tmp/lark-cli.tar.gz "https://github.com/larksuite/cli/releases/download/v1.0.57/lark-cli-1.0.57-linux-arm64.tar.gz"
    tar -xzf /tmp/lark-cli.tar.gz -C /data/data/com.termux/files/usr/bin/
    chmod +x /data/data/com.termux/files/usr/bin/lark
    
  2. 配置环境变量(~/.hermes/.env):

    FEISHU_APP_ID=cli_a91b01debab81cd1
    FEISHU_APP_SECRET=your_app_secret_here
    
  3. 绑定应用:

    lark config bind --source hermes --app-id cli_a91b01debab81cd1 --identity user-default --force
    

认证方式

由于 Android/Termux DNS 限制,使用 tenant_access_token 方式:

# 获取 token
curl -s -X POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal \
  -H "Content-Type: application/json" \
  -d '{"app_id":"cli_a91b01debab81cd1","app_secret":"your_secret"}'

核心功能

1. 消息管理 (IM)

发送文本消息到群聊

lark im message create \
  --receive_id_type chat_id \
  --receive_id "oc_xxxxxx" \
  --msg_type text \
  --content '{"text":"消息内容"}'

发送富文本消息

lark im message create \
  --receive_id_type chat_id \
  --receive_id "oc_xxxxxx" \
  --msg_type post \
  --content '{"zh_cn":{"title":"标题","content":[[{"tag":"text","text":"内容"}]]}}'

获取群聊列表

lark im chat list

获取群成员

lark im chat member list --chat_id "oc_xxxxxx"

2. 文档管理 (Docs)

创建文档

lark docs create --title "文档标题" --content "文档内容"

获取文档内容

lark docs content get --document_id "doccnxxxxxx"

列出文档

lark docs list

3. 日历管理 (Calendar)

获取日历列表

lark api GET /open-apis/calendar/v4/calendars

创建事件

lark calendar event create \
  --calendar_id "primary" \
  --summary "会议标题" \
  --start_time "2026-06-25T10:00:00+08:00" \
  --end_time "2026-06-25T11:00:00+08:00"

4. 云盘管理 (Drive)

上传文件

lark drive file upload --file_path "/path/to/file" --parent_node "folder_token"

列出文件

lark drive file list --parent_node "folder_token"

5. 联系人管理 (Contact)

搜索用户

lark contact user search --query "用户名"

获取用户信息

lark contact user get --user_id "ou_xxxxxx"

6. 多维表格 (Base)

列出表格

lark base app list

获取记录

lark base record list --app_token "bas_xxxxxx" --table_id "tbl_xxxxxx"

常用 API 调用

通用 API 调用方式

lark api GET <path> [--params '<json>']
lark api POST <path> [--data '<json>']
lark api PUT <path> [--data '<json>']
lark api DELETE <path>

示例:获取用户信息

lark api GET /open-apis/contact/v3/users/ou_xxxxxx

示例:发送消息(注意 content 格式)

# ❌ 错误:content 不是 JSON 字符串
lark api POST /open-apis/im/v1/messages \
  --data '{
    "receive_id": "oc_xxxxxx",
    "msg_type": "text",
    "content": {"text": "Hello"}  # 错误!
  }'

# ✅ 正确:content 必须是 JSON 字符串
lark api POST /open-apis/im/v1/messages \
  --data '{
    "receive_id": "oc_xxxxxx",
    "msg_type": "text",
    "content": "{\"text\":\"Hello\"}"  # 正确!
  }'

Python 辅助脚本(处理 JSON 转义):

import json
import urllib.request

APP_ID = "cli_a91b01debab81cd1"
APP_SECRET = "your_secret"

# 获取 token
token_data = json.dumps({"app_id": APP_ID, "app_secret": APP_SECRET}).encode('utf-8')
token_req = urllib.request.Request(
    'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
    data=token_data,
    headers={'Content-Type': 'application/json'},
    method='POST'
)
with urllib.request.urlopen(token_req, timeout=30) as response:
    token_result = json.loads(response.read().decode('utf-8'))
    TOKEN = token_result['tenant_access_token']

# 发送消息(content 自动转义)
message_data = {
    "receive_id": "oc_xxxxxx",
    "msg_type": "text",
    "content": json.dumps({"text": "Hello"})  # 自动转义
}

msg_req = urllib.request.Request(
    'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',
    data=json.dumps(message_data).encode('utf-8'),
    headers={
        'Authorization': f'Bearer {TOKEN}',
        'Content-Type': 'application/json'
    },
    method='POST'
)
with urllib.request.urlopen(msg_req, timeout=30) as response:
    result = json.loads(response.read().decode('utf-8'))
    print(result)

实用脚本

快速发送消息(Bash)

#!/bin/bash
# send_feishu_msg.sh

CHAT_ID="$1"
MESSAGE="$2"

if [ -z "$CHAT_ID" ] || [ -z "$MESSAGE" ]; then
    echo "Usage: $0 <chat_id> <message>"
    exit 1
fi

lark im message create \
    --receive_id_type chat_id \
    --receive_id "$CHAT_ID" \
    --msg_type text \
    --content "{\"text\":\"$MESSAGE\"}"

发送消息(Python - 推荐,自动处理 JSON 转义)

# 使用内置脚本(自动处理 content 格式)
python3 ~/.hermes/skills/productivity/feishu-lark/scripts/send_message.py \
    oc_xxxxxx "Hello World"

# 发送卡片消息
python3 ~/.hermes/skills/productivity/feishu-lark/scripts/send_message.py \
    oc_xxxxxx '{"config":{"wide_screen_mode":true},"header":{"title":{"tag":"plain_text","content":"标题"},"template":"blue"},"elements":[{"tag":"div","text":{"tag":"lark_md","content":"**内容**"}}]}' \
    interactive

Python 脚本优势:

  • 自动处理 JSON 转义(避免 9499 错误)
  • 自动获取 token
  • 支持 text/post/interactive 消息类型
  • 更好的错误提示

获取 Token 脚本

#!/bin/bash
# get_feishu_token.sh

APP_ID="${FEISHU_APP_ID}"
APP_SECRET="${FEISHU_APP_SECRET}"

if [ -z "$APP_ID" ] || [ -z "$APP_SECRET" ]; then
    echo "Error: FEISHU_APP_ID and FEISHU_APP_SECRET must be set"
    exit 1
fi

RESPONSE=$(curl -s -X POST \
    https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal \
    -H "Content-Type: application/json" \
    -d "{\"app_id\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}")

TOKEN=$(echo "$RESPONSE" | grep -o '"tenant_access_token":"[^"]*"' | cut -d'"' -f4)
EXPIRE=$(echo "$RESPONSE" | grep -o '"expire":[0-9]*' | cut -d':' -f2)

echo "Token: $TOKEN"
echo "Expire: $EXPIRE seconds"

故障排除

DNS 问题

如果在 Android/Termux 遇到 DNS 解析错误:

# 配置 DNS
echo "nameserver 8.8.8.8
nameserver 114.114.114.114" > /data/data/com.termux/files/usr/etc/resolv.conf

# 手动添加 hosts
echo "198.18.0.87 accounts.feishu.cn" >> /data/data/com.termux/files/usr/etc/hosts

# 或使用 IP 直接访问 API
curl -H "Host: open.feishu.cn" https://198.18.0.87/open-apis/...

认证失败

# 检查配置
lark config show

# 检查认证状态
lark auth status

# 重新绑定
lark config bind --source hermes --app-id cli_a91b01debab81cd1 --identity user-default --force

Gateway 配置(接收消息)

问题: 用户 @ 机器人但无回复

原因:

  1. Gateway 未运行
  2. 用户未授权
  3. 日志目录权限问题

解决方案:

  1. 配置 Gateway 允许所有用户 (~/.hermes/.env):

    GATEWAY_ALLOW_ALL_USERS=true
    
  2. 配置飞书平台 (config.yaml):

    platforms:
    feishu:
    streaming: true
    app_id: cli_a91b01debab81cd1
    domain: feishu
    allow_all_users: true
    
  3. 授权特定用户:

    # 用户首次使用会收到配对码
    hermes pairing approve feishu <PAIRING_CODE>
    
  4. 修复日志目录权限 (Termux 环境):

    # Gateway 日志默认写入 ~/.hermes/logs,但 Termux 可能有权限问题
    mkdir -p /sdcard/.hermes/logs
    rm -rf ~/.hermes/logs
    ln -s /sdcard/.hermes/logs ~/.hermes/logs
    
  5. 启动 Gateway:

    # 检查状态
    hermes gateway status
    

启动(前台)

hermes gateway run

或后台启动

nohup hermes gateway run > ~/.hermes/logs/gateway.log 2>&1 &


6. **验证 Gateway 连接**:
```bash
# 查看日志
tail -f ~/.hermes/logs/gateway.log

# 应看到:
# - "Connecting to feishu..."
# - "[Feishu] Connected in websocket mode"
# - "Gateway running with X platform(s)"

常见错误

错误: Unauthorized user: xxx on feishu

  • 解决: 设置 GATEWAY_ALLOW_ALL_USERS=true 或执行 hermes pairing approve feishu <code>

错误: Permission denied: '/.hermes'

  • 解决: 创建日志目录链接到 /sdcard

错误: cannot import name 'env_float' from 'utils'

  • 解决: 检查 Python 环境,可能需要更新 hermes-agent

Hermes 飞书插件集成

hermes-feishu 插件 (推荐)

arkseek/hermes-feishu - 增强 Hermes 飞书消息通道,支持卡片消息和表格渲染。

安装:

hermes plugins install arkseek/hermes-feishu
hermes plugins enable hermes-feishu

配置环境变量 (~/.hermes/.env):

FEISHU_APP_ID=cli_a91b01debab81cd1
FEISHU_APP_SECRET=your_secret
HERMES_FEISHU_CHAT_ID=oc_xxxxxx  # 默认群聊ID

提供的工具:

  • send_feishu_card - 发送卡片消息(支持 Markdown + 表格)
  • send_feishu_table - 发送结构化表格数据
  • pre_llm_call - 自动注入格式化指令

使用示例:

# 发送卡片消息(注意:table 使用 columns 而不是 headers)
lark api POST /open-apis/im/v1/messages \
  --data '{
    "receive_id": "oc_xxxxxx",
    "msg_type": "interactive",
    "content": "{\"config\":{\"wide_screen_mode\":true},\"header\":{\"title\":{\"tag\":\"plain_text\",\"content\":\"标题\"},\"template\":\"blue\"},\"elements\":[{\"tag\":\"div\",\"text\":{\"tag\":\"lark_md\",\"content\":\"**内容**\"}},{\"tag\":\"table\",\"columns\":[{\"tag\":\"text\",\"text\":\"列1\",\"width\":\"auto\",\"weight\":1},{\"tag\":\"text\",\"text\":\"列2\",\"width\":\"auto\",\"weight\":1}],\"rows\":[[{\"tag\":\"text\",\"text\":\"数据1\"},{\"tag\":\"text\",\"text\":\"数据2\"}]]}]}"
  }'

卡片消息格式要点:

  • config.wide_screen_mode: true(宽屏模式)
  • header.title: 标题(plain_text 或 lark_md)
  • header.template: 颜色模板(blue, red, green, orange, grey, default, wathet, turquoise, yellow, carmine, violet, purple, indigo)
  • elements: 内容元素数组
    • tag: div - 文本块(text 支持 lark_md 格式)
    • tag: table - 表格(使用 columns 而不是 headers)
    • tag: img - 图片
    • tag: action - 按钮

常见错误:

  • ❌ headers - 错误!table 不支持 headers
  • ✅ columns - 正确!table 使用 columns 定义表头
  • ❌ 直接传递 Python dict - 错误!content 必须是 JSON 字符串
  • ✅ json.dumps(content) - 正确!使用 json.dumps 转义

机器人身份

当前机器人: pixel phone agent (cli_a91b01debab81cd1)

  • Open ID: ou_187699924a3759c17932ac8f3c685978
  • 群聊: Lemonbot 全员+机器人群 (oc_3156253ca92a5f8649945c59769d9c52)

注意: 群里可能有多个机器人,用户需要 @ 正确的机器人才能收到回复。

参考文档