Skill: nbf819-web/pr-generator (version 3.0.0)

--- name: qrcode-generator description: "Generate QR codes from text, URLs, or images. Use when users ask to 'generate QR code', 'create QR', or 'make QR code for'. Supports text content, URLs, and local images (automatically compressed)." version: 2.0.0 author: bowen nan license: MIT permissions: file read (specified image paths), file write (temp directory) --- # QR Code Generator Generate QR codes from text, URLs, or local images. Perfect for sharing links, contact information, or small images via scannable codes. ## Features - ✅ Generate QR codes from text - ✅ Generate QR codes from URLs - ✅ Generate QR codes from local images (auto-compressed) - ✅ Customizable QR code size and colors - ✅ Returns image path for easy sharing ## Installation ```bash pip install qrcode[pil] pillow ``` ## Usage Examples ### Basic Usage ```python from agent import handle_call # Generate QR for URL result = handle_call({"content": "https://openclaw.ai"}) # Generate QR for text result = handle_call({"content": "Hello OpenClaw"}) # Generate QR from image result = handle_call({"image": "/path/to/image.jpg"}) ``` ### Command Line ```bash # Install dependencies first pip install qrcode[pil] pillow # Run the example python example.py ``` ## Parameters - `content` (string): Text or URL to encode - `image` (string): Full path to local image file ## Returns - `image_path`: Path to generated QR code image - `error`: Error message if failed - `message`: Informational message ## Notes - Images larger than 10MB will be rejected - Large images are automatically compressed for QR encoding - For best results with images, use URLs instead of local files

path: requirements.txt
content: qrcode[pil]>=7.4.2
Pillow>=10.0.0

path: example.py
content: #!/usr/bin/env python3
"""
二维码生成技能使用示例
"""

import sys
import os

# 添加技能路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from agent import handle_call

def example_text_qr():
    """示例1: 生成文本二维码"""
    print("📝 示例1: 生成文本二维码")
    result = handle_call({"content": "Hello OpenClaw! 欢迎使用二维码生成技能。"})
    print(f"结果: {result}")
    print()

def example_url_qr():
    """示例2: 生成链接二维码"""
    print("🔗 示例2: 生成链接二维码")
    result = handle_call({"content": "https://openclaw.ai"})
    print(f"结果: {result}")
    print()

def example_image_qr():
    """示例3: 生成图片二维码"""
    print("🖼️ 示例3: 生成图片二维码")
    
    # 创建一个测试图片
    from PIL import Image
    test_image_path = "/tmp/test_qr_image.jpg"
    
    # 生成一个简单的测试图片
    img = Image.new('RGB', (100, 100), color='red')
    img.save(test_image_path, 'JPEG')
    
    print(f"测试图片: {test_image_path}")
    result = handle_call({"image": test_image_path})
    print(f"结果: {result}")
    print()

def example_error():
    """示例4: 错误处理"""
    print("❌ 示例4: 错误处理")
    
    # 测试不存在的图片
    result = handle_call({"image": "/path/to/nonexistent/image.jpg"})
    print(f"不存在的图片: {result}")
    print()
    
    # 测试无参数
    result = handle_call({})
    print(f"无参数: {result}")
    print()

if __name__ == "__main__":
    print("=" * 50)
    print("二维码生成技能示例程序")
    print("=" * 50)
    print()
    
    example_text_qr()
    example_url_qr()
    example_image_qr()
    example_error()
    
    print("=" * 50)
    print("✅ 所有示例完成")
    print("=" * 50)

path: agent.py
content: import qrcode
import os
import tempfile
import base64
import mimetypes
from PIL import Image

MAX_QR_BYTES = 2953

def file_to_base64(file_path):
    """将本地文件转换为 base64 字符串（含 data URL 头）"""
    with open(file_path, 'rb') as f:
        data = f.read()
    b64 = base64.b64encode(data).decode('utf-8')
    mime = mimetypes.guess_type(file_path)[0] or 'application/octet-stream'
    return f"data:{mime};base64,{b64}"

def image_to_qr_data(image_path):
    """处理图片，返回要编码的数据"""
    base64_str = file_to_base64(image_path)
    if len(base64_str) <= MAX_QR_BYTES:
        return base64_str
    else:
        return f"图片太大无法直接存储，请上传至图床后使用 URL 生成二维码。"

def generate_qr(data: str) -> str:
    """生成二维码，返回图片路径"""
    qr = qrcode.QRCode(
        version=None,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=10,
        border=4,
    )
    qr.add_data(data)
    qr.make(fit=True)

    img = qr.make_image(fill_color="black", back_color="white")
    temp_dir = tempfile.gettempdir()
    file_path = os.path.join(temp_dir, f"qr_{hash(data)}.png")
    img.save(file_path)
    return file_path

def handle_call(args: dict):
    """技能入口函数"""
    content = args.get("content", "")
    image_path = args.get("image", "")

    # 优先处理图片
    if image_path:
        if not os.path.exists(image_path):
            return {"error": f"图片文件不存在：{image_path}"}
        file_size = os.path.getsize(image_path)
        if file_size > 10 * 1024 * 1024:
            return {"error": "图片太大，请选择小于10MB的图片"}
        qr_data = image_to_qr_data(image_path)
        if qr_data.startswith("图片太大"):
            return {"message": qr_data}
    elif content:
        qr_data = content
    else:
        return {"error": "没有提供任何内容或图片"}

    try:
        path = generate_qr(qr_data)
        return {"image_path": path}
    except Exception as e:
        return {"error": str(e)}


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