From 59c8349aba77643ebf071e0ede3646027c5b4314 Mon Sep 17 00:00:00 2001 From: cjy Date: Tue, 16 Dec 2025 10:16:09 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=BF=94=E5=9B=9E=E5=AE=8C=E6=95=B4?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/dto/aryshare_analytics.go | 196 ++++++++++++++++----------- internal/logic/aryshare_analytics.go | 15 ++ 2 files changed, 134 insertions(+), 77 deletions(-) diff --git a/internal/dto/aryshare_analytics.go b/internal/dto/aryshare_analytics.go index 8ef0f41..ec1d505 100644 --- a/internal/dto/aryshare_analytics.go +++ b/internal/dto/aryshare_analytics.go @@ -36,9 +36,11 @@ type BlueskyAnalytics struct { // BlueskyPlatformData Bluesky 平台数据 type BlueskyPlatformData struct { - ID string `json:"id,omitempty"` // Bluesky Social Post ID - PostUrl string `json:"postUrl,omitempty"` // 帖子 URL - Analytics *BlueskyAnalytics `json:"analytics,omitempty"` // 分析数据 + ID string `json:"id,omitempty"` // Bluesky Social Post ID + PostUrl string `json:"postUrl,omitempty"` // 帖子 URL + Analytics *BlueskyAnalytics `json:"analytics,omitempty"` // 分析数据 + LastUpdated string `json:"lastUpdated,omitempty"` // 最后更新时间 + NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间 } // FacebookReactions Facebook 反应数据 @@ -108,25 +110,62 @@ type FacebookAnalytics struct { // FacebookPlatformData Facebook 平台数据 type FacebookPlatformData struct { - ID string `json:"id,omitempty"` // Facebook Social Post ID - PostUrl string `json:"postUrl,omitempty"` // 帖子 URL - Analytics *FacebookAnalytics `json:"analytics,omitempty"` // 分析数据 + ID string `json:"id,omitempty"` // Facebook Social Post ID + PostUrl string `json:"postUrl,omitempty"` // 帖子 URL + Analytics *FacebookAnalytics `json:"analytics,omitempty"` // 分析数据 + LastUpdated string `json:"lastUpdated,omitempty"` // 最后更新时间 + NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间 +} + +// InstagramMediaUrl Instagram 媒体URL +type InstagramMediaUrl struct { + MediaUrl string `json:"mediaUrl,omitempty"` // 媒体URL } // InstagramAnalytics Instagram 平台的分析数据 type InstagramAnalytics struct { - CommentsCount int `json:"commentsCount,omitempty"` // 评论数 - LikeCount int `json:"likeCount,omitempty"` // 点赞数 - Reach int `json:"reach,omitempty"` // 触达数 - Saved int `json:"saved,omitempty"` // 收藏数 - Impressions int `json:"impressions,omitempty"` // 展示次数 + // FEED/REELS/STORY 通用字段 + Caption string `json:"caption,omitempty"` // 标题/描述 + CommentsCount int `json:"commentsCount,omitempty"` // 评论总数 + Created string `json:"created,omitempty"` // 创建时间 + EngagementCount int `json:"engagementCount,omitempty"` // 参与度(点赞、评论、保存) + FollowsCount int `json:"followsCount,omitempty"` // 获得的关注者数 + LikeCount int `json:"likeCount"` // 点赞总数(不包括推广帖子的点赞) + MediaProductType string `json:"mediaProductType,omitempty"` // IG分享类型: AD, FEED, STORY 或 REELS + MediaType string `json:"mediaType,omitempty"` // 媒体类型: CAROUSEL_ALBUM, IMAGE, 或 VIDEO + MediaUrls []InstagramMediaUrl `json:"mediaUrls,omitempty"` // 媒体URL列表 + ProfileActivityCount int `json:"profileActivityCount,omitempty"` // 用户访问个人资料后采取的操作数 + ProfileVisitsCount int `json:"profileVisitsCount,omitempty"` // 个人资料被访问的次数 + ReachCount int `json:"reachCount"` // 看到帖子的唯一账户数 + SavedCount int `json:"savedCount"` // 保存帖子的唯一账户数 + SharesCount int `json:"sharesCount"` // 帖子被分享的次数 + Username string `json:"username,omitempty"` // 用户名 + ViewsCount int `json:"viewsCount"` // 帖子被查看的总次数 + + // REELS 特定字段 + ClipsReplaysCount int `json:"clipsReplaysCount,omitempty"` // Reels重播次数(同一会话中1ms或更长的重播) + IgReelsAggregatedAllPlaysCount int `json:"igReelsAggregatedAllPlaysCount,omitempty"` // Reels播放或重播的总次数(1ms或更长,仅自然播放) + IgReelsAvgWatchTimeCount int `json:"igReelsAvgWatchTimeCount,omitempty"` // Reels平均观看时间(观看时间除以播放次数) + IgReelsVideoViewTotalTimeCount int `json:"igReelsVideoViewTotalTimeCount,omitempty"` // Reels总观看时间(包括重播时间) + PlaysCount int `json:"playsCount,omitempty"` // Reels播放次数(3秒或播放到结尾,仅自然播放) + + // STORY 特定字段 + NotEnoughViews bool `json:"notEnoughViews,omitempty"` // 如果少于5个唯一洞察,则为true + NavigationCount int `json:"navigationCount,omitempty"` // 点击和滑动的总导航交互数 + RepliesCount int `json:"repliesCount,omitempty"` // 回复数 + SwipeForwardCount int `json:"swipeForwardCount,omitempty"` // 在原生界面上滑动"下一个故事"的次数 + TapBackCount int `json:"tapBackCount,omitempty"` // 在原生界面上点击"返回"的次数 + TapForwardCount int `json:"tapForwardCount,omitempty"` // 在原生界面上点击"前进"的次数 + TapExitCount int `json:"tapExitCount,omitempty"` // 在原生界面上点击"退出"的次数 } // InstagramPlatformData Instagram 平台数据 type InstagramPlatformData struct { - ID string `json:"id,omitempty"` // Instagram Social Post ID - PostUrl string `json:"postUrl,omitempty"` // 帖子 URL - Analytics *InstagramAnalytics `json:"analytics,omitempty"` // 分析数据 + ID string `json:"id,omitempty"` // Instagram Social Post ID + PostUrl string `json:"postUrl,omitempty"` // 帖子 URL + Analytics *InstagramAnalytics `json:"analytics,omitempty"` // 分析数据 + LastUpdated string `json:"lastUpdated,omitempty"` // 最后更新时间 + NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间 } // LinkedInAnalytics LinkedIn 平台的分析数据 @@ -139,9 +178,11 @@ type LinkedInAnalytics struct { // LinkedInPlatformData LinkedIn 平台数据 type LinkedInPlatformData struct { - ID string `json:"id,omitempty"` // LinkedIn Social Post ID - PostUrl string `json:"postUrl,omitempty"` // 帖子 URL - Analytics *LinkedInAnalytics `json:"analytics,omitempty"` // 分析数据 + ID string `json:"id,omitempty"` // LinkedIn Social Post ID + PostUrl string `json:"postUrl,omitempty"` // 帖子 URL + Analytics *LinkedInAnalytics `json:"analytics,omitempty"` // 分析数据 + LastUpdated string `json:"lastUpdated,omitempty"` // 最后更新时间 + NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间 } // PinterestAnalytics Pinterest 平台的分析数据 @@ -151,9 +192,11 @@ type PinterestAnalytics struct { // PinterestPlatformData Pinterest 平台数据 type PinterestPlatformData struct { - ID string `json:"id,omitempty"` // Pinterest Social Post ID - PostUrl string `json:"postUrl,omitempty"` // 帖子 URL - Analytics *PinterestAnalytics `json:"analytics,omitempty"` // 分析数据 + ID string `json:"id,omitempty"` // Pinterest Social Post ID + PostUrl string `json:"postUrl,omitempty"` // 帖子 URL + Analytics *PinterestAnalytics `json:"analytics,omitempty"` // 分析数据 + LastUpdated string `json:"lastUpdated,omitempty"` // 最后更新时间 + NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间 } // SnapchatAnalytics Snapchat 平台的分析数据 @@ -163,9 +206,11 @@ type SnapchatAnalytics struct { // SnapchatPlatformData Snapchat 平台数据 type SnapchatPlatformData struct { - ID string `json:"id,omitempty"` // Snapchat Social Post ID - PostUrl string `json:"postUrl,omitempty"` // 帖子 URL - Analytics *SnapchatAnalytics `json:"analytics,omitempty"` // 分析数据 + ID string `json:"id,omitempty"` // Snapchat Social Post ID + PostUrl string `json:"postUrl,omitempty"` // 帖子 URL + Analytics *SnapchatAnalytics `json:"analytics,omitempty"` // 分析数据 + LastUpdated string `json:"lastUpdated,omitempty"` // 最后更新时间 + NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间 } // ThreadsAnalytics Threads 平台的分析数据 @@ -177,24 +222,42 @@ type ThreadsAnalytics struct { // ThreadsPlatformData Threads 平台数据 type ThreadsPlatformData struct { - ID string `json:"id,omitempty"` // Threads Social Post ID - PostUrl string `json:"postUrl,omitempty"` // 帖子 URL - Analytics *ThreadsAnalytics `json:"analytics,omitempty"` // 分析数据 + ID string `json:"id,omitempty"` // Threads Social Post ID + PostUrl string `json:"postUrl,omitempty"` // 帖子 URL + Analytics *ThreadsAnalytics `json:"analytics,omitempty"` // 分析数据 + LastUpdated string `json:"lastUpdated,omitempty"` // 最后更新时间 + NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间 } // TikTokAnalytics TikTok 平台的分析数据 type TikTokAnalytics struct { - CommentCount int `json:"commentCount,omitempty"` // 评论数 - LikeCount int `json:"likeCount,omitempty"` // 点赞数 - ShareCount int `json:"shareCount,omitempty"` // 分享数 - ViewCount int `json:"viewCount,omitempty"` // 查看数 + AddressClicks int `json:"addressClicks,omitempty"` // 过去 60 天在地址按钮上收集的点击数 + AppDownloadClicks int `json:"appDownloadClicks,omitempty"` // 过去 60 天在应用下载按钮上收集的点击数 + AudienceCountries []TikTokSocialAudienceCountry `json:"audienceCountries,omitempty"` // 受众国家(TikTok 每 24-48 小时更新) + BioLinkClicks int `json:"bioLinkClicks,omitempty"` // 过去 60 天在 Bio Link 按钮上收集的点击数 + CommentCountPeriod string `json:"commentCountPeriod,omitempty"` // "60 days" 或 "lifetime" - 从 2025 年 3 月 1 日开始,仅提供 60 天总数 + CommentCountTotal int `json:"commentCountTotal"` // 总评论数 + DisplayName string `json:"displayName,omitempty"` // 显示名称 + LikeCount int `json:"likeCount"` // 总点赞数(所有时间),发布后 24-48 小时可用 + EmailClicks int `json:"emailClicks,omitempty"` // 过去 60 天在 Email 按钮上收集的点击数 + LeadSubmissions int `json:"leadSubmissions,omitempty"` // 过去 60 天提交的潜在客户数 + PhoneNumberClicks int `json:"phoneNumberClicks,omitempty"` // 过去 60 天在电话号码按钮上收集的点击数 + ProfileViews int `json:"profileViews,omitempty"` // 过去 60 天的总个人资料浏览量 + ShareCountPeriod string `json:"shareCountPeriod,omitempty"` // "60 days" 或 "lifetime" - 从 2025 年 3 月 1 日开始,仅提供 60 天总数 + ShareCountTotal int `json:"shareCountTotal"` // 帖子的总分享数 + Username string `json:"username,omitempty"` // 用户名 + VideoCountTotal int `json:"videoCountTotal"` // 视频总数 + ViewCountPeriod string `json:"viewCountPeriod,omitempty"` // "60 days" 或 "lifetime" - 从 2025 年 3 月 1 日开始,仅提供 60 天总数 + ViewCountTotal int `json:"viewCountTotal"` // 视频的总观看次数 } // TikTokPlatformData TikTok 平台数据 type TikTokPlatformData struct { - ID string `json:"id,omitempty"` // TikTok Social Post ID - PostUrl string `json:"postUrl,omitempty"` // 帖子 URL - Analytics *TikTokAnalytics `json:"analytics,omitempty"` // 分析数据 + ID string `json:"id,omitempty"` // TikTok Social Post ID + PostUrl string `json:"postUrl,omitempty"` // 帖子 URL + Analytics *TikTokAnalytics `json:"analytics,omitempty"` // 分析数据 + LastUpdated string `json:"lastUpdated,omitempty"` // 最后更新时间 + NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间 } // TwitterMediaVariant Twitter 媒体变体 @@ -462,52 +525,31 @@ type FacebookSocialPlatformData struct { NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间 } -// InstagramSocialAudienceAge Instagram 受众年龄 -type InstagramSocialAudienceAge struct { - Percentage float64 `json:"percentage,omitempty"` // 百分比 - Age string `json:"age,omitempty"` // 年龄范围 -} - -// InstagramSocialAudienceCountry Instagram 受众国家 -type InstagramSocialAudienceCountry struct { - Percentage float64 `json:"percentage,omitempty"` // 百分比 - Country string `json:"country,omitempty"` // 国家 -} - -// InstagramSocialAudienceGender Instagram 受众性别 -type InstagramSocialAudienceGender struct { - Percentage float64 `json:"percentage,omitempty"` // 百分比 - Gender string `json:"gender,omitempty"` // 性别 -} - // InstagramSocialAnalytics Instagram 社交网络分析数据 type InstagramSocialAnalytics struct { - AudienceAges []InstagramSocialAudienceAge `json:"audienceAges,omitempty"` // 受众年龄(TikTok 每 24-48 小时更新) - AudienceCountries []InstagramSocialAudienceCountry `json:"audienceCountries,omitempty"` // 受众国家(TikTok 每 24-48 小时更新) - AudienceGenders []InstagramSocialAudienceGender `json:"audienceGenders,omitempty"` // 受众性别(TikTok 每 24-48 小时更新) - Bio string `json:"bio,omitempty"` // 个人简介 - BioLinkClicks int `json:"bioLinkClicks,omitempty"` // 过去 60 天在 Bio Link 按钮上收集的点击数 - CommentCountPeriod string `json:"commentCountPeriod,omitempty"` // "60 days" 或 "lifetime" - 从 2025 年 3 月 1 日开始,仅提供 60 天总数 - CommentCountTotal int `json:"commentCountTotal,omitempty"` // 总评论数 - DisplayName string `json:"displayName,omitempty"` // 显示名称 - DurationAverage string `json:"durationAverage,omitempty"` // 已弃用,将在未来移除,每 12 小时更新 - EmailClicks int `json:"emailClicks,omitempty"` // 过去 60 天在 Email 按钮上收集的点击数 - FollowerCount int `json:"followerCount,omitempty"` // 当前关注者数 - FollowingCount int `json:"followingCount,omitempty"` // 当前关注数 - LeadSubmissions int `json:"leadSubmissions,omitempty"` // 过去 60 天提交的潜在客户数 - IsBusinessAccount bool `json:"isBusinessAccount,omitempty"` // 账户是否为商业账户 - IsVerified bool `json:"isVerified,omitempty"` // TikTok 是否在确认账户属于其代表的用户后提供了验证徽章 - LikeCountTotal int `json:"likeCountTotal,omitempty"` // 总点赞数(所有时间) - PhoneNumberClicks int `json:"phoneNumberClicks,omitempty"` // 过去 60 天在电话号码按钮上收集的点击数 - ProfileViews int `json:"profileViews,omitempty"` // 过去 60 天的总个人资料浏览量 - ShareCountPeriod string `json:"shareCountPeriod,omitempty"` // "60 days" 或 "lifetime" - 从 2025 年 3 月 1 日开始,仅提供 60 天总数 - ShareCountTotal int `json:"shareCountTotal,omitempty"` // 帖子的总分享数 - URL string `json:"url,omitempty"` // URL - UserImage string `json:"userImage,omitempty"` // 用户头像 - Username string `json:"username,omitempty"` // 用户名 - VideoCountTotal int `json:"videoCountTotal,omitempty"` // 视频总数 - ViewCountPeriod string `json:"viewCountPeriod,omitempty"` // "60 days" 或 "lifetime" - 从 2025 年 3 月 1 日开始,仅提供 60 天总数 - ViewCountTotal int `json:"viewCountTotal,omitempty"` // 视频的总观看次数 + // 受众数据:以下受众人口统计数据仅适用于至少有 100 个关注者和参与度(过去 30 天)的 Instagram 用户 + // 此外,受众人口统计数据仅在每个人口统计类别中有超过 100 人时才可用 + AudienceCity map[string]int `json:"audienceCity,omitempty"` // 受众城市数据 + AudienceCityEngagedAudienceDemographics map[string]int `json:"audienceCityEngagedAudienceDemographics,omitempty"` // 参与受众的城市数据 + AudienceCountry map[string]int `json:"audienceCountry,omitempty"` // 受众国家数据 + AudienceCountryEngagedAudienceDemographics map[string]int `json:"audienceCountryEngagedAudienceDemographics,omitempty"` // 参与受众的国家数据 + AudienceGenderAge map[string]int `json:"audienceGenderAge,omitempty"` // 受众性别年龄数据 + AudienceGenderAgeEngagedAudienceDemographics map[string]int `json:"audienceGenderAgeEngagedAudienceDemographics,omitempty"` // 参与受众的性别年龄数据 + Biography string `json:"biography,omitempty"` // 个人简介 + CommentsCount int `json:"commentsCount,omitempty"` // 过去 500 个帖子的总评论数 + FollowersCount int `json:"followersCount,omitempty"` // 当前关注者总数(至少需要 100 个关注者才显示) + FollowsCount int `json:"followsCount,omitempty"` // 当前关注的用户总数 + ID string `json:"id,omitempty"` // Instagram 用户 ID + IgID int64 `json:"igId,omitempty"` // 传统 Instagram 用户 ID(仅当通过 Facebook Page 链接时可用) + IgLoginID string `json:"igLoginId,omitempty"` // Instagram 原生用户 ID(仅当通过直接 Instagram 登录链接时可用) + LikeCount int `json:"likeCount,omitempty"` // 过去 500 个帖子的总点赞数 + MediaCount int `json:"mediaCount,omitempty"` // 当前发布的媒体总数 + Name string `json:"name,omitempty"` // 名称 + ProfilePictureUrl string `json:"profilePictureUrl,omitempty"` // 个人资料图片 URL + ReachCount int `json:"reachCount,omitempty"` // 180 天期间查看过至少一个媒体的唯一用户数 + Username string `json:"username,omitempty"` // 用户名 + ViewsCount int `json:"viewsCount,omitempty"` // 180 天期间 IG 用户媒体被查看的总次数 + Website string `json:"website,omitempty"` // 网站 } // InstagramSocialPlatformData Instagram 社交网络平台数据 diff --git a/internal/logic/aryshare_analytics.go b/internal/logic/aryshare_analytics.go index 4d13c25..1cbaca5 100644 --- a/internal/logic/aryshare_analytics.go +++ b/internal/logic/aryshare_analytics.go @@ -74,6 +74,11 @@ func (a *AyrshareAnalytics) GetPostAnalytics(req *dto.AnalyticsPostRequest) (res return nil, errCommon.ReturnError(err, msg.ErrorJSONParse, "获取帖子分析数据失败: ") } + // 检查响应状态,即使状态码是 200,响应中也可能包含错误信息 + if analyticsResp.Status == "error" { + return nil, errCommon.ReturnError(fmt.Errorf("接口返回错误: code=%d, message=%s", analyticsResp.Code, result), msg.ErrorGetPostAnalyticsFailed, "获取帖子分析数据 失败: ") + } + errCommon.NoReturnInfo(&analyticsResp, "获取帖子分析数据 成功: ") res = &analyticsResp @@ -156,6 +161,11 @@ func (a *AyrshareAnalytics) GetPostAnalyticsBySocialID(req *dto.AnalyticsPostByS return nil, errCommon.ReturnError(err, msg.ErrorJSONParse, "通过 Social Post ID 获取帖子分析数据失败: ") } + // 检查响应状态,即使状态码是 200,响应中也可能包含错误信息 + if analyticsResp.Status == "error" { + return nil, errCommon.ReturnError(fmt.Errorf("接口返回错误: code=%d, message=%s", analyticsResp.Code, result), msg.ErrorGetPostAnalyticsBySocialIDFailed, "通过 Social Post ID 获取帖子分析数据 失败: ") + } + errCommon.NoReturnInfo(&analyticsResp, "通过 Social Post ID 获取帖子分析数据 成功: ") res = &analyticsResp @@ -232,6 +242,11 @@ func (a *AyrshareAnalytics) GetSocialAnalytics(req *dto.AnalyticsSocialRequest) return nil, errCommon.ReturnError(err, msg.ErrorJSONParse, "获取社交网络分析数据失败: ") } + // 检查响应状态,即使状态码是 200,响应中也可能包含错误信息 + if socialAnalyticsResp.Status == "error" { + return nil, errCommon.ReturnError(fmt.Errorf("接口返回错误: message=%s", result), msg.ErrorGetSocialAnalyticsFailed, "获取社交网络分析数据 失败: ") + } + errCommon.NoReturnInfo(&socialAnalyticsResp, "获取社交网络分析数据 成功: ") res = &socialAnalyticsResp