package viral import ( "sort" "strings" "haixun-backend/internal/library/placement" missionentity "haixun-backend/internal/model/copy_mission/domain/entity" ) func EnrichSimilarAccounts(existing []missionentity.SimilarAccount, posts []placement.ScanCandidate, limit int) []missionentity.SimilarAccount { if limit <= 0 { limit = MaxSimilarAccounts } byUser := map[string]missionentity.SimilarAccount{} order := []string{} for _, item := range existing { user := strings.ToLower(strings.TrimSpace(item.Username)) if user == "" { continue } if _, ok := byUser[user]; !ok { order = append(order, user) } byUser[user] = item } type authorScore struct { username string score int text string } authors := map[string]authorScore{} for _, post := range posts { user := strings.TrimSpace(post.Author) if user == "" || !isValidUsername(user) { continue } key := strings.ToLower(user) prev := authors[key] prev.username = user prev.score += post.EngagementScore if prev.text == "" && strings.TrimSpace(post.Text) != "" { prev.text = strings.TrimSpace(post.Text) } authors[key] = prev } ranked := make([]authorScore, 0, len(authors)) for _, item := range authors { ranked = append(ranked, item) } sort.Slice(ranked, func(i, j int) bool { return ranked[i].score > ranked[j].score }) for _, item := range ranked { key := strings.ToLower(item.username) if _, ok := byUser[key]; ok { continue } reason := "本次海巡高互動作者" if item.text != "" { runes := []rune(item.text) if len(runes) > 80 { reason = string(runes[:80]) } else { reason = item.text } } conf := "medium" if item.score >= 200 { conf = "high" } byUser[key] = missionentity.SimilarAccount{ Username: item.username, Reason: reason, Source: "scan", Confidence: conf, ProfileURL: "https://www.threads.net/@" + item.username, } order = append(order, key) } out := make([]missionentity.SimilarAccount, 0, len(order)) for _, key := range order { if acc, ok := byUser[key]; ok { out = append(out, acc) } } if len(out) > limit { out = out[:limit] } return out } func AccountTagsFromSimilar(accounts []missionentity.SimilarAccount, max int) []SuggestedTag { if max <= 0 { max = 2 } out := []SuggestedTag{} for _, acc := range accounts { user := strings.TrimSpace(acc.Username) if user == "" { continue } out = append(out, SuggestedTag{ Tag: "@" + user, Reason: acc.Reason, SearchType: "帳號", }) if len(out) >= max { break } } return out } func ToEntitySimilarAccounts(items []SimilarAccount) []missionentity.SimilarAccount { out := make([]missionentity.SimilarAccount, 0, len(items)) for _, item := range items { out = append(out, missionentity.SimilarAccount{ Username: item.Username, Reason: item.Reason, Source: item.Source, Confidence: item.Confidence, ProfileURL: item.ProfileURL, }) } return out }