geoGo/internal/publisher/csdn.go

203 lines
4.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package publisher
import (
"context"
"fmt"
"geo/internal/config"
"log"
"strings"
"time"
"github.com/go-rod/rod"
)
type CSDNPublisher struct {
*BasePublisher
}
func NewCSDNPublisher(ctx context.Context, task *TaskParams, cfg *config.Config, logger *log.Logger) PublisherInerface {
return &CSDNPublisher{NewBasePublisher(ctx, task, cfg, logger)}
}
func (p *CSDNPublisher) WaitLogin() (bool, string) {
p.LogInfo("开始等待登录...")
if err := p.SetupDriver(); err != nil {
return false, fmt.Sprintf("浏览器启动失败: %v", err)
}
defer p.Close()
p.Page.MustNavigate(p.EditorURL)
p.Sleep(3)
if p.CheckLoginStatus() {
p.SaveCookies()
p.LogInfo("已有登录状态")
return true, "already_logged_in"
}
startTime := time.Now()
timeout := 120
for time.Since(startTime) < time.Duration(timeout)*time.Second {
time.Sleep(1 * time.Second)
if p.CheckLoginStatus() {
p.SaveCookies()
p.LogInfo("登录成功")
return true, "login_success"
}
p.SleepMs(1000)
}
return false, "登录超时,请检查网络或账号状态"
}
func (p *CSDNPublisher) inputTitle() error {
p.LogInfo("输入文章标题...")
titleInput, err := p.WaitForElementVisible("#txtTitle", 5)
if err != nil {
return fmt.Errorf("未找到标题输入框: %v", err)
}
p.LogInfo("找到标题输入框")
if err := p.ClearInput(titleInput); err != nil {
titleInput.Input("")
}
p.SleepMs(200)
if err := p.SetInputValue(titleInput, p.Title); err != nil {
titleInput.Input(p.Title)
}
p.LogInfo(fmt.Sprintf("标题已输入: %s", p.Title))
p.SleepMs(300)
return nil
}
func (p *CSDNPublisher) inputContent(titleInput *rod.Element) error {
p.LogInfo("输入文章内容...")
p.SleepMs(1000)
return nil
}
func (p *CSDNPublisher) clickPublish() error {
p.LogInfo("点击发布按钮...")
btnBox, err := p.WaitForElementVisible("div.btn-box", 3)
if err != nil {
return fmt.Errorf("未找到发布按钮区域: %v", err)
}
publishBtn, err := btnBox.ElementX(".//button[contains(@class, 'btn-outline-danger') and .//span[text()='发布博客']]")
if err != nil {
publishBtn, err = p.Page.ElementX("//button[contains(@class, 'btn-outline-danger') and .//span[text()='发布博客']]")
if err != nil {
return fmt.Errorf("未找到发布按钮: %v", err)
}
}
if err := publishBtn.ScrollIntoView(); err != nil {
p.LogInfo(fmt.Sprintf("滚动到发布按钮失败: %v", err))
}
p.SleepMs(300)
if err := p.JSClick(publishBtn); err != nil {
return fmt.Errorf("点击发布按钮失败: %v", err)
}
p.LogInfo("已点击发布按钮")
p.SleepMs(2000)
return nil
}
func (p *CSDNPublisher) waitForPublishResult() (bool, string) {
p.LogInfo("等待发布结果...")
for attempt := 0; attempt < 10; attempt++ {
currentURL := p.GetCurrentURL()
p.LogInfo(fmt.Sprintf("第 %d 次检查 - URL: %s", attempt+1, currentURL))
if strings.Contains(currentURL, "success") {
p.LogInfo(fmt.Sprintf("发布成功URL: %s", currentURL))
return true, "发布成功"
}
errorSelectors := []string{
"[class*='el_mcm-message--error'] .el_mcm-message__content",
"[class*='el_mcm-message--error']",
"[class*='message--error']",
".error",
".alert-error",
}
for _, selector := range errorSelectors {
errorElements, _ := p.Page.Elements(selector)
for _, elem := range errorElements {
visible, _ := elem.Visible()
if visible {
text, _ := elem.Text()
if text != "" {
p.LogError(fmt.Sprintf("发布失败: %s", text))
return false, fmt.Sprintf("发布失败: %s", text)
}
}
}
}
// 截图保存用于调试
if attempt == 1 || attempt == 9 {
screenshotPath := fmt.Sprintf("debug_%s_%d.png", p.RequestID, attempt)
p.Screenshot(screenshotPath)
p.LogInfo(fmt.Sprintf("已保存截图: %s", screenshotPath))
}
p.SleepMs(1000)
}
return false, "发布结果未知"
}
func (p *CSDNPublisher) PublishNote() (bool, string) {
p.StartNote()
// 初始化浏览器
if err := p.SetupDriver(); err != nil {
return false, fmt.Sprintf("浏览器启动失败: %v", err)
}
defer p.Close()
// 执行发布流程
steps := []struct {
name string
fn func() error
}{
{"初始化", p.InitPage},
{"保存cookie", p.SaveCookies},
{"输入标题", p.inputTitle},
{"输入内容", func() error {
titleInput, _ := p.WaitForElementVisible("#txtTitle", 5)
return p.inputContent(titleInput)
}},
{"点击发布", p.clickPublish},
}
for _, step := range steps {
if err := step.fn(); err != nil {
p.LogStep(step.name, false, err.Error())
return false, fmt.Sprintf("%s失败: %v", step.name, err)
}
p.LogStep(step.name, true, "")
p.SleepMs(500)
}
// 等待发布结果
return p.waitForPublishResult()
}
func (p *CSDNPublisher) LogWarning(message string) {
p.Logger.Printf("⚠️ %s", message)
}