package usecase import ( "context" "strings" "haixun-backend/internal/library/clock" "haixun-backend/internal/library/placement" libviral "haixun-backend/internal/library/viral" accountentity "haixun-backend/internal/model/threads_account/domain/entity" domusecase "haixun-backend/internal/model/threads_account/domain/usecase" ) func (u *threadsAccountUseCase) GetKnownAccounts( ctx context.Context, tenantID, ownerUID, accountID string, ) (map[string]accountentity.KnownAccountProfile, error) { if err := requireActor(tenantID, ownerUID); err != nil { return nil, err } accountID = strings.TrimSpace(accountID) if accountID == "" { return map[string]accountentity.KnownAccountProfile{}, nil } account, err := u.assertOwned(ctx, tenantID, ownerUID, accountID) if err != nil { return nil, err } return cloneKnownAccounts(account.KnownAccounts), nil } func (u *threadsAccountUseCase) UpsertKnownAccountsFromScan( ctx context.Context, req domusecase.UpsertKnownAccountsFromScanRequest, ) error { if err := requireActor(req.TenantID, req.OwnerUID); err != nil { return err } accountID := strings.TrimSpace(req.AccountID) if accountID == "" || len(req.SimilarAccounts) == 0 { return nil } account, err := u.assertOwned(ctx, req.TenantID, req.OwnerUID, accountID) if err != nil { return err } now := clock.NowUnixNano() merged := libviral.MergeKnownAccountsFromScan( cloneKnownAccounts(account.KnownAccounts), req.SimilarAccounts, strings.TrimSpace(req.MissionID), strings.TrimSpace(req.PersonaID), req.SelectedTags, now, ) return u.repo.SetKnownAccounts(ctx, req.TenantID, req.OwnerUID, accountID, merged) } func (u *threadsAccountUseCase) ResolveMemberCapabilities( ctx context.Context, tenantID, ownerUID string, research placement.ResearchSettings, ) (placement.MemberCapabilities, error) { if err := requireActor(tenantID, ownerUID); err != nil { return placement.MemberCapabilities{}, err } member, err := u.ResolveMemberPlacementContext(ctx, tenantID, ownerUID, research) if err != nil { return placement.MemberCapabilities{}, err } _, aiErr := u.ResolveMemberAiCredential(ctx, tenantID, ownerUID) _, publishErr := u.ResolveMemberThreadsPublishCredential(ctx, tenantID, ownerUID) return placement.BuildMemberCapabilities(member, research, aiErr == nil, publishErr == nil), nil } func cloneKnownAccounts(in map[string]accountentity.KnownAccountProfile) map[string]accountentity.KnownAccountProfile { if len(in) == 0 { return map[string]accountentity.KnownAccountProfile{} } out := make(map[string]accountentity.KnownAccountProfile, len(in)) for key, item := range in { out[key] = accountentity.KnownAccountProfile{ FirstSeenAt: item.FirstSeenAt, LastSeenAt: item.LastSeenAt, Missions: append([]string(nil), item.Missions...), PersonaIds: append([]string(nil), item.PersonaIds...), Tags: append([]string(nil), item.Tags...), AvgEngagement: item.AvgEngagement, SeenCount: item.SeenCount, Status: item.Status, } } return out }