openclaw-qqbot-send-skill

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

OpenClaw QQBot Send Skill

OpenClaw QQBot Send Skill

Skill by ara.so — Hermes Skills collection.
An OpenClaw skill for safely sending local files, images, audio, video, and other media through QQBot. This skill stages local files into the QQBot media relay directory, sends them with
<qqmedia>...</qqmedia>
tags, and cleans up only the temporary staged copy after sending.
ara.so开发的Skill — 属于Hermes Skills集合。
这是一款OpenClaw Skill,用于通过QQBot安全发送本地文件、图片、音频、视频等媒体内容。该Skill会将本地文件暂存到QQBot媒体中转目录,使用
<qqmedia>...</qqmedia>
标签发送,并在发送完成后仅清理暂存的临时副本。

What It Does

功能介绍

  • Stages local files into
    ~/.openclaw/media/qqbot/
    with unique filenames
  • Sends media through QQBot using
    <qqmedia>...</qqmedia>
    XML tags
  • Cleans up safely by removing only the staged temporary copy, never the original
  • Enforces 10 MB limit for file size safety
  • Supports HTTP(S) URLs directly without staging or cleanup
  • Normalizes extensions to lowercase for consistency
  • 暂存本地文件:将文件以唯一文件名保存到
    ~/.openclaw/media/qqbot/
    目录
  • 发送媒体内容:通过QQBot使用
    <qqmedia>...</qqmedia>
    XML标签发送媒体
  • 安全清理:仅删除暂存的临时副本,绝不触碰原始文件
  • 文件大小限制:为保障安全,强制限制文件大小为10 MB
  • 支持HTTP(S) URL:可直接发送链接,无需暂存或清理
  • 统一扩展名:将文件扩展名统一转换为小写,保持一致性

Installation

安装步骤

Clone the repository:
bash
git clone https://github.com/ZJunCher/openclaw-qqbot-send-skill.git
cd openclaw-qqbot-send-skill
The skill uses Python's standard library only (no external dependencies required).
克隆仓库:
bash
git clone https://github.com/ZJunCher/openclaw-qqbot-send-skill.git
cd openclaw-qqbot-send-skill
该Skill仅使用Python标准库(无需额外依赖)。

Key Components

核心组件

scripts/stage_media.py

scripts/stage_media.py

The core staging and cleanup script with two operations:
  1. Stage: Copy a local file to
    ~/.openclaw/media/qqbot/
    with a unique name
  2. Cleanup: Delete the staged temporary copy after sending
核心暂存与清理脚本,包含两种操作:
  1. 暂存:将本地文件复制到
    ~/.openclaw/media/qqbot/
    并生成唯一文件名
  2. 清理:发送完成后删除暂存的临时副本

SKILL.md

SKILL.md

OpenClaw skill definition that tells the AI agent when and how to stage, send, and clean up media files.
OpenClaw Skill定义文件,用于告知AI Agent何时以及如何暂存、发送和清理媒体文件。

Usage Patterns

使用模式

Pattern 1: Send a Local File

模式1:发送本地文件

python
import subprocess
import os
python
import subprocess
import os

Step 1: Stage the local file

步骤1:暂存本地文件

source_file = "/home/user/Pictures/photo.jpg" result = subprocess.run( ["python", "scripts/stage_media.py", source_file], capture_output=True, text=True, check=True ) staged_path = result.stdout.strip()
source_file = "/home/user/Pictures/photo.jpg" result = subprocess.run( ["python", "scripts/stage_media.py", source_file], capture_output=True, text=True, check=True ) staged_path = result.stdout.strip()

Step 2: Send with QQBot using qqmedia tags

步骤2:使用qqmedia标签通过QQBot发送

qqbot_message = f"<qqmedia>{staged_path}</qqmedia>"
qqbot_message = f"<qqmedia>{staged_path}</qqmedia>"

... send qqbot_message through your QQBot integration ...

... 通过你的QQBot集成发送qqbot_message ...

Step 3: Clean up the staged copy

步骤3:清理暂存副本

subprocess.run( ["python", "scripts/stage_media.py", "--cleanup", staged_path], check=True )
undefined
subprocess.run( ["python", "scripts/stage_media.py", "--cleanup", staged_path], check=True )
undefined

Pattern 2: Send an HTTP(S) URL

模式2:发送HTTP(S)链接

python
undefined
python
undefined

No staging or cleanup needed for URLs

链接无需暂存或清理

url = "https://example.com/image.png" qqbot_message = f"<qqmedia>{url}</qqmedia>"
url = "https://example.com/image.png" qqbot_message = f"<qqmedia>{url}</qqmedia>"

... send directly through QQBot ...

... 直接通过QQBot发送 ...

undefined
undefined

Pattern 3: Batch Send Multiple Files

模式3:批量发送多个文件

python
import subprocess

files = [
    "/path/to/image1.png",
    "/path/to/video.mp4",
    "/path/to/audio.mp3"
]

staged_files = []

try:
    # Stage all files
    for source in files:
        result = subprocess.run(
            ["python", "scripts/stage_media.py", source],
            capture_output=True,
            text=True,
            check=True
        )
        staged_path = result.stdout.strip()
        staged_files.append(staged_path)
        
        # Send each file
        qqbot_message = f"<qqmedia>{staged_path}</qqmedia>"
        # ... send through QQBot ...
        
finally:
    # Always clean up all staged files
    for staged in staged_files:
        subprocess.run(
            ["python", "scripts/stage_media.py", "--cleanup", staged],
            check=False  # Don't fail if cleanup fails
        )
python
import subprocess

files = [
    "/path/to/image1.png",
    "/path/to/video.mp4",
    "/path/to/audio.mp3"
]

staged_files = []

try:
    # 暂存所有文件
    for source in files:
        result = subprocess.run(
            ["python", "scripts/stage_media.py", source],
            capture_output=True,
            text=True,
            check=True
        )
        staged_path = result.stdout.strip()
        staged_files.append(staged_path)
        
        # 发送每个文件
        qqbot_message = f"<qqmedia>{staged_path}</qqmedia>"
        # ... 通过QQBot发送 ...
        
finally:
    # 始终清理所有暂存文件
    for staged in staged_files:
        subprocess.run(
            ["python", "scripts/stage_media.py", "--cleanup", staged],
            check=False  # 清理失败不终止流程
        )

Command-Line Interface

命令行界面

Stage a File

暂存文件

bash
python scripts/stage_media.py <source_path>
Input: Path to the original file
Output: Absolute path to the staged copy in
~/.openclaw/media/qqbot/
Example:
bash
python scripts/stage_media.py "/home/user/document.pdf"
bash
python scripts/stage_media.py <source_path>
输入:原始文件路径
输出:暂存副本在
~/.openclaw/media/qqbot/
中的绝对路径
示例:
bash
python scripts/stage_media.py "/home/user/document.pdf"

Output: /home/user/.openclaw/media/qqbot/a1b2c3d4.pdf

输出:/home/user/.openclaw/media/qqbot/a1b2c3d4.pdf

undefined
undefined

Clean Up a Staged File

清理暂存文件

bash
python scripts/stage_media.py --cleanup <staged_path>
Input: The exact path returned by the staging command
Output: Success or error message
Example:
bash
python scripts/stage_media.py --cleanup "/home/user/.openclaw/media/qqbot/a1b2c3d4.pdf"
bash
python scripts/stage_media.py --cleanup <staged_path>
输入:暂存命令返回的准确路径
输出:成功或错误信息
示例:
bash
python scripts/stage_media.py --cleanup "/home/user/.openclaw/media/qqbot/a1b2c3d4.pdf"

Configuration

配置说明

File Size Limit

文件大小限制

Default: 10 MB
The script enforces this limit during staging. To modify:
python
undefined
默认值:10 MB
脚本在暂存阶段会强制执行该限制。如需修改:
python
undefined

In scripts/stage_media.py, locate:

在scripts/stage_media.py中找到:

MAX_FILE_SIZE = 10 * 1024 * 1024 # 10 MB
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10 MB

Change to desired size, e.g., 20 MB:

修改为目标大小,例如20 MB:

MAX_FILE_SIZE = 20 * 1024 * 1024
undefined
MAX_FILE_SIZE = 20 * 1024 * 1024
undefined

Media Relay Directory

媒体中转目录

Default:
~/.openclaw/media/qqbot/
The script automatically creates this directory if it doesn't exist. To change the location, modify the
MEDIA_DIR
constant in
scripts/stage_media.py
.
默认路径:
~/.openclaw/media/qqbot/
脚本会自动创建该目录(如果不存在)。如需修改路径,可修改
scripts/stage_media.py
中的
MEDIA_DIR
常量。

Safety Rules

安全规则

Critical: Only Clean Up Staged Paths

重要提示:仅清理暂存路径

DO:
python
staged = subprocess.run(["python", "scripts/stage_media.py", source], ...).stdout.strip()
subprocess.run(["python", "scripts/stage_media.py", "--cleanup", staged], ...)
DON'T:
python
undefined
正确操作
python
staged = subprocess.run(["python", "scripts/stage_media.py", source], ...).stdout.strip()
subprocess.run(["python", "scripts/stage_media.py", "--cleanup", staged], ...)
错误操作
python
undefined

NEVER clean up the original source

绝不要清理原始文件

subprocess.run(["python", "scripts/stage_media.py", "--cleanup", source], ...)
subprocess.run(["python", "scripts/stage_media.py", "--cleanup", source], ...)

NEVER clean up HTTP(S) URLs

绝不要清理HTTP(S)链接

subprocess.run(["python", "scripts/stage_media.py", "--cleanup", url], ...)
subprocess.run(["python", "scripts/stage_media.py", "--cleanup", url], ...)

NEVER guess or construct the staged path

绝不要猜测或构造暂存路径

subprocess.run(["python", "scripts/stage_media.py", "--cleanup", "~/.openclaw/media/qqbot/file.txt"], ...)
undefined
subprocess.run(["python", "scripts/stage_media.py", "--cleanup", "~/.openclaw/media/qqbot/file.txt"], ...)
undefined

What Gets Deleted

清理范围

  • Staged copy in
    ~/.openclaw/media/qqbot/
  • Original source file (never touched)
  • ~/.openclaw/media/qqbot/
    中的暂存副本
  • 原始源文件(绝不会被触碰)

Troubleshooting

故障排查

File Too Large

文件过大

Error: "File size exceeds 10 MB limit"
Solution: Reduce file size or increase
MAX_FILE_SIZE
in the script.
错误信息:"File size exceeds 10 MB limit"
解决方案:缩小文件大小或修改脚本中的
MAX_FILE_SIZE
值。

File Not Found

文件未找到

Error: "Source file does not exist"
Solution: Verify the path is correct and the file exists:
python
import os
if os.path.exists(source_file):
    # proceed with staging
else:
    print(f"File not found: {source_file}")
错误信息:"Source file does not exist"
解决方案:验证路径是否正确,文件是否存在:
python
import os
if os.path.exists(source_file):
    # 继续执行暂存
else:
    print(f"文件未找到:{source_file}")

Permission Denied

权限不足

Error: "Permission denied" or "Access denied"
Solution: Check file permissions and ensure the script has read access to the source file and write access to
~/.openclaw/media/qqbot/
.
错误信息:"Permission denied"或"Access denied"
解决方案:检查文件权限,确保脚本对源文件有读取权限,对
~/.openclaw/media/qqbot/
目录有写入权限。

Cleanup Fails After Successful Send

发送成功但清理失败

Best Practice: Always attempt cleanup even if sending fails:
python
staged_path = None
try:
    staged_path = stage_file(source)
    send_to_qqbot(staged_path)
except Exception as e:
    print(f"Send failed: {e}")
finally:
    if staged_path:
        try:
            cleanup_file(staged_path)
        except Exception as e:
            print(f"Cleanup failed for {staged_path}: {e}")
            # Log but don't delete manually
最佳实践:即使发送失败,也要尝试执行清理:
python
staged_path = None
try:
    staged_path = stage_file(source)
    send_to_qqbot(staged_path)
except Exception as e:
    print(f"发送失败:{e}")
finally:
    if staged_path:
        try:
            cleanup_file(staged_path)
        except Exception as e:
            print(f"清理失败 {staged_path}{e}")
            # 记录日志,但不要手动删除

Integration Example

集成示例

Complete flow for OpenClaw QQBot integration:
python
#!/usr/bin/env python3
import subprocess
import sys
import os

def send_media_to_qqbot(source_path):
    """Stage, send, and clean up media for QQBot."""
    
    # Check if it's a URL
    if source_path.startswith(("http://", "https://")):
        print(f"Sending URL directly: {source_path}")
        qqbot_message = f"<qqmedia>{source_path}</qqmedia>"
        # Send through QQBot API here
        return True
    
    # Check if file exists
    if not os.path.exists(source_path):
        print(f"Error: File not found: {source_path}")
        return False
    
    staged_path = None
    try:
        # Stage the file
        result = subprocess.run(
            ["python", "scripts/stage_media.py", source_path],
            capture_output=True,
            text=True,
            check=True
        )
        staged_path = result.stdout.strip()
        print(f"Staged to: {staged_path}")
        
        # Send through QQBot
        qqbot_message = f"<qqmedia>{staged_path}</qqmedia>"
        print(f"Sending: {qqbot_message}")
        # ... actual QQBot send logic here ...
        
        return True
        
    except subprocess.CalledProcessError as e:
        print(f"Staging failed: {e.stderr}")
        return False
        
    finally:
        # Always clean up the staged file
        if staged_path:
            try:
                subprocess.run(
                    ["python", "scripts/stage_media.py", "--cleanup", staged_path],
                    check=True
                )
                print(f"Cleaned up: {staged_path}")
            except subprocess.CalledProcessError as e:
                print(f"Cleanup failed: {e.stderr}")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: send_media.py <file_path_or_url>")
        sys.exit(1)
    
    send_media_to_qqbot(sys.argv[1])
OpenClaw QQBot完整集成流程:
python
#!/usr/bin/env python3
import subprocess
import sys
import os

def send_media_to_qqbot(source_path):
    """暂存、发送并清理QQBot媒体文件。"""
    
    # 判断是否为链接
    if source_path.startswith(("http://", "https://")):
        print(f"直接发送链接:{source_path}")
        qqbot_message = f"<qqmedia>{source_path}</qqmedia>"
        # 在此处调用QQBot API发送
        return True
    
    # 检查文件是否存在
    if not os.path.exists(source_path):
        print(f"错误:文件未找到:{source_path}")
        return False
    
    staged_path = None
    try:
        # 暂存文件
        result = subprocess.run(
            ["python", "scripts/stage_media.py", source_path],
            capture_output=True,
            text=True,
            check=True
        )
        staged_path = result.stdout.strip()
        print(f"暂存路径:{staged_path}")
        
        # 通过QQBot发送
        qqbot_message = f"<qqmedia>{staged_path}</qqmedia>"
        print(f"发送内容:{qqbot_message}")
        # ... 此处添加实际QQBot发送逻辑 ...
        
        return True
        
    except subprocess.CalledProcessError as e:
        print(f"暂存失败:{e.stderr}")
        return False
        
    finally:
        # 始终清理暂存文件
        if staged_path:
            try:
                subprocess.run(
                    ["python", "scripts/stage_media.py", "--cleanup", staged_path],
                    check=True
                )
                print(f"已清理:{staged_path}")
            except subprocess.CalledProcessError as e:
                print(f"清理失败:{e.stderr}")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("使用方法:send_media.py <文件路径或链接>")
        sys.exit(1)
    
    send_media_to_qqbot(sys.argv[1])

License

许可证

MIT License
MIT License