This commit is contained in:
parent
f923429b96
commit
cff74a8319
@ -16,6 +16,7 @@ type AyrshareProvider struct {
|
|||||||
aryshareMessageLogic logic.IAryshareMessage
|
aryshareMessageLogic logic.IAryshareMessage
|
||||||
aryshareCommentLogic logic.IAryshareComment
|
aryshareCommentLogic logic.IAryshareComment
|
||||||
aryshareAnalyticsLogic logic.IAryshareAnalytics
|
aryshareAnalyticsLogic logic.IAryshareAnalytics
|
||||||
|
aryshareTagLogic logic.IAryshareTag
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAyrshareProvider 创建 AyrshareProvider 实例
|
// NewAyrshareProvider 创建 AyrshareProvider 实例
|
||||||
@ -28,6 +29,7 @@ func NewAyrshareProvider() *AyrshareProvider {
|
|||||||
aryshareMessageLogic: &logic.AyrshareMessage{},
|
aryshareMessageLogic: &logic.AyrshareMessage{},
|
||||||
aryshareCommentLogic: &logic.AyrshareComment{},
|
aryshareCommentLogic: &logic.AyrshareComment{},
|
||||||
aryshareAnalyticsLogic: &logic.AyrshareAnalytics{},
|
aryshareAnalyticsLogic: &logic.AyrshareAnalytics{},
|
||||||
|
aryshareTagLogic: &logic.AyrshareTag{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
174
internal/controller/aryshare_tag.go
Normal file
174
internal/controller/aryshare_tag.go
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"micro-ayrshare/internal/dto"
|
||||||
|
"micro-ayrshare/pb/aryshare"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AutoHashtags 自动为帖子添加合适的标签
|
||||||
|
// 将 proto 请求转换为 DTO,调用 logic 层,然后再组装回 proto 响应。
|
||||||
|
func (a *AyrshareProvider) AutoHashtags(_ context.Context, req *aryshare.AutoHashtagsRequest) (res *aryshare.AutoHashtagsResponse, err error) {
|
||||||
|
res = new(aryshare.AutoHashtagsResponse)
|
||||||
|
|
||||||
|
// 组装 DTO 请求
|
||||||
|
dtoReq := &dto.AutoHashtagsRequest{
|
||||||
|
Post: req.Post,
|
||||||
|
Position: req.Position,
|
||||||
|
Language: req.Language,
|
||||||
|
ProfileKey: req.ProfileKey,
|
||||||
|
}
|
||||||
|
if req.Max != 0 {
|
||||||
|
max := int(req.Max)
|
||||||
|
dtoReq.Max = &max
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用 logic 层
|
||||||
|
dtoRes, err := a.aryshareTagLogic.AutoHashtags(dtoReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组装 proto 响应
|
||||||
|
res.Post = dtoRes.Post
|
||||||
|
res.Action = dtoRes.Action
|
||||||
|
res.Status = dtoRes.Status
|
||||||
|
res.Code = int32(dtoRes.Code)
|
||||||
|
res.Message = dtoRes.Message
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckBannedHashtag 查看某个标签是否被平台禁用
|
||||||
|
func (a *AyrshareProvider) CheckBannedHashtag(_ context.Context, req *aryshare.CheckBannedHashtagRequest) (res *aryshare.CheckBannedHashtagResponse, err error) {
|
||||||
|
res = new(aryshare.CheckBannedHashtagResponse)
|
||||||
|
|
||||||
|
// 组装 DTO 请求
|
||||||
|
dtoReq := &dto.CheckBannedHashtagRequest{
|
||||||
|
Hashtag: req.Hashtag,
|
||||||
|
ProfileKey: req.ProfileKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用 logic 层
|
||||||
|
dtoRes, err := a.aryshareTagLogic.CheckBannedHashtag(dtoReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组装 proto 响应
|
||||||
|
res.Hashtag = dtoRes.Hashtag
|
||||||
|
res.Banned = dtoRes.Banned
|
||||||
|
res.Action = dtoRes.Action
|
||||||
|
res.Status = dtoRes.Status
|
||||||
|
res.Code = int32(dtoRes.Code)
|
||||||
|
res.Message = dtoRes.Message
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecommendHashtags 根据关键字推荐热门标签
|
||||||
|
func (a *AyrshareProvider) RecommendHashtags(_ context.Context, req *aryshare.RecommendHashtagsRequest) (res *aryshare.RecommendHashtagsResponse, err error) {
|
||||||
|
res = new(aryshare.RecommendHashtagsResponse)
|
||||||
|
|
||||||
|
// 组装 DTO 请求
|
||||||
|
dtoReq := &dto.RecommendHashtagsRequest{
|
||||||
|
Keyword: req.Keyword,
|
||||||
|
ProfileKey: req.ProfileKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用 logic 层
|
||||||
|
dtoRes, err := a.aryshareTagLogic.RecommendHashtags(dtoReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组装 proto 响应
|
||||||
|
res.Keyword = dtoRes.Keyword
|
||||||
|
res.Action = dtoRes.Action
|
||||||
|
res.Status = dtoRes.Status
|
||||||
|
res.Code = int32(dtoRes.Code)
|
||||||
|
res.Message = dtoRes.Message
|
||||||
|
|
||||||
|
// 转换推荐列表
|
||||||
|
if len(dtoRes.Recommendations) > 0 {
|
||||||
|
res.Recommendations = make([]*aryshare.HashtagRecommendation, 0, len(dtoRes.Recommendations))
|
||||||
|
for _, r := range dtoRes.Recommendations {
|
||||||
|
res.Recommendations = append(res.Recommendations, &aryshare.HashtagRecommendation{
|
||||||
|
ViewCount: r.ViewCount,
|
||||||
|
Name: r.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtags 搜索话题标签,返回对应的 Instagram 媒体数据
|
||||||
|
func (a *AyrshareProvider) SearchHashtags(_ context.Context, req *aryshare.SearchHashtagsRequest) (res *aryshare.SearchHashtagsResponse, err error) {
|
||||||
|
res = new(aryshare.SearchHashtagsResponse)
|
||||||
|
|
||||||
|
// 组装 DTO 请求
|
||||||
|
dtoReq := &dto.SearchHashtagsRequest{
|
||||||
|
Keyword: req.Keyword,
|
||||||
|
SearchType: req.SearchType,
|
||||||
|
ProfileKey: req.ProfileKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用 logic 层
|
||||||
|
dtoRes, err := a.aryshareTagLogic.SearchHashtags(dtoReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组装 proto 响应
|
||||||
|
res.Status = dtoRes.Status
|
||||||
|
res.Count = int32(dtoRes.Count)
|
||||||
|
res.LastUpdated = dtoRes.LastUpdated
|
||||||
|
res.NextUpdate = dtoRes.NextUpdate
|
||||||
|
res.Action = dtoRes.Action
|
||||||
|
res.Code = int32(dtoRes.ErrorCode)
|
||||||
|
res.Message = dtoRes.Message
|
||||||
|
|
||||||
|
// 转换 hashtag 基本信息
|
||||||
|
if dtoRes.Hashtag != nil {
|
||||||
|
res.Hashtag = &aryshare.SearchHashtagInfo{
|
||||||
|
Id: dtoRes.Hashtag.ID,
|
||||||
|
Name: dtoRes.Hashtag.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换 searchResults 列表
|
||||||
|
if len(dtoRes.SearchResults) > 0 {
|
||||||
|
res.SearchResults = make([]*aryshare.SearchHashtagMedia, 0, len(dtoRes.SearchResults))
|
||||||
|
for _, media := range dtoRes.SearchResults {
|
||||||
|
protoMedia := &aryshare.SearchHashtagMedia{
|
||||||
|
Caption: media.Caption,
|
||||||
|
CommentsCount: int32(media.CommentsCount),
|
||||||
|
Id: media.ID,
|
||||||
|
LikeCount: int32(media.LikeCount),
|
||||||
|
MediaType: media.MediaType,
|
||||||
|
MediaUrl: media.MediaUrl,
|
||||||
|
Permalink: media.Permalink,
|
||||||
|
Timestamp: media.Timestamp,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换 children
|
||||||
|
if media.Children != nil && len(media.Children.Data) > 0 {
|
||||||
|
children := &aryshare.SearchHashtagChildren{
|
||||||
|
Data: make([]*aryshare.SearchHashtagChild, 0, len(media.Children.Data)),
|
||||||
|
}
|
||||||
|
for _, child := range media.Children.Data {
|
||||||
|
children.Data = append(children.Data, &aryshare.SearchHashtagChild{
|
||||||
|
Id: child.ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
protoMedia.Children = children
|
||||||
|
}
|
||||||
|
|
||||||
|
res.SearchResults = append(res.SearchResults, protoMedia)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
125
internal/dto/aryshare_tag.go
Normal file
125
internal/dto/aryshare_tag.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
// AutoHashtagsRequest 自动生成标签请求参数
|
||||||
|
// 对应 Ayrshare 接口文档: https://www.ayrshare.com/docs/apis/hashtags/auto-hashtags
|
||||||
|
type AutoHashtagsRequest struct {
|
||||||
|
Post string `json:"post"` // 必填,原始帖子内容,最大长度 1000 字符
|
||||||
|
Max *int `json:"max,omitempty"` // 可选,生成的最大标签数量,1-10,默认 2
|
||||||
|
Position string `json:"position,omitempty"` // 可选,标签插入位置,例如 "auto"
|
||||||
|
Language string `json:"language,omitempty"` // 可选,帖子语言代码,例如 "en"、"fr"
|
||||||
|
ProfileKey string `json:"-"` // 可选,多用户场景下的 Profile Key,通过请求头传递
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoHashtagsResponse 自动生成标签返回结果
|
||||||
|
// 正常情况仅返回替换后的 post;出错时返回 action/status/code/message
|
||||||
|
// 参考 internal/dto/自动标签返回参数.md
|
||||||
|
type AutoHashtagsResponse struct {
|
||||||
|
Post string `json:"post,omitempty"` // 自动补全标签后的帖子内容
|
||||||
|
|
||||||
|
// 错误相关字段(当调用失败时会返回)
|
||||||
|
Action string `json:"action,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
Code int `json:"code,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckBannedHashtagRequest 查看被禁用标签请求
|
||||||
|
// 对应 Ayrshare 接口文档: https://www.ayrshare.com/docs/apis/hashtags/check-hashtags
|
||||||
|
type CheckBannedHashtagRequest struct {
|
||||||
|
Hashtag string `json:"-"` // 必填,要检查的标签,例如 "bikinibody" 或 "#bikinibody"
|
||||||
|
ProfileKey string `json:"-"` // 可选,多用户场景下的 Profile Key,通过请求头传递
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckBannedHashtagResponse 查看被禁用标签返回结果
|
||||||
|
// 参考 internal/dto/查看被禁用的标签返回参数.md
|
||||||
|
type CheckBannedHashtagResponse struct {
|
||||||
|
Hashtag string `json:"hashtag,omitempty"` // 请求的标签
|
||||||
|
Banned bool `json:"banned,omitempty"` // 是否被禁用
|
||||||
|
|
||||||
|
// 出错时的通用返回结构
|
||||||
|
Action string `json:"action,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
Code int `json:"code,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashtagRecommendation 单条推荐标签信息
|
||||||
|
// 对应 Ayrshare Recommend Hashtags 返回中的 recommendations 数组元素
|
||||||
|
type HashtagRecommendation struct {
|
||||||
|
ViewCount int64 `json:"viewCount"` // 推荐标签在 TikTok 上的浏览次数
|
||||||
|
Name string `json:"name"` // 推荐的标签名称(不带 #)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecommendHashtagsRequest 推荐话题标签请求
|
||||||
|
// 对应 Ayrshare 接口文档: https://www.ayrshare.com/docs/apis/hashtags/recommend-hashtags
|
||||||
|
type RecommendHashtagsRequest struct {
|
||||||
|
Keyword string `json:"-"` // 必填,单个关键字,例如 "apple"
|
||||||
|
ProfileKey string `json:"-"` // 可选,多用户场景下的 Profile Key,通过请求头传递
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecommendHashtagsResponse 推荐话题标签返回结果
|
||||||
|
// 参考 internal/dto/推荐话话题返回参数.md
|
||||||
|
type RecommendHashtagsResponse struct {
|
||||||
|
Keyword string `json:"keyword,omitempty"` // 请求时的关键字
|
||||||
|
Recommendations []HashtagRecommendation `json:"recommendations,omitempty"` // 推荐的标签列表
|
||||||
|
|
||||||
|
// 出错时的通用返回结构
|
||||||
|
Action string `json:"action,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
Code int `json:"code,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagsRequest 搜索话题标签请求
|
||||||
|
// 对应 Ayrshare 接口文档: https://www.ayrshare.com/docs/apis/hashtags/search-hashtags
|
||||||
|
type SearchHashtagsRequest struct {
|
||||||
|
Keyword string `json:"-"` // 必填,要搜索的关键字,例如 "wisdom"
|
||||||
|
SearchType string `json:"-"` // 可选,搜索类型:top 或 recent,不传则使用服务端默认 top
|
||||||
|
ProfileKey string `json:"-"` // 可选,多用户场景下的 Profile Key,通过请求头传递
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagInfo 单个话题标签的基本信息
|
||||||
|
type SearchHashtagInfo struct {
|
||||||
|
ID string `json:"id"` // Hashtag ID
|
||||||
|
Name string `json:"name"` // Hashtag 名称,例如 "wisdom"
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagChild 搜索结果中 children.data 的元素
|
||||||
|
type SearchHashtagChild struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagChildren 搜索结果中的 children 对象
|
||||||
|
type SearchHashtagChildren struct {
|
||||||
|
Data []SearchHashtagChild `json:"data,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagMedia 搜索结果中的单条 Instagram 媒体信息
|
||||||
|
// 参考 internal/dto/搜索话题标签返回参数.md
|
||||||
|
type SearchHashtagMedia struct {
|
||||||
|
Caption string `json:"caption"` // 媒体文案
|
||||||
|
Children *SearchHashtagChildren `json:"children,omitempty"` // 多图时的子媒体 ID 列表
|
||||||
|
CommentsCount int `json:"commentsCount"` // 评论数
|
||||||
|
ID string `json:"id"` // 媒体 ID
|
||||||
|
LikeCount int `json:"likeCount"` // 点赞数
|
||||||
|
MediaType string `json:"mediaType"` // 媒体类型,例如 CAROUSEL_ALBUM
|
||||||
|
MediaUrl string `json:"mediaUrl"` // 媒体封面 URL
|
||||||
|
Permalink string `json:"permalink"` // Instagram 详情页链接
|
||||||
|
Timestamp string `json:"timestamp"` // 发布时间
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagsResponse 搜索话题标签响应
|
||||||
|
// 参考 internal/dto/搜索话题标签返回参数.md
|
||||||
|
type SearchHashtagsResponse struct {
|
||||||
|
Status string `json:"status,omitempty"` // 请求状态:success 或 error
|
||||||
|
Hashtag *SearchHashtagInfo `json:"hashtag,omitempty"` // 命中的 hashtag 信息
|
||||||
|
SearchResults []SearchHashtagMedia `json:"searchResults,omitempty"` // 搜索结果媒体列表
|
||||||
|
Count int `json:"count,omitempty"` // 返回结果条数
|
||||||
|
LastUpdated string `json:"lastUpdated,omitempty"` // 最后更新时间
|
||||||
|
NextUpdate string `json:"nextUpdate,omitempty"` // 下次更新时间
|
||||||
|
|
||||||
|
// 出错时的通用返回结构(情况二)
|
||||||
|
Action string `json:"action,omitempty"`
|
||||||
|
ErrorCode int `json:"code,omitempty"` // 错误码,为避免与正常字段冲突,这里使用不同的结构字段名
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
||||||
318
internal/logic/aryshare_tag.go
Normal file
318
internal/logic/aryshare_tag.go
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
errCommon "micro-ayrshare/pkg/err"
|
||||||
|
"micro-ayrshare/pkg/msg"
|
||||||
|
|
||||||
|
"micro-ayrshare/internal/dto"
|
||||||
|
"micro-ayrshare/pkg/app"
|
||||||
|
"micro-ayrshare/pkg/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IAryshareTag Hashtags 相关业务接口
|
||||||
|
// 封装 Ayrshare 的自动标签 / 禁用标签检查 / 推荐标签 / 搜索标签 四个接口
|
||||||
|
type IAryshareTag interface {
|
||||||
|
// AutoHashtags 自动为帖子添加合适的标签
|
||||||
|
AutoHashtags(req *dto.AutoHashtagsRequest) (res *dto.AutoHashtagsResponse, err error)
|
||||||
|
// CheckBannedHashtag 检查单个标签是否被社交平台禁用
|
||||||
|
CheckBannedHashtag(req *dto.CheckBannedHashtagRequest) (res *dto.CheckBannedHashtagResponse, err error)
|
||||||
|
// RecommendHashtags 根据关键字推荐热门标签
|
||||||
|
RecommendHashtags(req *dto.RecommendHashtagsRequest) (res *dto.RecommendHashtagsResponse, err error)
|
||||||
|
// SearchHashtags 搜索话题标签并返回相关媒体
|
||||||
|
SearchHashtags(req *dto.SearchHashtagsRequest) (res *dto.SearchHashtagsResponse, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AyrshareTag Hashtags 相关逻辑实现
|
||||||
|
type AyrshareTag struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoHashtags 自动为帖子添加合适的标签
|
||||||
|
// 文档: https://www.ayrshare.com/docs/apis/hashtags/auto-hashtags
|
||||||
|
func (a *AyrshareTag) AutoHashtags(req *dto.AutoHashtagsRequest) (res *dto.AutoHashtagsResponse, err error) {
|
||||||
|
errCommon.NoReturnInfo(req, "自动生成标签 参数信息: ")
|
||||||
|
|
||||||
|
res = new(dto.AutoHashtagsResponse)
|
||||||
|
|
||||||
|
// 基本参数校验:post 不能为空,其它参数交给 Ayrshare 校验,便于兼容后续扩展
|
||||||
|
if req.Post == "" {
|
||||||
|
return nil, errCommon.ReturnError(
|
||||||
|
fmt.Errorf(msg.ErrPostContentEmpty),
|
||||||
|
msg.ErrPostContentEmpty,
|
||||||
|
"自动生成标签 失败: ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建请求 URL
|
||||||
|
urlStr := fmt.Sprintf("%s/api/hashtags/auto", app.ModuleClients.AryshareClient.Config.Endpoint)
|
||||||
|
|
||||||
|
// 准备请求体(ProfileKey 使用请求头传递,因此结构体中使用 json:\"-\" 排除)
|
||||||
|
reqBody, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorJSONMarshal, "自动生成标签失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 准备请求头
|
||||||
|
headers := make(map[string]string)
|
||||||
|
headers["Authorization"] = fmt.Sprintf("Bearer %s", app.ModuleClients.AryshareClient.Config.ApiKey)
|
||||||
|
if req.ProfileKey != "" {
|
||||||
|
headers["Profile-Key"] = req.ProfileKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发起 HTTP 请求
|
||||||
|
statusCode, result, err := utils.PostWithHeaders(urlStr, reqBody, headers)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorAutoHashtagsFailed, "自动生成标签失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
var autoResp dto.AutoHashtagsResponse
|
||||||
|
if err := json.Unmarshal([]byte(result), &autoResp); err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorJSONParse, "自动生成标签失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ayrshare 文档未明确错误时的 HTTP 状态码,这里统一按照:
|
||||||
|
// - 200 且未返回 status=error 视为成功
|
||||||
|
// - 其它情况视为失败,并优先使用返回的 message/code 作为错误信息
|
||||||
|
if statusCode != http.StatusOK || autoResp.Status == "error" {
|
||||||
|
errMsg := autoResp.Message
|
||||||
|
if errMsg == "" {
|
||||||
|
errMsg = msg.ErrorAutoHashtagsFailed
|
||||||
|
}
|
||||||
|
if autoResp.Code != 0 {
|
||||||
|
errMsg = fmt.Sprintf("错误代码: %d, %s", autoResp.Code, errMsg)
|
||||||
|
}
|
||||||
|
return nil, errCommon.ReturnError(
|
||||||
|
fmt.Errorf("接口返回状态码: %d, 错误信息: %s, 响应结果: %s", statusCode, errMsg, result),
|
||||||
|
errMsg,
|
||||||
|
"自动生成标签 失败: ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
errCommon.NoReturnInfo(&autoResp, "自动生成标签 成功: ")
|
||||||
|
res = &autoResp
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckBannedHashtag 检查单个标签是否被社交平台禁用
|
||||||
|
// 文档: https://www.ayrshare.com/docs/apis/hashtags/check-hashtags
|
||||||
|
func (a *AyrshareTag) CheckBannedHashtag(req *dto.CheckBannedHashtagRequest) (res *dto.CheckBannedHashtagResponse, err error) {
|
||||||
|
errCommon.NoReturnInfo(req, "查看被禁用的标签 参数信息: ")
|
||||||
|
|
||||||
|
res = new(dto.CheckBannedHashtagResponse)
|
||||||
|
|
||||||
|
// 基本参数校验:hashtag 不能为空
|
||||||
|
if req.Hashtag == "" {
|
||||||
|
return nil, errCommon.ReturnError(
|
||||||
|
fmt.Errorf(msg.ErrHashtagEmpty),
|
||||||
|
msg.ErrHashtagEmpty,
|
||||||
|
"查看被禁用的标签 失败: ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建请求 URL 和查询参数
|
||||||
|
baseURL := fmt.Sprintf("%s/api/hashtags/banned", app.ModuleClients.AryshareClient.Config.Endpoint)
|
||||||
|
u, err := url.Parse(baseURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorParseURL, "查看被禁用的标签 失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
q := u.Query()
|
||||||
|
// Ayrshare 支持传入 "hashtag" 或 "#hashtag",这里直接透传,由底层接口校验
|
||||||
|
q.Set("hashtag", req.Hashtag)
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
fullURL := u.String()
|
||||||
|
|
||||||
|
// 准备请求头
|
||||||
|
headers := make(map[string]string)
|
||||||
|
headers["Authorization"] = fmt.Sprintf("Bearer %s", app.ModuleClients.AryshareClient.Config.ApiKey)
|
||||||
|
if req.ProfileKey != "" {
|
||||||
|
headers["Profile-Key"] = req.ProfileKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发起 HTTP 请求
|
||||||
|
statusCode, result, err := utils.GetWithHeaders(fullURL, headers)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorCheckBannedHashtagsFailed, "查看被禁用的标签失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应(无论成功还是失败,Ayrshare 都会返回 JSON)
|
||||||
|
var bannedResp dto.CheckBannedHashtagResponse
|
||||||
|
if err := json.Unmarshal([]byte(result), &bannedResp); err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorJSONParse, "查看被禁用的标签失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据文档:
|
||||||
|
// - 200:成功,返回 { "hashtag": "...", "banned": true/false }
|
||||||
|
// - 400:参数错误,返回 { "action": "request", "status": "error", "code": 101, "message": "..." }
|
||||||
|
if statusCode != http.StatusOK || bannedResp.Status == "error" {
|
||||||
|
errMsg := bannedResp.Message
|
||||||
|
if errMsg == "" {
|
||||||
|
errMsg = msg.ErrorCheckBannedHashtagsFailed
|
||||||
|
}
|
||||||
|
if bannedResp.Code != 0 {
|
||||||
|
errMsg = fmt.Sprintf("错误代码: %d, %s", bannedResp.Code, errMsg)
|
||||||
|
}
|
||||||
|
return nil, errCommon.ReturnError(
|
||||||
|
fmt.Errorf("接口返回状态码: %d, 错误信息: %s, 响应结果: %s", statusCode, errMsg, result),
|
||||||
|
errMsg,
|
||||||
|
"查看被禁用的标签 失败: ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
errCommon.NoReturnInfo(&bannedResp, "查看被禁用的标签 成功: ")
|
||||||
|
res = &bannedResp
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecommendHashtags 根据关键字推荐热门标签
|
||||||
|
// 文档: https://www.ayrshare.com/docs/apis/hashtags/recommend-hashtags
|
||||||
|
func (a *AyrshareTag) RecommendHashtags(req *dto.RecommendHashtagsRequest) (res *dto.RecommendHashtagsResponse, err error) {
|
||||||
|
errCommon.NoReturnInfo(req, "推荐话题标签 参数信息: ")
|
||||||
|
|
||||||
|
res = new(dto.RecommendHashtagsResponse)
|
||||||
|
|
||||||
|
// 基本参数校验:keyword 不能为空
|
||||||
|
if req.Keyword == "" {
|
||||||
|
return nil, errCommon.ReturnError(
|
||||||
|
fmt.Errorf(msg.ErrKeywordEmpty),
|
||||||
|
msg.ErrKeywordEmpty,
|
||||||
|
"推荐话题标签 失败: ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建请求 URL 和查询参数
|
||||||
|
baseURL := fmt.Sprintf("%s/api/hashtags/recommend", app.ModuleClients.AryshareClient.Config.Endpoint)
|
||||||
|
u, err := url.Parse(baseURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorParseURL, "推荐话题标签 失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
q := u.Query()
|
||||||
|
q.Set("keyword", req.Keyword)
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
fullURL := u.String()
|
||||||
|
|
||||||
|
// 准备请求头
|
||||||
|
headers := make(map[string]string)
|
||||||
|
headers["Authorization"] = fmt.Sprintf("Bearer %s", app.ModuleClients.AryshareClient.Config.ApiKey)
|
||||||
|
if req.ProfileKey != "" {
|
||||||
|
headers["Profile-Key"] = req.ProfileKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发起 HTTP 请求
|
||||||
|
statusCode, result, err := utils.GetWithHeaders(fullURL, headers)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorRecommendHashtagsFailed, "推荐话题标签失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
var recommendResp dto.RecommendHashtagsResponse
|
||||||
|
if err := json.Unmarshal([]byte(result), &recommendResp); err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorJSONParse, "推荐话题标签失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据文档:
|
||||||
|
// - 200:成功,返回 keyword + recommendations
|
||||||
|
// - 400:缺少 keyword,返回错误结构
|
||||||
|
if statusCode != http.StatusOK || recommendResp.Status == "error" {
|
||||||
|
errMsg := recommendResp.Message
|
||||||
|
if errMsg == "" {
|
||||||
|
errMsg = msg.ErrorRecommendHashtagsFailed
|
||||||
|
}
|
||||||
|
if recommendResp.Code != 0 {
|
||||||
|
errMsg = fmt.Sprintf("错误代码: %d, %s", recommendResp.Code, errMsg)
|
||||||
|
}
|
||||||
|
return nil, errCommon.ReturnError(
|
||||||
|
fmt.Errorf("接口返回状态码: %d, 错误信息: %s, 响应结果: %s", statusCode, errMsg, result),
|
||||||
|
errMsg,
|
||||||
|
"推荐话题标签 失败: ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
errCommon.NoReturnInfo(&recommendResp, "推荐话题标签 成功: ")
|
||||||
|
res = &recommendResp
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtags 搜索话题标签并返回相关媒体
|
||||||
|
// 文档: https://www.ayrshare.com/docs/apis/hashtags/search-hashtags
|
||||||
|
func (a *AyrshareTag) SearchHashtags(req *dto.SearchHashtagsRequest) (res *dto.SearchHashtagsResponse, err error) {
|
||||||
|
errCommon.NoReturnInfo(req, "搜索话题标签 参数信息: ")
|
||||||
|
|
||||||
|
res = new(dto.SearchHashtagsResponse)
|
||||||
|
|
||||||
|
// 基本参数校验:keyword 不能为空
|
||||||
|
if req.Keyword == "" {
|
||||||
|
return nil, errCommon.ReturnError(
|
||||||
|
fmt.Errorf(msg.ErrKeywordEmpty),
|
||||||
|
msg.ErrKeywordEmpty,
|
||||||
|
"搜索话题标签 失败: ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建请求 URL 和查询参数
|
||||||
|
baseURL := fmt.Sprintf("%s/api/hashtags/search", app.ModuleClients.AryshareClient.Config.Endpoint)
|
||||||
|
u, err := url.Parse(baseURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorParseURL, "搜索话题标签 失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
q := u.Query()
|
||||||
|
q.Set("keyword", req.Keyword)
|
||||||
|
// searchType 可选,默认 top,这里仅在调用方传入时追加
|
||||||
|
if req.SearchType != "" {
|
||||||
|
q.Set("searchType", req.SearchType)
|
||||||
|
}
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
fullURL := u.String()
|
||||||
|
|
||||||
|
// 准备请求头
|
||||||
|
headers := make(map[string]string)
|
||||||
|
headers["Authorization"] = fmt.Sprintf("Bearer %s", app.ModuleClients.AryshareClient.Config.ApiKey)
|
||||||
|
if req.ProfileKey != "" {
|
||||||
|
headers["Profile-Key"] = req.ProfileKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发起 HTTP 请求
|
||||||
|
statusCode, result, err := utils.GetWithHeaders(fullURL, headers)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorSearchHashtagsFailed, "搜索话题标签失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
var searchResp dto.SearchHashtagsResponse
|
||||||
|
if err := json.Unmarshal([]byte(result), &searchResp); err != nil {
|
||||||
|
return nil, errCommon.ReturnError(err, msg.ErrorJSONParse, "搜索话题标签失败: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据文档:
|
||||||
|
// - 200:成功,返回 status: success + hashtag + searchResults
|
||||||
|
// - 400:Bad Request,返回 status: error + action/code/message
|
||||||
|
if statusCode != http.StatusOK || searchResp.Status == "error" {
|
||||||
|
errMsg := searchResp.Message
|
||||||
|
if errMsg == "" {
|
||||||
|
errMsg = msg.ErrorSearchHashtagsFailed
|
||||||
|
}
|
||||||
|
if searchResp.ErrorCode != 0 {
|
||||||
|
errMsg = fmt.Sprintf("错误代码: %d, %s", searchResp.ErrorCode, errMsg)
|
||||||
|
}
|
||||||
|
return nil, errCommon.ReturnError(
|
||||||
|
fmt.Errorf("接口返回状态码: %d, 错误信息: %s, 响应结果: %s", statusCode, errMsg, result),
|
||||||
|
errMsg,
|
||||||
|
"搜索话题标签 失败: ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
errCommon.NoReturnInfo(&searchResp, "搜索话题标签 成功: ")
|
||||||
|
res = &searchResp
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -816,3 +816,85 @@ func (this *GetSocialAnalyticsRequest) Validate() error {
|
|||||||
func (this *GetSocialAnalyticsResponse) Validate() error {
|
func (this *GetSocialAnalyticsResponse) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (this *AutoHashtagsRequest) Validate() error {
|
||||||
|
if this.Post == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Post", fmt.Errorf(`post内容不能为空`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *AutoHashtagsResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *CheckBannedHashtagRequest) Validate() error {
|
||||||
|
if this.Hashtag == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Hashtag", fmt.Errorf(`hashtag不能为空`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *CheckBannedHashtagResponse) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *HashtagRecommendation) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RecommendHashtagsRequest) Validate() error {
|
||||||
|
if this.Keyword == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Keyword", fmt.Errorf(`keyword不能为空`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *RecommendHashtagsResponse) Validate() error {
|
||||||
|
for _, item := range this.Recommendations {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Recommendations", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *SearchHashtagsRequest) Validate() error {
|
||||||
|
if this.Keyword == "" {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Keyword", fmt.Errorf(`keyword不能为空`))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *SearchHashtagInfo) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *SearchHashtagChild) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *SearchHashtagChildren) Validate() error {
|
||||||
|
for _, item := range this.Data {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *SearchHashtagMedia) Validate() error {
|
||||||
|
if this.Children != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Children); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Children", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (this *SearchHashtagsResponse) Validate() error {
|
||||||
|
if this.Hashtag != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Hashtag); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("Hashtag", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, item := range this.SearchResults {
|
||||||
|
if item != nil {
|
||||||
|
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
|
||||||
|
return github_com_mwitkow_go_proto_validators.FieldError("SearchResults", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@ -53,6 +53,11 @@ type AyrshareClient interface {
|
|||||||
GetPostAnalytics(ctx context.Context, in *GetPostAnalyticsRequest, opts ...grpc_go.CallOption) (*GetPostAnalyticsResponse, common.ErrorWithAttachment)
|
GetPostAnalytics(ctx context.Context, in *GetPostAnalyticsRequest, opts ...grpc_go.CallOption) (*GetPostAnalyticsResponse, common.ErrorWithAttachment)
|
||||||
GetPostAnalyticsBySocialID(ctx context.Context, in *GetPostAnalyticsBySocialIDRequest, opts ...grpc_go.CallOption) (*GetPostAnalyticsResponse, common.ErrorWithAttachment)
|
GetPostAnalyticsBySocialID(ctx context.Context, in *GetPostAnalyticsBySocialIDRequest, opts ...grpc_go.CallOption) (*GetPostAnalyticsResponse, common.ErrorWithAttachment)
|
||||||
GetSocialAnalytics(ctx context.Context, in *GetSocialAnalyticsRequest, opts ...grpc_go.CallOption) (*GetSocialAnalyticsResponse, common.ErrorWithAttachment)
|
GetSocialAnalytics(ctx context.Context, in *GetSocialAnalyticsRequest, opts ...grpc_go.CallOption) (*GetSocialAnalyticsResponse, common.ErrorWithAttachment)
|
||||||
|
// Hashtags 相关 api
|
||||||
|
AutoHashtags(ctx context.Context, in *AutoHashtagsRequest, opts ...grpc_go.CallOption) (*AutoHashtagsResponse, common.ErrorWithAttachment)
|
||||||
|
CheckBannedHashtag(ctx context.Context, in *CheckBannedHashtagRequest, opts ...grpc_go.CallOption) (*CheckBannedHashtagResponse, common.ErrorWithAttachment)
|
||||||
|
RecommendHashtags(ctx context.Context, in *RecommendHashtagsRequest, opts ...grpc_go.CallOption) (*RecommendHashtagsResponse, common.ErrorWithAttachment)
|
||||||
|
SearchHashtags(ctx context.Context, in *SearchHashtagsRequest, opts ...grpc_go.CallOption) (*SearchHashtagsResponse, common.ErrorWithAttachment)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ayrshareClient struct {
|
type ayrshareClient struct {
|
||||||
@ -78,6 +83,10 @@ type AyrshareClientImpl struct {
|
|||||||
GetPostAnalytics func(ctx context.Context, in *GetPostAnalyticsRequest) (*GetPostAnalyticsResponse, error)
|
GetPostAnalytics func(ctx context.Context, in *GetPostAnalyticsRequest) (*GetPostAnalyticsResponse, error)
|
||||||
GetPostAnalyticsBySocialID func(ctx context.Context, in *GetPostAnalyticsBySocialIDRequest) (*GetPostAnalyticsResponse, error)
|
GetPostAnalyticsBySocialID func(ctx context.Context, in *GetPostAnalyticsBySocialIDRequest) (*GetPostAnalyticsResponse, error)
|
||||||
GetSocialAnalytics func(ctx context.Context, in *GetSocialAnalyticsRequest) (*GetSocialAnalyticsResponse, error)
|
GetSocialAnalytics func(ctx context.Context, in *GetSocialAnalyticsRequest) (*GetSocialAnalyticsResponse, error)
|
||||||
|
AutoHashtags func(ctx context.Context, in *AutoHashtagsRequest) (*AutoHashtagsResponse, error)
|
||||||
|
CheckBannedHashtag func(ctx context.Context, in *CheckBannedHashtagRequest) (*CheckBannedHashtagResponse, error)
|
||||||
|
RecommendHashtags func(ctx context.Context, in *RecommendHashtagsRequest) (*RecommendHashtagsResponse, error)
|
||||||
|
SearchHashtags func(ctx context.Context, in *SearchHashtagsRequest) (*SearchHashtagsResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AyrshareClientImpl) GetDubboStub(cc *triple.TripleConn) AyrshareClient {
|
func (c *AyrshareClientImpl) GetDubboStub(cc *triple.TripleConn) AyrshareClient {
|
||||||
@ -200,6 +209,30 @@ func (c *ayrshareClient) GetSocialAnalytics(ctx context.Context, in *GetSocialAn
|
|||||||
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/GetSocialAnalytics", in, out)
|
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/GetSocialAnalytics", in, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ayrshareClient) AutoHashtags(ctx context.Context, in *AutoHashtagsRequest, opts ...grpc_go.CallOption) (*AutoHashtagsResponse, common.ErrorWithAttachment) {
|
||||||
|
out := new(AutoHashtagsResponse)
|
||||||
|
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
|
||||||
|
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/AutoHashtags", in, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ayrshareClient) CheckBannedHashtag(ctx context.Context, in *CheckBannedHashtagRequest, opts ...grpc_go.CallOption) (*CheckBannedHashtagResponse, common.ErrorWithAttachment) {
|
||||||
|
out := new(CheckBannedHashtagResponse)
|
||||||
|
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
|
||||||
|
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/CheckBannedHashtag", in, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ayrshareClient) RecommendHashtags(ctx context.Context, in *RecommendHashtagsRequest, opts ...grpc_go.CallOption) (*RecommendHashtagsResponse, common.ErrorWithAttachment) {
|
||||||
|
out := new(RecommendHashtagsResponse)
|
||||||
|
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
|
||||||
|
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/RecommendHashtags", in, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ayrshareClient) SearchHashtags(ctx context.Context, in *SearchHashtagsRequest, opts ...grpc_go.CallOption) (*SearchHashtagsResponse, common.ErrorWithAttachment) {
|
||||||
|
out := new(SearchHashtagsResponse)
|
||||||
|
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
|
||||||
|
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/SearchHashtags", in, out)
|
||||||
|
}
|
||||||
|
|
||||||
// AyrshareServer is the server API for Ayrshare service.
|
// AyrshareServer is the server API for Ayrshare service.
|
||||||
// All implementations must embed UnimplementedAyrshareServer
|
// All implementations must embed UnimplementedAyrshareServer
|
||||||
// for forward compatibility
|
// for forward compatibility
|
||||||
@ -229,6 +262,11 @@ type AyrshareServer interface {
|
|||||||
GetPostAnalytics(context.Context, *GetPostAnalyticsRequest) (*GetPostAnalyticsResponse, error)
|
GetPostAnalytics(context.Context, *GetPostAnalyticsRequest) (*GetPostAnalyticsResponse, error)
|
||||||
GetPostAnalyticsBySocialID(context.Context, *GetPostAnalyticsBySocialIDRequest) (*GetPostAnalyticsResponse, error)
|
GetPostAnalyticsBySocialID(context.Context, *GetPostAnalyticsBySocialIDRequest) (*GetPostAnalyticsResponse, error)
|
||||||
GetSocialAnalytics(context.Context, *GetSocialAnalyticsRequest) (*GetSocialAnalyticsResponse, error)
|
GetSocialAnalytics(context.Context, *GetSocialAnalyticsRequest) (*GetSocialAnalyticsResponse, error)
|
||||||
|
// Hashtags 相关 api
|
||||||
|
AutoHashtags(context.Context, *AutoHashtagsRequest) (*AutoHashtagsResponse, error)
|
||||||
|
CheckBannedHashtag(context.Context, *CheckBannedHashtagRequest) (*CheckBannedHashtagResponse, error)
|
||||||
|
RecommendHashtags(context.Context, *RecommendHashtagsRequest) (*RecommendHashtagsResponse, error)
|
||||||
|
SearchHashtags(context.Context, *SearchHashtagsRequest) (*SearchHashtagsResponse, error)
|
||||||
mustEmbedUnimplementedAyrshareServer()
|
mustEmbedUnimplementedAyrshareServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,6 +329,18 @@ func (UnimplementedAyrshareServer) GetPostAnalyticsBySocialID(context.Context, *
|
|||||||
func (UnimplementedAyrshareServer) GetSocialAnalytics(context.Context, *GetSocialAnalyticsRequest) (*GetSocialAnalyticsResponse, error) {
|
func (UnimplementedAyrshareServer) GetSocialAnalytics(context.Context, *GetSocialAnalyticsRequest) (*GetSocialAnalyticsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetSocialAnalytics not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetSocialAnalytics not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedAyrshareServer) AutoHashtags(context.Context, *AutoHashtagsRequest) (*AutoHashtagsResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method AutoHashtags not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedAyrshareServer) CheckBannedHashtag(context.Context, *CheckBannedHashtagRequest) (*CheckBannedHashtagResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method CheckBannedHashtag not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedAyrshareServer) RecommendHashtags(context.Context, *RecommendHashtagsRequest) (*RecommendHashtagsResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method RecommendHashtags not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedAyrshareServer) SearchHashtags(context.Context, *SearchHashtagsRequest) (*SearchHashtagsResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method SearchHashtags not implemented")
|
||||||
|
}
|
||||||
func (s *UnimplementedAyrshareServer) XXX_SetProxyImpl(impl protocol.Invoker) {
|
func (s *UnimplementedAyrshareServer) XXX_SetProxyImpl(impl protocol.Invoker) {
|
||||||
s.proxyImpl = impl
|
s.proxyImpl = impl
|
||||||
}
|
}
|
||||||
@ -841,6 +891,122 @@ func _Ayrshare_GetSocialAnalytics_Handler(srv interface{}, ctx context.Context,
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _Ayrshare_AutoHashtags_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(AutoHashtagsRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
base := srv.(dubbo3.Dubbo3GrpcService)
|
||||||
|
args := []interface{}{}
|
||||||
|
args = append(args, in)
|
||||||
|
md, _ := metadata.FromIncomingContext(ctx)
|
||||||
|
invAttachment := make(map[string]interface{}, len(md))
|
||||||
|
for k, v := range md {
|
||||||
|
invAttachment[k] = v
|
||||||
|
}
|
||||||
|
invo := invocation.NewRPCInvocation("AutoHashtags", args, invAttachment)
|
||||||
|
if interceptor == nil {
|
||||||
|
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
|
||||||
|
return result, result.Error()
|
||||||
|
}
|
||||||
|
info := &grpc_go.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
|
||||||
|
return result, result.Error()
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Ayrshare_CheckBannedHashtag_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(CheckBannedHashtagRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
base := srv.(dubbo3.Dubbo3GrpcService)
|
||||||
|
args := []interface{}{}
|
||||||
|
args = append(args, in)
|
||||||
|
md, _ := metadata.FromIncomingContext(ctx)
|
||||||
|
invAttachment := make(map[string]interface{}, len(md))
|
||||||
|
for k, v := range md {
|
||||||
|
invAttachment[k] = v
|
||||||
|
}
|
||||||
|
invo := invocation.NewRPCInvocation("CheckBannedHashtag", args, invAttachment)
|
||||||
|
if interceptor == nil {
|
||||||
|
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
|
||||||
|
return result, result.Error()
|
||||||
|
}
|
||||||
|
info := &grpc_go.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
|
||||||
|
return result, result.Error()
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Ayrshare_RecommendHashtags_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(RecommendHashtagsRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
base := srv.(dubbo3.Dubbo3GrpcService)
|
||||||
|
args := []interface{}{}
|
||||||
|
args = append(args, in)
|
||||||
|
md, _ := metadata.FromIncomingContext(ctx)
|
||||||
|
invAttachment := make(map[string]interface{}, len(md))
|
||||||
|
for k, v := range md {
|
||||||
|
invAttachment[k] = v
|
||||||
|
}
|
||||||
|
invo := invocation.NewRPCInvocation("RecommendHashtags", args, invAttachment)
|
||||||
|
if interceptor == nil {
|
||||||
|
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
|
||||||
|
return result, result.Error()
|
||||||
|
}
|
||||||
|
info := &grpc_go.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
|
||||||
|
return result, result.Error()
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Ayrshare_SearchHashtags_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(SearchHashtagsRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
base := srv.(dubbo3.Dubbo3GrpcService)
|
||||||
|
args := []interface{}{}
|
||||||
|
args = append(args, in)
|
||||||
|
md, _ := metadata.FromIncomingContext(ctx)
|
||||||
|
invAttachment := make(map[string]interface{}, len(md))
|
||||||
|
for k, v := range md {
|
||||||
|
invAttachment[k] = v
|
||||||
|
}
|
||||||
|
invo := invocation.NewRPCInvocation("SearchHashtags", args, invAttachment)
|
||||||
|
if interceptor == nil {
|
||||||
|
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
|
||||||
|
return result, result.Error()
|
||||||
|
}
|
||||||
|
info := &grpc_go.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
|
||||||
|
return result, result.Error()
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
// Ayrshare_ServiceDesc is the grpc_go.ServiceDesc for Ayrshare service.
|
// Ayrshare_ServiceDesc is the grpc_go.ServiceDesc for Ayrshare service.
|
||||||
// It's only intended for direct use with grpc_go.RegisterService,
|
// It's only intended for direct use with grpc_go.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@ -920,6 +1086,22 @@ var Ayrshare_ServiceDesc = grpc_go.ServiceDesc{
|
|||||||
MethodName: "GetSocialAnalytics",
|
MethodName: "GetSocialAnalytics",
|
||||||
Handler: _Ayrshare_GetSocialAnalytics_Handler,
|
Handler: _Ayrshare_GetSocialAnalytics_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "AutoHashtags",
|
||||||
|
Handler: _Ayrshare_AutoHashtags_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "CheckBannedHashtag",
|
||||||
|
Handler: _Ayrshare_CheckBannedHashtag_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "RecommendHashtags",
|
||||||
|
Handler: _Ayrshare_RecommendHashtags_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "SearchHashtags",
|
||||||
|
Handler: _Ayrshare_SearchHashtags_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc_go.StreamDesc{},
|
Streams: []grpc_go.StreamDesc{},
|
||||||
Metadata: "pb/ayrshare.proto",
|
Metadata: "pb/ayrshare.proto",
|
||||||
|
|||||||
@ -38,6 +38,12 @@ service Ayrshare {
|
|||||||
rpc GetPostAnalytics(GetPostAnalyticsRequest) returns (GetPostAnalyticsResponse);
|
rpc GetPostAnalytics(GetPostAnalyticsRequest) returns (GetPostAnalyticsResponse);
|
||||||
rpc GetPostAnalyticsBySocialID(GetPostAnalyticsBySocialIDRequest) returns (GetPostAnalyticsResponse);
|
rpc GetPostAnalyticsBySocialID(GetPostAnalyticsBySocialIDRequest) returns (GetPostAnalyticsResponse);
|
||||||
rpc GetSocialAnalytics(GetSocialAnalyticsRequest) returns (GetSocialAnalyticsResponse);
|
rpc GetSocialAnalytics(GetSocialAnalyticsRequest) returns (GetSocialAnalyticsResponse);
|
||||||
|
|
||||||
|
// Hashtags 相关 api
|
||||||
|
rpc AutoHashtags(AutoHashtagsRequest) returns (AutoHashtagsResponse);
|
||||||
|
rpc CheckBannedHashtag(CheckBannedHashtagRequest) returns (CheckBannedHashtagResponse);
|
||||||
|
rpc RecommendHashtags(RecommendHashtagsRequest) returns (RecommendHashtagsResponse);
|
||||||
|
rpc SearchHashtags(SearchHashtagsRequest) returns (SearchHashtagsResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instagram 用户标签(带坐标)
|
// Instagram 用户标签(带坐标)
|
||||||
@ -1106,3 +1112,110 @@ message GetSocialAnalyticsResponse {
|
|||||||
string twitter = 12 [json_name = "twitter"];
|
string twitter = 12 [json_name = "twitter"];
|
||||||
string youtube = 13 [json_name = "youtube"];
|
string youtube = 13 [json_name = "youtube"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== Hashtags 相关消息定义 ==========
|
||||||
|
|
||||||
|
// AutoHashtagsRequest 自动生成标签请求参数
|
||||||
|
message AutoHashtagsRequest {
|
||||||
|
string post = 1 [json_name = "post", (validator.field) = {string_not_empty: true, human_error: "post内容不能为空"}];
|
||||||
|
int32 max = 2 [json_name = "max"];
|
||||||
|
string position = 3 [json_name = "position"];
|
||||||
|
string language = 4 [json_name = "language"];
|
||||||
|
string profileKey = 5 [json_name = "profileKey"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoHashtagsResponse 自动生成标签返回结果
|
||||||
|
message AutoHashtagsResponse {
|
||||||
|
string post = 1 [json_name = "post"];
|
||||||
|
string action = 2 [json_name = "action"];
|
||||||
|
string status = 3 [json_name = "status"];
|
||||||
|
int32 code = 4 [json_name = "code"];
|
||||||
|
string message = 5 [json_name = "message"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckBannedHashtagRequest 查看被禁用标签请求
|
||||||
|
message CheckBannedHashtagRequest {
|
||||||
|
string hashtag = 1 [json_name = "hashtag", (validator.field) = {string_not_empty: true, human_error: "hashtag不能为空"}];
|
||||||
|
string profileKey = 2 [json_name = "profileKey"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckBannedHashtagResponse 查看被禁用标签返回结果
|
||||||
|
message CheckBannedHashtagResponse {
|
||||||
|
string hashtag = 1 [json_name = "hashtag"];
|
||||||
|
bool banned = 2 [json_name = "banned"];
|
||||||
|
string action = 3 [json_name = "action"];
|
||||||
|
string status = 4 [json_name = "status"];
|
||||||
|
int32 code = 5 [json_name = "code"];
|
||||||
|
string message = 6 [json_name = "message"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashtagRecommendation 单条推荐标签信息
|
||||||
|
message HashtagRecommendation {
|
||||||
|
int64 viewCount = 1 [json_name = "viewCount"];
|
||||||
|
string name = 2 [json_name = "name"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecommendHashtagsRequest 推荐话题标签请求
|
||||||
|
message RecommendHashtagsRequest {
|
||||||
|
string keyword = 1 [json_name = "keyword", (validator.field) = {string_not_empty: true, human_error: "keyword不能为空"}];
|
||||||
|
string profileKey = 2 [json_name = "profileKey"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecommendHashtagsResponse 推荐话题标签返回结果
|
||||||
|
message RecommendHashtagsResponse {
|
||||||
|
string keyword = 1 [json_name = "keyword"];
|
||||||
|
repeated HashtagRecommendation recommendations = 2 [json_name = "recommendations"];
|
||||||
|
string action = 3 [json_name = "action"];
|
||||||
|
string status = 4 [json_name = "status"];
|
||||||
|
int32 code = 5 [json_name = "code"];
|
||||||
|
string message = 6 [json_name = "message"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagsRequest 搜索话题标签请求
|
||||||
|
message SearchHashtagsRequest {
|
||||||
|
string keyword = 1 [json_name = "keyword", (validator.field) = {string_not_empty: true, human_error: "keyword不能为空"}];
|
||||||
|
string searchType = 2 [json_name = "searchType"];
|
||||||
|
string profileKey = 3 [json_name = "profileKey"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagInfo 单个话题标签的基本信息
|
||||||
|
message SearchHashtagInfo {
|
||||||
|
string id = 1 [json_name = "id"];
|
||||||
|
string name = 2 [json_name = "name"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagChild 搜索结果中 children.data 的元素
|
||||||
|
message SearchHashtagChild {
|
||||||
|
string id = 1 [json_name = "id"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagChildren 搜索结果中的 children 对象
|
||||||
|
message SearchHashtagChildren {
|
||||||
|
repeated SearchHashtagChild data = 1 [json_name = "data"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagMedia 搜索结果中的单条 Instagram 媒体信息
|
||||||
|
message SearchHashtagMedia {
|
||||||
|
string caption = 1 [json_name = "caption"];
|
||||||
|
SearchHashtagChildren children = 2 [json_name = "children"];
|
||||||
|
int32 commentsCount = 3 [json_name = "commentsCount"];
|
||||||
|
string id = 4 [json_name = "id"];
|
||||||
|
int32 likeCount = 5 [json_name = "likeCount"];
|
||||||
|
string mediaType = 6 [json_name = "mediaType"];
|
||||||
|
string mediaUrl = 7 [json_name = "mediaUrl"];
|
||||||
|
string permalink = 8 [json_name = "permalink"];
|
||||||
|
string timestamp = 9 [json_name = "timestamp"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchHashtagsResponse 搜索话题标签响应
|
||||||
|
message SearchHashtagsResponse {
|
||||||
|
string status = 1 [json_name = "status"];
|
||||||
|
SearchHashtagInfo hashtag = 2 [json_name = "hashtag"];
|
||||||
|
repeated SearchHashtagMedia searchResults = 3 [json_name = "searchResults"];
|
||||||
|
int32 count = 4 [json_name = "count"];
|
||||||
|
string lastUpdated = 5 [json_name = "lastUpdated"];
|
||||||
|
string nextUpdate = 6 [json_name = "nextUpdate"];
|
||||||
|
string action = 7 [json_name = "action"];
|
||||||
|
int32 code = 8 [json_name = "code"];
|
||||||
|
string message = 9 [json_name = "message"];
|
||||||
|
}
|
||||||
|
|||||||
12
pkg/msg/tag_msg.go
Normal file
12
pkg/msg/tag_msg.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package msg
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Hashtags 相关错误消息
|
||||||
|
ErrorAutoHashtagsFailed = "自动生成标签失败"
|
||||||
|
ErrorCheckBannedHashtagsFailed = "查看被禁用的标签失败"
|
||||||
|
ErrorRecommendHashtagsFailed = "推荐话题标签失败"
|
||||||
|
ErrorSearchHashtagsFailed = "搜索话题标签失败"
|
||||||
|
|
||||||
|
ErrHashtagEmpty = "hashtag不能为空"
|
||||||
|
ErrKeywordEmpty = "keyword不能为空"
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue
Block a user