thread-master/backend/internal/model/own_post_formula/usecase/usecase.go

94 lines
3.1 KiB
Go
Raw Normal View History

2026-07-01 08:42:51 +00:00
package usecase
import (
"context"
"strings"
"time"
2026-07-03 14:42:19 +00:00
"haixun-backend/internal/library/clock"
2026-07-01 08:42:51 +00:00
app "haixun-backend/internal/library/errors"
"haixun-backend/internal/library/errors/code"
libownpost "haixun-backend/internal/library/ownpost"
"haixun-backend/internal/model/own_post_formula/domain/entity"
domrepo "haixun-backend/internal/model/own_post_formula/domain/repository"
)
const FormulaCacheTTL = 5 * time.Minute
type UseCase interface {
Get(ctx context.Context, tenantID, ownerUID, accountID, mediaID string) (*entity.Review, error)
SaveGenerated(ctx context.Context, tenantID, ownerUID, accountID, mediaID, personaID, postText string, review *libownpost.PostFormulaReview) (*entity.Review, error)
ListByAccount(ctx context.Context, tenantID, ownerUID, accountID string) ([]entity.Review, error)
IsFresh(review *entity.Review, now int64) bool
}
func (u *useCase) Get(ctx context.Context, tenantID, ownerUID, accountID, mediaID string) (*entity.Review, error) {
return u.repo.Get(ctx, tenantID, ownerUID, accountID, mediaID)
}
func (u *useCase) IsFresh(review *entity.Review, now int64) bool {
if review == nil || review.UpdateAt <= 0 {
return false
}
if now <= 0 {
now = clock.NowUnixNano()
}
return now-review.UpdateAt < int64(FormulaCacheTTL)
}
type useCase struct {
repo domrepo.Repository
}
func NewUseCase(repo domrepo.Repository) UseCase {
return &useCase{repo: repo}
}
func (u *useCase) SaveGenerated(
ctx context.Context,
tenantID, ownerUID, accountID, mediaID, personaID, postText string,
review *libownpost.PostFormulaReview,
) (*entity.Review, error) {
if review == nil {
return nil, app.For(code.ThreadsAccount).InputMissingRequired("review is required")
}
accountID = strings.TrimSpace(accountID)
mediaID = strings.TrimSpace(mediaID)
if accountID == "" || mediaID == "" {
return nil, app.For(code.ThreadsAccount).InputMissingRequired("account_id and media_id are required")
}
now := clock.NowUnixNano()
doc := &entity.Review{
ID: entity.ReviewDocID(accountID, mediaID),
TenantID: strings.TrimSpace(tenantID),
OwnerUID: strings.TrimSpace(ownerUID),
AccountID: accountID,
MediaID: mediaID,
PersonaID: strings.TrimSpace(personaID),
PostText: strings.TrimSpace(postText),
Summary: review.Summary,
Wins: review.Wins,
Improvements: review.Improvements,
Formula: review.Formula,
PostTemplate: review.PostTemplate,
HookPattern: review.HookPattern,
Structure: review.Structure,
ReplicationTips: review.ReplicationTips,
Avoid: review.Avoid,
CreateAt: now,
UpdateAt: now,
}
if existing, err := u.repo.Get(ctx, tenantID, ownerUID, accountID, mediaID); err == nil && existing != nil {
doc.CreateAt = existing.CreateAt
}
return u.repo.Upsert(ctx, doc)
}
func (u *useCase) ListByAccount(ctx context.Context, tenantID, ownerUID, accountID string) ([]entity.Review, error) {
accountID = strings.TrimSpace(accountID)
if accountID == "" {
return nil, app.For(code.ThreadsAccount).InputMissingRequired("account_id is required")
}
return u.repo.ListByAccount(ctx, tenantID, ownerUID, accountID)
2026-07-03 14:42:19 +00:00
}