// Code scaffolded by goctl. Safe to edit. // goctl 1.10.1 package brand import ( "context" "strings" app "haixun-backend/internal/library/errors" "haixun-backend/internal/library/errors/code" libthreads "haixun-backend/internal/library/threadsapi" scanpostentity "haixun-backend/internal/model/scan_post/domain/entity" scanpostusecase "haixun-backend/internal/model/scan_post/domain/usecase" "haixun-backend/internal/svc" "haixun-backend/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type PublishOutreachDraftLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewPublishOutreachDraftLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PublishOutreachDraftLogic { return &PublishOutreachDraftLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *PublishOutreachDraftLogic) PublishOutreachDraft(req *types.PublishOutreachDraftHandlerReq) (resp *types.PublishOutreachDraftData, err error) { tenantID, uid, err := actorFrom(l.ctx) if err != nil { return nil, err } scanPostID := strings.TrimSpace(req.ScanPostID) text := strings.TrimSpace(req.Text) confirm := req.Confirm if scanPostID == "" { return nil, app.For(code.Brand).InputMissingRequired("scan_post_id is required") } if !confirm { return nil, app.For(code.Brand).InputMissingRequired("請確認 confirm=true 後再發送留言") } if text == "" { return nil, app.For(code.Brand).InputMissingRequired("text is required") } if _, err := l.svcCtx.Brand.Get(l.ctx, tenantID, uid, req.ID); err != nil { return nil, err } post, err := l.svcCtx.ScanPost.Get(l.ctx, tenantID, uid, req.ID, scanPostID) if err != nil { return nil, err } externalID := strings.TrimSpace(post.ExternalID) if externalID == "" { return nil, app.For(code.Brand).InputMissingRequired("此貼文缺少 external_id,無法透過 API 回覆") } cred, err := l.svcCtx.ThreadsAccount.ResolveMemberThreadsPublishCredential(l.ctx, tenantID, uid) if err != nil { return nil, err } result, err := libthreads.PublishReply(l.ctx, libthreads.PublishReplyInput{ ThreadsUserID: cred.ThreadsUserID, AccessToken: cred.AccessToken, ReplyToID: externalID, Text: text, }) if err != nil { return nil, app.For(code.ThreadsAccount).SvcThirdParty("Threads API 發送留言失敗:" + err.Error()) } updated, err := l.svcCtx.ScanPost.UpdateOutreach(l.ctx, scanpostusecase.UpdateOutreachRequest{ TenantID: tenantID, OwnerUID: uid, BrandID: req.ID, PostID: scanPostID, Status: scanpostentity.OutreachStatusPublished, PublishedReplyID: result.MediaID, PublishedPermalink: result.Permalink, }) if err != nil { return nil, err } return &types.PublishOutreachDraftData{ ScanPostID: scanPostID, ReplyID: result.MediaID, Permalink: result.Permalink, OutreachStatus: updated.OutreachStatus, PublishedPermalink: updated.PublishedPermalink, Message: "獲客留言已透過 Threads API 發送", }, nil }