Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

free-feishu-voice

Send customized voice messages to Feishu chats by generating and uploading TTS audio using configurable credentials and options.

MIT-0 · Free to use, modify, and redistribute. No attribution required.
0 · 31 · 0 current installs · 0 all-time installs
MIT-0
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The name/description accurately describe generating TTS and uploading to Feishu. However, the registry metadata declares no required env vars or binaries while the SKILL.md clearly requires Feishu credentials (app_id, app_secret, chat_id) and system tools (jq, ffmpeg, espeak-ng or edge-tts). This mismatch suggests incomplete or inaccurate metadata.
!
Instruction Scope
The instructions tell the agent/user to read/write a config file under $HOME/.config, call external Feishu APIs, create temporary files under /tmp, and (in the Edge TTS path) run pip to install edge-tts at runtime. They rely on environment variables (FEISHU_* and optionally FEISHU_VOICE_CONFIG) even though the skill registry listed none. Runtime package installation and writing plaintext credentials to a home config file broaden the scope beyond a simple 'call Feishu' helper.
!
Install Mechanism
No install spec is provided in the registry, but SKILL.md instructs installing Python packages via pip (edge-tts) if missing. That means the script may modify the host Python environment without a declared install step; pip installs at runtime are higher-risk than an instruction-only script that only uses preinstalled dependencies.
!
Credentials
The only secrets the scripts need are Feishu app_id, app_secret, and chat_id, which are appropriate for the feature. However, the registry declares no required credentials, and the script writes/reads those secrets from a plaintext config file in the user's home by default. The skill also allows overriding via env vars, but the mismatch between declared and actual credential usage is a red flag.
Persistence & Privilege
The skill is instruction-only, not always-enabled, and does not request system-wide persistent privileges. It does create a config file under the user's home and may install Python packages at runtime, but it does not modify other skills or the agent platform.
What to consider before installing
This skill appears to do what it says (generate TTS and send it to Feishu), but the published metadata is incomplete and the runtime instructions perform environment changes. Before installing or running it: 1) Review the SKILL.md scripts yourself; they will create a plaintext config file (~/.config/feishu_voice_config.json) containing your Feishu app_id/app_secret and may install Python packages with pip. 2) Prefer running in a container or VM, or install dependencies manually rather than letting the script run pip automatically. 3) Use a Feishu credential with limited scope or a throwaway/test app if possible. 4) If you need stronger hygiene, convert the scripts to not auto-install packages and to store secrets in a more secure secret store instead of a plaintext file. Proceed only if you are comfortable with these trade-offs.

Like a lobster shell, security has layers — review code before you run it.

Current versionv1.0.0
Download zip
latestvk9783w7rzx7gmsh72547ye3qph831wbw

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

1. 配置文件模板(feishu_voice_config.json)

{
  "feishu_app_id": "your_app_id_here",
  "feishu_app_secret": "your_app_secret_here",
  "feishu_chat_id": "your_chat_id_here",
  "default_voice": "zh-CN-XiaoxiaoNeural",
  "default_text": "默认消息"
}

2. 基础版脚本(send_voice.sh)

#!/bin/bash
# send_voice.sh - 发送飞书语音消息(移除硬编码版)
set -euo pipefail

# ===================== 配置加载逻辑 =====================
# 配置文件路径(可通过环境变量覆盖)
CONFIG_FILE="${FEISHU_VOICE_CONFIG:-$HOME/.config/feishu_voice_config.json}"

# 加载配置文件(如果存在)
if [ -f "$CONFIG_FILE" ]; then
  APP_ID=$(jq -r '.feishu_app_id' "$CONFIG_FILE")
  APP_SECRET=$(jq -r '.feishu_app_secret' "$CONFIG_FILE")
  CHAT_ID=$(jq -r '.feishu_chat_id' "$CONFIG_FILE")
  DEFAULT_TEXT=$(jq -r '.default_text // "默认消息"' "$CONFIG_FILE")
else
  # 配置文件不存在时生成模板
  echo "⚠️ 配置文件不存在,生成模板到 $CONFIG_FILE"
  mkdir -p "$(dirname "$CONFIG_FILE")"
  cat > "$CONFIG_FILE" << 'EOF'
{
  "feishu_app_id": "your_app_id_here",
  "feishu_app_secret": "your_app_secret_here",
  "feishu_chat_id": "your_chat_id_here",
  "default_text": "默认消息"
}
EOF
  echo "❌ 请先编辑 $CONFIG_FILE 填写正确的配置后重试"
  exit 1
fi

# 环境变量覆盖配置文件(优先级更高)
APP_ID="${FEISHU_APP_ID:-$APP_ID}"
APP_SECRET="${FEISHU_APP_SECRET:-$APP_SECRET}"
CHAT_ID="${FEISHU_CHAT_ID:-$CHAT_ID}"
TEXT="${1:-$DEFAULT_TEXT}"

# ===================== 参数校验 =====================
if [ "$APP_ID" = "your_app_id_here" ] || [ -z "$APP_ID" ]; then
  echo "❌ 未配置飞书APP_ID,请检查配置文件或环境变量"
  exit 1
fi

if [ "$APP_SECRET" = "your_app_secret_here" ] || [ -z "$APP_SECRET" ]; then
  echo "❌ 未配置飞书APP_SECRET,请检查配置文件或环境变量"
  exit 1
fi

if [ "$CHAT_ID" = "your_chat_id_here" ] || [ -z "$CHAT_ID" ]; then
  echo "❌ 未配置飞书CHAT_ID,请检查配置文件或环境变量"
  exit 1
fi

# ===================== 核心逻辑 =====================
# 获取令牌
echo "🔑 获取飞书访问令牌..."
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\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" \
  | jq -r '.tenant_access_token // empty')

if [ -z "$TOKEN" ]; then
  echo "❌ 获取令牌失败,请检查APP_ID/APP_SECRET是否正确"
  exit 1
fi

# 生成语音
echo "🎙️ 生成语音文件..."
echo "$TEXT" | espeak-ng -v zh --stdout > /tmp/voice.wav 2>/dev/null
ffmpeg -i /tmp/voice.wav -acodec libopus -ac 1 -ar 16000 /tmp/voice.opus -y 2>/dev/null

# 上传文件
echo "📤 上传语音文件..."
UPLOAD_RESPONSE=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/files" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file_type=opus" \
  -F "file=@/tmp/voice.opus")

FILE_KEY=$(echo "$UPLOAD_RESPONSE" | jq -r '.data.file_key // empty')
if [ -z "$FILE_KEY" ] || [ "$FILE_KEY" = "null" ]; then
  echo "❌ 文件上传失败:$UPLOAD_RESPONSE"
  exit 1
fi

# 发送消息
echo "📨 发送语音消息..."
SEND_RESPONSE=$(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" \
  -d "{\"receive_id\":\"$CHAT_ID\",\"msg_type\":\"audio\",\"content\":\"{\\\"file_key\\\":\\\"$FILE_KEY\\\"}\"}")

# 结果判断
if echo "$SEND_RESPONSE" | jq -e '.code == 0' >/dev/null; then
  MSG_ID=$(echo "$SEND_RESPONSE" | jq -r '.data.message_id')
  echo "✅ 发送成功!消息ID:$MSG_ID"
else
  ERROR_MSG=$(echo "$SEND_RESPONSE" | jq -r '.msg // "未知错误"')
  echo "❌ 发送失败:$ERROR_MSG"
  exit 1
fi

# 清理临时文件
rm -f /tmp/voice.wav /tmp/voice.opus 2>/dev/null
echo "🧹 清理临时文件完成"

3. Edge TTS增强版脚本(send_voice_edge.sh)

#!/bin/bash
# send_voice_edge.sh - 使用Edge TTS发送高质量语音(移除硬编码版)
set -euo pipefail

# ===================== 配置加载逻辑 =====================
# 配置文件路径(可通过环境变量覆盖)
CONFIG_FILE="${FEISHU_VOICE_CONFIG:-$HOME/.config/feishu_voice_config.json}"

# 加载配置文件(如果存在)
if [ -f "$CONFIG_FILE" ]; then
  APP_ID=$(jq -r '.feishu_app_id' "$CONFIG_FILE")
  APP_SECRET=$(jq -r '.feishu_app_secret' "$CONFIG_FILE")
  CHAT_ID=$(jq -r '.feishu_chat_id' "$CONFIG_FILE")
  DEFAULT_TEXT=$(jq -r '.default_text // "默认消息"' "$CONFIG_FILE")
  DEFAULT_VOICE=$(jq -r '.default_voice // "zh-CN-XiaoxiaoNeural"' "$CONFIG_FILE")
else
  # 配置文件不存在时生成模板
  echo "⚠️ 配置文件不存在,生成模板到 $CONFIG_FILE"
  mkdir -p "$(dirname "$CONFIG_FILE")"
  cat > "$CONFIG_FILE" << 'EOF'
{
  "feishu_app_id": "your_app_id_here",
  "feishu_app_secret": "your_app_secret_here",
  "feishu_chat_id": "your_chat_id_here",
  "default_text": "默认消息",
  "default_voice": "zh-CN-XiaoxiaoNeural"
}
EOF
  echo "❌ 请先编辑 $CONFIG_FILE 填写正确的配置后重试"
  exit 1
fi

# 环境变量覆盖配置文件(优先级更高)
APP_ID="${FEISHU_APP_ID:-$APP_ID}"
APP_SECRET="${FEISHU_APP_SECRET:-$APP_SECRET}"
CHAT_ID="${FEISHU_CHAT_ID:-$CHAT_ID}"
TEXT="${1:-$DEFAULT_TEXT}"
VOICE="${2:-$DEFAULT_VOICE}"

# ===================== 依赖检查 =====================
check_dependency() {
  if ! command -v "$1" &> /dev/null; then
    echo "❌ 缺少依赖:$1,请先安装"
    exit 1
  fi
}

check_dependency "jq"
check_dependency "ffmpeg"
check_dependency "python3"
check_dependency "pip3"

# 检查edge_tts是否安装
if ! python3 -c "import edge_tts" &> /dev/null; then
  echo "📦 安装edge_tts依赖..."
  pip3 install edge-tts --quiet
fi

# ===================== 参数校验 =====================
if [ "$APP_ID" = "your_app_id_here" ] || [ -z "$APP_ID" ]; then
  echo "❌ 未配置飞书APP_ID,请检查配置文件或环境变量"
  exit 1
fi

if [ "$APP_SECRET" = "your_app_secret_here" ] || [ -z "$APP_SECRET" ]; then
  echo "❌ 未配置飞书APP_SECRET,请检查配置文件或环境变量"
  exit 1
fi

if [ "$CHAT_ID" = "your_chat_id_here" ] || [ -z "$CHAT_ID" ]; then
  echo "❌ 未配置飞书CHAT_ID,请检查配置文件或环境变量"
  exit 1
fi

# ===================== 核心逻辑 =====================
# 获取令牌
echo "🔑 获取飞书访问令牌..."
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\":\"$APP_ID\",\"app_secret\":\"$APP_SECRET\"}" \
  | jq -r '.tenant_access_token // empty')

if [ -z "$TOKEN" ]; then
  echo "❌ 获取令牌失败,请检查APP_ID/APP_SECRET是否正确"
  exit 1
fi

# 使用Edge TTS生成语音
echo "🎙️ 生成高质量语音($VOICE)..."
OPUS_FILE=$(python3 << EOF
import asyncio
import edge_tts
import subprocess
import tempfile
import os

async def generate_voice():
    # 生成MP3临时文件
    with tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) as mp3_file:
        communicate = edge_tts.Communicate("""$TEXT""", """$VOICE""")
        await communicate.save(mp3_file.name)
        
        # 转换为OPUS格式
        opus_file = mp3_file.name.replace('.mp3', '.opus')
        cmd = [
            'ffmpeg', '-i', mp3_file.name,
            '-acodec', 'libopus', '-ac', '1', '-ar', '16000',
            opus_file, '-y'
        ]
        subprocess.run(cmd, capture_output=True, check=True)
        return opus_file

# 兼容Windows系统
import sys
if sys.platform == "win32":
    asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())

opus_path = asyncio.run(generate_voice())
print(opus_path)
EOF
)

# 上传文件
echo "📤 上传语音文件..."
UPLOAD_RESPONSE=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/files" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file_type=opus" \
  -F "file=@$OPUS_FILE")

FILE_KEY=$(echo "$UPLOAD_RESPONSE" | jq -r '.data.file_key // empty')
if [ -z "$FILE_KEY" ] || [ "$FILE_KEY" = "null" ]; then
  echo "❌ 文件上传失败:$UPLOAD_RESPONSE"
  rm -f "$OPUS_FILE" "${OPUS_FILE%.opus}.mp3" 2>/dev/null
  exit 1
fi

# 发送消息
echo "📨 发送语音消息..."
SEND_RESPONSE=$(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" \
  -d "{\"receive_id\":\"$CHAT_ID\",\"msg_type\":\"audio\",\"content\":\"{\\\"file_key\\\":\\\"$FILE_KEY\\\"}\"}")

# 结果判断
if echo "$SEND_RESPONSE" | jq -e '.code == 0' >/dev/null; then
  MSG_ID=$(echo "$SEND_RESPONSE" | jq -r '.data.message_id')
  echo "✅ 发送成功!消息ID:$MSG_ID"
else
  ERROR_MSG=$(echo "$SEND_RESPONSE" | jq -r '.msg // "未知错误"')
  ERROR_CODE=$(echo "$SEND_RESPONSE" | jq -r '.code // "未知码"')
  echo "❌ 发送失败 [$ERROR_CODE]:$ERROR_MSG"
  rm -f "$OPUS_FILE" "${OPUS_FILE%.opus}.mp3" 2>/dev/null
  exit 1
fi

# 清理临时文件
rm -f "$OPUS_FILE" "${OPUS_FILE%.opus}.mp3" 2>/dev/null
echo "🧹 清理临时文件完成"

4. 使用说明

(1)初始化配置

# 首次运行会自动生成配置文件,编辑填写真实信息
vim ~/.config/feishu_voice_config.json

(2)环境变量临时覆盖(可选)

# 临时使用不同的配置(优先级高于配置文件)
export FEISHU_APP_ID="临时APP_ID"
export FEISHU_APP_SECRET="临时SECRET"
export FEISHU_CHAT_ID="临时CHAT_ID"

# 执行脚本
bash send_voice_edge.sh "测试消息"

(3)常规使用

# 基础版
bash send_voice.sh "早上好!"

# Edge TTS版(自定义语音)
bash send_voice_edge.sh "床前明月光" "zh-CN-YunxiNeural"

5. 关键优化点

优化项说明
移除硬编码所有敏感信息通过配置文件/环境变量管理,避免代码泄露
配置优先级环境变量 > 配置文件 > 默认值,灵活适配不同场景
依赖检查自动检查jq/ffmpeg/python/edge_tts等依赖,缺失时提示安装
错误处理每个步骤增加校验,失败时输出明确错误信息,避免静默失败
配置模板自动生成首次运行自动生成配置文件模板,降低使用门槛
临时文件安全清理任何失败场景都确保临时文件被清理,避免磁盘占用
结构化输出使用jq替代python单行解析JSON,更稳定、易读

6. 依赖安装

# Debian/Ubuntu
sudo apt update && sudo apt install -y jq ffmpeg python3 python3-pip

# CentOS/RHEL
sudo yum install -y jq ffmpeg python3 python3-pip

# macOS
brew install jq ffmpeg python3

# 安装Python依赖
pip3 install edge-tts

Files

1 total
Select a file
Select a file to preview.

Comments

Loading comments…