-
Notifications
You must be signed in to change notification settings - Fork 7
HDHiveBridge
影巢 Browser Bridge 是独立 Chromium 服务,用于调用影巢网页运行时里的签名接口,支持网页登录取 Cookie、签到、积分日志、天翼资源查询和资源解锁。
项目地址:https://github.com/wobuhui666/hdhive-browser-bridge
建议在以下场景部署:
- 需要使用影巢
/api/customer/*网页签名能力。 - 希望影巢资源查询和解锁不受主项目容器冷启动影响。
- 使用VPS、NAS 或自建 Docker 环境运行常驻浏览器。
- 希望把影巢登录态持久化到云端数据库,容器重启后自动恢复。
# 1. 准备 cookie (可选,可以直接在cloud189-auto-save内配置账号密码登录)
node dump-cookies.mjs "your@email.com" "your-password"
# 输出到 /tmp/hdhive-cookies.txt
# 2. 启动容器 (直接使用现成镜像)
docker run -d \
--name hdhive-api \
-p 10000:10000 \
-e BRIDGE_TOKEN=your-secret-token \
-e HDHIVE_COOKIE="$(cat /tmp/hdhive-cookies.txt)" \
-v hdhive-data:/tmp/hdhive-cache \
--restart unless-stopped \
ghcr.io/wobuhui666/hdhive-bridge:latest
# 1. 准备 cookie
node dump-cookies.mjs "your@email.com" "your-password"
# 2. 写 .env 文件
cat > .env <<EOF
BRIDGE_TOKEN=your-secret-token
HDHIVE_COOKIE=$(cat /tmp/hdhive-cookies.txt)
EOF
# 3. 启动
docker-compose up -d
# 4. 查看日志
docker-compose logs -f hdhive-api
| 变量 | 必需 | 默认值 | 说明 |
|---|---|---|---|
| BRIDGE_TOKEN | ❌ | 空 | API 保护 token。空 = 不校验(生产环境务必设置) |
| HDHIVE_COOKIE | ❌ | 空 | 默认 cookie。如果不设,每个请求需单独传 |
| HDHIVE_BASE_URL | ❌ | https://hdhive.com | 影巢基础 URL |
| BROWSER_HEADLESS | ❌ | true | 是否无头模式(调试可设 false) |
| ACTION_TIMEOUT_MS | ❌ | 180000 | 单个接口超时(毫秒) |
| AUTO_WARMUP | ❌ | true | 启动时自动预热浏览器 |
| CAPTCHA_AI_BASE_URL | ❌ | 空 | 自动签到验证码 AI endpoint,例如 https://example.com/v1 |
| CAPTCHA_AI_API_KEY | ❌ | 空 | 自动签到验证码 AI key。只用于验证码图片识别,不会发送 Cookie |
| CAPTCHA_AI_MODEL | ❌ | gemini-auto | 自动签到验证码模型 |
| CAPTCHA_SOLVER | ❌ | 空 | 默认验证码求解器,可设 ai、auto 或 heuristic |
| PORT | ❌ | 10000 | HTTP 端口 |
| DATABASE_URL | ❌ | 空 | Postgres 连接串。设置后启用 cookie 持久化 |
| BRIDGE_STATE_SECRET | ❌ | BRIDGE_TOKEN | 加密密钥(用于数据库存储 cookie) |
| COOKIE_KEY | ❌ | default | 数据库中 cookie 的 key(多实例时区分) |
每个请求的 cookie 按以下优先级获取:
- 请求 body:POST /hdhive/login body 中传 {"cookie": "..."}
- 请求头:x-hdhive-cookie: ...
- 环境变量:HDHIVE_COOKIE
| 接口 | 说明 |
|---|---|
| POST /hdhive/login | 账号密码登录,返回新 cookie 字符串 |
| GET /hdhive/cookies | 读取当前 client 的所有 cookies |
| POST /browser/restart | 重启浏览器(清空登录态) |
| 完整容器化部署流程: |
# 1. 启动容器(不预置 cookie)
docker run -d --name hdhive-api -p 10000:10000 \
-e BRIDGE_TOKEN=xxx ghcr.io/wobuhui666/hdhive-bridge:latest
# 2. 通过 API 登录获取 cookie
COOKIE=$(curl -s -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{"username":"you@email.com","password":"xxx"}' \
http://localhost:10000/hdhive/login | jq -r '.data.cookie')
# 3. 用 cookie 调用 API
curl -H "x-bridge-token: xxx" \
-H "x-hdhive-cookie: $COOKIE" \
http://localhost:10000/hdhive/customer/current
# 或保存到环境变量并重启容器
docker stop hdhive-api && docker rm hdhive-api
docker run -d --name hdhive-api -p 10000:10000 \
-e BRIDGE_TOKEN=xxx \
-e HDHIVE_COOKIE="$COOKIE" \
ghcr.io/wobuhui666/hdhive-bridge:latest
设置 DATABASE_URL 后,cookie 会加密保存到 Postgres,容器重启后自动恢复。
# 1. 准备 .env
cat > .env <<EOF
BRIDGE_TOKEN=your-strong-token
BRIDGE_STATE_SECRET=$(openssl rand -hex 32)
POSTGRES_PASSWORD=hdhive_secret
EOF
# 2. 启动(自动包含 Postgres)
docker-compose up -d
# 3. 首次登录(会自动写入数据库)
COOKIE=$(curl -s -X POST -H "x-bridge-token: $(grep BRIDGE_TOKEN .env | cut -d= -f2)" \
-H "Content-Type: application/json" \
-d '{"username":"you@email.com","password":"your-pass"}' \
http://localhost:10000/hdhive/login | jq -r '.data.cookie')
# 4. 验证数据库中有 cookie
curl -H "x-bridge-token: $(grep BRIDGE_TOKEN .env | cut -d= -f2)" \
http://localhost:10000/admin/cookies
| 启动场景 | 行为 |
|---|---|
| 启动时 DB 无 cookie + env 有 HDHIVE_COOKIE | 自动保存 env cookie 到 DB |
| 启动时 DB 有 cookie + env 无 HDHIVE_COOKIE | 自动加载 DB cookie 作为默认 |
| 启动时 DB 有 cookie + env 有 HDHIVE_COOKIE | 优先用 env,DB 保留 |
| 调用 POST /hdhive/login | 登录后自动加密保存到 DB |
| 调用 POST /admin/cookies/:key | 手动设置(无登录直接写) |
CREATE TABLE hdhive_cookies (
key TEXT PRIMARY KEY, -- COOKIE_KEY 配置
cookie_encrypted TEXT NOT NULL, -- AES-256-GCM 加密
meta JSONB DEFAULT '{}'::jsonb, -- 元数据(hdh_uid, source, ua)
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
- 算法:AES-256-GCM
- 密钥:从 BRIDGE_STATE_SECRET 派生(SHA-256)
- IV:每次加密随机生成(12 bytes)
- 认证:authTag 防止篡改
- 存储格式:base64(iv + authTag + ciphertext),约 150% 原文大小
用 COOKIE_KEY 区分不同 cookie:
# 实例 1:保存 user A 的 cookie
COOKIE_KEY=user-a docker run ... ghcr.io/wobuhui666/hdhive-bridge:latest
# 实例 2:保存 user B 的 cookie(不同容器端口)
COOKIE_KEY=user-b docker run -p 10001:10000 ... ghcr.io/wobuhui666/hdhive-bridge:latest
# 或同一实例多账号(手动调用)
curl -X POST -H "x-bridge-token: xxx" \
-d '{"cookie":"...","key":"user-b"}' \
http://localhost:10000/admin/cookies/user-b
# 从一个环境迁移 cookie 到另一个
docker exec hdhive-postgres pg_dump -t hdhive_cookies > cookies.sql
docker exec -i hdhive-postgres-new psql < cookies.sql
所有接口(除 /health)需要 x-bridge-token 请求头。
健康检查(不需要 token)。
curl http://localhost:10000/health
# {"success":true,"status":"healthy","uptime":12345,...}
查看指标。
curl -H "x-bridge-token: xxx" http://localhost:10000/metrics
预热浏览器(手动触发)。
curl -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{}' \
http://localhost:10000/warmup
账号密码登录,返回 cookie 字符串(会消耗一次登录请求)。
curl -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{"username":"your@email.com","password":"your-password"}' \
http://localhost:10000/hdhive/login
读取当前 client 的所有 cookies(需要已登录)。
curl -H "x-bridge-token: xxx" http://localhost:10000/hdhive/cookies
重启浏览器(清空登录态)。
curl -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{}' \
http://localhost:10000/browser/restart
列出所有保存的 cookie keys(不含明文)。
curl -H "x-bridge-token: xxx" http://localhost:10000/admin/cookies
手动设置 cookie 到数据库(无需登录)。
curl -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{"cookie":"hdh_sa_token=xxx; token=eyJ...; csrf_access_token=xxx; hdh_uid=xxx"}' \
http://localhost:10000/admin/cookies/default
删除指定 key 的 cookie。
curl -X DELETE -H "x-bridge-token: xxx" \
http://localhost:10000/admin/cookies/default
当前用户信息。
curl -H "x-bridge-token: xxx" http://localhost:10000/hdhive/customer/current
积分日志。
签到。默认返回归一化状态和签到前后积分;如需跳过额外用户信息查询,可追加 ?includeUser=false。如果当前环境要求验证码,可追加 ?autoVerify=true&verificationSolver=ai,并配置 CAPTCHA_AI_BASE_URL 与 CAPTCHA_AI_API_KEY。
curl -X POST -H "x-bridge-token: xxx" http://localhost:10000/hdhive/customer/checkin
curl -X POST -H "x-bridge-token: xxx" \
"http://localhost:10000/hdhive/customer/checkin?autoVerify=true&verificationSolver=ai&verificationAttempts=3"
未读消息数。
我的播放列表。
订阅检查。
curl -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{"target_type":"media_resource","target_key":"movie:550"}' \
http://localhost:10000/hdhive/customer/subscriptions/check
资源详情。
curl -H "x-bridge-token: xxx" \
http://localhost:10000/hdhive/customer/resources/3fb1cb6823c64ae4a7a0f8f23bd4bed3
解锁资源。
curl -X POST -H "x-bridge-token: xxx" \
http://localhost:10000/hdhive/customer/resources/3fb1cb6823c64ae4a7a0f8f23bd4bed3/unlock
检查分享链接。
curl -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{"url":"https://hdhive.com/resource/189/abc123..."}' \
http://localhost:10000/hdhive/customer/check/resource
最新公告。
只查询不解锁,列出所有资源 + 所需积分(不消耗积分)。
curl -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{}' \
http://localhost:10000/hdhive/preview/tmdb/372058
从 TMDB ID 一键解锁并拿网盘。
curl -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{"type":"movie"}' \
http://localhost:10000/hdhive/unlock/tmdb/372058
通过 resource slug 解锁。
curl -X POST -H "x-bridge-token: xxx" \
http://localhost:10000/hdhive/unlock/resource/3fb1cb6823c64ae4a7a0f8f23bd4bed3
通过分享 URL 解锁。
curl -X POST -H "x-bridge-token: xxx" \
-H "Content-Type: application/json" \
-d '{"url":"https://hdhive.com/movie/0816e198eae211ed8d4e0242ac190003","movieId":372058}' \
http://localhost:10000/hdhive/unlock/share
单独提取 189 网盘链接(仅已解锁资源可用)。
curl -H "x-bridge-token: xxx" \
http://localhost:10000/hdhive/resource/3fb1cb6823c64ae4a7a0f8f23bd4bed3/cloud189
/hdhive/unlock/ 接口会消耗积分*。生产部署务必加预览+预算控制。
| 资源状态 | 调用 unlock 接口后 |
|---|---|
| unlock_points = 0(免费) | ❌ 不扣 |
| unlock_points > 0 已解锁 | ❌ 不重复扣(返回 already_owned: true) |
| unlock_points > 0 未解锁 | ✅ 扣 unlock_points 积分 |
# 第 1 步:预览(不消耗积分)
curl -X POST -H "x-bridge-token: xxx" -d '{}' \
http://localhost:10000/hdhive/preview/tmdb/372058
# 检查返回的 totalCost 和 currentPoints,确认预算
# 第 2 步:确认后一键解锁(消耗积分)
curl -X POST -H "x-bridge-token: xxx" -d '{}' \
http://localhost:10000/hdhive/unlock/tmdb/372058
const POINTS_BUDGET = 50;
let totalSpent = 0;
for (const tmdbId of [372058, 550, 129]) {
// 1. 预览(不消耗积分)
const preview = await fetch(`http://hdhive-api:10000/hdhive/preview/tmdb/${tmdbId}`, {
method: 'POST',
headers: { 'x-bridge-token': 'xxx' }
}).then(r => r.json());
// 2. 预算检查
if (totalSpent + preview.data.cheapestCost > POINTS_BUDGET) {
console.log(`⊘ TMDB ${tmdbId}: 预算不足`);
continue;
}
// 3. 解锁
const result = await fetch(`http://hdhive-api:10000/hdhive/unlock/tmdb/${tmdbId}`, {
method: 'POST',
headers: { 'x-bridge-token': 'xxx' }
}).then(r => r.json());
totalSpent += preview.data.cheapestCost;
console.log(`✓ TMDB ${tmdbId}: ${result.data.cloud189.fullText}`);
}- GET /health
- GET /metrics
- POST /warmup
- GET /hdhive/customer/current
- GET /hdhive/customer/points-logs
- GET /hdhive/customer/messages/unread-count
- POST /hdhive/customer/checkin(增加积分;可用 autoVerify=true 自动处理验证码)
- GET /hdhive/customer/playlists/my
- POST /hdhive/customer/subscriptions/check
- POST /hdhive/customer/check/resource
- POST /hdhive/preview/tmdb/:id ⭐
- GET /hdhive/public/bulletins/latest
- GET /hdhive/resource/:slug/cloud189(仅已解锁)
- POST /hdhive/unlock/tmdb/:id
- POST /hdhive/unlock/resource/:slug
- POST /hdhive/unlock/share
version: '3.8'
services:
hdhive-api:
image: ghcr.io/wobuhui666/hdhive-bridge:latest
container_name: hdhive-api
restart: unless-stopped
ports:
- "10000:10000"
environment:
- BRIDGE_TOKEN=your-strong-token-here
- HDHIVE_COOKIE=${HDHIVE_COOKIE}
- HDHIVE_BASE_URL=https://hdhive.com
- BROWSER_HEADLESS=true
- AUTO_WARMUP=true
volumes:
- hdhive-data:/tmp/hdhive-cache
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:10000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
volumes:
hdhive-data:
- 使用反向代理(nginx / caddy):
location /hdhive/ {
proxy_pass http://127.0.0.1:10000;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_read_timeout 300s; # 关键:解锁可能耗时 30-60s
}
- 持久化浏览器数据:用 volumes 挂载 /tmp/hdhive-cache
- 资源限制:
deploy:
resources:
limits:
memory: 4G # Chromium 浏览器较耗内存
- 日志收集:配置 logging.driver 收集日志到 ELK/Loki
- 健康检查:用 /health 端点做健康检查
apiVersion: apps/v1
kind: Deployment
metadata:
name: hdhive-api
spec:
replicas: 1 # 注意:单例,因为共享浏览器状态
selector:
matchLabels:
app: hdhive-api
template:
metadata:
labels:
app: hdhive-api
spec:
containers:
- name: hdhive-api
image: ghcr.io/wobuhui666/hdhive-bridge:latest
ports:
- containerPort: 10000
env:
- name: BRIDGE_TOKEN
valueFrom:
secretKeyRef:
name: hdhive-secrets
key: bridge-token
- name: HDHIVE_COOKIE
valueFrom:
secretKeyRef:
name: hdhive-secrets
key: cookie
resources:
limits:
memory: 4Gi
cpu: "2"
livenessProbe:
httpGet:
path: /health
port: 10000
initialDelaySeconds: 60
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 10000
initialDelaySeconds: 30
periodSeconds: 10
volumeMounts:
- name: cache
mountPath: /tmp/hdhive-cache
volumes:
- name: cache
emptyDir: {}
# 查看日志
docker logs hdhive-api
# 常见原因:cookie 过期 / token 错误 / 端口冲突
# 进入容器调试
docker exec -it hdhive-api /bin/bash
wget -qO- http://localhost:10000/health
- 首次启动需要 20-40s(浏览器冷启动 + 加载 webpack)
- 后续 API 调用:8-15s/次
- 共享浏览器后,并发能力受限(建议单例部署)
Chromium 默认占用 200-500MB 内存,建议容器至少 2GB。
测试环境:Linux + Docker + 4GB 内存容器
| 接口 | 平均耗时 |
|---|---|
| /health | < 10ms |
| /hdhive/customer/current | 0.5-2s |
| /hdhive/unlock/tmdb/372058 (首次) | 25-40s |
| /hdhive/unlock/tmdb/X (后续) | 8-15s |
# 拉取最新镜像
docker pull ghcr.io/wobuhui666/hdhive-bridge:latest
# 重启容器以应用新镜像
docker-compose up -d