| name | openclaw-qqbot-send-skill |
| description | Stage and send local media files through OpenClaw QQBot with safe temporary staging and automatic cleanup |
| triggers | ["send a file through QQBot","how do I send local media with OpenClaw QQBot","stage a file for QQBot sending","send image/audio/video through QQ bot","clean up QQBot staged files","how to send local files with qqmedia tags","OpenClaw QQBot media relay","QQBot file size limit"] |
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.
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
Installation
Clone the repository:
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).
Key Components
scripts/stage_media.py
The core staging and cleanup script with two operations:
- Stage: Copy a local file to
~/.openclaw/media/qqbot/ with a unique name
- Cleanup: Delete the staged temporary copy after sending
SKILL.md
OpenClaw skill definition that tells the AI agent when and how to stage, send, and clean up media files.
Usage Patterns
Pattern 1: Send a Local File
import subprocess
import os
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()
qqbot_message = f"<qqmedia>{staged_path}</qqmedia>"
subprocess.run(
["python", "scripts/stage_media.py", "--cleanup", staged_path],
check=True
)
Pattern 2: Send an HTTP(S) URL
url = "https://example.com/image.png"
qqbot_message = f"<qqmedia>{url}</qqmedia>"
Pattern 3: Batch Send Multiple Files
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>"
finally:
for staged in staged_files:
subprocess.run(
["python", "scripts/stage_media.py", "--cleanup", staged],
check=False
)
Command-Line Interface
Stage a File
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:
python scripts/stage_media.py "/home/user/document.pdf"
Clean Up a Staged File
python scripts/stage_media.py --cleanup <staged_path>
Input: The exact path returned by the staging command
Output: Success or error message
Example:
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:
MAX_FILE_SIZE = 10 * 1024 * 1024
MAX_FILE_SIZE = 20 * 1024 * 1024
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.
Safety Rules
Critical: Only Clean Up Staged Paths
DO:
staged = subprocess.run(["python", "scripts/stage_media.py", source], ...).stdout.strip()
subprocess.run(["python", "scripts/stage_media.py", "--cleanup", staged], ...)
DON'T:
subprocess.run(["python", "scripts/stage_media.py", "--cleanup", source], ...)
subprocess.run(["python", "scripts/stage_media.py", "--cleanup", url], ...)
subprocess.run(["python", "scripts/stage_media.py", "--cleanup", "~/.openclaw/media/qqbot/file.txt"], ...)
What Gets Deleted
- ✅ Staged copy in
~/.openclaw/media/qqbot/
- ❌ Original source file (never touched)
Troubleshooting
File Too Large
Error: "File size exceeds 10 MB limit"
Solution: Reduce file size or increase MAX_FILE_SIZE in the script.
File Not Found
Error: "Source file does not exist"
Solution: Verify the path is correct and the file exists:
import os
if os.path.exists(source_file):
else:
print(f"File not found: {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/.
Cleanup Fails After Successful Send
Best Practice: Always attempt cleanup even if sending fails:
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}")
Integration Example
Complete flow for OpenClaw QQBot integration:
import subprocess
import sys
import os
def send_media_to_qqbot(source_path):
"""Stage, send, and clean up media for QQBot."""
if source_path.startswith(("http://", "https://")):
print(f"Sending URL directly: {source_path}")
qqbot_message = f"<qqmedia>{source_path}</qqmedia>"
return True
if not os.path.exists(source_path):
print(f"Error: File not found: {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 to: {staged_path}")
qqbot_message = f"<qqmedia>{staged_path}</qqmedia>"
print(f"Sending: {qqbot_message}")
subprocess.CalledProcessError e:
()
:
staged_path:
:
subprocess.run(
[, , , staged_path],
check=
)
()
subprocess.CalledProcessError e:
()
__name__ == :
(sys.argv) < :
()
sys.exit()
send_media_to_qqbot(sys.argv[])
License
MIT License