Skill: magicaldd/feishu-reaction (version 1.1.0)

--- name: feishu-reaction description: Add or remove emoji reactions on Feishu (Lark) messages, and respond to user reactions. Use when the user asks to react to a message, add an emoji/expression to a message, when you want to acknowledge a message with a reaction instead of a text reply, or when the user reacts to your message with an emoji. Also enables proactive reactions to incoming messages based on sentiment. Requires Feishu channel configured in OpenClaw with im:message.reactions permission. --- # Feishu Reaction Add/remove emoji reactions on Feishu messages via API. Enables richer, more playful interactions beyond text. ## Usage ```bash # Add reaction bash scripts/feishu-reaction.sh <message_id> <emoji_type> # Remove reaction bash scripts/feishu-reaction.sh <message_id> <emoji_type> remove ``` Resolve `scripts/feishu-reaction.sh` relative to this skill's directory. ## Getting message_id The `message_id` comes from inbound message metadata (e.g., `om_x100b554e82c620a4c...`). Use the current message's `message_id` from conversation context. ## Behavior Guide ### Proactive reactions to user messages React to user messages naturally, like a human would: - User says something nice → HEART, THUMBSUP, or YEAH - User shares good news → PARTY, FIREWORKS, or CLAP - User asks for help → OK (then reply with text) - User sends something funny → SMILE or WITTY Don't overdo it — not every message needs a reaction. Use when it adds warmth without cluttering. ### Responding to user reactions When a user reacts to your message with an emoji, respond appropriately: **Positive/neutral reactions** (HEART, THUMBSUP, YEAH, GoGoGo, FISTBUMP, PARTY, CLAP, SMILE, WOW, SaluteFace, WINK, GLANCE, etc.): → React back with a complementary emoji. No text reply needed. **Negative/questioning reactions** (ANGRY, SPEECHLESS, FACEPALM, CRY, TERROR, SWEAT, WHAT, etc.): → React back with a caring emoji (HUG, HEART) AND follow up with a text message asking what's wrong. ### Choosing reaction emojis Pick reactions that feel natural and varied — don't always use the same one. Match the energy: - They send ❤️ → reply with 🤗 or ❤️ - They send 💪 → reply with 🔥 or 💪 - They send 👀 → reply with 😉 ## Available Emoji Types Common: `THUMBSUP`, `SMILE`, `OK`, `HEART`, `LOVE`, `THANKS`, `YEAH`, `AWESOME`, `PARTY`, `CLAP`, `APPLAUSE` Emotions: `CRY`, `ANGRY`, `SHY`, `BLUSH`, `SPEECHLESS`, `TERROR`, `WOW`, `FACEPALM`, `SWEAT`, `PROUD`, `OBSESSED` Actions: `WAVE`, `HUG`, `KISS`, `WINK`, `TONGUE`, `MUSCLE`, `SALUTE` Objects: `FIRE`, `BEER`, `CAKE`, `GIFT`, `ROSE`, `FIREWORKS` Other: `WITTY`, `JIAYI` ## Prerequisites - Feishu channel configured in OpenClaw (`openclaw.json` has `channels.feishu.appId` and `appSecret`) - App has `im:message:reaction` permission (飞书开放平台 → 应用权限 → 消息与群组 → 表情回复) ## Examples React with thumbs up to acknowledge a message: ```bash bash scripts/feishu-reaction.sh "om_xxx" "THUMBSUP" ``` React with heart to show appreciation: ```bash bash scripts/feishu-reaction.sh "om_xxx" "HEART" ``` Remove a reaction: ```bash bash scripts/feishu-reaction.sh "om_xxx" "THUMBSUP" remove ```

path: scripts/feishu-reaction.sh
content: #!/bin/bash
# Feishu Message Reaction Tool
# Usage: feishu-reaction.sh <message_id> <emoji_type> [remove]
# Adds or removes an emoji reaction on a Feishu message.

set -euo pipefail

MSG_ID="${1:?Usage: $0 <message_id> <emoji_type> [remove]}"
EMOJI_TYPE="${2:-THUMBSUP}"
ACTION="${3:-add}"

# Locate openclaw config
CONFIG="${OPENCLAW_CONFIG:-$HOME/.openclaw/openclaw.json}"
if [ ! -f "$CONFIG" ]; then
  echo "Error: openclaw.json not found at $CONFIG" >&2
  exit 1
fi

# Extract Feishu credentials
APP_ID=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appId'])")
APP_SECRET=$(python3 -c "import json;print(json.load(open('$CONFIG'))['channels']['feishu']['appSecret'])")

# Get tenant access token
[REDACTED_SECRET] -sf '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\"}" \
  | python3 -c "import json,sys;print(json.load(sys.stdin)['tenant_access_token'])")

if [ "$ACTION" = "remove" ]; then
  # Find the bot's reaction_id for this emoji, then delete it
  REACTION_ID=$(curl -sf "https://open.feishu.cn/open-apis/im/v1/messages/${MSG_ID}/reactions?reaction_type=${EMOJI_TYPE}" \
    -H "Authorization: Bearer $TOKEN" \
    | python3 -c "
import json,sys
d=json.load(sys.stdin)
for item in d.get('data',{}).get('items',[]):
    if item.get('reaction_type',{}).get('emoji_type')=='${EMOJI_TYPE}':
        if item.get('operator',{}).get('operator_type')=='app':
            print(item['reaction_id']); break
" 2>/dev/null)

  if [ -n "$REACTION_ID" ]; then
    curl -sf -X DELETE "https://open.feishu.cn/open-apis/im/v1/messages/${MSG_ID}/reactions/${REACTION_ID}" \
      -H "Authorization: Bearer $TOKEN" \
      | python3 -c "import json,sys;d=json.load(sys.stdin);print(f'code={d[\"code\"]}, msg={d[\"msg\"]}')"
  else
    echo "No matching reaction found to remove"
  fi
else
  # Add reaction
  curl -sf -X POST "https://open.feishu.cn/open-apis/im/v1/messages/${MSG_ID}/reactions" \
    -H "Authorization: Bearer $TOKEN" \
    -H 'Content-Type: application/json' \
    -d "{\"reaction_type\":{\"emoji_type\":\"${EMOJI_TYPE}\"}}" \
    | python3 -c "import json,sys;d=json.load(sys.stdin);print(f'code={d[\"code\"]}, msg={d[\"msg\"]}')"
fi


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)