package copy_mission import ( copydraftdomain "haixun-backend/internal/model/copy_draft/domain/usecase" missionentity "haixun-backend/internal/model/copy_mission/domain/entity" missiondomain "haixun-backend/internal/model/copy_mission/domain/usecase" personadomain "haixun-backend/internal/model/persona/domain/usecase" scanpostdomain "haixun-backend/internal/model/scan_post/domain/usecase" "haixun-backend/internal/types" ) func seedMissionResearchFromPersona(persona personadomain.PersonaSummary) (*missionentity.ResearchMap, []string) { src := persona.CopyResearchMap if src.AudienceSummary == "" && src.ContentGoal == "" && len(src.SuggestedTags) == 0 { return nil, nil } tags := make([]missionentity.SuggestedTag, 0, len(src.SuggestedTags)) for _, tag := range src.SuggestedTags { if tag == "" { continue } tags = append(tags, missionentity.SuggestedTag{Tag: tag}) } selected := append([]string(nil), src.SuggestedTags...) if len(selected) > 6 { selected = selected[:6] } rm := &missionentity.ResearchMap{ AudienceSummary: src.AudienceSummary, ContentGoal: src.ContentGoal, Questions: append([]string(nil), src.Questions...), Pillars: append([]string(nil), src.Pillars...), Exclusions: append([]string(nil), src.Exclusions...), SuggestedTags: tags, BenchmarkNotes: src.BenchmarkNotes, } return rm, selected } func toMissionPatch(req *types.UpdateCopyMissionReq) missiondomain.MissionPatch { if req == nil { return missiondomain.MissionPatch{} } patch := missiondomain.MissionPatch{ Label: req.Label, SeedQuery: req.SeedQuery, Brief: req.Brief, } if req.AudienceSummary != nil { patch.AudienceSummary = req.AudienceSummary } if req.ContentGoal != nil { patch.ContentGoal = req.ContentGoal } if req.Questions != nil { patch.QuestionsSet = true patch.Questions = append([]string(nil), req.Questions...) } if req.Pillars != nil { patch.PillarsSet = true patch.Pillars = append([]string(nil), req.Pillars...) } if req.Exclusions != nil { patch.ExclusionsSet = true patch.Exclusions = append([]string(nil), req.Exclusions...) } if req.BenchmarkNotes != nil { patch.BenchmarkNotes = req.BenchmarkNotes } if req.SelectedTags != nil { patch.SelectedTagsSet = true patch.SelectedTags = append([]string(nil), req.SelectedTags...) } return patch } func toCopyMissionData(item missiondomain.MissionSummary) types.CopyMissionData { tags := make([]types.CopySuggestedTagData, 0, len(item.ResearchMap.SuggestedTags)) for _, tag := range item.ResearchMap.SuggestedTags { tags = append(tags, types.CopySuggestedTagData{ Tag: tag.Tag, Reason: tag.Reason, SearchIntent: tag.SearchIntent, SearchType: tag.SearchType, }) } accounts := make([]types.CopySimilarAccountData, 0, len(item.ResearchMap.SimilarAccounts)) for _, acc := range item.ResearchMap.SimilarAccounts { accounts = append(accounts, types.CopySimilarAccountData{ Username: acc.Username, Reason: acc.Reason, Source: acc.Source, Confidence: acc.Confidence, ProfileUrl: acc.ProfileURL, AuthorVerified: acc.AuthorVerified, FollowerCount: acc.FollowerCount, EngagementScore: acc.EngagementScore, LikeCount: acc.LikeCount, ReplyCount: acc.ReplyCount, PostCount: acc.PostCount, }) } return types.CopyMissionData{ ID: item.ID, PersonaID: item.PersonaID, Label: item.Label, SeedQuery: item.SeedQuery, Brief: item.Brief, ResearchMap: types.CopyMissionResearchMapData{ AudienceSummary: item.ResearchMap.AudienceSummary, ContentGoal: item.ResearchMap.ContentGoal, Questions: append([]string(nil), item.ResearchMap.Questions...), Pillars: append([]string(nil), item.ResearchMap.Pillars...), Exclusions: append([]string(nil), item.ResearchMap.Exclusions...), SuggestedTags: tags, SimilarAccounts: accounts, BenchmarkNotes: item.ResearchMap.BenchmarkNotes, }, SelectedTags: append([]string(nil), item.SelectedTags...), LastScanJobID: item.LastScanJobID, Status: item.Status, CreateAt: item.CreateAt, UpdateAt: item.UpdateAt, } } func toListData(result *missiondomain.ListResult) *types.ListCopyMissionsData { if result == nil { return &types.ListCopyMissionsData{List: []types.CopyMissionData{}} } list := make([]types.CopyMissionData, 0, len(result.List)) for _, item := range result.List { list = append(list, toCopyMissionData(item)) } return &types.ListCopyMissionsData{List: list} } func toEntityResearchMap(data types.CopyMissionResearchMapData) missionentity.ResearchMap { tags := make([]missionentity.SuggestedTag, 0, len(data.SuggestedTags)) for _, tag := range data.SuggestedTags { tags = append(tags, missionentity.SuggestedTag{ Tag: tag.Tag, Reason: tag.Reason, SearchIntent: tag.SearchIntent, SearchType: tag.SearchType, }) } accounts := make([]missionentity.SimilarAccount, 0, len(data.SimilarAccounts)) for _, acc := range data.SimilarAccounts { accounts = append(accounts, missionentity.SimilarAccount{ Username: acc.Username, Reason: acc.Reason, Source: acc.Source, Confidence: acc.Confidence, ProfileURL: acc.ProfileUrl, AuthorVerified: acc.AuthorVerified, FollowerCount: acc.FollowerCount, EngagementScore: acc.EngagementScore, LikeCount: acc.LikeCount, ReplyCount: acc.ReplyCount, PostCount: acc.PostCount, }) } return missionentity.ResearchMap{ AudienceSummary: data.AudienceSummary, ContentGoal: data.ContentGoal, Questions: append([]string(nil), data.Questions...), Pillars: append([]string(nil), data.Pillars...), Exclusions: append([]string(nil), data.Exclusions...), SuggestedTags: tags, SimilarAccounts: accounts, BenchmarkNotes: data.BenchmarkNotes, } } func toViralScanPostsData(posts []scanpostdomain.ScanPostSummary) *types.ListPersonaViralScanPostsData { list := make([]types.ViralScanPostData, 0, len(posts)) for _, post := range posts { list = append(list, types.ViralScanPostData{ ID: post.ID, SearchTag: post.SearchTag, Permalink: post.Permalink, Author: post.Author, AuthorVerified: post.AuthorVerified, FollowerCount: post.FollowerCount, Text: post.Text, LikeCount: post.LikeCount, ReplyCount: post.ReplyCount, EngagementScore: post.EngagementScore, Source: post.Source, ScanJobID: post.ScanJobID, Replies: toScanReplyData(post.Replies), CreateAt: post.CreateAt, }) } return &types.ListPersonaViralScanPostsData{List: list, Total: len(list)} } func toScanReplyData(replies []scanpostdomain.ScanReplySummary) []types.ScanReplyData { if len(replies) == 0 { return nil } out := make([]types.ScanReplyData, 0, len(replies)) for _, reply := range replies { out = append(out, types.ScanReplyData{ ExternalID: reply.ExternalID, Author: reply.Author, Text: reply.Text, Permalink: reply.Permalink, LikeCount: reply.LikeCount, PostedAt: reply.PostedAt, }) } return out } func toCopyDraftData(item copydraftdomain.CopyDraftSummary) types.CopyDraftData { return types.CopyDraftData{ ID: item.ID, PersonaID: item.PersonaID, CopyMissionID: item.CopyMissionID, ScanPostID: item.ScanPostID, DraftType: item.DraftType, SortOrder: item.SortOrder, Text: item.Text, Angle: item.Angle, Hook: item.Hook, Rationale: item.Rationale, ReferenceNotes: item.ReferenceNotes, Sources: item.Sources, Status: item.Status, PublishedMediaID: item.PublishedMediaID, PublishedPermalink: item.PublishedPermalink, PublishedAt: item.PublishedAt, CreateAt: item.CreateAt, } }