2026-06-26 08:37:04 +00:00
|
|
|
package usecase
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2026-06-30 07:09:44 +00:00
|
|
|
"encoding/json"
|
|
|
|
|
"time"
|
2026-06-26 08:37:04 +00:00
|
|
|
|
|
|
|
|
"haixun-backend/internal/library/placement"
|
2026-06-28 08:28:42 +00:00
|
|
|
missionentity "haixun-backend/internal/model/copy_mission/domain/entity"
|
|
|
|
|
"haixun-backend/internal/model/threads_account/domain/entity"
|
2026-06-26 08:37:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type AccountSummary struct {
|
2026-06-30 07:09:44 +00:00
|
|
|
ID string
|
|
|
|
|
DisplayName string
|
|
|
|
|
Username string
|
|
|
|
|
ThreadsUserID string
|
|
|
|
|
PersonaID string
|
|
|
|
|
BrowserConnected bool
|
|
|
|
|
ApiConnected bool
|
|
|
|
|
APITokenExpiresAt int64
|
|
|
|
|
Status string
|
|
|
|
|
CreateAt int64
|
|
|
|
|
UpdateAt int64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type TokenRefreshCandidate struct {
|
|
|
|
|
AccountID string
|
|
|
|
|
TenantID string
|
|
|
|
|
OwnerUID string
|
|
|
|
|
ExpiresAt int64
|
2026-06-26 08:37:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ConnectionPrefs struct {
|
|
|
|
|
SearchViaApi bool
|
|
|
|
|
SearchSourceMode string
|
|
|
|
|
PublishViaApi bool
|
|
|
|
|
DevMode bool
|
|
|
|
|
ScrapeReplies bool
|
|
|
|
|
RepliesPerPost int
|
|
|
|
|
PublishHeaded bool
|
|
|
|
|
PlaywrightDebug bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ConnectionData struct {
|
|
|
|
|
AccountID string
|
|
|
|
|
AccountName string
|
|
|
|
|
Username string
|
|
|
|
|
BrowserConnected bool
|
|
|
|
|
ApiConnected bool
|
|
|
|
|
Prefs ConnectionPrefs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type CreateRequest struct {
|
|
|
|
|
TenantID string
|
|
|
|
|
OwnerUID string
|
|
|
|
|
DisplayName string
|
|
|
|
|
Activate bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type UpdateAccountRequest struct {
|
|
|
|
|
TenantID string
|
|
|
|
|
OwnerUID string
|
|
|
|
|
AccountID string
|
|
|
|
|
DisplayName *string
|
|
|
|
|
PersonaID *string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type UpdateConnectionRequest struct {
|
|
|
|
|
TenantID string
|
|
|
|
|
OwnerUID string
|
|
|
|
|
AccountID string
|
|
|
|
|
Prefs ConnectionPrefsPatch
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ImportBrowserSessionRequest struct {
|
|
|
|
|
TenantID string
|
|
|
|
|
OwnerUID string
|
|
|
|
|
AccountID string
|
|
|
|
|
StorageState string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ImportBrowserSessionResult struct {
|
|
|
|
|
AccountID string
|
|
|
|
|
Username string
|
|
|
|
|
Synced bool
|
|
|
|
|
Valid bool
|
|
|
|
|
Message string
|
|
|
|
|
UpdateAt int64
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-27 16:03:28 +00:00
|
|
|
type SecretsData struct {
|
|
|
|
|
AccountID string
|
|
|
|
|
APIAccessToken string
|
|
|
|
|
APITokenExpiresAt int64
|
|
|
|
|
UpdateAt int64
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-26 08:37:04 +00:00
|
|
|
type BrowserSessionData struct {
|
|
|
|
|
AccountID string
|
|
|
|
|
StorageState string
|
|
|
|
|
UpdateAt int64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type AiSettings struct {
|
|
|
|
|
AccountID string
|
|
|
|
|
Provider string
|
|
|
|
|
Model string
|
|
|
|
|
ResearchProvider string
|
|
|
|
|
ResearchModel string
|
|
|
|
|
ApiKeys map[string]string
|
|
|
|
|
ApiKeysConfigured map[string]bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type AiSettingsPatch struct {
|
|
|
|
|
Provider *string
|
|
|
|
|
Model *string
|
|
|
|
|
ResearchProvider *string
|
|
|
|
|
ResearchModel *string
|
|
|
|
|
ApiKeys map[string]string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WorkerAiCredential carries raw provider settings for internal workers (never expose to clients).
|
|
|
|
|
type WorkerAiCredential struct {
|
|
|
|
|
Provider string
|
|
|
|
|
Model string
|
|
|
|
|
APIKey string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ThreadsPublishCredential struct {
|
|
|
|
|
AccountID string
|
|
|
|
|
ThreadsUserID string
|
|
|
|
|
AccessToken string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ConnectionPrefsPatch struct {
|
|
|
|
|
SearchViaApi *bool
|
|
|
|
|
SearchSourceMode *string
|
|
|
|
|
PublishViaApi *bool
|
|
|
|
|
DevMode *bool
|
|
|
|
|
ScrapeReplies *bool
|
|
|
|
|
RepliesPerPost *int
|
|
|
|
|
PublishHeaded *bool
|
|
|
|
|
PlaywrightDebug *bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ListResult struct {
|
|
|
|
|
List []AccountSummary
|
|
|
|
|
ActiveAccountID string
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-30 07:09:44 +00:00
|
|
|
type OAuthStartResult struct {
|
|
|
|
|
AuthorizeURL string
|
|
|
|
|
State string
|
|
|
|
|
AccountID string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type OAuthCallbackResult struct {
|
|
|
|
|
AccountID string
|
|
|
|
|
Username string
|
|
|
|
|
ThreadsUserID string
|
|
|
|
|
RedirectURL string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type OAuthDebugLogEntry struct {
|
|
|
|
|
At int64
|
|
|
|
|
Level string
|
|
|
|
|
Stage string
|
|
|
|
|
AccountID string
|
|
|
|
|
Message string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type APISmokeTestItem struct {
|
|
|
|
|
Scope string
|
|
|
|
|
Name string
|
|
|
|
|
Status string // ok, error, skip, manual
|
|
|
|
|
Message string
|
|
|
|
|
Count int
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type APIPlaygroundRequest struct {
|
|
|
|
|
Action string
|
|
|
|
|
Query string
|
|
|
|
|
Username string
|
|
|
|
|
MediaID string
|
|
|
|
|
ReplyID string
|
|
|
|
|
ReplyToID string
|
|
|
|
|
Text string
|
|
|
|
|
LocationQuery string
|
|
|
|
|
Limit int
|
|
|
|
|
Hide bool
|
|
|
|
|
SearchType string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type APIPlaygroundResult struct {
|
|
|
|
|
Action string
|
|
|
|
|
Ok bool
|
|
|
|
|
Message string
|
|
|
|
|
Data json.RawMessage
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type PostMetricCapability struct {
|
|
|
|
|
Scope string
|
|
|
|
|
Name string
|
|
|
|
|
Metrics []string
|
|
|
|
|
Trackable bool
|
|
|
|
|
Note string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type InsightMetricItem struct {
|
|
|
|
|
Name string
|
|
|
|
|
Value int
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type AccountInsightsBlock struct {
|
|
|
|
|
Status string
|
|
|
|
|
Message string
|
|
|
|
|
Metrics []InsightMetricItem
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type PostPerformanceItem struct {
|
|
|
|
|
MediaID string
|
|
|
|
|
Text string
|
|
|
|
|
Permalink string
|
|
|
|
|
Timestamp string
|
|
|
|
|
LikeCount int
|
|
|
|
|
ReplyCount int
|
|
|
|
|
RepostCount int
|
|
|
|
|
QuoteCount int
|
|
|
|
|
Views int
|
|
|
|
|
Shares int
|
|
|
|
|
InsightsStatus string
|
|
|
|
|
InsightsMessage string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type PostPerformanceResult struct {
|
|
|
|
|
AccountID string
|
|
|
|
|
Username string
|
|
|
|
|
ThreadsUserID string
|
|
|
|
|
FetchedAt int64
|
|
|
|
|
Capabilities []PostMetricCapability
|
|
|
|
|
AccountInsights AccountInsightsBlock
|
|
|
|
|
Posts []PostPerformanceItem
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 08:28:42 +00:00
|
|
|
type UpsertKnownAccountsFromScanRequest struct {
|
|
|
|
|
TenantID string
|
|
|
|
|
OwnerUID string
|
|
|
|
|
AccountID string
|
|
|
|
|
MissionID string
|
|
|
|
|
PersonaID string
|
|
|
|
|
SelectedTags []string
|
|
|
|
|
SimilarAccounts []missionentity.SimilarAccount
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-26 08:37:04 +00:00
|
|
|
type UseCase interface {
|
|
|
|
|
List(ctx context.Context, tenantID, ownerUID string) (*ListResult, error)
|
|
|
|
|
Create(ctx context.Context, req CreateRequest) (*AccountSummary, error)
|
|
|
|
|
Get(ctx context.Context, tenantID, ownerUID, accountID string) (*AccountSummary, error)
|
|
|
|
|
Update(ctx context.Context, req UpdateAccountRequest) (*AccountSummary, error)
|
|
|
|
|
Activate(ctx context.Context, tenantID, ownerUID, accountID string) error
|
|
|
|
|
GetConnection(ctx context.Context, tenantID, ownerUID, accountID string) (*ConnectionData, error)
|
|
|
|
|
UpdateConnection(ctx context.Context, req UpdateConnectionRequest) (*ConnectionData, error)
|
|
|
|
|
ImportBrowserSession(ctx context.Context, req ImportBrowserSessionRequest) (*ImportBrowserSessionResult, error)
|
|
|
|
|
GetBrowserSession(ctx context.Context, tenantID, ownerUID, accountID string) (*BrowserSessionData, error)
|
|
|
|
|
GetAiSettings(ctx context.Context, tenantID, ownerUID, accountID string) (*AiSettings, error)
|
|
|
|
|
UpdateAiSettings(ctx context.Context, tenantID, ownerUID, accountID string, patch AiSettingsPatch) (*AiSettings, error)
|
2026-06-27 14:49:17 +00:00
|
|
|
ResolveAiProviderAPIKey(ctx context.Context, tenantID, ownerUID, accountID, provider, overrideKey string) (string, error)
|
2026-06-26 08:37:04 +00:00
|
|
|
ResolveWorkerAiCredential(ctx context.Context, tenantID, ownerUID, accountID string) (*WorkerAiCredential, error)
|
|
|
|
|
ResolveMemberAiCredential(ctx context.Context, tenantID, ownerUID string) (*WorkerAiCredential, error)
|
2026-06-30 07:09:44 +00:00
|
|
|
ResolveMemberResearchAiCredential(ctx context.Context, tenantID, ownerUID string) (*WorkerAiCredential, error)
|
2026-06-26 08:37:04 +00:00
|
|
|
ResolveMemberPlacementContext(ctx context.Context, tenantID, ownerUID string, research placement.ResearchSettings) (placement.MemberContext, error)
|
|
|
|
|
ResolveMemberThreadsPublishCredential(ctx context.Context, tenantID, ownerUID string) (*ThreadsPublishCredential, error)
|
2026-06-27 16:03:28 +00:00
|
|
|
SaveAPIAccessToken(ctx context.Context, accountID, accessToken string, expiresAt int64) (*SecretsData, error)
|
2026-06-30 07:09:44 +00:00
|
|
|
StartThreadsOAuth(ctx context.Context, tenantID, ownerUID, accountID string) (*OAuthStartResult, error)
|
|
|
|
|
CompleteThreadsOAuthCallback(ctx context.Context, code, state string) (*OAuthCallbackResult, error)
|
|
|
|
|
DisconnectThreadsAPI(ctx context.Context, tenantID, ownerUID, accountID string) (*AccountSummary, error)
|
|
|
|
|
ListOAuthDebugLogs(limit int) []OAuthDebugLogEntry
|
|
|
|
|
RecordOAuthDebug(level, stage, accountID, message string)
|
|
|
|
|
RunAPISmokeTest(ctx context.Context, tenantID, ownerUID, accountID string) ([]APISmokeTestItem, error)
|
|
|
|
|
RunAPIPlayground(ctx context.Context, tenantID, ownerUID, accountID string, req APIPlaygroundRequest) (*APIPlaygroundResult, error)
|
|
|
|
|
ListPostPerformance(ctx context.Context, tenantID, ownerUID, accountID string, limit int) (*PostPerformanceResult, error)
|
|
|
|
|
ResolveAccountAPIAccessToken(ctx context.Context, tenantID, ownerUID, accountID string) (string, error)
|
|
|
|
|
RefreshAccountAPIAccessToken(ctx context.Context, tenantID, ownerUID, accountID string) (*SecretsData, error)
|
|
|
|
|
ListTokenRefreshCandidates(ctx context.Context, leadTime time.Duration) ([]TokenRefreshCandidate, error)
|
2026-06-28 08:28:42 +00:00
|
|
|
ResolveMemberCapabilities(ctx context.Context, tenantID, ownerUID string, research placement.ResearchSettings) (placement.MemberCapabilities, error)
|
|
|
|
|
GetKnownAccounts(ctx context.Context, tenantID, ownerUID, accountID string) (map[string]entity.KnownAccountProfile, error)
|
|
|
|
|
UpsertKnownAccountsFromScan(ctx context.Context, req UpsertKnownAccountsFromScanRequest) error
|
2026-06-26 08:37:04 +00:00
|
|
|
}
|