package controller import ( "context" "encoding/json" "fmt" "micro-ayrshare/internal/dto" "micro-ayrshare/pb/aryshare" ) // PostComment 发布评论到社交媒体平台 func (a *AyrshareProvider) PostComment(_ context.Context, req *aryshare.PostCommentRequest) (res *aryshare.PostCommentResponse, err error) { res = new(aryshare.PostCommentResponse) // 将 proto 请求转换为 DTO dtoReq := &dto.PostCommentRequest{ ID: req.Id, Comment: req.Comment, Platforms: req.Platforms, MediaUrls: req.MediaUrls, ProfileKey: req.ProfileKey, } if req.SearchPlatformId { dtoReq.SearchPlatformId = &req.SearchPlatformId } // 调用 logic 层 dtoRes, err := a.aryshareCommentLogic.PostComment(dtoReq) if err != nil { return nil, err } // 将 DTO 响应转换为 proto 响应 res.Status = dtoRes.Status res.CommentID = dtoRes.CommentID res.CommentIdAlt = dtoRes.CommentId res.Id = dtoRes.ID res.Action = dtoRes.Action res.Code = int32(dtoRes.Code) res.Message = dtoRes.Message res.Platform = dtoRes.Platform // 转换 Bluesky 响应 if dtoRes.Bluesky != nil { res.Bluesky = &aryshare.BlueskyCommentResponse{ Status: dtoRes.Bluesky.Status, CommentId: dtoRes.Bluesky.CommentId, Cid: dtoRes.Bluesky.Cid, Comment: dtoRes.Bluesky.Comment, Platform: dtoRes.Bluesky.Platform, PostUrl: dtoRes.Bluesky.PostUrl, } } // 转换 Facebook 响应 if dtoRes.Facebook != nil { res.Facebook = &aryshare.FacebookCommentResponse{ Status: dtoRes.Facebook.Status, CommentId: dtoRes.Facebook.CommentId, Comment: dtoRes.Facebook.Comment, Platform: dtoRes.Facebook.Platform, } } // 转换 Instagram 响应 if dtoRes.Instagram != nil { res.Instagram = &aryshare.InstagramCommentResponse{ Status: dtoRes.Instagram.Status, CommentId: dtoRes.Instagram.CommentId, Comment: dtoRes.Instagram.Comment, Platform: dtoRes.Instagram.Platform, } } // 转换 LinkedIn 响应 if dtoRes.LinkedIn != nil { res.Linkedin = &aryshare.LinkedInCommentResponse{ Status: dtoRes.LinkedIn.Status, CommentId: dtoRes.LinkedIn.CommentId, Comment: dtoRes.LinkedIn.Comment, CommentUrn: dtoRes.LinkedIn.CommentUrn, Platform: dtoRes.LinkedIn.Platform, } } // 转换 TikTok 响应 if dtoRes.TikTok != nil { res.Tiktok = &aryshare.TikTokCommentResponse{ Status: dtoRes.TikTok.Status, CommentId: dtoRes.TikTok.CommentId, Comment: dtoRes.TikTok.Comment, Platform: dtoRes.TikTok.Platform, VideoId: dtoRes.TikTok.VideoId, } } // 转换 Twitter 响应 if dtoRes.Twitter != nil { res.Twitter = &aryshare.TwitterCommentResponse{ Status: dtoRes.Twitter.Status, CommentId: dtoRes.Twitter.CommentId, Comment: dtoRes.Twitter.Comment, PostUrl: dtoRes.Twitter.PostUrl, } } // 转换 YouTube 响应 if dtoRes.YouTube != nil { res.Youtube = &aryshare.YouTubeCommentResponse{ Status: dtoRes.YouTube.Status, CommentId: dtoRes.YouTube.CommentId, Comment: dtoRes.YouTube.Comment, Platform: dtoRes.YouTube.Platform, } } // 转换 Errors if len(dtoRes.Errors) > 0 { res.Errors = make([]*aryshare.PlatformError, 0, len(dtoRes.Errors)) for _, e := range dtoRes.Errors { res.Errors = append(res.Errors, &aryshare.PlatformError{ Action: e.Action, Status: e.Status, Code: int32(e.Code), Message: e.Message, Platform: e.Platform, }) } } return } // GetComment 获取评论列表 func (a *AyrshareProvider) GetComment(_ context.Context, req *aryshare.GetCommentRequest) (res *aryshare.GetCommentResponse, err error) { res = new(aryshare.GetCommentResponse) // 将 proto 请求转换为 DTO dtoReq := &dto.GetCommentRequest{ ID: req.Id, ProfileKey: req.ProfileKey, } // 调用 logic 层 dtoRes, err := a.aryshareCommentLogic.GetComment(dtoReq) if err != nil { return nil, err } // 将 DTO 响应转换为 proto 响应 res.Status = dtoRes.Status res.Id = dtoRes.ID res.LastUpdated = dtoRes.LastUpdated res.NextUpdate = dtoRes.NextUpdate res.Action = dtoRes.Action res.Code = int32(dtoRes.Code) res.Message = dtoRes.Message // 转换 Bluesky 评论列表 if len(dtoRes.Bluesky) > 0 { res.Bluesky = make([]*aryshare.BlueskyComment, 0, len(dtoRes.Bluesky)) for _, c := range dtoRes.Bluesky { res.Bluesky = append(res.Bluesky, convertBlueskyComment(&c)) } } // 转换 Facebook 评论列表 if len(dtoRes.Facebook) > 0 { res.Facebook = make([]*aryshare.FacebookComment, 0, len(dtoRes.Facebook)) for _, c := range dtoRes.Facebook { res.Facebook = append(res.Facebook, convertFacebookComment(&c)) } } // 转换 Instagram 评论列表 if len(dtoRes.Instagram) > 0 { res.Instagram = make([]*aryshare.InstagramComment, 0, len(dtoRes.Instagram)) for _, instagramComment := range dtoRes.Instagram { protoComment := convertInstagramComment(&instagramComment) res.Instagram = append(res.Instagram, protoComment) } } // 转换 LinkedIn 评论列表 if len(dtoRes.LinkedIn) > 0 { res.Linkedin = make([]*aryshare.LinkedInComment, 0, len(dtoRes.LinkedIn)) for _, c := range dtoRes.LinkedIn { res.Linkedin = append(res.Linkedin, convertLinkedInComment(&c)) } } // 转换 Reddit 评论列表 if len(dtoRes.Reddit) > 0 { res.Reddit = make([]*aryshare.RedditComment, 0, len(dtoRes.Reddit)) for _, c := range dtoRes.Reddit { res.Reddit = append(res.Reddit, convertRedditComment(&c)) } } // 转换 Threads 评论列表 if len(dtoRes.Threads) > 0 { res.Threads = make([]*aryshare.ThreadsComment, 0, len(dtoRes.Threads)) for _, c := range dtoRes.Threads { res.Threads = append(res.Threads, convertThreadsComment(&c)) } } // 转换 TikTok 评论列表 if len(dtoRes.TikTok) > 0 { res.Tiktok = make([]*aryshare.TikTokComment, 0, len(dtoRes.TikTok)) for _, tiktokComment := range dtoRes.TikTok { protoComment := convertTikTokComment(&tiktokComment) res.Tiktok = append(res.Tiktok, protoComment) } } // 转换 Twitter 评论列表 if len(dtoRes.Twitter) > 0 { res.Twitter = make([]*aryshare.TwitterComment, 0, len(dtoRes.Twitter)) for _, c := range dtoRes.Twitter { res.Twitter = append(res.Twitter, convertTwitterComment(&c)) } } // 转换 YouTube 评论列表 if len(dtoRes.YouTube) > 0 { res.Youtube = make([]*aryshare.YouTubeComment, 0, len(dtoRes.YouTube)) for _, c := range dtoRes.YouTube { res.Youtube = append(res.Youtube, convertYouTubeComment(&c)) } } return } // DeleteComment 删除评论 func (a *AyrshareProvider) DeleteComment(_ context.Context, req *aryshare.DeleteCommentRequest) (res *aryshare.DeleteCommentResponse, err error) { res = new(aryshare.DeleteCommentResponse) // 将 proto 请求转换为 DTO dtoReq := &dto.DeleteCommentRequest{ ID: req.Id, Platforms: req.Platforms, Platform: req.Platform, ProfileKey: req.ProfileKey, } if req.SearchPlatformId { searchPlatformId := true dtoReq.SearchPlatformId = &searchPlatformId } // 调用 logic 层 dtoRes, err := a.aryshareCommentLogic.DeleteComment(dtoReq) if err != nil { return nil, err } // 将 DTO 响应转换为 proto 响应 res.Status = dtoRes.Status res.Action = dtoRes.Action res.Code = int32(dtoRes.Code) res.Message = dtoRes.Message // 各平台删除结果字段可能是单个对象或数组,统一转换为 JSON 字符串,方便前端直接解析 if dtoRes.Bluesky != nil { if b, err := json.Marshal(dtoRes.Bluesky); err == nil { res.Bluesky = string(b) } } if dtoRes.Facebook != nil { if b, err := json.Marshal(dtoRes.Facebook); err == nil { res.Facebook = string(b) } } if dtoRes.Instagram != nil { if b, err := json.Marshal(dtoRes.Instagram); err == nil { res.Instagram = string(b) } } if dtoRes.LinkedIn != nil { if b, err := json.Marshal(dtoRes.LinkedIn); err == nil { res.Linkedin = string(b) } } if dtoRes.Threads != nil { if b, err := json.Marshal(dtoRes.Threads); err == nil { res.Threads = string(b) } } if dtoRes.TikTok != nil { if b, err := json.Marshal(dtoRes.TikTok); err == nil { res.Tiktok = string(b) } } if dtoRes.Twitter != nil { if b, err := json.Marshal(dtoRes.Twitter); err == nil { res.Twitter = string(b) } } if dtoRes.YouTube != nil { if b, err := json.Marshal(dtoRes.YouTube); err == nil { res.Youtube = string(b) } } return } // ReplyComment 回复评论 func (a *AyrshareProvider) ReplyComment(_ context.Context, req *aryshare.ReplyCommentRequest) (res *aryshare.ReplyCommentResponse, err error) { res = new(aryshare.ReplyCommentResponse) // 将 proto 请求转换为 DTO dtoReq := &dto.ReplyCommentRequest{ ID: req.Id, Comment: req.Comment, Platforms: req.Platforms, ProfileKey: req.ProfileKey, } // 调用 logic 层 dtoRes, err := a.aryshareCommentLogic.ReplyComment(dtoReq) if err != nil { return nil, err } // 将 DTO 响应转换为 proto 响应 res.Status = dtoRes.Status res.CommentId = dtoRes.CommentId res.Id = dtoRes.ID res.Action = dtoRes.Action res.Code = int32(dtoRes.Code) res.Message = dtoRes.Message // 转换 Instagram 响应 if dtoRes.Instagram != nil { res.Instagram = &aryshare.InstagramReplyResponse{ Status: dtoRes.Instagram.Status, CommentId: dtoRes.Instagram.CommentId, SourceCommentId: dtoRes.Instagram.SourceCommentId, Comment: dtoRes.Instagram.Comment, Platform: dtoRes.Instagram.Platform, } } // 转换 TikTok 响应 if dtoRes.TikTok != nil { res.Tiktok = &aryshare.TikTokReplyResponse{ Status: dtoRes.TikTok.Status, CommentId: dtoRes.TikTok.CommentId, SourceCommentId: dtoRes.TikTok.SourceCommentId, Comment: dtoRes.TikTok.Comment, Platform: dtoRes.TikTok.Platform, VideoId: dtoRes.TikTok.VideoId, } } // 转换 Bluesky 响应 if dtoRes.Bluesky != nil { res.Bluesky = &aryshare.BlueskyReplyResponse{ Status: dtoRes.Bluesky.Status, CommentId: dtoRes.Bluesky.CommentId, SourceCommentId: dtoRes.Bluesky.SourceCommentId, Comment: dtoRes.Bluesky.Comment, Platform: dtoRes.Bluesky.Platform, Cid: dtoRes.Bluesky.Cid, PostUrl: dtoRes.Bluesky.PostUrl, } } // 转换 Facebook 响应 if dtoRes.Facebook != nil { res.Facebook = &aryshare.FacebookReplyResponse{ Status: dtoRes.Facebook.Status, CommentId: dtoRes.Facebook.CommentId, SourceCommentId: dtoRes.Facebook.SourceCommentId, Comment: dtoRes.Facebook.Comment, Platform: dtoRes.Facebook.Platform, } } // 转换 LinkedIn 响应 if dtoRes.LinkedIn != nil { res.Linkedin = &aryshare.LinkedInReplyResponse{ Status: dtoRes.LinkedIn.Status, CommentId: dtoRes.LinkedIn.CommentId, SourceCommentId: dtoRes.LinkedIn.SourceCommentId, Comment: dtoRes.LinkedIn.Comment, Platform: dtoRes.LinkedIn.Platform, } } // 转换 Twitter 响应 if dtoRes.Twitter != nil { res.Twitter = &aryshare.TwitterReplyResponse{ Status: dtoRes.Twitter.Status, CommentId: dtoRes.Twitter.CommentId, SourceCommentId: dtoRes.Twitter.SourceCommentId, Comment: dtoRes.Twitter.Comment, Platform: dtoRes.Twitter.Platform, PostUrl: dtoRes.Twitter.PostUrl, } } // 转换 YouTube 响应 if dtoRes.YouTube != nil { res.Youtube = &aryshare.YouTubeReplyResponse{ Status: dtoRes.YouTube.Status, CommentId: dtoRes.YouTube.CommentId, SourceCommentId: dtoRes.YouTube.SourceCommentId, Comment: dtoRes.YouTube.Comment, Platform: dtoRes.YouTube.Platform, } } return } // convertInstagramComment 转换 Instagram 评论 func convertInstagramComment(comment *dto.InstagramComment) *aryshare.InstagramComment { protoComment := &aryshare.InstagramComment{ Comment: comment.Comment, CommentId: comment.CommentId, Id: comment.Id, Created: comment.Created, Hidden: comment.Hidden, LikeCount: int32(comment.LikeCount), ParentId: comment.ParentId, Platform: comment.Platform, PostId: comment.PostId, UserName: comment.UserName, UsernameAlt: comment.Username, } // 转换 From if comment.From != nil { protoComment.From = &aryshare.InstagramUser{ Name: comment.From.Name, Id: comment.From.Id, Username: comment.From.Username, } } // 转换 User if comment.User != nil { protoComment.User = &aryshare.InstagramUserInfo{ Id: comment.User.Id, } } // 转换 Replies if len(comment.Replies) > 0 { protoComment.Replies = make([]*aryshare.InstagramComment, 0, len(comment.Replies)) for _, reply := range comment.Replies { protoComment.Replies = append(protoComment.Replies, convertInstagramComment(&reply)) } } return protoComment } // convertTikTokComment 转换 TikTok 评论 func convertTikTokComment(comment *dto.TikTokComment) *aryshare.TikTokComment { protoComment := &aryshare.TikTokComment{ Comment: comment.Comment, CommentId: comment.CommentId, Created: comment.Created, CreateTime: comment.CreateTime, DisplayName: comment.DisplayName, Liked: comment.Liked, Likes: int32(comment.Likes), LikeCount: int32(comment.LikeCount), Owner: comment.Owner, ParentCommentId: comment.ParentCommentId, Pinned: comment.Pinned, Platform: comment.Platform, ProfileImageUrl: comment.ProfileImageUrl, Status: comment.Status, UserId: comment.UserId, Username: comment.Username, VideoId: comment.VideoId, Visibility: comment.Visibility, } // 转换 Replies if len(comment.Replies) > 0 { protoComment.Replies = make([]*aryshare.TikTokComment, 0, len(comment.Replies)) for _, reply := range comment.Replies { protoComment.Replies = append(protoComment.Replies, convertTikTokComment(&reply)) } } return protoComment } // convertBlueskyComment 转换 Bluesky 评论 func convertBlueskyComment(comment *dto.BlueskyComment) *aryshare.BlueskyComment { protoComment := &aryshare.BlueskyComment{ Comment: comment.Comment, CommentId: comment.CommentId, Created: comment.Created, DisplayName: comment.DisplayName, LikeCount: int32(comment.LikeCount), Platform: comment.Platform, ProfileImageUrl: comment.ProfileImageUrl, QuoteCount: int32(comment.QuoteCount), ReplyCount: int32(comment.ReplyCount), ReplyTo: comment.ReplyTo, RepostCount: int32(comment.RepostCount), UserName: comment.UserName, } // 转换 Replies if len(comment.Replies) > 0 { protoComment.Replies = make([]*aryshare.BlueskyComment, 0, len(comment.Replies)) for _, reply := range comment.Replies { protoComment.Replies = append(protoComment.Replies, convertBlueskyComment(&reply)) } } return protoComment } // convertFacebookComment 转换 Facebook 评论 func convertFacebookComment(comment *dto.FacebookComment) *aryshare.FacebookComment { protoComment := &aryshare.FacebookComment{ Comment: comment.Comment, CommentId: comment.CommentId, CommentCount: int32(comment.CommentCount), CommentUrl: comment.CommentUrl, Company: comment.Company, Created: comment.Created, LikeCount: int32(comment.LikeCount), Platform: comment.Platform, UserLikes: comment.UserLikes, } // 转换 From if comment.From != nil { protoComment.From = &aryshare.FacebookUser{ Name: comment.From.Name, Id: comment.From.Id, } } // 转换 Parent if comment.Parent != nil { protoComment.Parent = &aryshare.FacebookParent{ CreatedTime: comment.Parent.CreatedTime, Message: comment.Parent.Message, Id: comment.Parent.Id, } if comment.Parent.From != nil { protoComment.Parent.From = &aryshare.FacebookUser{ Name: comment.Parent.From.Name, Id: comment.Parent.From.Id, } } } // 转换 Replies if len(comment.Replies) > 0 { protoComment.Replies = make([]*aryshare.FacebookComment, 0, len(comment.Replies)) for _, reply := range comment.Replies { protoComment.Replies = append(protoComment.Replies, convertFacebookComment(&reply)) } } return protoComment } // convertLinkedInComment 转换 LinkedIn 评论 func convertLinkedInComment(comment *dto.LinkedInComment) *aryshare.LinkedInComment { protoComment := &aryshare.LinkedInComment{ Comment: comment.Comment, CommentId: comment.CommentId, CommentUrn: comment.CommentUrn, Created: comment.Created, LikeCount: int32(comment.LikeCount), Platform: comment.Platform, ProfileImageUrl: comment.ProfileImageUrl, UserName: comment.UserName, Founded: int32(comment.Founded), OrganizationType: comment.OrganizationType, Website: comment.Website, } // 转换 From if comment.From != nil { protoComment.From = &aryshare.LinkedInFrom{ Name: comment.From.Name, Id: fmt.Sprintf("%v", comment.From.Id), Url: comment.From.Url, Description: comment.From.Description, } } // 转换 Media if len(comment.Media) > 0 { protoComment.Media = make([]*aryshare.LinkedInMedia, 0, len(comment.Media)) for _, m := range comment.Media { protoComment.Media = append(protoComment.Media, &aryshare.LinkedInMedia{ Type: m.Type, Url: m.Url, }) } } return protoComment } // convertRedditComment 转换 Reddit 评论 func convertRedditComment(comment *dto.RedditComment) *aryshare.RedditComment { protoComment := &aryshare.RedditComment{ Comment: comment.Comment, CommentId: comment.CommentId, Created: comment.Created, CommentUrl: comment.CommentUrl, Subreddit: comment.Subreddit, Ups: int32(comment.Ups), IsSubmitter: comment.IsSubmitter, } // 转换 From if comment.From != nil { protoComment.From = &aryshare.RedditUser{ Name: comment.From.Name, Id: comment.From.Id, } } return protoComment } // convertThreadsComment 转换 Threads 评论 func convertThreadsComment(comment *dto.ThreadsComment) *aryshare.ThreadsComment { protoComment := &aryshare.ThreadsComment{ Comment: comment.Comment, CommentId: comment.CommentId, CommentUrl: comment.CommentUrl, Created: comment.Created, HasReplies: comment.HasReplies, IsQuotePost: comment.IsQuotePost, IsReply: comment.IsReply, IsReplyOwnedByMe: comment.IsReplyOwnedByMe, MediaType: comment.MediaType, ParentId: comment.ParentId, Platform: comment.Platform, PostId: comment.PostId, ReplyAudience: comment.ReplyAudience, Shortcode: comment.Shortcode, UserName: comment.UserName, } // 转换 Replies if len(comment.Replies) > 0 { protoComment.Replies = make([]*aryshare.ThreadsComment, 0, len(comment.Replies)) for _, reply := range comment.Replies { protoComment.Replies = append(protoComment.Replies, convertThreadsComment(&reply)) } } return protoComment } // convertTwitterComment 转换 Twitter/X 评论 func convertTwitterComment(comment *dto.TwitterComment) *aryshare.TwitterComment { protoComment := &aryshare.TwitterComment{ BookmarkCount: int32(comment.BookmarkCount), Comment: comment.Comment, CommentId: comment.CommentId, Created: comment.Created, Description: comment.Description, Id: comment.Id, ImpressionCount: int32(comment.ImpressionCount), LikeCount: int32(comment.LikeCount), Name: comment.Name, Platform: comment.Platform, ProfileImageUrl: comment.ProfileImageUrl, QuoteCount: int32(comment.QuoteCount), ReplyCount: int32(comment.ReplyCount), ThreadNumber: int32(comment.ThreadNumber), UserName: comment.UserName, } // 转换 PublicMetrics if comment.PublicMetrics != nil { protoComment.PublicMetrics = &aryshare.TwitterPublicMetrics{ FollowersCount: int32(comment.PublicMetrics.FollowersCount), FollowingCount: int32(comment.PublicMetrics.FollowingCount), TweetCount: int32(comment.PublicMetrics.TweetCount), ListedCount: int32(comment.PublicMetrics.ListedCount), LikeCount: int32(comment.PublicMetrics.LikeCount), MediaCount: int32(comment.PublicMetrics.MediaCount), } } // 转换 ReferencedTweets if len(comment.ReferencedTweets) > 0 { protoComment.ReferencedTweets = make([]*aryshare.TwitterReferencedTweet, 0, len(comment.ReferencedTweets)) for _, r := range comment.ReferencedTweets { protoComment.ReferencedTweets = append(protoComment.ReferencedTweets, &aryshare.TwitterReferencedTweet{ Type: r.Type, Id: r.Id, }) } } // 转换 ReplyTo if comment.ReplyTo != nil { protoComment.ReplyTo = &aryshare.TwitterReplyTo{ CreatedAt: comment.ReplyTo.CreatedAt, Description: comment.ReplyTo.Description, Id: comment.ReplyTo.Id, Location: comment.ReplyTo.Location, Name: comment.ReplyTo.Name, ProfileImageUrl: comment.ReplyTo.ProfileImageUrl, Url: comment.ReplyTo.Url, Username: comment.ReplyTo.Username, } if comment.ReplyTo.PublicMetrics != nil { protoComment.ReplyTo.PublicMetrics = &aryshare.TwitterPublicMetrics{ FollowersCount: int32(comment.ReplyTo.PublicMetrics.FollowersCount), FollowingCount: int32(comment.ReplyTo.PublicMetrics.FollowingCount), TweetCount: int32(comment.ReplyTo.PublicMetrics.TweetCount), ListedCount: int32(comment.ReplyTo.PublicMetrics.ListedCount), LikeCount: int32(comment.ReplyTo.PublicMetrics.LikeCount), MediaCount: int32(comment.ReplyTo.PublicMetrics.MediaCount), } } } return protoComment } // convertYouTubeComment 转换 YouTube 评论 func convertYouTubeComment(comment *dto.YouTubeComment) *aryshare.YouTubeComment { protoComment := &aryshare.YouTubeComment{ ChannelUrl: comment.ChannelUrl, Comment: comment.Comment, CommentId: comment.CommentId, Created: comment.Created, IsPublic: comment.IsPublic, LikeCount: int32(comment.LikeCount), Platform: comment.Platform, ProfileImageUrl: comment.ProfileImageUrl, UserName: comment.UserName, } // 转换 Replies if len(comment.Replies) > 0 { protoComment.Replies = make([]*aryshare.YouTubeReply, 0, len(comment.Replies)) for _, r := range comment.Replies { protoComment.Replies = append(protoComment.Replies, &aryshare.YouTubeReply{ ChannelUrl: r.ChannelUrl, Comment: r.Comment, CommentId: r.CommentId, Created: r.Created, LikeCount: int32(r.LikeCount), Platform: r.Platform, ProfileImageUrl: r.ProfileImageUrl, UserName: r.UserName, ParentId: r.ParentId, }) } } return protoComment }