108 lines
3.1 KiB
Go
108 lines
3.1 KiB
Go
|
|
package persona
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
app "haixun-backend/internal/library/errors"
|
||
|
|
"haixun-backend/internal/library/errors/code"
|
||
|
|
libthreads "haixun-backend/internal/library/threadsapi"
|
||
|
|
"haixun-backend/internal/library/threadspost"
|
||
|
|
copydraftdomain "haixun-backend/internal/model/copy_draft/domain/usecase"
|
||
|
|
"haixun-backend/internal/svc"
|
||
|
|
"haixun-backend/internal/types"
|
||
|
|
)
|
||
|
|
|
||
|
|
type PublishPersonaCopyDraftLogic struct {
|
||
|
|
ctx context.Context
|
||
|
|
svcCtx *svc.ServiceContext
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewPublishPersonaCopyDraftLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PublishPersonaCopyDraftLogic {
|
||
|
|
return &PublishPersonaCopyDraftLogic{ctx: ctx, svcCtx: svcCtx}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (l *PublishPersonaCopyDraftLogic) PublishPersonaCopyDraft(
|
||
|
|
req *types.PublishCopyDraftHandlerReq,
|
||
|
|
) (*types.PublishCopyDraftData, error) {
|
||
|
|
tenantID, uid, err := actorFrom(l.ctx)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
personaID := strings.TrimSpace(req.ID)
|
||
|
|
draftID := strings.TrimSpace(req.DraftID)
|
||
|
|
if !req.Confirm {
|
||
|
|
return nil, app.For(code.Persona).InputMissingRequired("請確認 confirm=true 後再發布貼文")
|
||
|
|
}
|
||
|
|
if _, err := l.svcCtx.Persona.Get(l.ctx, tenantID, uid, personaID); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
draftItem, err := l.svcCtx.CopyDraft.Get(l.ctx, tenantID, uid, personaID, draftID)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
draft := draftItem
|
||
|
|
if draft.Status == "published" {
|
||
|
|
return nil, app.For(code.Persona).ResInvalidState("此草稿已發布")
|
||
|
|
}
|
||
|
|
|
||
|
|
text := strings.TrimSpace(req.Text)
|
||
|
|
if text == "" {
|
||
|
|
text = strings.TrimSpace(draft.Text)
|
||
|
|
}
|
||
|
|
if text == "" {
|
||
|
|
return nil, app.For(code.Persona).InputMissingRequired("text is required")
|
||
|
|
}
|
||
|
|
if err := threadspost.ValidatePublish(text); err != nil {
|
||
|
|
return nil, app.For(code.Persona).InputInvalidFormat(err.Error())
|
||
|
|
}
|
||
|
|
if strings.TrimSpace(req.Text) != "" && req.Text != draft.Text {
|
||
|
|
updatedText, err := l.svcCtx.CopyDraft.Update(l.ctx, copydraftdomain.UpdateRequest{
|
||
|
|
TenantID: tenantID,
|
||
|
|
OwnerUID: uid,
|
||
|
|
PersonaID: personaID,
|
||
|
|
DraftID: draftID,
|
||
|
|
Patch: copydraftdomain.CopyDraftPatch{Text: &req.Text},
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
draft = updatedText
|
||
|
|
text = strings.TrimSpace(updatedText.Text)
|
||
|
|
}
|
||
|
|
|
||
|
|
cred, err := l.svcCtx.ThreadsAccount.ResolveMemberThreadsPublishCredential(l.ctx, tenantID, uid)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
result, err := libthreads.PublishText(l.ctx, libthreads.PublishTextInput{
|
||
|
|
ThreadsUserID: cred.ThreadsUserID,
|
||
|
|
AccessToken: cred.AccessToken,
|
||
|
|
Text: text,
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
return nil, app.For(code.ThreadsAccount).SvcThirdParty("Threads API 發布貼文失敗:" + err.Error())
|
||
|
|
}
|
||
|
|
|
||
|
|
updated, err := l.svcCtx.CopyDraft.MarkPublished(l.ctx, copydraftdomain.MarkPublishedRequest{
|
||
|
|
TenantID: tenantID,
|
||
|
|
OwnerUID: uid,
|
||
|
|
PersonaID: personaID,
|
||
|
|
DraftID: draftID,
|
||
|
|
MediaID: result.MediaID,
|
||
|
|
Permalink: result.Permalink,
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return &types.PublishCopyDraftData{
|
||
|
|
DraftID: draftID,
|
||
|
|
MediaID: result.MediaID,
|
||
|
|
Permalink: result.Permalink,
|
||
|
|
Status: updated.Status,
|
||
|
|
Message: "仿寫貼文已透過 Threads API 發布",
|
||
|
|
}, nil
|
||
|
|
}
|