Files
EveryPublish/client/core/internal/exec/cdnbase/base.go
T

117 lines
3.3 KiB
Go

// cdnbase 三平台执行器公共底座:保险库 + 浏览器档案目录 + 代理 + 执行入口。
package cdnbase
import (
"context"
"encoding/json"
"path/filepath"
"everypublish/agentcore/internal/exec"
"everypublish/agentcore/internal/exec/cdp"
"everypublish/agentcore/internal/vault"
"everypublish/shared/proto"
)
// Platform 三平台执行器公共底座
type Platform struct {
Vault *vault.Vault
RootDir string // 浏览器档案根目录(每账号子目录)
Proxy string // 账号固定 IP 代理
ChromePath string
Headless bool
ReceiptDir string // 截图回执目录
Name string // 平台名(日志)
PublishCfg cdp.PublishConfig
LoginCfg cdp.QRLoginConfig
LoginDomain string // 登录 cookie 域名
}
// credentials 保险库凭据
type credentials struct {
Cookies string `json:"cookies"`
}
// loadCookies 读账号 cookie(无则空,触发扫码)
func (p *Platform) loadCookies(accountID string) string {
raw, err := p.Vault.Load(accountID)
if err != nil {
return ""
}
var c credentials
if json.Unmarshal(raw, &c) != nil {
return ""
}
return c.Cookies
}
// profileDir 账号独立档案目录
func (p *Platform) profileDir(accountID string) string {
return filepath.Join(p.RootDir, p.Name, accountID)
}
// Publish 通用发布入口(下载素材 → 启动浏览器 → 发布 → 回传)
func (p *Platform) Publish(ctx context.Context, task exec.Task) exec.Result {
fail := func(err string) exec.Result {
return exec.Result{TaskID: task.TaskID, Status: "failed", Error: err}
}
cookies := p.loadCookies(task.AccountID)
if len(task.MaterialURLs) == 0 {
return fail("任务缺少素材")
}
videoPath, cleanup, err := cdp.DownloadFile(ctx, task.MaterialURLs[0])
if err != nil {
return fail("素材下载失败: " + err.Error())
}
defer cleanup()
br, err := cdp.Launch(ctx, cdp.Options{
UserDataDir: p.profileDir(task.AccountID),
Proxy: p.Proxy,
Headless: p.Headless,
ChromePath: p.ChromePath,
})
if err != nil {
return fail("浏览器启动失败: " + err.Error())
}
defer br.Close()
cfg := p.PublishCfg
cfg.Platform = p.Name
cfg.ReceiptDir = p.ReceiptDir
res, err := br.Publish(ctx, cfg, videoPath, task.Title, task.Content, task.Tags, cookies, p.LoginDomain)
if err != nil {
return fail("发布失败: " + err.Error())
}
return exec.Result{
TaskID: task.TaskID,
Status: "success",
PublishedURL: res.URL,
Receipts: res.Receipts,
}
}
// SolveChallenge CDP 扫码登录:二维码截图经 onQR 展示 → 轮询登录 → 保存 cookie
func (p *Platform) SolveChallenge(ctx context.Context, ch proto.Challenge, onQR func(qrToken, qrURL string)) (bool, string) {
br, err := cdp.Launch(ctx, cdp.Options{
UserDataDir: p.profileDir(ch.AccountID),
Proxy: p.Proxy,
Headless: p.Headless,
ChromePath: p.ChromePath,
})
if err != nil {
cdp.Log("%s: 扫码浏览器启动失败: %v", p.Name, err)
return false, ""
}
defer br.Close()
cookies, err := br.QRLogin(ctx, p.LoginCfg, onQR)
if err != nil {
cdp.Log("%s: 扫码登录失败: %v", p.Name, err)
return false, ""
}
if cookies == "" {
return false, ""
}
_ = p.Vault.Save(ch.AccountID, []byte(`{"cookies":"`+cdp.EscapeJSON(cookies)+`"}`))
return true, "confirmed"
}