pet-ai/server/plugin/wechat-integration/service/mp_draft_service.go

375 lines
11 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 service
import (
"errors"
"fmt"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/silenceper/wechat/v2/officialaccount"
"github.com/silenceper/wechat/v2/officialaccount/draft"
)
type MpDraftService struct{}
// DraftListResponse 草稿列表响应结构
type DraftListResponse struct {
Items []DraftItem `json:"items"`
TotalCount int `json:"totalCount"`
}
// DraftItem 草稿项目结构
type DraftItem struct {
MediaID string `json:"mediaId"`
Content DraftContent `json:"content"`
UpdateTime int64 `json:"updateTime"`
}
// DraftContent 草稿内容结构
type DraftContent struct {
NewsItem []DraftArticle `json:"newsItem"`
}
// DraftArticle 草稿文章结构
type DraftArticle struct {
Title string `json:"title"`
Author string `json:"author"`
Digest string `json:"digest"`
Content string `json:"content"`
ContentSourceURL string `json:"contentSourceUrl"`
ThumbMediaID string `json:"thumbMediaId"`
ShowCoverPic int `json:"showCoverPic"`
NeedOpenComment int `json:"needOpenComment"`
OnlyFansCanComment int `json:"onlyFansCanComment"`
ThumbURL string `json:"thumbUrl,omitempty"`
}
// GetDraftList 获取草稿列表
func (m *MpDraftService) GetDraftList(page, pageSize int, title, author string) (*DraftListResponse, error) {
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return nil, err
}
// 计算偏移量
offset := int64((page - 1) * pageSize)
count := int64(pageSize)
// 调用微信API获取草稿列表
draftService := oa.GetDraft()
articleList, err := draftService.PaginateDraft(offset, count, false)
if err != nil {
global.GVA_LOG.Error("获取微信草稿列表失败: " + err.Error())
return nil, fmt.Errorf("获取草稿列表失败: %v", err)
}
// 转换数据格式
response := &DraftListResponse{
Items: make([]DraftItem, 0, len(articleList.Item)),
TotalCount: int(articleList.TotalCount),
}
for _, item := range articleList.Item {
draftItem := DraftItem{
MediaID: item.MediaID,
UpdateTime: item.UpdateTime,
Content: DraftContent{
NewsItem: make([]DraftArticle, 0, len(item.Content.NewsItem)),
},
}
// 转换文章列表
for _, article := range item.Content.NewsItem {
draftArticle := DraftArticle{
Title: article.Title,
Author: article.Author,
Digest: article.Digest,
Content: article.Content,
ContentSourceURL: article.ContentSourceURL,
ThumbMediaID: article.ThumbMediaID,
ShowCoverPic: int(article.ShowCoverPic),
NeedOpenComment: int(article.NeedOpenComment),
OnlyFansCanComment: int(article.OnlyFansCanComment),
}
draftItem.Content.NewsItem = append(draftItem.Content.NewsItem, draftArticle)
}
// 应用过滤条件
if title != "" || author != "" {
matched := false
for _, article := range draftItem.Content.NewsItem {
if title != "" && article.Title != "" &&
len(article.Title) > 0 &&
article.Title == title {
matched = true
break
}
if author != "" && article.Author != "" &&
len(article.Author) > 0 &&
article.Author == author {
matched = true
break
}
}
if matched {
response.Items = append(response.Items, draftItem)
}
} else {
response.Items = append(response.Items, draftItem)
}
}
global.GVA_LOG.Info(fmt.Sprintf("成功获取草稿列表,共 %d 条记录", len(response.Items)))
return response, nil
}
// getOfficialAccount 获取微信公众号实例
func (m *MpDraftService) getOfficialAccount() (*officialaccount.OfficialAccount, error) {
// 使用用户服务获取公众号实例
mpUserService := &MpUserService{}
return mpUserService.GetOfficialAccount()
}
// GetDraftInfo 获取草稿详情通过MediaID
func (m *MpDraftService) GetDraftInfo(mediaID string) (*DraftItem, error) {
if mediaID == "" {
return nil, errors.New("MediaID不能为空")
}
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return nil, err
}
// 调用微信API获取草稿详情
draftService := oa.GetDraft()
articles, err := draftService.GetDraft(mediaID)
if err != nil {
global.GVA_LOG.Error("获取微信草稿详情失败: " + err.Error())
return nil, fmt.Errorf("获取草稿详情失败: %v", err)
}
// 转换数据格式
draftItem := &DraftItem{
MediaID: mediaID,
UpdateTime: 0, // 微信API返回的草稿详情不包含更新时间需要从列表接口获取
Content: DraftContent{
NewsItem: make([]DraftArticle, 0, len(articles)),
},
}
// 转换文章列表
for _, article := range articles {
draftArticle := DraftArticle{
Title: article.Title,
Author: article.Author,
Digest: article.Digest,
Content: article.Content,
ContentSourceURL: article.ContentSourceURL,
ThumbMediaID: article.ThumbMediaID,
ShowCoverPic: int(article.ShowCoverPic),
NeedOpenComment: int(article.NeedOpenComment),
OnlyFansCanComment: int(article.OnlyFansCanComment),
}
draftItem.Content.NewsItem = append(draftItem.Content.NewsItem, draftArticle)
}
global.GVA_LOG.Info(fmt.Sprintf("成功获取草稿详情MediaID: %s", mediaID))
return draftItem, nil
}
// CreateDraftRequest 创建草稿请求结构
type CreateDraftRequest struct {
Articles []DraftArticle `json:"articles"`
}
// CreateDraft 创建草稿
func (m *MpDraftService) CreateDraft(req *CreateDraftRequest) (string, error) {
if len(req.Articles) == 0 {
return "", errors.New("文章列表不能为空")
}
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return "", err
}
// 构建微信API请求参数
articles := make([]*draft.Article, 0, len(req.Articles))
for _, article := range req.Articles {
if article.Title == "" {
return "", errors.New("文章标题不能为空")
}
wxArticle := &draft.Article{
Title: article.Title,
Author: article.Author,
Digest: article.Digest,
Content: article.Content,
ContentSourceURL: article.ContentSourceURL,
ThumbMediaID: article.ThumbMediaID,
ShowCoverPic: uint(article.ShowCoverPic),
NeedOpenComment: uint(article.NeedOpenComment),
OnlyFansCanComment: uint(article.OnlyFansCanComment),
}
articles = append(articles, wxArticle)
}
// 调用微信API创建草稿
draftService := oa.GetDraft()
mediaID, err := draftService.AddDraft(articles)
if err != nil {
global.GVA_LOG.Error("创建微信草稿失败: " + err.Error())
return "", fmt.Errorf("创建草稿失败: %v", err)
}
return mediaID, nil
}
// UpdateDraftRequest 更新草稿请求结构
type UpdateDraftRequest struct {
MediaID string `json:"mediaId"`
Index int `json:"index"`
Articles []DraftArticle `json:"articles"`
}
// UpdateDraft 更新草稿
func (m *MpDraftService) UpdateDraft(req *UpdateDraftRequest) error {
if req.MediaID == "" {
return errors.New("草稿MediaID不能为空")
}
if len(req.Articles) == 0 {
return errors.New("文章列表不能为空")
}
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return err
}
// 微信API只支持单篇文章更新需要逐个更新
draftService := oa.GetDraft()
for i, article := range req.Articles {
if article.Title == "" {
return fmt.Errorf("第%d篇文章标题不能为空", i+1)
}
wxArticle := &draft.Article{
Title: article.Title,
Author: article.Author,
Digest: article.Digest,
Content: article.Content,
ContentSourceURL: article.ContentSourceURL,
ThumbMediaID: article.ThumbMediaID,
ShowCoverPic: uint(article.ShowCoverPic),
NeedOpenComment: uint(article.NeedOpenComment),
OnlyFansCanComment: uint(article.OnlyFansCanComment),
}
// 调用微信API更新草稿
err = draftService.UpdateDraft(wxArticle, req.MediaID, uint(i))
if err != nil {
global.GVA_LOG.Error(fmt.Sprintf("更新草稿第%d篇文章失败: %s", i+1, err.Error()))
return fmt.Errorf("更新草稿第%d篇文章失败: %v", i+1, err)
}
}
global.GVA_LOG.Info(fmt.Sprintf("成功更新草稿MediaID: %s共更新 %d 篇文章", req.MediaID, len(req.Articles)))
return nil
}
// DeleteDraft 删除草稿
func (m *MpDraftService) DeleteDraft(mediaID string) error {
if mediaID == "" {
return errors.New("草稿MediaID不能为空")
}
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return err
}
// 调用微信API删除草稿
draftService := oa.GetDraft()
err = draftService.DeleteDraft(mediaID)
if err != nil {
global.GVA_LOG.Error("删除微信草稿失败: " + err.Error())
return fmt.Errorf("删除草稿失败: %v", err)
}
return nil
}
// PublishDraft 发布草稿
func (m *MpDraftService) PublishDraft(mediaID string) error {
if mediaID == "" {
return errors.New("草稿MediaID不能为空")
}
// 获取微信公众号实例
_, err := m.getOfficialAccount()
if err != nil {
return err
}
// 注意微信公众号草稿发布需要使用freepublish模块
// 这里我们先记录日志实际发布功能需要使用freepublish.SubmitPublish
global.GVA_LOG.Info(fmt.Sprintf("草稿发布请求MediaID: %s。注意实际发布需要使用freepublish模块", mediaID))
// 由于草稿发布涉及到发布流程,这里暂时只做记录
// 实际项目中可以调用 oa.GetFreePublish().SubmitPublish(mediaID) 来发布
return fmt.Errorf("草稿发布功能需要使用freepublish模块MediaID: %s", mediaID)
}
// SyncDrafts 同步草稿
func (m *MpDraftService) SyncDrafts() error {
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return err
}
// 获取草稿总数
draftService := oa.GetDraft()
total, err := draftService.CountDraft()
if err != nil {
global.GVA_LOG.Error("获取草稿总数失败: " + err.Error())
return fmt.Errorf("同步草稿失败: %v", err)
}
global.GVA_LOG.Info(fmt.Sprintf("草稿同步完成,当前草稿总数: %d", total))
return nil
}
// GetDraftCount 获取草稿数量统计
func (m *MpDraftService) GetDraftCount() (map[string]int64, error) {
// 获取微信公众号实例
oa, err := m.getOfficialAccount()
if err != nil {
return nil, err
}
// 调用微信API获取草稿总数
draftService := oa.GetDraft()
total, err := draftService.CountDraft()
if err != nil {
global.GVA_LOG.Error("获取草稿总数失败: " + err.Error())
return nil, fmt.Errorf("获取草稿数量失败: %v", err)
}
result := map[string]int64{
"draft": int64(total),
"published": 0, // 发布数量需要通过其他API获取
"total": int64(total),
}
global.GVA_LOG.Info(fmt.Sprintf("成功获取草稿数量统计,总数: %d", total))
return result, nil
}