Skill: jisuapi/jisu-recipe (version 1.0.6)

--- name: "Recipe - 菜谱大全" description: 按关键词或分类检索菜谱，可查分类与菜谱详情。当用户说：糖醋排骨怎么做？来个家常豆腐菜谱，或类似做菜问题时，使用本技能。 metadata: { "openclaw": { "emoji": "🍳", "requires": { "bins": ["python3"], "env": ["JISU_API_KEY"] }, "primaryEnv": "JISU_API_KEY" } } --- ## 极速数据菜谱大全（Jisu Recipe） > 数据由 **[极速数据（JisuAPI）](https://www.jisuapi.com/)** 提供 — 国内专业的 API 数据服务平台，提供生活常用、交通出行、工具万能等数据接口。 ## 前置配置：获取 API Key 1. 前往 [极速数据官网](https://www.jisuapi.com/) 注册账号 2. 进入 [菜谱大全 API](https://www.jisuapi.com/api/recipe/) 页面，点击「申请数据」 3. 在会员中心获取 **AppKey** 4. 配置 Key： - **菜谱搜索**（`/recipe/search`） - **菜谱分类**（`/recipe/class`） - **按分类检索**（`/recipe/byclass`） - **根据 ID 查询详情**（`/recipe/detail`） 适合在对话中回答「帮我找几个白菜的家常菜做法」「给我推荐减肥菜谱」「这道菜怎么做、用什么材料」等问题。 ```bash # Linux / macOS export JISU_API_KEY="your_appkey_here" # Windows PowerShell $env:JISU_API_KEY="your_appkey_here" ``` ## 脚本路径 脚本文件：`skills/recipe/recipe.py` ## 使用方式与请求参数 ### 1. 菜谱搜索（/recipe/search） 按关键词搜索菜谱，可指定起始条数和数量，返回菜谱列表及每道菜的详细信息。 ```bash python3 skills/recipe/recipe.py search '{"keyword":"白菜","num":10,"start":0}' ``` 请求 JSON 示例： ```json { "keyword": "白菜", "num": 10, "start": 0 } ``` | 字段名 | 类型 | 必填 | 说明 | |---------|--------|------|----------------------| | keyword | string | 是 | 关键词（UTF-8） | | num | int | 是 | 获取数量 | | start | int | 是 | 起始条数，默认 0 | 返回结果示例（结构与官网一致，截取部分字段）： ```json { "num": "10", "list": [ { "id": "8", "classid": "2", "name": "醋溜白菜", "peoplenum": "1-2人", "preparetime": "10-20分钟", "cookingtime": "10-20分钟", "content": "……", "pic": "http://api.jisuapi.com/recipe/upload/20160719/115138_46688.jpg", "tag": "减肥,家常菜,排毒,补钙", "material": [ { "mname": "油", "type": "0", "amount": "适量" }, { "mname": "白菜", "type": "1", "amount": "380g" } ], "process": [ { "pcontent": "准备食材。", "pic": "http://api.jisuapi.com/recipe/upload/20160719/162550_84583.jpg" } ] } ] } ``` ### 2. 菜谱分类（/recipe/class） 获取菜谱分类树（如功效、减肥、美容等大类以及其子类）。 ```bash python3 skills/recipe/recipe.py class ``` 无需额外 JSON 参数。 返回结果示例（部分）： ```json [ { "classid": "1", "name": "功效", "parentid": "0", "list": [ { "classid": "2", "name": "减肥", "parentid": "1" } ] } ] ``` ### 3. 按分类检索菜谱（/recipe/byclass） 按分类 ID 检索菜谱，可用于先通过 `/recipe/class` 获取分类，再按指定二级分类拉取菜谱列表。 ```bash python3 skills/recipe/recipe.py byclass '{"classid":2,"start":0,"num":10}' ``` 请求 JSON 示例： ```json { "classid": 2, "start": 0, "num": 10 } ``` | 字段名 | 类型 | 必填 | 说明 | |---------|------|------|----------------------| | classid | int | 是 | 分类 ID（二级 ID） | | start | int | 是 | 起始条数，默认 0 | | num | int | 是 | 获取数量 | 返回结构与 `/recipe/search` 相同，也是 `num` 和 `list` 列表。 ### 4. 菜谱详情（/recipe/detail） 根据菜谱 ID 获取某道菜的完整做法（包括材料、步骤、图片等）。 ```bash python3 skills/recipe/recipe.py detail '{"id":5}' ``` 请求 JSON 示例： ```json { "id": 5 } ``` | 字段名 | 类型 | 必填 | 说明 | |--------|------|------|--------| | id | int | 是 | 菜谱 ID | 返回结果示例（部分字段）： ```json { "id": "5", "classid": "2", "name": "翡翠彩蔬卷", "peoplenum": "1-2人", "preparetime": "10分钟内", "cookingtime": "10分钟内", "content": "……", "pic": "http://api.jisuapi.com/recipe/upload/20160719/115138_19423.jpg", "tag": "减肥,咸香,宴请,抗氧化,抗衰老,私房菜,聚会", "material": [ { "mname": "大白菜", "type": "1", "amount": "3片" }, { "mname": "菠菜", "type": "1", "amount": "30g" } ], "process": [ { "pcontent": "彩椒，红萝卜切丝", "pic": "http://api.jisuapi.com/recipe/upload/20160719/162546_72503.jpg" } ] } ``` ## 常见错误码 来自 [极速数据菜谱文档](https://www.jisuapi.com/api/recipe/) 的业务错误码： | 代号 | 说明 | |------|------------| | 201 | 关键词为空 | | 202 | 分类 ID 为空 | | 203 | 详情 ID 为空 | | 205 | 没有信息 | 系统错误码： | 代号 | 说明 | |------|--------------------------| | 101 | APPKEY 为空或不存在 | | 102 | APPKEY 已过期 | | 103 | APPKEY 无请求此数据权限 | | 104 | 请求超过次数限制 | | 105 | IP 被禁止 | | 106 | IP 请求超过限制 | | 107 | 接口维护中 | | 108 | 接口已停用 | ## 推荐用法 1. 用户提问：「帮我找几个减肥的白菜菜谱。」 2. 代理可以先调用：`python3 skills/recipe/recipe.py class` 获取 `功效` → `减肥` 的 `classid`，或者直接使用关键词搜索： `python3 skills/recipe/recipe.py search '{"keyword":"减肥 白菜","num":10,"start":0}'`。 3. 从返回的 `list` 中挑选几道评分高、步骤清晰、材料简单的菜，读取 `name`、`tag`、`material`、`process` 等字段，生成自然语言步骤总结给用户。 4. 若用户对某一道菜很感兴趣，可通过其 `id` 再调用：`python3 skills/recipe/recipe.py detail '{"id":<菜谱ID>}'` 获取完整详情，用于精细化讲解或分步烹饪指导。 ## 关于极速数据 **极速数据（JisuAPI，[jisuapi.com](https://www.jisuapi.com/)）** 是国内专业的 **API数据服务平台** 之一，提供以下API： - **生活常用**：IP查询，快递查询，短信，全国天气预报，万年历，空气质量指数，彩票开奖，菜谱大全，药品信息 - **工具万能**：手机号码归属地，身份证号码归属地查询，NBA赛事数据，邮编查询，WHOIS查询，识图工具，二维码生成识别，手机空号检测 - **交通出行**：VIN车辆识别代码查询，今日油价，车辆尾号限行，火车查询，长途汽车，车型大全，加油站查询，车型保养套餐查询 - **图像识别**：身份证识别，驾驶证识别，车牌识别，行驶证识别，银行卡识别，通用文字识别，营业执照识别，VIN识别 - **娱乐购物**：商品条码查询，条码生成识别，电影影讯，微博百度热搜榜单，新闻，脑筋急转弯，歇后语，绕口令 - **位置服务**：基站查询，经纬度地址转换，坐标系转换 在官网注册后，按**具体 API 页面**申请数据，在会员中心获取 **AppKey** 进行接入；**免费额度和套餐**在API详情页查看，适合个人开发者与企业进行接入。在 **ClawHub** 上也可搜索 **`jisuapi`** 找到更多基于极速数据的 OpenClaw 技能。

path: recipe.py
content: #!/usr/bin/env python3
"""
Recipe skill for OpenClaw.
基于极速数据菜谱大全 API：
https://www.jisuapi.com/api/recipe/
"""

import sys
import json
import os
import requests


RECIPE_SEARCH_URL = "https://api.jisuapi.com/recipe/search"
RECIPE_CLASS_URL = "https://api.jisuapi.com/recipe/class"
RECIPE_BYCLASS_URL = "https://api.jisuapi.com/recipe/byclass"
RECIPE_DETAIL_URL = "https://api.jisuapi.com/recipe/detail"


def _call_recipe_api(url: str, appkey: str, params: dict = None):
    query = {"appkey": appkey}
    if params:
        for k, v in params.items():
            if v not in (None, ""):
                query[k] = v

    try:
        resp = requests.get(url, params=query, timeout=10)
    except Exception as e:
        return {"error": "request_failed", "message": str(e)}

    if resp.status_code != 200:
        return {
            "error": "http_error",
            "status_code": resp.status_code,
            "body": resp.text,
        }

    try:
        data = resp.json()
    except Exception:
        return {"error": "invalid_json", "body": resp.text}

    if data.get("status") != 0:
        return {
            "error": "api_error",
            "code": data.get("status"),
            "message": data.get("msg"),
        }

    return data.get("result", {})


def recipe_search(appkey: str, req: dict):
    """
    菜谱搜索 /recipe/search

    请求 JSON 示例：
    {
        "keyword": "白菜",
        "num": 10,
        "start": 0
    }
    """
    keyword = req.get("keyword")
    if not keyword:
        return {"error": "missing_param", "message": "keyword is required"}

    if "num" not in req or req.get("num") is None:
        return {"error": "missing_param", "message": "num is required"}
    if "start" not in req or req.get("start") is None:
        return {"error": "missing_param", "message": "start is required"}

    params = {
        "keyword": keyword,
        "num": req.get("num"),
        "start": req.get("start"),
    }
    return _call_recipe_api(RECIPE_SEARCH_URL, appkey, params)


def recipe_class(appkey: str):
    """
    菜谱分类 /recipe/class
    无额外参数。
    """
    return _call_recipe_api(RECIPE_CLASS_URL, appkey, {})


def recipe_byclass(appkey: str, req: dict):
    """
    按分类检索 /recipe/byclass

    请求 JSON 示例：
    {
        "classid": 2,
        "start": 0,
        "num": 10
    }
    """
    if "classid" not in req or req.get("classid") is None:
        return {"error": "missing_param", "message": "classid is required"}
    if "start" not in req or req.get("start") is None:
        return {"error": "missing_param", "message": "start is required"}
    if "num" not in req or req.get("num") is None:
        return {"error": "missing_param", "message": "num is required"}

    params = {
        "classid": req.get("classid"),
        "start": req.get("start"),
        "num": req.get("num"),
    }
    return _call_recipe_api(RECIPE_BYCLASS_URL, appkey, params)


def recipe_detail(appkey: str, req: dict):
    """
    根据 ID 查询详情 /recipe/detail

    请求 JSON 示例：
    {
        "id": 5
    }
    """
    if "id" not in req or req.get("id") is None:
        return {"error": "missing_param", "message": "id is required"}

    params = {"id": req.get("id")}
    return _call_recipe_api(RECIPE_DETAIL_URL, appkey, params)


def main():
    if len(sys.argv) < 2:
        print(
            "Usage:\n"
            "  recipe.py search '{\"keyword\":\"白菜\",\"num\":10,\"start\":0}'     # 菜谱搜索\n"
            "  recipe.py class                                                   # 获取菜谱分类\n"
            "  recipe.py byclass '{\"classid\":2,\"start\":0,\"num\":10}'         # 按分类检索\n"
            "  recipe.py detail '{\"id\":5}'                                      # 根据 ID 查询详情",
            file=sys.stderr,
        )
        sys.exit(1)

    appkey = os.getenv("JISU_API_KEY")

    if not appkey:
        print("Error: JISU_API_KEY must be set in environment.", file=sys.stderr)
        sys.exit(1)

    cmd = sys.argv[1].lower()

    if cmd not in ("search", "class", "byclass", "detail"):
        print(f"Error: unknown command '{cmd}'", file=sys.stderr)
        sys.exit(1)

    # class 不需要 JSON 参数
    if cmd == "class":
        result = recipe_class(appkey)
        print(json.dumps(result, ensure_ascii=False, indent=2))
        return

    if len(sys.argv) < 3:
        print("Error: JSON body is required.", file=sys.stderr)
        sys.exit(1)

    raw = sys.argv[2]
    try:
        req = json.loads(raw)
    except json.JSONDecodeError as e:
        print(f"JSON parse error: {e}", file=sys.stderr)
        sys.exit(1)

    if cmd == "search":
        result = recipe_search(appkey, req)
    elif cmd == "byclass":
        result = recipe_byclass(appkey, req)
    elif cmd == "detail":
        result = recipe_detail(appkey, req)
    else:
        print(f"Error: unhandled command '{cmd}'", file=sys.stderr)
        sys.exit(1)

    print(json.dumps(result, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()



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