You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
6.8 KiB
255 lines
6.8 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"encoding/json" |
|
"go-common/app/interface/bbq/app-bbq/api/http/v1" |
|
topic "go-common/app/service/bbq/topic/api" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
"net/http" |
|
"net/url" |
|
) |
|
|
|
func (s *Service) getExtension(ctx context.Context, svids []int64) (res map[int64]*topic.VideoExtension, err error) { |
|
res = make(map[int64]*topic.VideoExtension, len(svids)) |
|
// 0. check |
|
|
|
// 1. get extension |
|
req := &topic.ListExtensionReq{Svids: svids} |
|
reply, err := s.topicClient.ListExtension(ctx, req) |
|
if err != nil { |
|
log.Warnw(ctx, "log", "get extension fail") |
|
return |
|
} |
|
|
|
// 2. form extension |
|
for _, extension := range reply.List { |
|
res[extension.Svid] = extension |
|
} |
|
return |
|
} |
|
|
|
// TopicDetail 获取话题详情 |
|
func (s *Service) TopicDetail(ctx context.Context, mid int64, req *topic.TopicVideosReq) (res *v1.TopicDetail, err error) { |
|
res = new(v1.TopicDetail) |
|
// 0. check |
|
if req.TopicId == 0 { |
|
err = ecode.TopicReqParamErr |
|
log.Warnw(ctx, "log", "topic id is 0") |
|
return |
|
} |
|
|
|
// 1. 获取话题信息及话题内视频 |
|
topicDetails, err := s.topicClient.ListTopicVideos(ctx, req) |
|
if err != nil { |
|
log.Errorw(ctx, "log", "get list topic videos fail") |
|
return |
|
} |
|
|
|
// 2. 获取视频详情 |
|
// 2.0 获取视频id |
|
var svids []int64 |
|
topicVideoMap := make(map[int64]*topic.VideoItem) |
|
for _, item := range topicDetails.List { |
|
if _, exists := topicVideoMap[item.Svid]; !exists { |
|
topicVideoMap[item.Svid] = item |
|
svids = append(svids, item.Svid) |
|
} |
|
} |
|
// 2.1 获取详情 |
|
svInfos, err := s.svInfos(ctx, svids, mid, false) |
|
if err != nil { |
|
log.Warnw(ctx, "log", "get sv infos fail", "svid", svids) |
|
return |
|
} |
|
|
|
// 3. 组装回包 |
|
res.TopicInfo = topicDetails.TopicInfo |
|
res.HasMore = topicDetails.HasMore |
|
for _, item := range topicDetails.List { |
|
var topicVideo *v1.TopicVideo |
|
if svInfo, exists := svInfos[item.Svid]; !exists { |
|
log.Errorw(ctx, "log", "cannot find topicVideo response in topic detail", "svid", item.Svid) |
|
continue |
|
} else { |
|
topicVideo = new(v1.TopicVideo) |
|
topicVideo.VideoResponse = svInfo |
|
} |
|
topicVideo.CursorValue = item.CursorValue |
|
topicVideo.HotType = item.HotType |
|
res.List = append(res.List, topicVideo) |
|
} |
|
|
|
return |
|
} |
|
|
|
func (s *Service) getDiscoveryData(ctx context.Context, uri string) (data []byte, err error) { |
|
var ret struct { |
|
Code int `json:"code"` |
|
Msg string `json:"message"` |
|
Data json.RawMessage `json:"data"` |
|
} |
|
|
|
req, err := s.httpClient.NewRequest(http.MethodGet, uri, "", url.Values{}) |
|
if err != nil { |
|
log.Errorw(ctx, "log", "http.NewRequest error", "err", err) |
|
return |
|
} |
|
if err = s.httpClient.Do(ctx, req, &ret); err != nil { |
|
log.Errorw(ctx, "log", "client Do error", "err", err) |
|
return |
|
} |
|
if ret.Code != 0 { |
|
log.Errorw(ctx, "log", "return code error", "code", ret.Code) |
|
return |
|
} |
|
data = ret.Data |
|
return |
|
} |
|
|
|
func (s *Service) getHotWords(ctx context.Context) (list []string, err error) { |
|
list = make([]string, 0, 1) |
|
|
|
data, err := s.getDiscoveryData(ctx, "http://bbq-mng.bilibili.co/bbq/cms/hotword/api") |
|
if err != nil { |
|
log.Warnw(ctx, "log", "get discovery data fail") |
|
return |
|
} |
|
|
|
var hotWordResponse struct { |
|
OnshelfList []string `json:"onshelf_list"` |
|
} |
|
err = json.Unmarshal(data, &hotWordResponse) |
|
if err != nil { |
|
log.Errorw(ctx, "log", "unmarshal hot word response fail", "data", string(data)) |
|
return |
|
} |
|
list = hotWordResponse.OnshelfList |
|
if list == nil { |
|
list = make([]string, 0, 1) |
|
} |
|
return |
|
} |
|
|
|
func (s *Service) getBanner(ctx context.Context) (list []*v1.Banner, err error) { |
|
list = make([]*v1.Banner, 0, 1) |
|
|
|
data, err := s.getDiscoveryData(ctx, "http://bbq-mng.bilibili.co/bbq/cms/banner/api") |
|
if err != nil { |
|
log.Warnw(ctx, "log", "get discovery data fail") |
|
return |
|
} |
|
|
|
type httpBanner struct { |
|
Title string `json:"title"` |
|
ImgUrl string `json:"img_url"` |
|
JumpUrl string `json:"jump_url"` |
|
} |
|
var bannerResponse struct { |
|
BannerList []*httpBanner `json:"banner_list"` |
|
} |
|
bannerResponse.BannerList = make([]*httpBanner, 0) |
|
err = json.Unmarshal(data, &bannerResponse) |
|
if err != nil { |
|
log.Errorw(ctx, "log", "unmarshal hot word response fail", "data", string(data)) |
|
return |
|
} |
|
|
|
for _, item := range bannerResponse.BannerList { |
|
banner := new(v1.Banner) |
|
banner.Name = item.Title |
|
banner.PIC = item.ImgUrl |
|
banner.Scheme = item.JumpUrl |
|
list = append(list, banner) |
|
} |
|
|
|
if list == nil { |
|
list = make([]*v1.Banner, 0, 1) |
|
} |
|
return |
|
} |
|
|
|
// Discovery 发现页 |
|
func (s *Service) Discovery(ctx context.Context, mid int64, req *v1.DiscoveryReq) (res *v1.DiscoveryRes, err error) { |
|
res = new(v1.DiscoveryRes) |
|
res.BannerList = make([]*v1.Banner, 0, 10) |
|
res.HotWords = make([]string, 0, 10) |
|
res.TopicList = make([]*v1.TopicDetail, 0, 10) |
|
res.HasMore = false |
|
// check |
|
|
|
// 1. 条件判断 |
|
if req.Page == 1 { |
|
// 请求热词 |
|
if res.HotWords, err = s.getHotWords(ctx); err != nil { |
|
log.Warnw(ctx, "log", "get hot words fail", "err", err) |
|
} |
|
// 请求banner |
|
if res.BannerList, err = s.getBanner(ctx); err != nil { |
|
log.Warnw(ctx, "log", "get banner fail", "err", err) |
|
} |
|
} |
|
|
|
// 2. 请求话题详情 |
|
reply, err := s.topicClient.ListDiscoveryTopics(ctx, &topic.ListDiscoveryTopicReq{Page: req.Page}) |
|
if err != nil { |
|
log.Errorw(ctx, "log", "get discovery topics list fail") |
|
return |
|
} |
|
// 2.1 收集svid |
|
var svids []int64 |
|
for _, topicDetail := range reply.List { |
|
for _, videoItem := range topicDetail.List { |
|
svids = append(svids, videoItem.Svid) |
|
} |
|
} |
|
// 2.2 获取视频详情 |
|
svInfos, err := s.svInfos(ctx, svids, mid, false) |
|
if err != nil { |
|
log.Warnw(ctx, "log", "get sv infos fail", "svids", svids) |
|
return |
|
} |
|
|
|
// 3. 组装回包 |
|
res.HasMore = reply.HasMore |
|
for _, topicDetail := range reply.List { |
|
newTopicDetail := new(v1.TopicDetail) |
|
newTopicDetail.TopicInfo = topicDetail.TopicInfo |
|
newTopicDetail.HasMore = topicDetail.HasMore |
|
for _, videoItem := range topicDetail.List { |
|
if val, exists := svInfos[videoItem.Svid]; exists { |
|
topicVideo := &v1.TopicVideo{CursorValue: videoItem.CursorValue, VideoResponse: val} |
|
newTopicDetail.List = append(newTopicDetail.List, topicVideo) |
|
} else { |
|
log.Warnw(ctx, "log", "get sv info fail", "svid", videoItem.Svid) |
|
} |
|
} |
|
if len(newTopicDetail.List) == 0 { |
|
log.Warnw(ctx, "log", "topic has nothing", "topic", topicDetail) |
|
continue |
|
} |
|
res.TopicList = append(res.TopicList, newTopicDetail) |
|
} |
|
|
|
return |
|
} |
|
|
|
// TopicSearch 话题搜索 |
|
func (s *Service) TopicSearch(ctx context.Context, req *v1.TopicSearchReq) (res *v1.TopicSearchResponse, err error) { |
|
res = new(v1.TopicSearchResponse) |
|
|
|
if len(req.Keyword) == 0 { |
|
var reply *topic.ListTopicsReply |
|
reply, err = s.topicClient.ListTopics(ctx, &topic.ListTopicsReq{Page: 1}) |
|
if err != nil { |
|
log.Warnw(ctx, "log", "get topic list fail", "err", err) |
|
return |
|
} |
|
res.List = reply.List |
|
res.HasMore = reply.HasMore |
|
} |
|
res.HasMore = false |
|
|
|
return |
|
}
|
|
|