#!/bin/bash # Torna OpenAPI 文档下载脚本 # 用法: ./download-torna-openapi.sh TORNA_API_URL="https://dev-torna.pwtk.cc/api" TOKEN="339f378808a9416ca5365e5b991e0878" OUTPUT_DIR="./torna-docs" VERSION="1.0" mkdir -p "$OUTPUT_DIR" echo "========================================" echo "Torna OpenAPI 文档下载工具" echo "========================================" echo "" # 函数:发送 OpenAPI 请求 (使用 Torna SDK 的格式 - JSON Body) send_request() { local api_name="$1" local data="$2" local timestamp=$(date "+%Y-%m-%d %H:%M:%S") # URL 编码 data 参数 local encoded_data=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$data'))") # 构建 JSON 请求体 local json_body=$(cat << EOF { "name": "$api_name", "version": "$VERSION", "data": "$encoded_data", "timestamp": "$timestamp", "access_token": "$TOKEN" } EOF ) curl -s -X POST "${TORNA_API_URL}" \ -H "Content-Type: application/json" \ -H "Accept-Language: zh-CN" \ -d "$json_body" } # 1. 获取模块信息 echo ">>> 1. 获取模块信息 (module.get)..." MODULE_RESULT=$(send_request "module.get" "{}") echo "$MODULE_RESULT" | jq . echo "$MODULE_RESULT" > "$OUTPUT_DIR/module-info.json" echo "" # 2. 获取文档列表 echo ">>> 2. 获取文档列表 (doc.list)..." DOC_LIST_RESULT=$(send_request "doc.list" "{}") echo "$DOC_LIST_RESULT" | jq . echo "$DOC_LIST_RESULT" > "$OUTPUT_DIR/doc-list.json" echo "" # 检查是否成功 CODE=$(echo "$DOC_LIST_RESULT" | jq -r '.code // "1"') if [ "$CODE" != "0" ]; then echo "请求失败,错误信息: $(echo "$DOC_LIST_RESULT" | jq -r '.msg')" echo "" echo "可能的原因:" echo "1. Token 已过期或无效" echo "2. API URL 不正确" echo "" exit 1 fi # 提取文档 ID 列表 DOC_IDS=$(echo "$DOC_LIST_RESULT" | jq -r '.data.docList[]?.id // empty' 2>/dev/null | head -50) if [ -n "$DOC_IDS" ]; then echo ">>> 3. 获取文档详情..." # 将 ID 列表转换为 JSON 数组 IDS_ARRAY=$(echo "$DOC_IDS" | jq -R -s 'split("\n") | map(select(length > 0) | tonumber)') # 批量获取文档详情 DETAILS_RESULT=$(send_request "doc.details" "{\"docIds\":$IDS_ARRAY}") echo "$DETAILS_RESULT" | jq . echo "$DETAILS_RESULT" > "$OUTPUT_DIR/doc-details.json" echo "" # 转换为 OpenAPI 格式 echo ">>> 4. 生成 OpenAPI 规范文件..." python3 << 'PYTHON_SCRIPT' import json import sys try: with open("./torna-docs/doc-details.json", "r") as f: data = json.load(f) with open("./torna-docs/module-info.json", "r") as f: module_data = json.load(f) module_name = module_data.get("data", {}).get("name", "Torna API") openapi = { "openapi": "3.0.0", "info": { "title": module_name, "version": "1.0.0", "description": "从 Torna 导出的 API 文档" }, "servers": [], "paths": {}, "components": { "schemas": {} } } docs = data.get("data", []) if not docs: docs = [] for doc in docs: if doc.get("isFolder") == 1: continue url = doc.get("url", "/unknown") if not url: continue method = (doc.get("httpMethod") or "GET").lower() if url not in openapi["paths"]: openapi["paths"][url] = {} operation = { "summary": doc.get("name", ""), "description": doc.get("description", ""), "operationId": f"{method}_{url.replace('/', '_').replace('{', '').replace('}', '')}", "tags": [], "parameters": [], "responses": { "200": { "description": "成功响应" } } } # 添加请求参数 for param in (doc.get("requestParams") or []): param_obj = { "name": param.get("name", ""), "in": "query", "description": param.get("description", ""), "required": param.get("required") == 1, "schema": { "type": param.get("type", "string") } } operation["parameters"].append(param_obj) # 添加请求头 for header in (doc.get("headerParams") or []): header_obj = { "name": header.get("name", ""), "in": "header", "description": header.get("description", ""), "required": header.get("required") == 1, "schema": { "type": "string" } } operation["parameters"].append(header_obj) openapi["paths"][url][method] = operation with open("./torna-docs/openapi.json", "w", encoding="utf-8") as f: json.dump(openapi, f, ensure_ascii=False, indent=2) print(f"成功生成 OpenAPI 文档,包含 {len(openapi['paths'])} 个接口路径") except Exception as e: print(f"转换失败: {e}") import traceback traceback.print_exc() sys.exit(1) PYTHON_SCRIPT else echo "未找到文档 ID,跳过详情获取" fi echo "" echo "========================================" echo "下载完成!文件保存在: $OUTPUT_DIR/" echo "========================================" ls -la "$OUTPUT_DIR/"