chore: 初始化 123yunpan skill 仓库 (v1.3.0)

- 完整 skill 本体:SKILL.md / README.md / manifest.json / config.json
- scripts/123yunpan.py:零依赖 CLI(含空间双配额、QPS 限流、零依赖 XLSX)
- references/ 参考资料
- 排除 .workbuddy/ 开发目录与 __pycache__
This commit is contained in:
2026-09-27 22:41:43 +08:00
commit f0ecfa6de0
8 changed files with 5124 additions and 0 deletions
+124
View File
@@ -0,0 +1,124 @@
# 123云盘上传模式 & 竞品分析
> 来源:分析 Skillhub 上 `123pan-upload` skill 的实现,提取可借鉴的模式。
## 短直链生成(Short Direct Link)
直链 URL 包含 user_id 和文件路径,较长且暴露用户信息。短直链只用 file_id,更隐私友好:
```python
import base64, json
def get_user_id_from_token(token: str) -> int:
"""从 JWT token 解析 user_id,无需额外 API 调用"""
parts = token.split(".")
if len(parts) >= 2:
payload = parts[1]
padding = 4 - len(payload) % 4
if padding != 4:
payload += "=" * padding
data = json.loads(base64.b64decode(payload))
return data.get("id", 0)
return 0
def get_short_direct_link(user_id: int, file_id: int) -> str:
return f"https://{user_id}.v.123pan.cn/{user_id}/{file_id}"
```
**对比:**
| 类型 | URL 格式 | 隐私性 | 可直链下载 |
|------|---------|--------|-----------|
| 分享链接 | `https://www.123pan.com/s/{shareKey}` | ✅ 好 | ❌ 需跳转 |
| 完整直链 | `https://{user_id}.v.123pan.cn/{user_id}/{file_id}/{filename}` | ⚠️ 暴露路径 | ✅ |
| 短直链 | `https://{user_id}.v.123pan.cn/{user_id}/{file_id}` | ⚠️ 暴露 user_id | ✅ |
## 上传流程(V2 API)
> ⚠️ **2026-05 验证**:以下流程经过实际 API 调用验证,修正了早期文档中的错误。
### 两个域名
| 域名 | 用途 | 端点 |
|------|------|------|
| `https://open-api.123pan.com` | 主 API(认证、文件管理、chunked create) | `/api/v1/*`, `/api/v2/*`, `/upload/v2/file/create` |
| `https://openapi-upload.123242.com` | 上传专用(获取上传域名返回此值) | `/upload/v2/file/single/create`, `/upload/v2/file/slice`, `/upload/v2/file/upload_complete` |
获取上传域名:`GET /upload/v2/file/domain` → 返回 `["https://openapi-upload.123242.com"]`(列表,非对象)
### 单文件上传(<100MB)
```
1. GET open-api.123pan.com/upload/v2/file/domain → 获取上传服务器地址
2. POST openapi-upload.123242.com/upload/v2/file/single/create → multipart/form-data 上传
```
**关键坑点**:
- `single/create` **必须用 multipart/form-data**,不能用 JSON body。JSON 会导致 500 服务器崩溃。
- 表单字段:`parentFileID`(text), `filename`(text), `etag`(text), `size`(text), `file`(file)
- `duplicate` 字段:**不要传 `0`**(会导致 "duplicate参数错误")。不传默认覆盖,或传 `1`(重命名)/`2`(覆盖)。
- 响应:`{"code":0, "data":{"fileID": 12345, "completed": true}}` — 无需额外上传步骤。
### 分片上传(100MB-10GB)
```
1. POST open-api.123pan.com/upload/v2/file/create → 创建上传任务(主域名)
2. POST openapi-upload.123242.com/upload/v2/file/slice → 逐片上传(上传域名)
3. POST openapi-upload.123242.com/upload/v2/file/upload_complete → 完成上传(上传域名)
```
**关键坑点**:
- `create` 调用主 API 域名,不是上传域名!
- `slice` 和 `upload_complete` 调用上传域名。
- `slice` 请求体字段名为 `partMd5`(注意:不是 `sliceMD5`,后者会导致 500)。
- 分片大小由 `create` 响应中的 `sliceSize` 决定(通常 16MB)。
### SHA1 秒传
```python
# create_file 响应中 reuse=true 表示文件已存在,跳过上传
if create_result["reuse"]:
return {"file_id": create_result["file_id"], ...}
```
### 上传校验轮询
```python
# upload_complete 响应中 completed=false 时需轮询
# 建议间隔:1 秒
# 最大等待:~5 分钟/GB(10GB 文件约 50 分钟)
# 文件大小越大,校验时间越长
for attempt in range(max_retries):
resp = api_post("/upload/v2/file/upload_complete", {"preuploadID": preupload_id})
if resp["data"].get("completed"):
return resp["data"] # 校验完成
time.sleep(1) # 按 API 文档要求,每秒轮询一次
```
### MD5 作为 Etag
上传创建时需要提供文件的 MD5 作为 `etag` 字段:
```python
import hashlib
etag = hashlib.md5(open(file_path, "rb").read()).hexdigest()
```
## WebDAV 上传(>10GB 文件)
API 上传上限 10GB,超大文件可用 WebDAV + rclone:
```bash
# 1. 配置 rclone(隔离配置,避免读取其他云服务凭证)
rclone config --config ~/123pan-rclone.conf
# 添加 "123pan-webdav" remote
# 2. 上传
RCLONE_CONFIG=~/123pan-rclone.conf rclone copy /path/to/large/file 123pan-webdav:/folder -P
# 3. 上传后通过 API 查找文件(WebDAV 上传有 30-90 秒索引延迟)
# 需要轮询 file/list 接口等待文件出现
```
**注意:** WebDAV 上传后文件不会立即出现在 API 列表中,需要重试查找(最多 30 次,每次间隔 3 秒)。
## 安全实践
- rclone 配置隔离:用 `RCLONE_CONFIG` 环境变量指定独立配置文件
- 凭证存储:用环境变量或 `.env` 文件,不要硬编码
- Token 刷新:123yunpan.py CLI 已自动处理 401 响应时的 token 刷新