{
  "openapi": "3.1.0",
  "info": {
    "title": "云盘管家 API",
    "version": "1.0.0",
    "description": "夸克、百度网盘和迅雷网盘的多账号管理与精确转存接口。所有业务数据均按 API 密钥所属用户隔离。",
    "contact": {
      "name": "云盘管家",
      "url": "https://wp.ypsoso.com/api-docs.html"
    }
  },
  "servers": [
    {
      "url": "https://wp.ypsoso.com/api/v1",
      "description": "生产环境"
    }
  ],
  "tags": [
    { "name": "Identity", "description": "身份与套餐" },
    { "name": "Accounts", "description": "当前用户自己的网盘账号" },
    { "name": "Files", "description": "文件浏览与索引搜索" },
    { "name": "Transfers", "description": "分享链接解析与精确转存" },
    { "name": "Tasks", "description": "异步任务状态" }
  ],
  "security": [
    { "bearerAuth": [] }
  ],
  "paths": {
    "/me": {
      "get": {
        "tags": ["Identity"],
        "summary": "获取当前 API 身份",
        "operationId": "getCurrentIdentity",
        "responses": {
          "200": {
            "description": "当前用户、套餐和有效权限",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Identity" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/accounts": {
      "get": {
        "tags": ["Accounts"],
        "summary": "列出自己的网盘账号",
        "operationId": "listAccounts",
        "x-required-scope": "accounts:read",
        "responses": {
          "200": {
            "description": "账号列表",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["accounts"],
                  "properties": {
                    "accounts": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Account" }
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/files": {
      "get": {
        "tags": ["Files"],
        "summary": "浏览指定网盘目录",
        "operationId": "listFiles",
        "x-required-scope": "files:read",
        "parameters": [
          {
            "name": "accountId",
            "in": "query",
            "required": true,
            "schema": { "type": "integer", "minimum": 1 },
            "description": "当前用户的网盘账号 ID"
          },
          {
            "name": "dir",
            "in": "query",
            "schema": { "type": "string" },
            "description": "目录 ID 或路径；百度根目录为 /，夸克根目录为 0"
          },
          {
            "name": "refresh",
            "in": "query",
            "schema": { "type": "boolean", "default": false },
            "description": "跳过缓存并重新读取上游"
          }
        ],
        "responses": {
          "200": {
            "description": "目录内容",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FileList" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "502": { "$ref": "#/components/responses/UpstreamError" }
        }
      }
    },
    "/search": {
      "get": {
        "tags": ["Files"],
        "summary": "搜索当前用户的文件索引",
        "operationId": "searchFileIndex",
        "x-required-scope": "files:read",
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string", "maxLength": 160 } },
          { "name": "accountId", "in": "query", "schema": { "type": "integer", "minimum": 1 } },
          { "name": "kind", "in": "query", "schema": { "type": "string", "enum": ["file", "dir"] } },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["video", "archive", "document", "image", "audio"]
            }
          },
          { "name": "minSize", "in": "query", "schema": { "type": "integer", "minimum": 0 } },
          { "name": "maxSize", "in": "query", "schema": { "type": "integer", "minimum": 0 } },
          { "name": "modifiedAfter", "in": "query", "schema": { "type": "integer", "minimum": 0 } },
          { "name": "modifiedBefore", "in": "query", "schema": { "type": "integer", "minimum": 0 } },
          { "name": "duplicate", "in": "query", "schema": { "type": "string", "enum": ["0", "1"] } },
          {
            "name": "limit",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 200 }
          }
        ],
        "responses": {
          "200": {
            "description": "索引搜索结果",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["rows"],
                  "properties": {
                    "rows": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/SearchItem" }
                    }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/share-links/probe": {
      "post": {
        "tags": ["Transfers"],
        "summary": "解析外部分享链接",
        "operationId": "probeShareLink",
        "x-required-scope": "files:read",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ProbeRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "20 分钟有效的解析结果",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ProbeResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "502": { "$ref": "#/components/responses/UpstreamError" }
        }
      }
    },
    "/transfers": {
      "post": {
        "tags": ["Transfers"],
        "summary": "精确转存已选择项目",
        "description": "只转存 selectedIds 中明确选择的文件或文件夹。相同幂等密钥的结果保留 24 小时。",
        "operationId": "createTransfer",
        "x-required-scope": "transfer:write",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": { "type": "string", "minLength": 8, "maxLength": 120 },
            "description": "每次业务操作唯一的 UUID 或等价随机值"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/TransferRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "任务在快速等待窗口内完成",
            "headers": {
              "Idempotency-Replayed": {
                "description": "为 true 时表示返回已保存的幂等响应",
                "schema": { "type": "string", "enum": ["true"] }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/TaskSubmission" }
              }
            }
          },
          "202": {
            "description": "任务已进入后台队列",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/TaskSubmission" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "502": { "$ref": "#/components/responses/UpstreamError" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/tasks/{taskId}": {
      "get": {
        "tags": ["Tasks"],
        "summary": "查询自己的任务",
        "operationId": "getTask",
        "x-required-scope": "tasks:read",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": { "type": "string", "minLength": 1 }
          }
        ],
        "responses": {
          "200": {
            "description": "任务详情",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["task"],
                  "properties": {
                    "task": { "$ref": "#/components/schemas/Task" }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "wpk_<id>_<secret>",
        "description": "在账户设置中创建；明文只显示一次。"
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "当前密钥和来源 IP 的每分钟请求上限",
        "schema": { "type": "integer", "minimum": 1 }
      },
      "RateLimitRemaining": {
        "description": "当前自然分钟剩余请求数",
        "schema": { "type": "integer", "minimum": 0 }
      },
      "RateLimitReset": {
        "description": "限流窗口重置时间，Unix 秒",
        "schema": { "type": "integer", "minimum": 0 }
      }
    },
    "schemas": {
      "Identity": {
        "type": "object",
        "required": ["id", "username", "role", "authentication", "scopes", "plan"],
        "properties": {
          "id": { "type": "integer" },
          "username": { "type": "string" },
          "role": { "type": "string", "enum": ["user", "admin"] },
          "authentication": { "type": "string", "enum": ["api_key"] },
          "scopes": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Scope" }
          },
          "plan": { "$ref": "#/components/schemas/Plan" }
        }
      },
      "Plan": {
        "type": "object",
        "required": ["code", "name", "apiEnabled", "apiRateLimit", "apiScopes"],
        "properties": {
          "code": { "type": "string" },
          "name": { "type": "string" },
          "accountLimit": { "type": "integer" },
          "dailyWrites": { "type": "integer" },
          "automationLimit": { "type": "integer" },
          "agentLimit": { "type": "integer" },
          "apiEnabled": { "type": "boolean" },
          "apiRateLimit": { "type": "integer" },
          "apiScopes": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Scope" }
          }
        }
      },
      "Scope": {
        "type": "string",
        "enum": [
          "accounts:read",
          "files:read",
          "files:write",
          "transfer:write",
          "shares:write",
          "tasks:read"
        ]
      },
      "Platform": {
        "type": "string",
        "enum": ["quark", "baidu", "xunlei"]
      },
      "Account": {
        "type": "object",
        "required": ["id", "platform", "accountId", "accountName", "status"],
        "properties": {
          "id": { "type": "integer" },
          "platform": { "$ref": "#/components/schemas/Platform" },
          "accountId": { "type": "string" },
          "accountName": { "type": "string" },
          "remark": { "type": "string" },
          "vipStatus": { "type": "string" },
          "capacityText": { "type": "string" },
          "totalBytes": { "type": "integer", "minimum": 0 },
          "usedBytes": { "type": "integer", "minimum": 0 },
          "freeBytes": { "type": "integer", "minimum": 0 },
          "usedPercent": { "type": "number", "minimum": 0 },
          "status": { "type": "string", "enum": ["valid", "invalid", "paused"] },
          "rootFileCount": { "type": "integer", "minimum": 0 },
          "authExpiresAt": { "type": "integer", "minimum": 0 },
          "updatedAt": { "type": "integer", "minimum": 0 },
          "lastVerifiedAt": { "type": "integer", "minimum": 0 }
        }
      },
      "FileItem": {
        "type": "object",
        "required": ["id", "name", "isDir"],
        "properties": {
          "id": { "type": "string" },
          "parent": { "type": "string" },
          "name": { "type": "string" },
          "path": { "type": "string" },
          "isDir": { "type": "boolean" },
          "size": { "type": "integer", "minimum": 0 },
          "updatedAt": { "type": "integer", "minimum": 0 },
          "canDownload": { "type": "boolean" }
        },
        "additionalProperties": true
      },
      "FileList": {
        "type": "object",
        "required": ["account", "current", "rows", "cache", "capabilities"],
        "properties": {
          "account": { "$ref": "#/components/schemas/AccountSummary" },
          "current": {
            "type": "object",
            "required": ["id", "path"],
            "properties": {
              "id": { "type": "string" },
              "path": { "type": "string" }
            }
          },
          "rows": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/FileItem" }
          },
          "cache": {
            "type": "object",
            "properties": {
              "state": { "type": "string" },
              "updatedAt": { "type": "integer" },
              "revalidating": { "type": "boolean" },
              "warning": { "type": "string" },
              "errorCategory": { "type": "string" }
            }
          },
          "capabilities": { "type": "object", "additionalProperties": { "type": "boolean" } }
        }
      },
      "AccountSummary": {
        "type": "object",
        "required": ["id", "platform", "accountName"],
        "properties": {
          "id": { "type": "integer" },
          "platform": { "$ref": "#/components/schemas/Platform" },
          "accountId": { "type": "string" },
          "accountName": { "type": "string" },
          "remark": { "type": "string" }
        }
      },
      "SearchItem": {
        "type": "object",
        "required": ["id", "name", "path", "type", "isDir", "size", "account"],
        "properties": {
          "id": { "type": "string" },
          "parent": { "type": "string" },
          "name": { "type": "string" },
          "path": { "type": "string" },
          "type": { "type": "string", "enum": ["file", "dir"] },
          "isDir": { "type": "boolean" },
          "size": { "type": "integer", "minimum": 0 },
          "updatedAt": { "type": "integer", "minimum": 0 },
          "indexedAt": { "type": "integer", "minimum": 0 },
          "account": { "$ref": "#/components/schemas/AccountSummary" }
        }
      },
      "ProbeRequest": {
        "type": "object",
        "required": ["accountId", "url"],
        "properties": {
          "accountId": { "type": "integer", "minimum": 1 },
          "url": { "type": "string", "format": "uri", "maxLength": 1200 },
          "code": { "type": "string", "maxLength": 20 }
        },
        "additionalProperties": false
      },
      "ProbeResponse": {
        "type": "object",
        "required": ["probeId", "platform", "count", "rows", "expiresAt"],
        "properties": {
          "probeId": { "type": "string", "format": "uuid" },
          "platform": { "$ref": "#/components/schemas/Platform" },
          "count": { "type": "integer", "minimum": 0 },
          "rows": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/FileItem" }
          },
          "expiresAt": { "type": "integer", "minimum": 0 }
        }
      },
      "TransferRequest": {
        "type": "object",
        "required": ["accountId", "probeId", "selectedIds", "rightsConfirmed"],
        "properties": {
          "accountId": { "type": "integer", "minimum": 1 },
          "probeId": { "type": "string", "format": "uuid" },
          "selectedIds": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "uniqueItems": true,
            "items": { "type": "string", "minLength": 1 }
          },
          "destination": { "type": "string" },
          "conflictStrategy": {
            "type": "string",
            "enum": ["skip", "rename", "merge", "overwrite"],
            "default": "rename"
          },
          "applyRules": { "type": "boolean", "default": true },
          "autoShare": { "type": "boolean", "default": false },
          "shareCode": { "type": "string", "maxLength": 12 },
          "shareExpireDays": { "type": "integer", "enum": [0, 1, 7, 30], "default": 0 },
          "rightsConfirmed": {
            "type": "boolean",
            "const": true,
            "description": "调用方确认有权保存和使用所选内容"
          }
        },
        "additionalProperties": false
      },
      "TaskSubmission": {
        "type": "object",
        "required": ["ok", "taskId"],
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "queued": { "type": "boolean" },
          "reused": { "type": "boolean" },
          "taskId": { "type": "string" },
          "status": { "type": "string" },
          "message": { "type": "string" },
          "result": { "type": "object", "additionalProperties": true }
        }
      },
      "Task": {
        "type": "object",
        "required": ["id", "type", "status", "progress"],
        "properties": {
          "id": { "type": "string" },
          "type": { "type": "string" },
          "platform": { "type": "string" },
          "accountId": { "type": "integer" },
          "title": { "type": "string" },
          "status": {
            "type": "string",
            "enum": ["waiting", "running", "paused", "completed", "failed", "cancelled"]
          },
          "progress": { "type": "number", "minimum": 0, "maximum": 100 },
          "request": {
            "type": "object",
            "properties": {
              "destination": { "type": "string" },
              "name": { "type": "string" },
              "size": { "type": "integer" },
              "selectedCount": { "type": "integer" },
              "conflictStrategy": { "type": "string" }
            }
          },
          "result": { "type": "object", "additionalProperties": true },
          "error": { "type": "string" },
          "createdAt": { "type": "integer" },
          "startedAt": { "type": "integer" },
          "finishedAt": { "type": "integer" },
          "updatedAt": { "type": "integer" }
        },
        "additionalProperties": true
      },
      "Error": {
        "type": "object",
        "required": ["code", "message"],
        "properties": {
          "code": { "type": "string" },
          "message": { "type": "string" },
          "category": { "type": "string" },
          "retryable": { "type": "boolean" },
          "authExpired": { "type": "boolean" }
        },
        "additionalProperties": true
      }
    },
    "responses": {
      "BadRequest": {
        "description": "请求参数无效",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "Unauthorized": {
        "description": "API 密钥无效、到期、撤销或用户已停用",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "Forbidden": {
        "description": "套餐未开放、Scope 不足或接口不允许 API 密钥调用",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "NotFound": {
        "description": "资源不存在或不属于当前用户",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "Conflict": {
        "description": "幂等密钥或任务状态冲突",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "RateLimited": {
        "description": "API 或上游网盘限流",
        "headers": {
          "X-RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
          "X-RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
          "X-RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" }
        },
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "UpstreamError": {
        "description": "上游网盘请求失败",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "Unavailable": {
        "description": "任务队列或依赖服务暂不可用",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      }
    }
  }
}
