send-feishu

📁 jssfy/k-skills 📅 7 days ago
46
总安装量
46
周安装量
#8376
全站排名
安装命令
npx skills add https://github.com/jssfy/k-skills --skill send-feishu

Agent 安装分布

codex 46
github-copilot 45
kimi-cli 45
gemini-cli 45
cursor 45
amp 45

Skill 文档

Send Feishu Message

Send messages, images, and files to Feishu groups or individuals.

Environment Variables

Variable Purpose Required
FEISHU_WEBHOOK Group Webhook URL For text/card/image to group
FEISHU_APP_ID App credential For image/file upload & API send
FEISHU_APP_SECRET App credential For image/file upload & API send
FEISHU_CHAT_ID Group chat ID (oc_xxx) For API send to group
FEISHU_USER_OPEN_ID Personal open_id (ou_xxx) For send to individual

Decision Logic

Choose the sending method based on content type and target:

Text/Card to group     → Webhook (simple, no auth needed)
Image to group         → Get token → Upload image → Webhook send image_key
File to group          → Get token → Upload file → API send to chat_id
Image/File to person   → Get token → Upload resource → API send to open_id
Text/Card to person    → Get token → API send to open_id

Choosing Format

Use text — simple one-liner (status update, quick note).

Use card — content has title + body, structured data, summary, or report.

Use image — user explicitly asks to send an image file, screenshot, or chart.

Use file — user asks to send .html/.md/.pdf/.doc/.xls etc., or content is too long for card display.

Send to individual — user says “发给我”, “私发”, “发到我的飞书”, or specifies a person.

Step A: Get tenant_access_token

Required for image upload, file upload, and API message sending. Skip this step if only sending text/card via Webhook.

curl -s -X POST 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' \
  -H 'Content-Type: application/json' \
  -d '{"app_id":"'"$FEISHU_APP_ID"'","app_secret":"'"$FEISHU_APP_SECRET"'"}'

Response: {"code":0,"msg":"ok","tenant_access_token":"t-xxx","expire":7200}

Extract the token and store in a variable for subsequent steps.

Step B: Upload Image (get image_key)

Required when sending an image. Supports JPEG/PNG/WEBP/GIF/TIFF/BMP/ICO, max 10MB.

curl -s -X POST 'https://open.feishu.cn/open-apis/im/v1/images' \
  -H "Authorization: Bearer $TOKEN" \
  -F 'image_type="message"' \
  -F 'image=@"/path/to/image.png"'

Response: {"code":0,"data":{"image_key":"img_xxx"}}

Step C: Upload File (get file_key)

Required when sending a file. Max 30MB.

curl -s -X POST 'https://open.feishu.cn/open-apis/im/v1/files' \
  -H "Authorization: Bearer $TOKEN" \
  -F 'file_type="stream"' \
  -F 'file_name="report.md"' \
  -F 'file=@"/path/to/file"'

file_type values: opus (audio), mp4 (video), pdf, doc, xls, ppt, stream (binary, use as default).

Response: {"code":0,"data":{"file_key":"file_xxx"}}

Sending via Webhook

Send Text

curl -s -X POST "$FEISHU_WEBHOOK" -H "Content-Type: application/json" \
  -d '{"msg_type":"text","content":{"text":"MESSAGE_HERE"}}'

Send Card

Pick header color by sentiment:

  • green — success, complete, done
  • orange — warning, attention
  • red — error, failure
  • blue — info, neutral (default)
  • purple — highlight, special

Short content (no special characters):

curl -s -X POST "$FEISHU_WEBHOOK" -H "Content-Type: application/json" \
  -d '{
    "msg_type":"interactive",
    "card":{
      "header":{"title":{"content":"TITLE","tag":"plain_text"},"template":"COLOR"},
      "elements":[{"tag":"div","text":{"content":"BODY_LARK_MD","tag":"lark_md"}}]
    }
  }'

Long content or content with special characters ($, ", \n, etc.) — always use this pattern:

python3 - << 'EOF' | curl -s -X POST "$FEISHU_WEBHOOK" \
  -H "Content-Type: application/json" -d @-
import json
card = {
    "msg_type": "interactive",
    "card": {
        "header": {"title": {"content": "TITLE", "tag": "plain_text"}, "template": "COLOR"},
        "elements": [
            {"tag": "div", "text": {"content": "BODY LINE 1\nBODY LINE 2", "tag": "lark_md"}},
            {"tag": "hr"},
            {"tag": "div", "text": {"content": "SECTION 2 CONTENT", "tag": "lark_md"}}
        ]
    }
}
print(json.dumps(card))
EOF

Card body supports lark_md: **bold**, *italic*, ~~strike~~, [link](url), \n for newlines.

Send Image via Webhook

After uploading image (Step B) to get image_key:

curl -s -X POST "$FEISHU_WEBHOOK" \
  -H "Content-Type: application/json" \
  -d '{"msg_type":"image","content":{"image_key":"img_xxx"}}'

Sending via API

Use API when sending files, or sending any content to an individual.

Send to Group (chat_id)

curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{"receive_id":"'"$FEISHU_CHAT_ID"'","msg_type":"MSG_TYPE","content":"CONTENT_JSON_STRING"}'

Send to Individual (open_id)

curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{"receive_id":"'"$FEISHU_USER_OPEN_ID"'","msg_type":"MSG_TYPE","content":"CONTENT_JSON_STRING"}'

API Content Formats

The content field must be a JSON-encoded string (escaped JSON inside JSON).

Text:

{"receive_id":"ID","msg_type":"text","content":"{\"text\":\"Hello\"}"}

Image (after upload):

{"receive_id":"ID","msg_type":"image","content":"{\"image_key\":\"img_xxx\"}"}

File (after upload):

{"receive_id":"ID","msg_type":"file","content":"{\"file_key\":\"file_xxx\"}"}

After Sending

Check the response JSON:

  • Webhook: {"code":0,"msg":"success"} → success
  • API: {"code":0,"msg":"success","data":{...}} → success
  • code != 0 → report the error:
    • 19001: webhook URL invalid
    • 19021: signature check failed
    • 19022: IP not whitelisted
    • 19024: keyword check failed
    • 99991663: token invalid or expired (re-run Step A)
    • 230001: bot not in chat or no permission

Important

  • Always escape special characters in JSON (quotes, backslashes, newlines)
  • Use printf '%s' or heredoc to safely pass message content to curl if it contains special characters
  • If required env vars are not set, tell user which ones to configure
  • Keep messages concise — Feishu cards have display limits
  • Token from Step A is valid for 2 hours; no need to refresh within a session
  • App permissions required: im:message:send_as_bot (send messages), im:resource (upload images and files)