docs: update reverse engineering manuals with latest findings

- Add cos_upload.py pure-Python COS upload method (no browser needed)
- Expand API endpoint table to include all discovered endpoints
- Document dual-verification login detection (URL + DOM)
- Add COS V1 signing algorithm explanation
- Update file reference table to match current codebase
- Remove obsolete file references (get_resource_id.py, etc.)
- Sync Chinese and English versions

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-05-27 03:43:39 +08:00
parent bf4e1e5755
commit 58ab0d6655
2 changed files with 176 additions and 60 deletions

View File

@@ -47,14 +47,23 @@ param_str = "nonce=yyy&timestamp=xxx"
sign = HMAC-SHA256(param_str, key="Hf6d6KFB3D")
```
### 3. Image URL Format
### 3. Image Upload Evolution
Must use Tencent's internal resource format:
```
https://3d.hunyuan.tencent.com/api/3d/resource/download?resourceId=<32-digit-hex>
```
#### Method 1: Browser Automation Upload (Original)
Upload via `generator.py` inside the browser to obtain a Tencent internal `resourceId`.
You cannot directly use a COS URL; you must upload through the browser to obtain a resourceId.
#### Method 2: Pure Python COS Direct Upload (New)
Upload directly via `cos_upload.py` without a browser:
1. Call `/resource/genUploadInfo` to obtain temporary STS credentials (`encryptTmpSecretId` / `encryptTmpSecretKey` / `encryptToken`)
2. Generate the `Authorization` header using the COS V1 signing algorithm
3. `PUT` directly to `*.cos.accelerate.myqcloud.com`
4. Obtain `resourceUrl` for subsequent image-to-3D API calls
```python
from hunyuan3dweb.cos_upload import upload_image
resource_url = upload_image("/path/to/image.png")
```
---
@@ -63,9 +72,14 @@ You cannot directly use a COS URL; you must upload through the browser to obtain
| File | Description |
|------|-------------|
| `hunyuan3dweb/sign.py` | Signing algorithm in pure Python |
| `hunyuan3dweb/api.py` | Pure Python API client |
| `hunyuan3dweb/api.py` | Basic API client (image2model, text2model) |
| `hunyuan3dweb/api_complete.py` | Full API client (all generation modes) |
| `hunyuan3dweb/cos_upload.py` | Pure Python COS upload helper (no browser needed) |
| `hunyuan3dweb/config.py` | User config path management (cookies, profile) |
| `hunyuan3dweb/cli.py` | CLI entry point |
| `hunyuan3dweb/browser/login.py` | Browser automation login tool |
| `doc/api.md` | API endpoint documentation |
| `hunyuan3dweb/browser/generator.py` | Browser automation image-to-3D |
| `hunyuan3dweb/browser/sniffer.py` | API request sniffer |
---
@@ -77,29 +91,46 @@ You cannot directly use a COS URL; you must upload through the browser to obtain
hunyuan3dweb-login
# Follow prompts to enter email and verification code
# Login state is automatically saved to ~/.config/hunyuan3dweb/profile
# Cookies are also exported to ~/.config/hunyuan3dweb/cookies.txt
```
**Login State Detection Logic** (dual verification):
- Check if the current page URL contains `"login"`
- Check if a "Login" button exists on the page
- Only considered logged in when URL does NOT contain login **AND** no login button is present
### 2. Pure Python 3D Generation
```python
from hunyuan3dweb import Hunyuan3DAPI
# Automatically load cookie from ~/.config/hunyuan3dweb/cookies.txt
api = Hunyuan3DAPI()
# Check quota
quota = api.get_quota_info()
# Generate 3D model
result = api.generate_3d(
image_url="https://3d.hunyuan.tencent.com/api/3d/resource/download?resourceId=...",
scene_type="playGround3D-2.0",
model_type="image2ModelV3.1"
)
# Text-to-3D
result = api.generate_text("a cute panda", title="Panda Model")
# Query status
status = api.get_generation_status(result["creationsId"])
```
### 3. Local Image Upload + Image-to-3D (Pure Python)
```python
from hunyuan3dweb.cos_upload import upload_image
from hunyuan3dweb import Hunyuan3DAPIComplete
# Upload local image to COS
resource_url = upload_image("/path/to/image.png")
# Call image-to-3D API
api = Hunyuan3DAPIComplete()
result = api.generate_from_image(resource_url, title="My Model")
```
---
## API Endpoints
@@ -110,6 +141,14 @@ status = api.get_generation_status(result["creationsId"])
| Quota query | POST | `/quotainfo` | Query params |
| Generate 3D | POST | `/creations/generations` | Query params |
| Query status | GET | `/creations/detail` | Query params |
| Creation list | POST | `/creations/list` | Query params |
| Creation count | POST | `/creations/count` | Query params |
| Cancel generation | POST | `/creations/cancel` | Query params |
| Upload credentials | POST | `/resource/genUploadInfo` | Query params |
| Resource review | POST | `/resource/review` | Query params |
| Create share | POST | `/share` | Query params |
| Global config | GET | `/config` | Query params |
| Animation templates | GET | `/workflow/action/templates` | Query params |
---
@@ -146,6 +185,32 @@ def derive_key(c: bytes) -> str:
return n[:r].decode('utf-8')
```
### COS V1 Signature (for Direct Upload)
```python
def _cos_v1_auth(method, pathname, query_params, headers, secret_id, secret_key, key_time):
sign_key = hmac.new(secret_key.encode("utf-8"), key_time.encode("utf-8"), hashlib.sha1).hexdigest()
query_str = _obj2str(query_params, True)
headers_str = _obj2str(headers, True)
format_string = f"{method}\n{pathname}\n{query_str}\n{headers_str}\n"
format_string_sha1 = hashlib.sha1(format_string.encode("utf-8")).hexdigest()
string_to_sign = f"sha1\n{key_time}\n{format_string_sha1}\n"
signature = hmac.new(sign_key.encode("utf-8"), string_to_sign.encode("utf-8"), hashlib.sha1).hexdigest()
return "&".join([
"q-sign-algorithm=sha1",
f"q-ak={secret_id}",
f"q-sign-time={key_time}",
f"q-key-time={key_time}",
f"q-header-list={';'.join(sorted(headers.keys())).lower()}",
f"q-url-param-list={';'.join(sorted(query_params.keys())).lower()}",
f"q-signature={signature}",
])
```
### Request Signing
```python
@@ -180,15 +245,16 @@ def sign(params: dict) -> dict:
| Quota query | Works | Works | ✅ |
| Generate request | Works | Works | ✅ |
| Status query | Works | Works | ✅ |
| COS direct upload | Browser upload | Python upload | ✅ |
---
## Limitations and Notes
1. **Image Upload**: Still requires a browser environment to upload images and obtain resourceId (Tencent COS requires temporary signatures)
2. **Cookie Expiration**: Login sessions expire and need periodic re-login
3. **Quota Limit**: Each account has a generation quota limit (default 20/day)
4. **Rate Limiting**: Frequent calls may trigger anti-bot measures
1. **Cookie Expiration**: Login sessions expire and need periodic re-login
2. **Quota Limit**: Each account has a generation quota limit (default 20/day)
3. **Rate Limiting**: Frequent calls may trigger anti-bot measures
4. **Concurrency Safety**: When multiple tools run simultaneously, `login.py` exclusively uses the standard profile directory, while `sniffer.py` / `generator.py` automatically copy the profile to a temporary directory to avoid Chromium `SingletonLock` conflicts
---
@@ -196,7 +262,7 @@ def sign(params: dict) -> dict:
```
requests
cloakbrowser (for login and upload)
cloakbrowser (for login and browser automation)
```
---