client: Windows 客户端(WinUI3 壳 + agent-core;调试用 Electron 壳存档);localserver token 改为常数时间比较
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
// 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"
|
||||
}
|
||||
Reference in New Issue
Block a user