Create & Init Project...
This commit is contained in:
97
app/interface/live/app-interface/service/v2/BUILD
Normal file
97
app/interface/live/app-interface/service/v2/BUILD
Normal file
@ -0,0 +1,97 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"activity_card.go",
|
||||
"apprelationfilterstrategy.go",
|
||||
"apprelationsortstrategy.go",
|
||||
"common.go",
|
||||
"daowrapper.go",
|
||||
"index.go",
|
||||
"live_rec.go",
|
||||
"live_user.go",
|
||||
"livehomepage.go",
|
||||
"pic_list.go",
|
||||
"rank.go",
|
||||
"rec_pool.go",
|
||||
"room_ex.go",
|
||||
"room_list.go",
|
||||
"sky_horse.go",
|
||||
"tools.go",
|
||||
],
|
||||
importpath = "go-common/app/interface/live/app-interface/service/v2",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/interface/live/app-interface/api/http/v1:go_default_library",
|
||||
"//app/interface/live/app-interface/api/http/v2:go_default_library",
|
||||
"//app/interface/live/app-interface/conf:go_default_library",
|
||||
"//app/interface/live/app-interface/dao:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/account:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/av:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/fans_medal:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/live_data:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/live_user:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/rankdb:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/relation:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/room:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/room_ex:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/user_ext:go_default_library",
|
||||
"//app/interface/live/app-interface/dao/xuser:go_default_library",
|
||||
"//app/interface/live/app-interface/model:go_default_library",
|
||||
"//app/interface/live/app-interface/service/v1:go_default_library",
|
||||
"//app/interface/live/app-interface/service/v1/relation:go_default_library",
|
||||
"//app/service/live/av/api/liverpc/v1:go_default_library",
|
||||
"//app/service/live/fans_medal/api/liverpc/v1:go_default_library",
|
||||
"//app/service/live/live_data/api/liverpc/v1:go_default_library",
|
||||
"//app/service/live/live_user/api/liverpc/v1:go_default_library",
|
||||
"//app/service/live/recommend/api/grpc/v1:go_default_library",
|
||||
"//app/service/live/relation/api/liverpc/v1:go_default_library",
|
||||
"//app/service/live/room/api/liverpc/v1:go_default_library",
|
||||
"//app/service/live/room/api/liverpc/v2:go_default_library",
|
||||
"//app/service/live/room_ex/api/liverpc/v1:go_default_library",
|
||||
"//app/service/live/third_api/bvc:go_default_library",
|
||||
"//app/service/live/userext/api/liverpc/v1:go_default_library",
|
||||
"//app/service/live/xroom-feed/api:go_default_library",
|
||||
"//app/service/live/xuser/api/grpc/v1:go_default_library",
|
||||
"//app/service/main/account/api:go_default_library",
|
||||
"//app/service/main/account/model:go_default_library",
|
||||
"//app/service/main/account/rpc/client:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/metadata:go_default_library",
|
||||
"//library/sync/errgroup:go_default_library",
|
||||
"//library/xstr:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["room_list_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//app/interface/live/app-interface/conf:go_default_library"],
|
||||
)
|
76
app/interface/live/app-interface/service/v2/activity_card.go
Normal file
76
app/interface/live/app-interface/service/v2/activity_card.go
Normal file
@ -0,0 +1,76 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
)
|
||||
|
||||
// getActivityCard 活动模块
|
||||
func (s *IndexService) getActivityCard(ctx context.Context) (resp []*v2pb.MActivityCard) {
|
||||
resp = []*v2pb.MActivityCard{}
|
||||
ids := s.getIdsFromModuleMap(ctx, []int64{_activityType})
|
||||
if len(ids) <= 0 {
|
||||
return
|
||||
}
|
||||
err, activityCardMap := s.roomDao.GetActivityCard(ctx, ids, "GetAllList")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
listMap := make(map[int64][]*v2pb.ActivityCardItem)
|
||||
for i, ac := range activityCardMap {
|
||||
respAc := &v2pb.ActivityCardItem{Room: []*v2pb.RoomCardItem{}, Av: []*v2pb.AvCardItem{}}
|
||||
respAc.Card = &v2pb.BannerCardItem{
|
||||
Aid: ac.Card.Aid,
|
||||
Pic: ac.Card.Pic,
|
||||
Title: ac.Card.Title,
|
||||
Text: ac.Card.Text,
|
||||
PicLink: ac.Card.PicLink,
|
||||
GoLink: ac.Card.GoLink,
|
||||
ButtonText: ac.Card.ButtonText,
|
||||
Status: ac.Card.Status,
|
||||
Sort: ac.Card.Sort,
|
||||
}
|
||||
if len(ac.Room) > 0 {
|
||||
for _, room := range ac.Room {
|
||||
roomCard := &v2pb.RoomCardItem{
|
||||
IsLive: room.IsLive,
|
||||
RoomId: room.Roomid,
|
||||
Title: room.Title,
|
||||
UName: room.Uname,
|
||||
Online: room.Online,
|
||||
Cover: room.Cover,
|
||||
AreaV2ParentId: room.AreaV2ParentId,
|
||||
AreaV2Id: room.AreaV2Id,
|
||||
Sort: room.Sort,
|
||||
}
|
||||
respAc.Room = append(respAc.Room, roomCard)
|
||||
}
|
||||
}
|
||||
if len(ac.Av) > 0 {
|
||||
for _, av := range ac.Av {
|
||||
avCard := &v2pb.AvCardItem{
|
||||
Avid: av.Avid,
|
||||
Title: av.Title,
|
||||
ViewCount: av.ViewCount,
|
||||
DanMaKu: av.Danmaku,
|
||||
Duration: av.Duration,
|
||||
Cover: av.Cover,
|
||||
Sort: av.Sort,
|
||||
}
|
||||
respAc.Av = append(respAc.Av, avCard)
|
||||
}
|
||||
}
|
||||
listMap[i] = append(listMap[i], respAc)
|
||||
}
|
||||
moduleInfoMap := s.getAllModuleInfoMap(ctx)
|
||||
for _, m := range moduleInfoMap[_activityType] {
|
||||
if l, ok := listMap[m.Id]; ok {
|
||||
resp = append(resp, &v2pb.MActivityCard{
|
||||
ModuleInfo: m,
|
||||
List: l,
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
v1pb "go-common/app/interface/live/app-interface/api/http/v1"
|
||||
fansMedalV1 "go-common/app/service/live/fans_medal/api/liverpc/v1"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// const (
|
||||
// // AppFilterDefault implementation
|
||||
// // 默认排序
|
||||
// AppFilterDefault = 0
|
||||
// // AppFilterFansMedal implementation
|
||||
// // 只看我有粉丝勋章的
|
||||
// AppFilterFansMedal = 1
|
||||
// // AppFilterGoldType implementation
|
||||
// // 按照金瓜子排序
|
||||
// AppFilterGoldType = 2
|
||||
// )
|
||||
|
||||
// AppFilterRuleFansMedal implementation
|
||||
// [app端关注二级页]过滤粉丝勋章
|
||||
func (s *IndexService) AppFilterRuleFansMedal(ctx context.Context, originResult *v1pb.LiveAnchorResp, targetUIDs []int64) (resp []*v1pb.LiveAnchorResp_Rooms, err error) {
|
||||
uid := GetUIDFromHeader(ctx)
|
||||
resp = make([]*v1pb.LiveAnchorResp_Rooms, 0)
|
||||
if originResult == nil || len(originResult.Rooms) == 0 {
|
||||
return
|
||||
}
|
||||
fansParams := &fansMedalV1.FansMedalTargetsWithMedalReq{Uid: uid, TargetIds: targetUIDs}
|
||||
hasMedalUIDs, err := s.GetFansMedal(ctx, fansParams)
|
||||
if err != nil {
|
||||
log.Error("[LiveAnchor][FilterType]get_FansMedal_rpc_error")
|
||||
resp = originResult.Rooms
|
||||
return
|
||||
}
|
||||
for _, v := range originResult.Rooms {
|
||||
if _, exist := hasMedalUIDs[v.Uid]; exist {
|
||||
resp = append(resp, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AppFilterGold implementation
|
||||
// [app端关注二级页]过滤送礼
|
||||
func (s *IndexService) AppFilterGold(ctx context.Context, originResult *v1pb.LiveAnchorResp) (resp []*v1pb.LiveAnchorResp_Rooms, err error) {
|
||||
giftInfo, err := GetGiftInfo(ctx)
|
||||
resp = make([]*v1pb.LiveAnchorResp_Rooms, 0)
|
||||
if originResult == nil || len(originResult.Rooms) == 0 {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("[LiveAnchor][FilterType]get_RelationGift_rpc_error")
|
||||
resp = originResult.Rooms
|
||||
return
|
||||
}
|
||||
for _, v := range originResult.Rooms {
|
||||
if _, exist := giftInfo[v.Uid]; exist {
|
||||
resp = append(resp, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
@ -0,0 +1,229 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
"go-common/library/log"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// const (
|
||||
// // AppSortDefaultT ...
|
||||
// // 默认排序
|
||||
// AppSortDefaultT = 0
|
||||
// // AppSortRuleLiveTimeT ...
|
||||
// // 开播时间倒序
|
||||
// AppSortRuleLiveTimeT = 1
|
||||
// // AppSortRuleOnlineT ...
|
||||
// // 人气值倒序
|
||||
// AppSortRuleOnlineT = 2
|
||||
// // AppSortRuleGoldT ...
|
||||
// // 金瓜子倒序
|
||||
// AppSortRuleGoldT = 3
|
||||
// )
|
||||
|
||||
// SendGift ...
|
||||
// [app端关注二级页]按照金瓜子排序结构
|
||||
type SendGift struct {
|
||||
Mid int64
|
||||
gold int64
|
||||
}
|
||||
|
||||
// SortLiveTime ... implementation
|
||||
// [app端关注二级页]按照开播时间排序
|
||||
type SortLiveTime []*v2pb.MyIdolItem
|
||||
|
||||
// SortOnlineTime ... implementation
|
||||
// [app端关注二级页]按照房间人气值排序
|
||||
type SortOnlineTime []*v2pb.MyIdolItem
|
||||
|
||||
// SortUIDGift ... implementation
|
||||
// [app端关注二级页]按照送礼排序
|
||||
type SortUIDGift []SendGift
|
||||
|
||||
// AppSortRuleLiveTime implementation
|
||||
// [app端关注二级页]按照开播时间排序
|
||||
func (p SortLiveTime) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
// AppSortRuleLiveTime implementation
|
||||
// [app端关注二级页]按照开播时间排序
|
||||
func (p SortLiveTime) Len() int { return len(p) }
|
||||
|
||||
// AppSortRuleLiveTime implementation
|
||||
// [app端关注二级页]按照开播时间排序
|
||||
func (p SortLiveTime) Less(i, j int) bool { return p[i].LiveTime > p[j].LiveTime }
|
||||
|
||||
// AppSortRuleLiveTime implementation
|
||||
// [app端关注二级页]按照开播时间排序
|
||||
func (p SortOnlineTime) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
// AppSortRuleLiveTime implementation
|
||||
// [app端关注二级页]按照开播时间排序
|
||||
func (p SortOnlineTime) Len() int { return len(p) }
|
||||
|
||||
// AppSortRuleLiveTime implementation
|
||||
// [app端关注二级页]按照开播时间排序
|
||||
func (p SortOnlineTime) Less(i, j int) bool { return p[i].Online > p[j].Online }
|
||||
|
||||
// Swap
|
||||
// [app端关注二级页]自定义排序结构
|
||||
func (p SortUIDGift) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
// Len
|
||||
// [app端关注二级页]自定义排序结构
|
||||
func (p SortUIDGift) Len() int { return len(p) }
|
||||
|
||||
// Less
|
||||
// [app端关注二级页]自定义排序结构
|
||||
func (p SortUIDGift) Less(i, j int) bool { return p[i].gold > p[j].gold }
|
||||
|
||||
// AppSortRuleLiveTime implementation
|
||||
// [app端关注二级页]按照开播时间排序
|
||||
func (s *IndexService) AppSortRuleLiveTime(originResult []*v2pb.MyIdolItem) (resp []*v2pb.MyIdolItem) {
|
||||
resp = make([]*v2pb.MyIdolItem, 0)
|
||||
if originResult == nil {
|
||||
return
|
||||
}
|
||||
p := make(SortLiveTime, len(originResult))
|
||||
i := 0
|
||||
for _, v := range originResult {
|
||||
p[i] = &v2pb.MyIdolItem{
|
||||
Roomid: v.Roomid,
|
||||
Uid: v.Uid,
|
||||
Uname: v.Uname,
|
||||
Face: v.Face,
|
||||
Title: v.Title,
|
||||
LiveTagName: v.LiveTagName,
|
||||
LiveTime: v.LiveTime,
|
||||
Online: v.Online,
|
||||
PlayUrl: v.PlayUrl,
|
||||
AcceptQuality: v.AcceptQuality,
|
||||
CurrentQuality: v.CurrentQuality,
|
||||
PkId: v.PkId,
|
||||
SpecialAttention: v.SpecialAttention,
|
||||
Area: v.Area,
|
||||
AreaName: v.AreaName,
|
||||
AreaV2Id: v.AreaV2Id,
|
||||
AreaV2Name: v.AreaV2Name,
|
||||
AreaV2ParentName: v.AreaV2ParentName,
|
||||
AreaV2ParentId: v.AreaV2ParentId,
|
||||
BroadcastType: v.BroadcastType,
|
||||
OfficialVerify: v.OfficialVerify,
|
||||
Link: v.Link,
|
||||
Cover: v.Cover,
|
||||
PendentRu: v.PendentRu,
|
||||
PendentRuColor: v.PendentRuColor,
|
||||
PendentRuPic: v.PendentRuPic}
|
||||
i++
|
||||
}
|
||||
sort.Sort(p)
|
||||
resp = p
|
||||
return
|
||||
}
|
||||
|
||||
// AppSortRuleOnline implementation
|
||||
// [app端关注二级页]按照人气值排序
|
||||
func AppSortRuleOnline(originResult []*v2pb.MyIdolItem) (resp []*v2pb.MyIdolItem) {
|
||||
resp = make([]*v2pb.MyIdolItem, 0)
|
||||
if originResult == nil {
|
||||
return
|
||||
}
|
||||
p := make(SortOnlineTime, len(originResult))
|
||||
i := 0
|
||||
for _, v := range originResult {
|
||||
p[i] = &v2pb.MyIdolItem{
|
||||
Roomid: v.Roomid,
|
||||
Uid: v.Uid,
|
||||
Uname: v.Uname,
|
||||
Face: v.Face,
|
||||
Title: v.Title,
|
||||
LiveTagName: v.LiveTagName,
|
||||
LiveTime: v.LiveTime,
|
||||
Online: v.Online,
|
||||
PlayUrl: v.PlayUrl,
|
||||
AcceptQuality: v.AcceptQuality,
|
||||
CurrentQuality: v.CurrentQuality,
|
||||
PkId: v.PkId,
|
||||
SpecialAttention: v.SpecialAttention,
|
||||
Area: v.Area,
|
||||
AreaName: v.AreaName,
|
||||
AreaV2Id: v.AreaV2Id,
|
||||
AreaV2Name: v.AreaV2Name,
|
||||
AreaV2ParentName: v.AreaV2ParentName,
|
||||
AreaV2ParentId: v.AreaV2ParentId,
|
||||
BroadcastType: v.BroadcastType,
|
||||
OfficialVerify: v.OfficialVerify,
|
||||
Link: v.Link,
|
||||
Cover: v.Cover,
|
||||
PendentRu: v.PendentRu,
|
||||
PlayUrlH265: v.PlayUrlH265,
|
||||
PendentRuColor: v.PendentRuColor,
|
||||
PendentRuPic: v.PendentRuPic}
|
||||
i++
|
||||
}
|
||||
sort.Sort(p)
|
||||
resp = p
|
||||
return
|
||||
}
|
||||
|
||||
// AppSortRuleGold implementation
|
||||
// [app端关注二级页]按照送礼排序
|
||||
func (s *IndexService) AppSortRuleGold(ctx context.Context, originResult *v2pb.MMyIdol) (resp []*v2pb.MyIdolItem) {
|
||||
resp = make([]*v2pb.MyIdolItem, 0)
|
||||
if originResult == nil {
|
||||
return
|
||||
}
|
||||
|
||||
giftInfo, err := GetGiftInfo(ctx)
|
||||
if err != nil {
|
||||
log.Error("[LiveAnchor][FilterType][AppSortRuleGold]get_RelationGift_rpc_error")
|
||||
resp = originResult.List
|
||||
return
|
||||
}
|
||||
if len(giftInfo) == 0 {
|
||||
resp = AppSortRuleOnline(originResult.List)
|
||||
return
|
||||
}
|
||||
|
||||
respHasGold := make([]*v2pb.MyIdolItem, 0)
|
||||
respNoGold := make([]*v2pb.MyIdolItem, 0)
|
||||
GiftRank := make(map[int64]int64)
|
||||
GiftNoGold := make([]int64, 0)
|
||||
// 计算金瓜子排行榜,uid分key
|
||||
for _, v := range originResult.List {
|
||||
roomUID := v.Uid
|
||||
if _, exist := giftInfo[roomUID]; exist {
|
||||
GiftRank[roomUID] += giftInfo[roomUID]
|
||||
}
|
||||
}
|
||||
sorted := SortMap(GiftRank)
|
||||
|
||||
// 没有送礼的用户
|
||||
for _, v := range originResult.List {
|
||||
if _, exist := GiftRank[v.Uid]; !exist {
|
||||
GiftNoGold = append(GiftNoGold, v.Uid)
|
||||
}
|
||||
}
|
||||
|
||||
for _, vv := range sorted {
|
||||
for _, v := range originResult.List {
|
||||
if v.Uid == vv.Key {
|
||||
respHasGold = append(respHasGold, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range originResult.List {
|
||||
for _, vv := range GiftNoGold {
|
||||
if v.Uid == vv {
|
||||
respNoGold = append(respNoGold, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
tempLiveAnchor := &v2pb.MMyIdol{}
|
||||
tempLiveAnchor.List = respNoGold
|
||||
respNoGoldSorted := AppSortRuleOnline(tempLiveAnchor.List)
|
||||
resp = append(resp, respHasGold...)
|
||||
resp = append(resp, respNoGoldSorted...)
|
||||
return
|
||||
}
|
235
app/interface/live/app-interface/service/v2/common.go
Normal file
235
app/interface/live/app-interface/service/v2/common.go
Normal file
@ -0,0 +1,235 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/interface/live/app-interface/dao"
|
||||
"go-common/app/interface/live/app-interface/model"
|
||||
"go-common/app/service/main/account/api"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
"go-common/app/interface/live/app-interface/conf"
|
||||
roomV1 "go-common/app/service/live/room/api/liverpc/v1"
|
||||
roomV2 "go-common/app/service/live/room/api/liverpc/v2"
|
||||
"go-common/library/log"
|
||||
"go-common/library/sync/errgroup"
|
||||
)
|
||||
|
||||
// 统一cover获取方式
|
||||
func (s *IndexService) getCover(userCover string, systemCover string) (cover string) {
|
||||
if userCover != "" {
|
||||
cover = userCover
|
||||
} else {
|
||||
cover = systemCover
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) ifHitSkyHorse(mid int64, device string) (hit bool) {
|
||||
if mid == 0 {
|
||||
return false
|
||||
}
|
||||
if device == "pad" {
|
||||
return false
|
||||
}
|
||||
lastMid := strconv.Itoa(int(mid % 100))
|
||||
if len(lastMid) < 2 {
|
||||
lastMid = "0" + lastMid
|
||||
}
|
||||
_, isSkyHorseGray := s.conf.SkyHorseGray[lastMid]
|
||||
|
||||
return isSkyHorseGray && conf.Conf.SkyHorseStatus
|
||||
}
|
||||
|
||||
func (s *IndexService) ifHitLiveRec(mid int64, device string) (hit bool) {
|
||||
if mid == 0 {
|
||||
return false
|
||||
}
|
||||
if device == "pad" {
|
||||
return false
|
||||
}
|
||||
lastMid := strconv.Itoa(int(mid % 100))
|
||||
if len(lastMid) < 2 {
|
||||
lastMid = "0" + lastMid
|
||||
}
|
||||
_, isLiveRec := s.conf.LiveGray[lastMid]
|
||||
return isLiveRec
|
||||
}
|
||||
|
||||
func (s *IndexService) getRecRoomList(ctx context.Context, roomIds []int64, recPoolRoomListResp map[int64]*v2pb.CommonRoomItem, build int64, platform string, idolDuplicateMap map[int64]bool, recType int64, quality int64) (respRecRoomList []*v2pb.CommonRoomItem, err error) {
|
||||
wg, wgCtx := errgroup.WithContext(ctx)
|
||||
|
||||
multiRoomListResp := make(map[int64]*roomV2.RoomGetByIdsResp_RoomInfo)
|
||||
wg.Go(func() error {
|
||||
// 天马房间基础信息,有错误cancel其他没必要执行
|
||||
fields := []string{
|
||||
"roomid",
|
||||
"title",
|
||||
"uname",
|
||||
"online",
|
||||
"cover",
|
||||
"user_cover",
|
||||
"link",
|
||||
"face",
|
||||
"area_v2_parent_id",
|
||||
"area_v2_parent_name",
|
||||
"area_v2_id",
|
||||
"area_v2_name",
|
||||
"broadcast_type",
|
||||
"uid",
|
||||
}
|
||||
multiRoomList, err := s.roomDao.GetRoomInfoByIds(wgCtx, roomIds, fields, "app-interface-skyHorseRec")
|
||||
if err != nil {
|
||||
log.Error("[getRecRoomList]getByIds error:%+v", err)
|
||||
}
|
||||
multiRoomListResp = multiRoomList
|
||||
return err
|
||||
})
|
||||
|
||||
pendantRoomListResp := make(map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result)
|
||||
wg.Go(func() error {
|
||||
pendantRoomList, err := s.roomDao.GetRoomPendant(wgCtx, roomIds, "mobile_index_badge", 2)
|
||||
if err != nil {
|
||||
log.Error("[getRecRoomList]getPendantByIds error:%+v", err)
|
||||
}
|
||||
pendantRoomListResp = pendantRoomList
|
||||
return nil
|
||||
})
|
||||
|
||||
err = wg.Wait()
|
||||
if err != nil {
|
||||
log.Error("[getRecRoomList]wait error(%+v)", err)
|
||||
return
|
||||
}
|
||||
|
||||
respSlice := make([]*roomV2.RoomGetByIdsResp_RoomInfo, 0)
|
||||
for _, roomBaseInfo := range multiRoomListResp {
|
||||
respSlice = append(respSlice, roomBaseInfo)
|
||||
}
|
||||
|
||||
respRecRoomList = make([]*v2pb.CommonRoomItem, 0)
|
||||
for i := 0; i < 6; i++ {
|
||||
if recInfo, ok := recPoolRoomListResp[int64(i+1)]; ok {
|
||||
if _, ok := idolDuplicateMap[recInfo.Roomid]; !ok {
|
||||
respRecRoomList = append(respRecRoomList, recInfo)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if len(respSlice) <= 0 {
|
||||
continue
|
||||
}
|
||||
tmpItem := respSlice[0:1][0]
|
||||
respSlice = respSlice[1:]
|
||||
pendantValue, pendantBgPic, pendantBgColor := s.getPendant(tmpItem.Roomid, pendantRoomListResp)
|
||||
// 统一cover产品逻辑
|
||||
cover := s.getCover(tmpItem.UserCover, tmpItem.Cover)
|
||||
|
||||
respRecRoomList = append(respRecRoomList, &v2pb.CommonRoomItem{
|
||||
Roomid: tmpItem.Roomid,
|
||||
Title: tmpItem.Title,
|
||||
Uname: tmpItem.Uname,
|
||||
Online: tmpItem.Online,
|
||||
Cover: cover,
|
||||
Link: "/" + strconv.Itoa(int(tmpItem.Roomid)),
|
||||
Face: tmpItem.Face,
|
||||
AreaV2ParentId: tmpItem.AreaV2ParentId,
|
||||
AreaV2ParentName: tmpItem.AreaV2ParentName,
|
||||
AreaV2Id: tmpItem.AreaV2Id,
|
||||
AreaV2Name: tmpItem.AreaV2Name,
|
||||
BroadcastType: tmpItem.BroadcastType,
|
||||
PendentRu: pendantValue,
|
||||
PendentRuPic: pendantBgPic,
|
||||
PendentRuColor: pendantBgColor,
|
||||
RecType: recType,
|
||||
})
|
||||
}
|
||||
|
||||
s.getPlayUrl(ctx, respRecRoomList, quality, build, platform)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) getExtraDataForRoom(ctx context.Context, roomIds []int64, uids []int64, roomIdToUid map[int64]int64) (extraInfo map[int64]*model.ExtraRecInfo) {
|
||||
wg, wgCtx := errgroup.WithContext(ctx)
|
||||
extraInfo = make(map[int64]*model.ExtraRecInfo)
|
||||
|
||||
userInfos := make(map[int64]*api.Info)
|
||||
wg.Go(func() error {
|
||||
userResult, err := s.accountDao.GetUserInfos(wgCtx, uids)
|
||||
if err != nil {
|
||||
log.Error("[getExtraDataForRoom]getByIds error:%+v", err)
|
||||
}
|
||||
userInfos = userResult
|
||||
return err
|
||||
})
|
||||
|
||||
pendantRoomListResp := make(map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result)
|
||||
wg.Go(func() error {
|
||||
pendantRoomList, err := s.roomDao.GetRoomPendant(wgCtx, roomIds, "mobile_index_badge", 2)
|
||||
if err != nil {
|
||||
log.Error("[getExtraDataForRoom]getPendantByIds error:%+v", err)
|
||||
}
|
||||
pendantRoomListResp = pendantRoomList
|
||||
return nil
|
||||
})
|
||||
|
||||
err := wg.Wait()
|
||||
if err != nil {
|
||||
log.Error("[getExtraDataForRoom]getExtraDataForRoom_waitError:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, roomId := range roomIds {
|
||||
pendantValue, pendantBgPic, pendantBgColor := s.getPendant(roomId, pendantRoomListResp)
|
||||
if _, ok := extraInfo[roomId]; !ok {
|
||||
extraInfo[roomId] = &model.ExtraRecInfo{}
|
||||
}
|
||||
extraInfo[roomId].PendentRu = pendantValue
|
||||
extraInfo[roomId].PendentRuPic = pendantBgPic
|
||||
extraInfo[roomId].PendentRuColor = pendantBgColor
|
||||
if uid, ok := roomIdToUid[roomId]; ok {
|
||||
if _, ok := userInfos[uid]; ok {
|
||||
extraInfo[roomId].UName = userInfos[uid].Name
|
||||
extraInfo[roomId].Face = userInfos[uid].Face
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) getPendant(roomId int64, pendantRoomListResp map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result) (pendantValue, pendantBgPic, pendantBgColor string) {
|
||||
if pendantRoomListResp != nil {
|
||||
if _, ok := pendantRoomListResp[roomId]; ok {
|
||||
// 移动端取value, web取name
|
||||
pendantValue = pendantRoomListResp[roomId].Value
|
||||
pendantBgPic = pendantRoomListResp[roomId].BgPic
|
||||
if pendantRoomListResp[roomId].BgColor != "" {
|
||||
pendantBgColor = pendantRoomListResp[roomId].BgColor
|
||||
} else {
|
||||
pendantBgColor = _mobileIndexBadgeColorDefault
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) getPlayUrl(ctx context.Context, roomList []*v2pb.CommonRoomItem, quality, build int64, platform string) {
|
||||
roomIdsForPlayUrl := make([]int64, 0)
|
||||
for _, commRoomBlock := range roomList {
|
||||
roomIdsForPlayUrl = append(roomIdsForPlayUrl, commRoomBlock.Roomid)
|
||||
}
|
||||
changeRoomListPlayURLMap := dao.BvcApi.GetPlayUrlMulti(ctx, roomIdsForPlayUrl, 0, quality, build, platform)
|
||||
|
||||
for _, vv := range roomList {
|
||||
if changeRoomListPlayURLMap[vv.Roomid] != nil {
|
||||
vv.AcceptQuality = changeRoomListPlayURLMap[vv.Roomid].AcceptQuality
|
||||
vv.CurrentQuality = changeRoomListPlayURLMap[vv.Roomid].CurrentQuality
|
||||
vv.PlayUrl = changeRoomListPlayURLMap[vv.Roomid].Url["h264"]
|
||||
vv.PlayUrlH265 = changeRoomListPlayURLMap[vv.Roomid].Url["h265"]
|
||||
}
|
||||
}
|
||||
}
|
572
app/interface/live/app-interface/service/v2/daowrapper.go
Normal file
572
app/interface/live/app-interface/service/v2/daowrapper.go
Normal file
@ -0,0 +1,572 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
ServiceConf "go-common/app/interface/live/app-interface/conf"
|
||||
"go-common/app/interface/live/app-interface/dao"
|
||||
relationT "go-common/app/interface/live/app-interface/service/v1/relation"
|
||||
avV1 "go-common/app/service/live/av/api/liverpc/v1"
|
||||
fansMedalV1 "go-common/app/service/live/fans_medal/api/liverpc/v1"
|
||||
liveDataV1 "go-common/app/service/live/live_data/api/liverpc/v1"
|
||||
relationV1 "go-common/app/service/live/relation/api/liverpc/v1"
|
||||
roomV1 "go-common/app/service/live/room/api/liverpc/v1"
|
||||
roomV2 "go-common/app/service/live/room/api/liverpc/v2"
|
||||
roomExV1 "go-common/app/service/live/room_ex/api/liverpc/v1"
|
||||
userExV1 "go-common/app/service/live/userext/api/liverpc/v1"
|
||||
liveUserExpM "go-common/app/service/live/xuser/api/grpc/v1"
|
||||
accountM "go-common/app/service/main/account/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
"go-common/library/sync/errgroup"
|
||||
)
|
||||
|
||||
// ChunkCallInfo ...
|
||||
// 日志结构体
|
||||
type ChunkCallInfo struct {
|
||||
ParamsName string
|
||||
URLName string
|
||||
ChunkSize int64
|
||||
ChunkNum int64
|
||||
RPCTimeout int64
|
||||
}
|
||||
|
||||
const (
|
||||
// GoRoutingErr ...
|
||||
// 协程wait错误
|
||||
GoRoutingErr = "协程等待数据错误"
|
||||
)
|
||||
|
||||
// UIDs2roomIDs ...
|
||||
// uid转换roomID,每批最大400
|
||||
func (s *IndexService) UIDs2roomIDs(ctx context.Context, UIDs []int64) (roomIDs map[int64]int64, err error) {
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(ServiceConf.GetRoomID)
|
||||
params := ServiceConf.ChunkCallInfo{ParamsName: "uids", URLName: ServiceConf.GetRoomID, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
roomIDs = make(map[int64]int64)
|
||||
lens := len(UIDs)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([]map[string]string, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkUfosIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkUfosIds = UIDs[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkUfosIds = UIDs[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.roomDao.UIDs2roomIDs(ctx, &roomV2.RoomRoomIdByUidMultiReq{Uids: chunkUfosIds}, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chunkResult[x-1] = ret.Data
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := ServiceConf.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = ServiceConf.GetRoomID
|
||||
erelongInfo.ErrDesc = GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.RelationFrameWorkGoRoutingError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
// 整理数据
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for k, item := range chunkItemList {
|
||||
if item != "" {
|
||||
Index := RParseInt(k, 1)
|
||||
itemInt := RParseInt(item, 1)
|
||||
roomIDs[Index] = itemInt
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetRoomInfo ...
|
||||
// 获取room信息
|
||||
func (s *IndexService) GetRoomInfo(ctx context.Context, input *roomV1.RoomGetStatusInfoByUidsReq) (roomResult map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo, err error) {
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(ServiceConf.GetStatusInfoByUfos)
|
||||
params := ServiceConf.ChunkCallInfo{ParamsName: "uids", URLName: ServiceConf.GetStatusInfoByUfos, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
roomResult = make(map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo)
|
||||
lens := len(input.Uids)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([]map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkUfosIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkUfosIds = input.Uids[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkUfosIds = input.Uids[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.roomDao.GetRoomInfo(ctx, &roomV1.RoomGetStatusInfoByUidsReq{Uids: chunkUfosIds, FilterOffline: input.FilterOffline, NeedBroadcastType: input.NeedBroadcastType}, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chunkResult[x-1] = ret.Data
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := ServiceConf.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = ServiceConf.GetStatusInfoByUfos
|
||||
erelongInfo.ErrDesc = GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.RoomFrameWorkGoRoutingError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
// 整理数据
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for _, item := range chunkItemList {
|
||||
if item != nil {
|
||||
roomResult[item.Uid] = item
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetLastLiveTime ...
|
||||
// 获取Record信息
|
||||
func (s *IndexService) GetLastLiveTime(ctx context.Context, rolaids []int64) (resp map[string]string, err error) {
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(ServiceConf.Record)
|
||||
params := ServiceConf.ChunkCallInfo{ParamsName: "uids", URLName: ServiceConf.Record, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
resp = make(map[string]string)
|
||||
lens := len(rolaids)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([]map[string]*liveDataV1.RecordGetResp_TimeInfo, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkRoomIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkRoomIds = rolaids[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkRoomIds = rolaids[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.livedataDao.GetLastLiveTime(ctx, &liveDataV1.RecordGetReq{Roomids: chunkRoomIds}, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chunkResult[x-1] = ret
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := ServiceConf.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = ServiceConf.Record
|
||||
erelongInfo.ErrDesc = GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.RecordFrameWorkGoRoutingError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
// 整理数据
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for k, item := range chunkItemList {
|
||||
if item != nil {
|
||||
resp[k] = item.RecentEndTime
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetRoomNewsInfo ...
|
||||
// 获取公告信息
|
||||
func (s *IndexService) GetRoomNewsInfo(ctx context.Context, rolaids *roomExV1.RoomNewsMultiGetReq) (roomNewsResult map[int64]*roomExV1.RoomNewsMultiGetResp_Data, err error) {
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(ServiceConf.RoomNews)
|
||||
params := ServiceConf.ChunkCallInfo{ParamsName: "roomids", URLName: ServiceConf.RoomNews, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
roomNewsResult = make(map[int64]*roomExV1.RoomNewsMultiGetResp_Data)
|
||||
lens := len(rolaids.RoomIds)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([][]*roomExV1.RoomNewsMultiGetResp_Data, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkRoomIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkRoomIds = rolaids.RoomIds[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkRoomIds = rolaids.RoomIds[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.roomexDao.GetRoomNewsInfo(ctx, &roomExV1.RoomNewsMultiGetReq{RoomIds: chunkRoomIds, IsDecoded: rolaids.IsDecoded}, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chunkResult[x-1] = ret.Data
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := ServiceConf.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = ServiceConf.RoomNews
|
||||
erelongInfo.ErrDesc = GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.RoomNewsFrameWorkGoRoutingError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
// 整理数据
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for _, item := range chunkItemList {
|
||||
if item != nil {
|
||||
if mid, err := strconv.ParseInt(item.Roomid, 10, 64); err == nil {
|
||||
roomNewsResult[mid] = item
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetRoomPendantInfo ...
|
||||
// 获取角标信息
|
||||
func (s *IndexService) GetRoomPendantInfo(ctx context.Context, req *roomV1.RoomPendantGetPendantByIdsReq) (roomNewsResult map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result, err error) {
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(ServiceConf.RoomPendent)
|
||||
params := ServiceConf.ChunkCallInfo{ParamsName: "ids", URLName: ServiceConf.RoomPendent, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
roomNewsResult = make(map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result)
|
||||
lens := len(req.Ids)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([]map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkRoomIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkRoomIds = req.Ids[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkRoomIds = req.Ids[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.roomDao.GetRoomPendantInfo(ctx, &roomV1.RoomPendantGetPendantByIdsReq{Ids: chunkRoomIds, Type: req.Type, Position: req.Position}, params)
|
||||
if err != nil || ret == nil {
|
||||
return err
|
||||
}
|
||||
chunkResult[x-1] = ret.Data.Result
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := ServiceConf.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = ServiceConf.RoomPendent
|
||||
erelongInfo.ErrDesc = GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.RoomPendentFrameWorkGoRoutingError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
// 整理数据
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for k, item := range chunkItemList {
|
||||
if item != nil {
|
||||
roomNewsResult[k] = item
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetPkID ...
|
||||
// 获取PkId信息
|
||||
func (s *IndexService) GetPkID(ctx context.Context, req *avV1.PkGetPkIdsByRoomIdsReq) (avResult map[string]int64, err error) {
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(ServiceConf.GetPkIdsByRoomIds)
|
||||
params := ServiceConf.ChunkCallInfo{ParamsName: "ids", URLName: ServiceConf.GetPkIdsByRoomIds, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
avResult = make(map[string]int64)
|
||||
lens := len(req.RoomIds)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([]map[string]int64, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkRoomIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkRoomIds = req.RoomIds[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkRoomIds = req.RoomIds[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.avDao.GetPkID(ctx, &avV1.PkGetPkIdsByRoomIdsReq{RoomIds: chunkRoomIds, Platform: req.Platform}, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chunkResult[x-1] = ret.Data
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := ServiceConf.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = ServiceConf.GetPkIdsByRoomIds
|
||||
erelongInfo.ErrDesc = GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.PkIDFrameWorkGoRoutingError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
// 整理数据
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for k, item := range chunkItemList {
|
||||
avResult[k] = item
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetFansMedal ...
|
||||
// 获取粉丝勋章佩戴信息
|
||||
func (s *IndexService) GetFansMedal(ctx context.Context, req *fansMedalV1.FansMedalTargetsWithMedalReq) (fansResult map[int64]bool, err error) {
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(ServiceConf.TargetsWithMedal)
|
||||
params := ServiceConf.ChunkCallInfo{ParamsName: "ids", URLName: ServiceConf.TargetsWithMedal, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
fansResult = make(map[int64]bool)
|
||||
lens := len(req.TargetIds)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([][]int64, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkRoomIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkRoomIds = req.TargetIds[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkRoomIds = req.TargetIds[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.fansMedalDao.GetFansMedal(ctx, &fansMedalV1.FansMedalTargetsWithMedalReq{Uid: req.Uid, TargetIds: chunkRoomIds}, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chunkResult[x-1] = ret.Data
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := ServiceConf.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = ServiceConf.TargetsWithMedal
|
||||
erelongInfo.ErrDesc = GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.FansMedalFrameWorkGoRoutingError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
// 整理数据
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for _, item := range chunkItemList {
|
||||
fansResult[item] = true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetGrayRule ...
|
||||
// 获取灰度规则信息
|
||||
func (s *IndexService) GetGrayRule(ctx context.Context, req *userExV1.GrayRuleGetByMarkReq) (extResult *userExV1.GrayRuleGetByMarkResp_Data, err error) {
|
||||
extResult = &userExV1.GrayRuleGetByMarkResp_Data{}
|
||||
if req == nil {
|
||||
return nil, nil
|
||||
}
|
||||
ret, err := s.userextDao.GetGrayRule(ctx, req)
|
||||
if err != nil {
|
||||
log.Error("call_userExt_grayRule error,err:%v", err)
|
||||
err = errors.WithMessage(ecode.GetGrayRuleError, "GET SEA PATROL FAIL")
|
||||
return
|
||||
}
|
||||
extResult = ret.Data
|
||||
return
|
||||
}
|
||||
|
||||
// GetGiftInfo ...
|
||||
// 获取送礼信息
|
||||
func GetGiftInfo(ctx context.Context) (giftInfo map[int64]int64, err error) {
|
||||
relationParams := &relationV1.BaseInfoGetGiftInfoReq{}
|
||||
giftInfo = make(map[int64]int64)
|
||||
ret, err := dao.RelationApi.V1BaseInfo.GetGiftInfo(ctx, relationParams)
|
||||
|
||||
for _, v := range ret.Data {
|
||||
giftInfo[v.Mid] = v.Gold
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetUserInfo 获取用户信息
|
||||
func (s *IndexService) GetUserInfo(ctx context.Context, UIDs []int64) (userResult map[int64]*accountM.Card, err error) {
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(ServiceConf.AccountGRPC)
|
||||
params := ServiceConf.ChunkCallInfo{ParamsName: "uids", URLName: ServiceConf.AccountGRPC, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
userResult = make(map[int64]*accountM.Card)
|
||||
lens := len(UIDs)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([]map[int64]*accountM.Card, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkUfosIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkUfosIds = UIDs[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkUfosIds = UIDs[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.accountDao.GetUserInfoData(ctx, chunkUfosIds)
|
||||
if err != nil {
|
||||
err = errors.WithMessage(ecode.AccountGRPCError, "GET SEA PATROL FAIL")
|
||||
log.Error("Call main.Account.Cards Error.Infos(%+v) error(%+v)", chunkUfosIds, err)
|
||||
return nil
|
||||
}
|
||||
chunkResult[x-1] = ret
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := relationT.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = relationT.AccountGRPC
|
||||
erelongInfo.ErrDesc = relationT.GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.AccountGRPCFrameError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for _, item := range chunkItemList {
|
||||
if item != nil {
|
||||
userResult[item.Mid] = item
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetLiveUserExp 获取用户经验信息
|
||||
func (s *IndexService) GetLiveUserExp(ctx context.Context, UIDs []int64) (userResult map[int64]*liveUserExpM.LevelInfo, err error) {
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(ServiceConf.LiveUserExpGRPC)
|
||||
params := ServiceConf.ChunkCallInfo{ParamsName: "uids", URLName: ServiceConf.LiveUserExpGRPC, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
userResult = make(map[int64]*liveUserExpM.LevelInfo)
|
||||
lens := len(UIDs)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([]map[int64]*liveUserExpM.LevelInfo, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkUfosIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkUfosIds = UIDs[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkUfosIds = UIDs[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.xuserDao.GetUserExpData(ctx, chunkUfosIds)
|
||||
if err != nil {
|
||||
err = errors.WithMessage(ecode.AccountGRPCError, "GET SEA PATROL FAIL")
|
||||
log.Error("Call main.Account.Cards Error.Infos(%+v) error(%+v)", chunkUfosIds, err)
|
||||
return nil
|
||||
}
|
||||
chunkResult[x-1] = ret
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := relationT.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = relationT.LiveUserExpGRPC
|
||||
erelongInfo.ErrDesc = relationT.GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.AccountGRPCFrameError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for _, item := range chunkItemList {
|
||||
if item != nil {
|
||||
userResult[item.Uid] = item
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
532
app/interface/live/app-interface/service/v2/index.go
Normal file
532
app/interface/live/app-interface/service/v2/index.go
Normal file
@ -0,0 +1,532 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"go-common/app/interface/live/app-interface/dao/account"
|
||||
|
||||
"go-common/app/interface/live/app-interface/dao/av"
|
||||
"go-common/app/interface/live/app-interface/dao/fans_medal"
|
||||
"go-common/app/interface/live/app-interface/dao/live_data"
|
||||
"go-common/app/interface/live/app-interface/dao/rankdb"
|
||||
"go-common/app/interface/live/app-interface/dao/relation"
|
||||
"go-common/app/interface/live/app-interface/dao/room_ex"
|
||||
"go-common/app/interface/live/app-interface/dao/user_ext"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
"go-common/app/interface/live/app-interface/conf"
|
||||
"go-common/app/interface/live/app-interface/dao"
|
||||
liveuserDao "go-common/app/interface/live/app-interface/dao/live_user"
|
||||
roomDao "go-common/app/interface/live/app-interface/dao/room"
|
||||
roomexDao "go-common/app/interface/live/app-interface/dao/room_ex"
|
||||
xuserDao "go-common/app/interface/live/app-interface/dao/xuser"
|
||||
liveUserV1 "go-common/app/service/live/live_user/api/liverpc/v1"
|
||||
recommendV1 "go-common/app/service/live/recommend/api/grpc/v1"
|
||||
roomV2 "go-common/app/service/live/room/api/liverpc/v2"
|
||||
xrf "go-common/app/service/live/xroom-feed/api"
|
||||
"go-common/library/log"
|
||||
"go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/metadata"
|
||||
"go-common/library/sync/errgroup"
|
||||
"go-common/library/xstr"
|
||||
)
|
||||
|
||||
const (
|
||||
_bannerType = 1
|
||||
_entranceType = 2
|
||||
_yunyingRecFormType = 3
|
||||
_yunyingRecSquareType = 4
|
||||
_rankType = 5
|
||||
_recFormType = 6
|
||||
_recSquareType = 7
|
||||
_feedType = 8
|
||||
_parentAreaFormType = 9
|
||||
_parentAreaSquareType = 10
|
||||
_activityType = 11
|
||||
_myAreaTagType = 12
|
||||
_myAreaTagListType = 13
|
||||
_seaPatrolType = 14
|
||||
)
|
||||
|
||||
// IndexService struct
|
||||
type IndexService struct {
|
||||
conf *conf.Config
|
||||
commonType []int64
|
||||
// dao
|
||||
dao *dao.Dao
|
||||
roomDao *roomDao.Dao
|
||||
liveuserDao *liveuserDao.Dao
|
||||
rankdbDao *rankdb.Dao
|
||||
livedataDao *live_data.Dao
|
||||
relationDao *relation.Dao
|
||||
roomexDao *room_ex.Dao
|
||||
userextDao *user_ext.Dao
|
||||
avDao *av.Dao
|
||||
fansMedalDao *fans_medal.Dao
|
||||
accountDao *account.Dao
|
||||
xuserDao *xuserDao.Dao
|
||||
// cache
|
||||
// all base module cache
|
||||
//AllMInfoMap map[int64][]*v2pb.ModuleInfo
|
||||
AllMInfoMap atomic.Value
|
||||
//areaEntranceMap map[int64][]*v2pb.PicItem
|
||||
areaEntranceListMap atomic.Value
|
||||
commonRoomList atomic.Value
|
||||
recommendConn recommendV1.RecommendClient
|
||||
xrfClient *xrf.Client
|
||||
}
|
||||
|
||||
// NewIndexService init
|
||||
func NewIndexService(c *conf.Config) (s *IndexService) {
|
||||
s = &IndexService{
|
||||
conf: c,
|
||||
dao: dao.New(c),
|
||||
roomDao: roomDao.New(c),
|
||||
liveuserDao: liveuserDao.New(c),
|
||||
rankdbDao: rankdb.New(c),
|
||||
roomexDao: roomexDao.New(c),
|
||||
accountDao: account.New(c),
|
||||
xuserDao: xuserDao.New(c),
|
||||
commonType: []int64{
|
||||
_yunyingRecFormType,
|
||||
_yunyingRecSquareType,
|
||||
_recFormType,
|
||||
_recSquareType,
|
||||
_parentAreaFormType,
|
||||
_parentAreaSquareType,
|
||||
},
|
||||
}
|
||||
// init cache data
|
||||
s.loadAllModuleInfoMap()
|
||||
s.loadAreaEntranceCache()
|
||||
s.loadCommonListMap()
|
||||
s.loadLastHourData(context.TODO())
|
||||
go s.allModuleInfoProc()
|
||||
go s.areaEntranceProc()
|
||||
go s.allcommonListProc()
|
||||
go s.loadLastHour()
|
||||
conn, err := recommendV1.NewClient(conf.Conf.Warden)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
s.recommendConn = conn
|
||||
xrfc, err := xrf.NewClient(conf.Conf.Warden)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
s.xrfClient = xrfc
|
||||
return s
|
||||
}
|
||||
|
||||
// Index 相关服务
|
||||
|
||||
// GetAllList implementation
|
||||
// 首页大接口
|
||||
// `midware:"guest,verify"`
|
||||
func (s *IndexService) GetAllList(ctx context.Context, req *v2pb.GetAllListReq) (resp *v2pb.GetAllListResp, err error) {
|
||||
resp = &v2pb.GetAllListResp{
|
||||
Interval: 10,
|
||||
IsSkyHorseGray: 0,
|
||||
Banner: []*v2pb.MBanner{},
|
||||
MyTag: []*v2pb.MMyTag{},
|
||||
AreaEntrance: []*v2pb.MAreaEntrance{},
|
||||
SeaPatrol: []*v2pb.MSeaPatrol{},
|
||||
MyIdol: []*v2pb.MMyIdol{},
|
||||
RoomList: []*v2pb.MRoomBlock{},
|
||||
HourRank: []*v2pb.MHourRank{},
|
||||
ActivityCard: []*v2pb.MActivityCard{},
|
||||
}
|
||||
moduleInfoMap := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
if moduleInfoMap == nil {
|
||||
log.Error("[GetAllList]module info list is nil, moduleIds:%+v", moduleInfoMap)
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化各模块返回信息
|
||||
respCommonRoomList := make([]*v2pb.MRoomBlock, 0)
|
||||
respMultiRoomList := make([]*v2pb.MRoomBlock, 0)
|
||||
myAreaMap := make(map[int64]bool)
|
||||
respMyIdol := &v2pb.MMyIdol{}
|
||||
respSkyHorseRoomList := make([]*v2pb.CommonRoomItem, 0)
|
||||
respLiveRecRoomList := make([]*v2pb.CommonRoomItem, 0)
|
||||
|
||||
// 大多使用header里的mid解析, 框架已封装请求的header
|
||||
midInterface, isUIDSet := metadata.Value(ctx, metadata.Mid).(int64)
|
||||
mid := int64(0)
|
||||
if isUIDSet {
|
||||
mid = midInterface
|
||||
}
|
||||
|
||||
buvid := ""
|
||||
// 主站封好的,可从device里获取到sid、buvid、buvid3、build、channel、device、mobi_app、platform
|
||||
device, ok := metadata.Value(ctx, metadata.Device).(*blademaster.Device)
|
||||
if ok {
|
||||
buvid = device.Buvid
|
||||
}
|
||||
|
||||
// 第一波并发获取数据,无依赖
|
||||
func(device *blademaster.Device) {
|
||||
wg1 := errgroup.Group{}
|
||||
|
||||
// banner
|
||||
if s.isModuleExist(_bannerType) {
|
||||
wg1.Go(func() (err error) {
|
||||
resp.Banner = s.getIndexBanner(ctx, req.Platform, req.Device, req.Build)
|
||||
return
|
||||
})
|
||||
}
|
||||
// 常用标签列表
|
||||
if s.isModuleExist(_myAreaTagType) {
|
||||
wg1.Go(func() (err error) {
|
||||
resp.MyTag, _ = s.GetIndexV2TagList(ctx, &liveUserV1.UserSettingGetTagReq{})
|
||||
return
|
||||
})
|
||||
}
|
||||
// 分区入口
|
||||
if s.isModuleExist(_entranceType) {
|
||||
wg1.Go(func() (err error) {
|
||||
resp.AreaEntrance = s.getAreaEntrance(ctx)
|
||||
return
|
||||
})
|
||||
}
|
||||
// 我的关注
|
||||
if s.isModuleExist(_feedType) {
|
||||
wg1.Go(func() (err error) {
|
||||
resp.MyIdol = s.LiveAnchorHomePage(ctx, req.RelationPage, req.Build, req.Platform, req.Quality)
|
||||
if len(resp.MyIdol) > 0 {
|
||||
respMyIdol = resp.MyIdol[0]
|
||||
}
|
||||
return
|
||||
})
|
||||
}
|
||||
// 通用房间列表(肯定是有的,此处不做判断),推荐、运营推荐分区、常用分区(特殊:要在第二波拿)、一级分区
|
||||
wg1.Go(func() (err error) {
|
||||
respCommonRoomList = s.getCommonRoomListForIndex(ctx, req.Build, req.Platform, req.Quality)
|
||||
return
|
||||
})
|
||||
// 活动卡片
|
||||
if s.isModuleExist(_activityType) {
|
||||
wg1.Go(func() (err error) {
|
||||
resp.ActivityCard = s.getActivityCard(ctx)
|
||||
return
|
||||
})
|
||||
}
|
||||
// 小时榜
|
||||
if s.isModuleExist(_rankType) {
|
||||
wg1.Go(func() (err error) {
|
||||
resp.HourRank, _ = s.getLastHourTop3(ctx)
|
||||
return
|
||||
})
|
||||
}
|
||||
// 大航海
|
||||
mobiApp := device.RawMobiApp
|
||||
if s.isModuleExist(_seaPatrolType) && mobiApp != "iphone_b" && mobiApp != "android_b" {
|
||||
wg1.Go(func() (err error) {
|
||||
resp.SeaPatrol, _ = s.GetIndexV2SeaPatrol(ctx, &liveUserV1.NoteGetReq{})
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
err1 := wg1.Wait()
|
||||
if err1 != nil {
|
||||
log.Error("[GetAllList]wg1 wait error: %+v", err1)
|
||||
}
|
||||
}(device)
|
||||
|
||||
// 第二波获取数据 (依赖第一波)
|
||||
func() {
|
||||
wg2 := errgroup.Group{}
|
||||
// 天马个性化推荐 无法缓存 依赖关注
|
||||
if s.ifHitSkyHorse(mid, req.Device) {
|
||||
wg2.Go(func() (err error) {
|
||||
//目前只对第一个关注模块去重
|
||||
respSkyHorseRoomList, err = s.getSkyHorseRoomListForIndex(ctx, respMyIdol, mid, buvid, req.Build, req.Platform, req.RecPage, req.Quality)
|
||||
return
|
||||
})
|
||||
}
|
||||
// 直播个性化推荐 无法缓存 依赖关注
|
||||
if s.ifHitLiveRec(mid, req.Device) {
|
||||
wg2.Go(func() (err error) {
|
||||
respLiveRecRoomList, err = s.getLiveRecRoomList(ctx, respMyIdol, mid, req.Build, req.Platform, req.RecPage, req.Quality)
|
||||
return
|
||||
})
|
||||
}
|
||||
// 常用标签房间列表
|
||||
wg2.Go(func() (err error) {
|
||||
respMultiRoomList, myAreaMap = s.getMultiRoomList(ctx, resp.MyTag, req.Platform, req.Build, req.Quality)
|
||||
resp.RoomList = append(resp.RoomList, respMultiRoomList...)
|
||||
return
|
||||
})
|
||||
|
||||
// 对保底逻辑的一些处理,对关注去重, 数量限制, 获取投放系统数据
|
||||
wg2.Go(func() (err error) {
|
||||
respCommonRoomList = s.handleCommonRoomList(ctx, respMyIdol, respCommonRoomList, req.Quality, req.Build, req.Platform, req.Device)
|
||||
return
|
||||
})
|
||||
|
||||
err2 := wg2.Wait()
|
||||
if err2 != nil {
|
||||
log.Error("[GetAllList]wg2 wait error: %+v", err2)
|
||||
}
|
||||
}()
|
||||
|
||||
// 推荐直播最终处理
|
||||
handleRecResult(resp, respCommonRoomList, respSkyHorseRoomList, respLiveRecRoomList, myAreaMap)
|
||||
if resp.IsSkyHorseGray == 0 && s.ifHitLiveRec(mid, req.Device) {
|
||||
log.Info("live rec hit miss, mid:%d, liveRec:%+v", mid, respLiveRecRoomList)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Change implementation
|
||||
// 换一换接口
|
||||
// `midware:"guest,verify"`
|
||||
func (s *IndexService) Change(ctx context.Context, req *v2pb.ChangeReq) (resp *v2pb.ChangeResp, err error) {
|
||||
resp = &v2pb.ChangeResp{}
|
||||
mid, isUIDSet := metadata.Value(ctx, metadata.Mid).(int64)
|
||||
var uid int64
|
||||
if isUIDSet {
|
||||
uid = mid
|
||||
}
|
||||
|
||||
duplicates, _ := xstr.SplitInts(req.AttentionRoomId)
|
||||
duplicatesMap := make(map[int64]bool)
|
||||
|
||||
for _, roomID := range duplicates {
|
||||
duplicatesMap[roomID] = true
|
||||
}
|
||||
buvid := ""
|
||||
// 主站封好的,可从device里获取到sid、buvid、buvid3、build、channel、device、mobi_app、platform
|
||||
device, ok := metadata.Value(ctx, metadata.Device).(*blademaster.Device)
|
||||
if ok {
|
||||
buvid = device.Buvid
|
||||
}
|
||||
|
||||
moduleInfo, err := s.roomDao.GetAllModuleInfo(ctx, req.ModuleId)
|
||||
if err != nil || moduleInfo[0] == nil {
|
||||
log.Error("[Change]GetModuleInfoById error:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 给moduleInfo赋值
|
||||
resp.ModuleInfo = &v2pb.ModuleInfo{
|
||||
Id: moduleInfo[0].Id,
|
||||
Link: moduleInfo[0].Link,
|
||||
Pic: moduleInfo[0].Pic,
|
||||
Title: moduleInfo[0].Title,
|
||||
Type: moduleInfo[0].Type,
|
||||
Sort: moduleInfo[0].Sort,
|
||||
Count: moduleInfo[0].Count,
|
||||
}
|
||||
resp.List = make([]*v2pb.CommonRoomItem, 0)
|
||||
|
||||
isDefault := true
|
||||
if s.ifHitSkyHorse(uid, req.Device) {
|
||||
skyHorseList, err := s.getSkyHorseRoomList(ctx, mid, buvid, req.Build, req.Platform, duplicates, req.Page, req.Quality)
|
||||
if err == nil && len(skyHorseList) > 0 {
|
||||
isDefault = false
|
||||
resp.IsSkyHorseGray = 1
|
||||
resp.List = skyHorseList
|
||||
}
|
||||
}
|
||||
|
||||
if s.ifHitLiveRec(mid, req.Device) {
|
||||
respLiveRoomList, err := s.getLiveRecRoomListForChange(ctx, mid, req.Build, req.Platform, duplicates, req.Page, req.Quality)
|
||||
if err == nil && len(respLiveRoomList) > 0 {
|
||||
isDefault = false
|
||||
resp.IsSkyHorseGray = 1
|
||||
resp.List = respLiveRoomList
|
||||
} else {
|
||||
log.Info("live rec hit miss, from:change, mid:%d, err:%+v, liveRec:%+v", mid, err, respLiveRoomList)
|
||||
}
|
||||
}
|
||||
|
||||
if isDefault {
|
||||
resp.IsSkyHorseGray = 0
|
||||
respCommonRoomList, errTemp := s.getCommonRoomListByID(ctx, req.ModuleId, req.Build, req.Platform, req.Quality, req.Device, duplicates)
|
||||
if errTemp != nil {
|
||||
log.Error("[Change]GetModuleInfoById error:%+v", errTemp)
|
||||
err = errTemp
|
||||
return
|
||||
}
|
||||
|
||||
resp.List = respCommonRoomList
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 指定模块是否存在
|
||||
func (s *IndexService) isModuleExist(iType int64) (res bool) {
|
||||
res = false
|
||||
mInfoMap := s.GetAllModuleInfoMapFromCache(context.TODO())
|
||||
if _, ok := mInfoMap[iType]; ok {
|
||||
res = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 推荐模块最终处理:天马、对关注去重
|
||||
func handleRecResult(resp *v2pb.GetAllListResp, respCommonRoomList []*v2pb.MRoomBlock, respSkyHorseRoomList []*v2pb.CommonRoomItem, respLiveRecRoomList []*v2pb.CommonRoomItem, myAreaMap map[int64]bool) {
|
||||
afterHandleRoomList := make([]*v2pb.MRoomBlock, 0)
|
||||
for _, roomBlock := range respCommonRoomList {
|
||||
if roomBlock.ModuleInfo.Type == _recFormType || roomBlock.ModuleInfo.Type == _recSquareType {
|
||||
if len(respSkyHorseRoomList) > 0 {
|
||||
resp.IsSkyHorseGray = 1
|
||||
roomBlock.List = respSkyHorseRoomList
|
||||
} else if len(respLiveRecRoomList) > 0 {
|
||||
resp.IsSkyHorseGray = 1
|
||||
roomBlock.List = respLiveRecRoomList
|
||||
}
|
||||
|
||||
afterHandleRoomList = append(afterHandleRoomList, roomBlock)
|
||||
continue
|
||||
}
|
||||
// 常用分区对运营推荐分区去重
|
||||
if roomBlock.ModuleInfo.Type == _yunyingRecFormType || roomBlock.ModuleInfo.Type == _yunyingRecSquareType {
|
||||
for _, item := range roomBlock.List {
|
||||
if _, ok := myAreaMap[item.AreaV2Id]; !ok {
|
||||
afterHandleRoomList = append(afterHandleRoomList, roomBlock)
|
||||
break
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
afterHandleRoomList = append(afterHandleRoomList, roomBlock)
|
||||
}
|
||||
resp.RoomList = append(resp.RoomList, afterHandleRoomList...)
|
||||
}
|
||||
|
||||
// get AllModuleInfoMap
|
||||
func (s *IndexService) getAllModuleInfoMap(ctx context.Context) (allMInfoCacheMap map[int64][]*v2pb.ModuleInfo) {
|
||||
var allMInfoData []*roomV2.AppIndexGetBaseMInfoListResp_ModuleInfo
|
||||
var err error
|
||||
var retry int64
|
||||
for i := 1; i <= 3; i++ {
|
||||
// 最多重试3次
|
||||
allMInfoData, err = s.roomDao.GetAllModuleInfo(ctx, 0)
|
||||
if err != nil || len(allMInfoData) <= 0 {
|
||||
retry++
|
||||
log.Error("[loadAllModuleInfoMap] GetAllModuleInfo error(%+v) retry_times(%d)", err, retry)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if len(allMInfoData) > 0 && allMInfoData[1] != nil {
|
||||
allMInfoCacheMap = make(map[int64][]*v2pb.ModuleInfo)
|
||||
for _, m := range allMInfoData {
|
||||
allMInfoCacheMap[m.Type] = append(allMInfoCacheMap[m.Type], &v2pb.ModuleInfo{
|
||||
Id: m.Id,
|
||||
Link: m.Link,
|
||||
Pic: m.Pic,
|
||||
Title: m.Title,
|
||||
Type: m.Type,
|
||||
Sort: m.Sort,
|
||||
Count: m.Count,
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// cache load
|
||||
func (s *IndexService) loadAllModuleInfoMap() {
|
||||
allMInfoCacheMap := s.getAllModuleInfoMap(context.TODO())
|
||||
if len(allMInfoCacheMap) > 0 {
|
||||
s.AllMInfoMap.Store(allMInfoCacheMap)
|
||||
log.Info("[loadAllModuleInfoMap]load data success!")
|
||||
}
|
||||
}
|
||||
|
||||
// ticker
|
||||
func (s *IndexService) allModuleInfoProc() {
|
||||
for {
|
||||
time.Sleep(time.Second * 5)
|
||||
s.loadAllModuleInfoMap()
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllModuleInfoMapFromCache get all module info fromcache
|
||||
func (s *IndexService) GetAllModuleInfoMapFromCache(ctx context.Context) (res map[int64][]*v2pb.ModuleInfo) {
|
||||
// load
|
||||
i := s.AllMInfoMap.Load()
|
||||
// assert
|
||||
res, ok := i.(map[int64][]*v2pb.ModuleInfo)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
// 回源&log
|
||||
res = s.getAllModuleInfoMap(ctx)
|
||||
log.Warn("[GetAllModuleInfoMap]memory cache miss!! i:%+v; res:%+v", i, res)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) getCommonListFromCache(sIds []int64) (commonList map[int64]*roomV2.AppIndexGetRoomListByIdsResp_RoomList) {
|
||||
commonListCache, ok := s.commonRoomList.Load().(map[int64]*roomV2.AppIndexGetRoomListByIdsResp_RoomList)
|
||||
if ok {
|
||||
commonList = commonListCache
|
||||
return
|
||||
}
|
||||
|
||||
roomListMap, err := s.roomDao.GetListByIds(context.TODO(), sIds)
|
||||
if err != nil {
|
||||
log.Error("[getCommonListFromCache]GetListByIds error, error:%+v", err)
|
||||
return
|
||||
}
|
||||
commonList = roomListMap
|
||||
log.Warn("[getCommonListFromCache]memory cache miss!! res:%+v", commonList)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) loadCommonListMap() {
|
||||
sIds := s.getIdsFromModuleMap(context.TODO(), s.commonType)
|
||||
|
||||
roomListMap, err := s.roomDao.GetListByIds(context.TODO(), sIds)
|
||||
if err != nil {
|
||||
log.Error("[loadCommonListMap]GetListByIds error, error:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
copyRoomListMap := make(map[int64]*roomV2.AppIndexGetRoomListByIdsResp_RoomList)
|
||||
|
||||
for moduleId, roomList := range roomListMap {
|
||||
for _, item := range roomList.List {
|
||||
if _, ok := copyRoomListMap[moduleId]; !ok {
|
||||
copyRoomListMap[moduleId] = &roomV2.AppIndexGetRoomListByIdsResp_RoomList{
|
||||
List: make([]*roomV2.AppIndexGetRoomListByIdsResp_RoomInfo, 0),
|
||||
}
|
||||
}
|
||||
copyRoomListMap[moduleId].List = append(copyRoomListMap[moduleId].List, item)
|
||||
}
|
||||
}
|
||||
s.commonRoomList.Store(copyRoomListMap)
|
||||
}
|
||||
|
||||
func (s *IndexService) allcommonListProc() {
|
||||
for {
|
||||
time.Sleep(time.Second * 2)
|
||||
s.loadCommonListMap()
|
||||
}
|
||||
}
|
||||
|
||||
// 根据type从模块信息map拿到模块ids列表
|
||||
func (s *IndexService) getIdsFromModuleMap(ctx context.Context, iTypes []int64) (sIds []int64) {
|
||||
mMap := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
sIds = make([]int64, 0)
|
||||
for _, iType := range iTypes {
|
||||
typeList, ok := mMap[iType]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, item := range typeList {
|
||||
if item != nil {
|
||||
sIds = append(sIds, item.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
89
app/interface/live/app-interface/service/v2/live_rec.go
Normal file
89
app/interface/live/app-interface/service/v2/live_rec.go
Normal file
@ -0,0 +1,89 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
recommendV1 "go-common/app/service/live/recommend/api/grpc/v1"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_recTypeRecommend = 5
|
||||
_recNum = 6 //获取推荐的数量
|
||||
)
|
||||
|
||||
func (s *IndexService) getLiveRecRoomList(ctx context.Context, respMyIdol *v2pb.MMyIdol, mid int64, build int64, platform string, recPage int64, quality int64) (respLiuGangRecRoomList []*v2pb.CommonRoomItem, err error) {
|
||||
duplicate := make([]int64, 0)
|
||||
// ctx可以换带cancel或timeout的
|
||||
for _, idol := range respMyIdol.List {
|
||||
duplicate = append(duplicate, idol.Roomid)
|
||||
}
|
||||
|
||||
return s.getRecInfo(ctx, mid, duplicate, build, platform, recPage, quality)
|
||||
}
|
||||
|
||||
func (s *IndexService) getLiveRecRoomListForChange(ctx context.Context, mid int64, build int64, platform string, duplicate []int64, recPage int64, quality int64) (respLiuGangRecRoomList []*v2pb.CommonRoomItem, err error) {
|
||||
return s.getRecInfo(ctx, mid, duplicate, build, platform, recPage, quality)
|
||||
}
|
||||
|
||||
func (s *IndexService) getRecInfo(ctx context.Context, mid int64, duplicate []int64, build int64, platform string, recPage int64, quality int64) (respLiveRecRoomList []*v2pb.CommonRoomItem, err error) {
|
||||
// 天马对关注去重
|
||||
duplicates := duplicate
|
||||
|
||||
idolDuplicateMap := make(map[int64]bool)
|
||||
|
||||
for _, id := range duplicates {
|
||||
if _, ok := idolDuplicateMap[id]; !ok {
|
||||
idolDuplicateMap[id] = true
|
||||
}
|
||||
}
|
||||
// 获取强推
|
||||
strongRecLen := 0
|
||||
//不考虑位置好的
|
||||
recPool := s.getRecPoolAllPosition(ctx, nil, duplicates)
|
||||
// 获取强推
|
||||
if len(recPool) > 0 {
|
||||
for _, strongInfo := range recPool {
|
||||
if strongInfo.Roomid == 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := idolDuplicateMap[strongInfo.Roomid]; !ok {
|
||||
duplicates = append(duplicates, strongInfo.Roomid)
|
||||
strongRecLen++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
respLiveRecRoomList = make([]*v2pb.CommonRoomItem, 0)
|
||||
count := _recNum - strongRecLen
|
||||
if count <= 0 {
|
||||
count = _recNum
|
||||
}
|
||||
GetRandomRecResp, err := s.recommendConn.RandomRecsByUser(ctx, &recommendV1.GetRandomRecReq{
|
||||
Uid: mid,
|
||||
Count: uint32(count), // 首页6个推荐
|
||||
ExistIds: duplicates,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Error("[GetLiveRoomList]GetLiveRecResp err, err:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if GetRandomRecResp == nil {
|
||||
log.Error("[GetLiveRoomList]GetLiveRecResp empty err")
|
||||
return
|
||||
}
|
||||
|
||||
if len(GetRandomRecResp.RoomIds) < count {
|
||||
log.Info("[GetLiveRoomList]GetLiveRecResp not enough num:%d,mid:%d", len(GetRandomRecResp.RoomIds), mid)
|
||||
return
|
||||
}
|
||||
|
||||
respLiveRecRoomList, err = s.getRecRoomList(ctx, GetRandomRecResp.RoomIds, recPool, build, platform, idolDuplicateMap, _recTypeRecommend, quality)
|
||||
if err != nil {
|
||||
log.Error("[GetLiveRoomList]FillLiveRecRoomList err:%+v", err)
|
||||
}
|
||||
return
|
||||
}
|
110
app/interface/live/app-interface/service/v2/live_user.go
Normal file
110
app/interface/live/app-interface/service/v2/live_user.go
Normal file
@ -0,0 +1,110 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
liveUserDao "go-common/app/interface/live/app-interface/dao/live_user"
|
||||
liveUserV1 "go-common/app/service/live/live_user/api/liverpc/v1"
|
||||
"go-common/library/log"
|
||||
"go-common/library/net/metadata"
|
||||
)
|
||||
|
||||
const (
|
||||
_mmtagType = 12
|
||||
_mseaType = 14
|
||||
)
|
||||
|
||||
// GetIndexV2TagList ...
|
||||
// 获取APP首页 - 我的个人标签列表
|
||||
func (s *IndexService) GetIndexV2TagList(ctx context.Context, req *liveUserV1.UserSettingGetTagReq) (ret []*v2pb.MMyTag, err error) {
|
||||
ret = []*v2pb.MMyTag{}
|
||||
ExtraInfo := &v2pb.MyTagExtra{
|
||||
Offline: []*v2pb.OfflineTag{},
|
||||
}
|
||||
List := make([]*v2pb.MyTagItem, 0)
|
||||
res := &v2pb.MMyTag{}
|
||||
d := &liveUserDao.Dao{}
|
||||
moduleList := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
module, ok := moduleList[_mmtagType]
|
||||
if false == ok || 0 == len(module) {
|
||||
log.Error("[GetUserTagList]AllMinfoMap is empty error:%+v, %+v", err, moduleList)
|
||||
return
|
||||
}
|
||||
for _, v := range module {
|
||||
if v.Type == _mmtagType {
|
||||
var data *liveUserV1.UserSettingGetTagResp_Data
|
||||
data, err = d.GetUserTagList(ctx, req)
|
||||
if err != nil {
|
||||
log.Error("[GetUserTagList]live_user.v1.getTag rpc error:%+v, %+v", err, data)
|
||||
return
|
||||
}
|
||||
ExtraInfo.IsGray = data.IsGray
|
||||
for _, offlineInfo := range data.Offline {
|
||||
ExtraInfo.Offline = append(ExtraInfo.Offline, &v2pb.OfflineTag{Id: int64(offlineInfo.Id), AreaV2Name: offlineInfo.Name})
|
||||
}
|
||||
|
||||
for _, tagInfo := range data.Tags {
|
||||
link := fmt.Sprintf("http://live.bilibili.com/app/area?parent_area_id=%d&parent_area_name=%s&area_id=%d&area_name=%s", tagInfo.ParentId, tagInfo.ParentName, tagInfo.Id, tagInfo.Name)
|
||||
List = append(List, &v2pb.MyTagItem{AreaV2Id: int64(tagInfo.Id), AreaV2Name: tagInfo.Name, AreaV2ParentId: int64(tagInfo.ParentId), AreaV2ParentName: tagInfo.ParentName, Link: link, Pic: tagInfo.Pic, IsAdvice: int64(tagInfo.IsAdvice)})
|
||||
if len(List) >= 4 {
|
||||
break
|
||||
}
|
||||
}
|
||||
List = append(List, &v2pb.MyTagItem{AreaV2Id: 0, AreaV2Name: "全部标签", AreaV2ParentId: 0, AreaV2ParentName: "", Pic: "http://i0.hdslb.com/bfs/vc/ff03528785fc8c91491d79e440398484811d6d87.png", Link: "http://live.bilibili.com/app/mytag/", IsAdvice: 1})
|
||||
res.ExtraInfo = ExtraInfo
|
||||
res.List = List
|
||||
res.ModuleInfo = v
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
ret = append(ret, res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetIndexV2SeaPatrol ...
|
||||
// 获取APP首页 - 我的大航海提示信息
|
||||
func (s *IndexService) GetIndexV2SeaPatrol(ctx context.Context, req *liveUserV1.NoteGetReq) (ret []*v2pb.MSeaPatrol, err error) {
|
||||
ret = []*v2pb.MSeaPatrol{}
|
||||
_, isUIDSet := metadata.Value(ctx, metadata.Mid).(int64)
|
||||
if !isUIDSet {
|
||||
return
|
||||
}
|
||||
ExtraInfo := &v2pb.PicItem{}
|
||||
res := &v2pb.MSeaPatrol{}
|
||||
d := &liveUserDao.Dao{}
|
||||
moduleList := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
module, ok := moduleList[_mseaType]
|
||||
if false == ok || 0 == len(module) {
|
||||
log.Error("[GetIndexV2SeaPatrol]AllMinfoMap is empty error:%+v, %+v", err, moduleList)
|
||||
return
|
||||
}
|
||||
for _, v := range module {
|
||||
if v.Type == _mseaType {
|
||||
var data *liveUserV1.NoteGetResp_Data
|
||||
data, err = d.GetDaHangHai(ctx, req)
|
||||
if err != nil {
|
||||
log.Error("[GetIndexV2SeaPatrol]live_user.v1.getNoteSea rpc error:%+v, %+v", err, data)
|
||||
return
|
||||
}
|
||||
if data.Title == "" || data.Link == "" { // 返回信息为空
|
||||
return
|
||||
}
|
||||
ExtraInfo.Title = data.Title
|
||||
ExtraInfo.Pic = data.Logo
|
||||
ExtraInfo.Link = data.Link
|
||||
ExtraInfo.Content = data.Content
|
||||
ExtraInfo.Id = 0
|
||||
|
||||
res.ExtraInfo = ExtraInfo
|
||||
res.ModuleInfo = v
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
ret = append(ret, res)
|
||||
|
||||
return
|
||||
}
|
578
app/interface/live/app-interface/service/v2/livehomepage.go
Normal file
578
app/interface/live/app-interface/service/v2/livehomepage.go
Normal file
@ -0,0 +1,578 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/service/live/third_api/bvc"
|
||||
"go-common/library/sync/errgroup"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
"go-common/app/interface/live/app-interface/conf"
|
||||
"go-common/app/interface/live/app-interface/dao"
|
||||
relationV1 "go-common/app/interface/live/app-interface/service/v1"
|
||||
relationT "go-common/app/interface/live/app-interface/service/v1/relation"
|
||||
avV1 "go-common/app/service/live/av/api/liverpc/v1"
|
||||
relationRpcV1 "go-common/app/service/live/relation/api/liverpc/v1"
|
||||
roomV1 "go-common/app/service/live/room/api/liverpc/v1"
|
||||
accountM "go-common/app/service/main/account/model"
|
||||
actmdl "go-common/app/service/main/account/model"
|
||||
account "go-common/app/service/main/account/rpc/client"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// RelationService struct
|
||||
type RelationService struct {
|
||||
conf *conf.Config
|
||||
accountRPC *account.Service3
|
||||
}
|
||||
|
||||
const (
|
||||
relationPageSize = 4
|
||||
app536relationPageSize = 2
|
||||
)
|
||||
|
||||
// CheckLiveAnchorParams ... implementation
|
||||
// [app端关注首页]入参校验
|
||||
func CheckLiveAnchorParams(ctx context.Context, page int64) (uid int64, relationPage int64, err error) {
|
||||
mid := relationT.GetUIDFromHeader(ctx)
|
||||
relationPage = page
|
||||
err = nil
|
||||
if mid == 0 {
|
||||
err = errors.WithMessage(ecode.NeedLogIn, "GET SEA PATROL FAIL")
|
||||
return
|
||||
}
|
||||
if page <= 0 {
|
||||
err = errors.WithMessage(ecode.ResourceParamErr, "GET SEA PATROL FAIL")
|
||||
return
|
||||
}
|
||||
return mid, relationPage, err
|
||||
}
|
||||
|
||||
// LiveAnchorHomePage ... implementation
|
||||
// [app端关注首页]正在直播接口
|
||||
func (s *IndexService) LiveAnchorHomePage(ctx context.Context, relationPage int64, build int64, platform string, quality int64) (Resp []*v2pb.MMyIdol) {
|
||||
List := make([]*v2pb.MyIdolItem, 0)
|
||||
ExtraInfo := &v2pb.MyIdolExtra{CardType: relationT.App533CardType}
|
||||
Resp = make([]*v2pb.MMyIdol, 0)
|
||||
s.MakeLiveAnchorDefaultResult(Resp, ExtraInfo)
|
||||
uid, relationPage, err := CheckLiveAnchorParams(ctx, relationPage)
|
||||
if err != nil && uid != 0 {
|
||||
log.Error("[LiveAnchorHomePage]CheckParamsError,uid:%d,relationPage:%d", uid, relationPage)
|
||||
return
|
||||
}
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
relationInfo, groupList, mapUfos2Rolaids, mapRoomID2UID, AllRoomID, err := relationV1.GetAttentionListAndGroup(ctx)
|
||||
if err != nil {
|
||||
log.Error("[LiveAnchorHomePage]get_attentionList_rpc_error")
|
||||
return
|
||||
}
|
||||
// 获取全量room信息,不过滤
|
||||
roomParams := &roomV1.RoomGetStatusInfoByUidsReq{Uids: groupList["all"], FilterOffline: 0, NeedBroadcastType: 1}
|
||||
// room
|
||||
roomResp := make(map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo)
|
||||
userResp := make(map[int64]*accountM.Card)
|
||||
roomCornerResp := make(map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result)
|
||||
pkResp := make(map[string]int64)
|
||||
wg.Go(func() error {
|
||||
roomResp, err = s.GetRoomInfo(ctx, roomParams)
|
||||
return err
|
||||
})
|
||||
if err = wg.Wait(); nil != err {
|
||||
log.Error("[LiveAnchorHomePage][first_step]get_room_rpc_error")
|
||||
return
|
||||
}
|
||||
livingUfos := make([]int64, 0)
|
||||
livingRolaids := make([]int64, 0)
|
||||
livingRoomInfo := GetLivingRooms(roomResp)
|
||||
// 没有人直播
|
||||
if len(livingRoomInfo) == 0 {
|
||||
GetLastLiveAnchorInfo(ctx, roomResp, AllRoomID, mapRoomID2UID, ExtraInfo)
|
||||
moduleInfoMap := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
for _, m := range moduleInfoMap[_feedType] {
|
||||
Resp = append(Resp, &v2pb.MMyIdol{ModuleInfo: m, List: List, ExtraInfo: ExtraInfo})
|
||||
}
|
||||
return
|
||||
}
|
||||
wgHasLive := &errgroup.Group{}
|
||||
wgHasLive, _ = errgroup.WithContext(ctx)
|
||||
for k, v := range livingRoomInfo {
|
||||
livingUfos = append(livingUfos, k)
|
||||
livingRolaids = append(livingRolaids, v.RoomId)
|
||||
}
|
||||
// user信息
|
||||
wgHasLive.Go(func() error {
|
||||
userResp, err = s.GetUserInfo(ctx, livingUfos)
|
||||
return err
|
||||
})
|
||||
// room
|
||||
roomPendentParams := &roomV1.RoomPendantGetPendantByIdsReq{Ids: livingRolaids, Type: relationT.PendentMobileBadge, Position: relationT.PendentPosition}
|
||||
wgHasLive.Go(func() error {
|
||||
roomCornerResp, err = s.GetRoomPendantInfo(ctx, roomPendentParams)
|
||||
return err
|
||||
})
|
||||
// pk_id
|
||||
pkParams := &avV1.PkGetPkIdsByRoomIdsReq{RoomIds: livingRolaids, Platform: platform}
|
||||
wgHasLive.Go(func() error {
|
||||
pkResp, err = s.GetPkID(ctx, pkParams)
|
||||
return err
|
||||
})
|
||||
if err = wgHasLive.Wait(); nil != err {
|
||||
log.Error("[LiveAnchorHomePage][second_step]room/main.account/pkID/rpc_error")
|
||||
return
|
||||
}
|
||||
attentionRoomListPlayURLMap := dao.BvcApi.GetPlayUrlMulti(ctx, livingRolaids, 0, quality, build, platform)
|
||||
// 下游数据收集完成
|
||||
mapSp := make([]int64, 0)
|
||||
normalSp := make([]int64, 0)
|
||||
mapSp = append(mapSp, groupList["special"]...)
|
||||
normalSp = append(normalSp, groupList["normal"]...)
|
||||
List = AdaptLivingField(livingRoomInfo, roomCornerResp, userResp, relationInfo, pkResp, attentionRoomListPlayURLMap, mapSp, normalSp, mapUfos2Rolaids)
|
||||
ExtraInfo.TotalCount = int64(len(List))
|
||||
|
||||
// 注释原因:app536灰度策略,需要恢复2卡样式(之前在535已全量4卡,但是需求变了)产品:古月
|
||||
// https://www.tapd.cn/20082211/prong/stories/view/1120082211001104459
|
||||
|
||||
// userExtParams := &userExV1.GrayRuleGetByMarkReq{Mark: relationT.App536GrayRule}
|
||||
// grayRule, err := relationT.GetGrayRule(ctx, userExtParams)
|
||||
// var UserExApp536Rule string
|
||||
// if err != nil {
|
||||
// log.Error("[LiveAnchorHomePage]get_GrayRule_rpc_error")
|
||||
// UserExApp536Rule = ""
|
||||
// } else if grayRule != nil {
|
||||
// UserExApp536Rule = grayRule.Content
|
||||
// }
|
||||
SliceList, page := s.SliceForHomePage(List, relationPage, uid, platform)
|
||||
ExtraInfo.RelationPage = page
|
||||
var result v2pb.MMyIdol
|
||||
result.ExtraInfo = ExtraInfo
|
||||
result.List = SliceList
|
||||
moduleInfoMap := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
for _, m := range moduleInfoMap[_feedType] {
|
||||
Resp = append(Resp, &v2pb.MMyIdol{ModuleInfo: m, List: result.List, ExtraInfo: result.ExtraInfo})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// AdaptLivingField ... implementation
|
||||
// [app端关注首页]填充数据
|
||||
func AdaptLivingField(roomInfo map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo,
|
||||
roomPendentInfo map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result,
|
||||
userResult map[int64]*accountM.Card,
|
||||
relationInfo map[int64]*relationRpcV1.BaseInfoGetFollowTypeResp_UidInfo,
|
||||
pkIDInfo map[string]int64, playURLInfo map[int64]*bvc.PlayUrlItem, specialUID []int64, normalUID []int64,
|
||||
mapUfos2Rolaids map[int64]int64) (resp []*v2pb.MyIdolItem) {
|
||||
|
||||
resp = make([]*v2pb.MyIdolItem, 0)
|
||||
normalResp := make([]*v2pb.MyIdolItem, 0)
|
||||
resp = make([]*v2pb.MyIdolItem, 0)
|
||||
if len(specialUID) > 0 {
|
||||
item := LiveFireField(roomInfo, roomPendentInfo, userResult, pkIDInfo, playURLInfo, relationInfo, specialUID, mapUfos2Rolaids)
|
||||
resp = AppSortRuleOnline(item)
|
||||
}
|
||||
if len(normalUID) > 0 {
|
||||
tempResp := LiveFireField(roomInfo, roomPendentInfo, userResult, pkIDInfo, playURLInfo, relationInfo, normalUID, mapUfos2Rolaids)
|
||||
normalResp = AppSortRuleOnline(tempResp)
|
||||
}
|
||||
if len(normalResp) > 0 {
|
||||
resp = append(resp, normalResp...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SliceForHomePage ... implementation
|
||||
// app534规则 [app端关注首页]首页slice逻辑,客户端只显示偶数个数,为兼容推荐去重,当个数为3时返回2
|
||||
// https://www.tapd.cn/20082211/prong/stories/view/1120082211001067961
|
||||
// https://www.tapd.cn/20082211/prong/stories/view/1120082211001085685
|
||||
//
|
||||
// app536规则 https://www.tapd.cn/20082211/prong/stories/view/1120082211001104459
|
||||
func (s *IndexService) SliceForHomePage(input []*v2pb.MyIdolItem, page int64, uid int64, platform string) (resp []*v2pb.MyIdolItem, relationPage int64) {
|
||||
resp = make([]*v2pb.MyIdolItem, 0)
|
||||
grayRule := s.App536ABTest(uid, platform)
|
||||
relationPage = page
|
||||
if len(input) <= 0 {
|
||||
return
|
||||
}
|
||||
count := int64(len(input))
|
||||
|
||||
// 536规则
|
||||
if grayRule == 1 {
|
||||
|
||||
switch count {
|
||||
case 1:
|
||||
{
|
||||
resp = input[:]
|
||||
relationPage = 1
|
||||
return
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
resp = input[:]
|
||||
relationPage = 1
|
||||
return
|
||||
}
|
||||
}
|
||||
var pageSize int64
|
||||
pageSize = page
|
||||
if page < 1 {
|
||||
pageSize = 1
|
||||
}
|
||||
start := (pageSize - 1) * app536relationPageSize
|
||||
end := int64(start + app536relationPageSize)
|
||||
// 正常slice
|
||||
if end <= count {
|
||||
resp = input[start:end]
|
||||
} else {
|
||||
// 回环逻辑,最后一页不足pagesize时返回第一页
|
||||
relationPage = 1
|
||||
startIndex := 0
|
||||
var startCount int64
|
||||
if count > app536relationPageSize {
|
||||
startCount = app536relationPageSize
|
||||
} else {
|
||||
startCount = count
|
||||
}
|
||||
resp = input[startIndex:startCount]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 536之前4卡逻辑
|
||||
switch count {
|
||||
case 1:
|
||||
{
|
||||
resp = input[:]
|
||||
relationPage = 1
|
||||
return
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
resp = input[:]
|
||||
relationPage = 1
|
||||
return
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
resp = input[0:2]
|
||||
relationPage = 1
|
||||
return
|
||||
}
|
||||
}
|
||||
var pageSize int64
|
||||
pageSize = page
|
||||
if page < 1 {
|
||||
pageSize = 1
|
||||
}
|
||||
start := (pageSize - 1) * relationPageSize
|
||||
end := int64(start + relationPageSize)
|
||||
if end <= count {
|
||||
resp = input[start:end]
|
||||
} else {
|
||||
relationPage = 1
|
||||
startIndex := 0
|
||||
var startCount int64
|
||||
if count > relationPageSize {
|
||||
startCount = relationPageSize
|
||||
} else {
|
||||
startCount = count
|
||||
}
|
||||
resp = input[startIndex:startCount]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// LiveFireField ... implementation
|
||||
// [app端关注首页]填充数据
|
||||
func LiveFireField(roomInfo map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo,
|
||||
roomPendentInfo map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result,
|
||||
userResult map[int64]*accountM.Card,
|
||||
pkIDInfo map[string]int64, playURLInfo map[int64]*bvc.PlayUrlItem,
|
||||
relationInfo map[int64]*relationRpcV1.BaseInfoGetFollowTypeResp_UidInfo,
|
||||
ufos []int64, mapUfos2Rolaids map[int64]int64) (resp []*v2pb.MyIdolItem) {
|
||||
for _, v := range ufos {
|
||||
item := v2pb.MyIdolItem{}
|
||||
roomID, roomIDExist := mapUfos2Rolaids[v]
|
||||
if !roomIDExist {
|
||||
continue
|
||||
}
|
||||
roomItem := roomInfo[v]
|
||||
roomPendentItem := roomPendentInfo[roomID]
|
||||
userItem := userResult[v]
|
||||
relationItem := relationInfo[v]
|
||||
pkItem := pkIDInfo[strconv.Itoa(int(roomID))]
|
||||
playURLItem := playURLInfo[roomID]
|
||||
if roomItem == nil || userItem == nil || relationItem == nil {
|
||||
continue
|
||||
}
|
||||
PlayURL := ""
|
||||
PlayURL265 := ""
|
||||
PlayURLAcc := make([]int64, 0)
|
||||
PlayURLCur := 0
|
||||
PendentRu := ""
|
||||
PendentRuColor := ""
|
||||
PendentRuPic := ""
|
||||
if playURLItem != nil {
|
||||
PlayURL = playURLItem.Url["h264"]
|
||||
PlayURL265 = playURLItem.Url["h265"]
|
||||
PlayURLAcc = playURLItem.AcceptQuality
|
||||
PlayURLCur = int(playURLItem.CurrentQuality)
|
||||
}
|
||||
if roomPendentItem != nil {
|
||||
PendentRu = roomPendentItem.Value
|
||||
PendentRuColor = roomPendentItem.BgColor
|
||||
PendentRuPic = roomPendentItem.BgPic
|
||||
}
|
||||
item.Roomid = roomItem.RoomId
|
||||
item.Uid = roomItem.Uid
|
||||
item.Uname = userItem.Name
|
||||
item.Face = userItem.Face
|
||||
item.Title = roomItem.Title
|
||||
item.LiveTagName = roomItem.AreaV2Name
|
||||
item.LiveTime = roomItem.LiveTime
|
||||
item.Online = roomItem.Online
|
||||
item.PlayUrl = PlayURL
|
||||
item.PlayUrlH265 = PlayURL265
|
||||
item.AcceptQuality = PlayURLAcc
|
||||
item.CurrentQuality = int64(PlayURLCur)
|
||||
item.PkId = pkItem
|
||||
item.Area = roomItem.Area
|
||||
item.AreaName = roomItem.AreaName
|
||||
item.AreaV2Id = roomItem.AreaV2Id
|
||||
item.AreaV2Name = roomItem.AreaV2Name
|
||||
item.AreaV2ParentId = roomItem.AreaV2ParentId
|
||||
item.AreaV2ParentName = roomItem.AreaV2ParentName
|
||||
item.BroadcastType = roomItem.BroadcastType
|
||||
item.Link = relationT.LiveDomain + strconv.Itoa(int(roomID)) + relationT.BoastURL + strconv.Itoa(int(item.BroadcastType))
|
||||
item.OfficialVerify = int64(RoleMap(userItem.Official.Role))
|
||||
item.SpecialAttention = relationItem.Special
|
||||
item.PendentRu = PendentRu
|
||||
item.PendentRuColor = PendentRuColor
|
||||
item.PendentRuPic = PendentRuPic
|
||||
if len(roomItem.CoverFromUser) == 0 {
|
||||
item.Cover = roomItem.Keyframe
|
||||
} else {
|
||||
item.Cover = roomItem.CoverFromUser
|
||||
}
|
||||
resp = append(resp, &item)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MakeLiveAnchorDefaultResult ...
|
||||
// 正在直播默认返回
|
||||
func (s *IndexService) MakeLiveAnchorDefaultResult(Resp []*v2pb.MMyIdol, ExtraInfo *v2pb.MyIdolExtra) {
|
||||
if ExtraInfo != nil {
|
||||
ExtraInfo.TotalCount = 0
|
||||
ExtraInfo.TagsDesc = ""
|
||||
ExtraInfo.UnameDesc = ""
|
||||
ExtraInfo.TimeDesc = ""
|
||||
// [历史原因]cardType只能为1,否则客户端报错,见 https://www.tapd.cn/20082211/prong/stories/view/1120082211001086997
|
||||
ExtraInfo.CardType = 1
|
||||
ExtraInfo.RelationPage = 1
|
||||
}
|
||||
moduleInfoMap := s.GetAllModuleInfoMapFromCache(context.TODO())
|
||||
for _, m := range moduleInfoMap[_feedType] {
|
||||
Resp = append(Resp, &v2pb.MMyIdol{ModuleInfo: m, List: []*v2pb.MyIdolItem{}, ExtraInfo: ExtraInfo})
|
||||
}
|
||||
}
|
||||
|
||||
// GetLivingRooms ... implementation
|
||||
// [app端关注首页]获取正在直播房间
|
||||
func GetLivingRooms(roomResult map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo) (liveRoom map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo) {
|
||||
liveRoom = make(map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo)
|
||||
if len(roomResult) == 0 {
|
||||
return
|
||||
}
|
||||
for k, v := range roomResult {
|
||||
if v.LiveStatus == relationV1.RoomStatusLive {
|
||||
liveRoom[k] = v
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CheckLiveAnchorParams implementation
|
||||
// 入参校验
|
||||
func (s *IndexService) CheckLiveAnchorParams(ctx context.Context, req *v2pb.GetAllListReq) (uid int64, relationPage int64, err error) {
|
||||
if req == nil {
|
||||
err = ecode.LiveAnchorReqV2ParamsNil
|
||||
return
|
||||
}
|
||||
uid = relationT.GetUIDFromHeader(ctx)
|
||||
if uid == 0 {
|
||||
err = errors.WithMessage(ecode.NeedLogIn, "GET SEA PATROL FAIL")
|
||||
return
|
||||
}
|
||||
if req.RelationPage <= 0 {
|
||||
log.Error("CallRelationLiveAnchorV2ParamsCheckError|relationPage:%d", req.RelationPage)
|
||||
err = errors.WithMessage(ecode.LiveAnchorReqV2ParamsError, "GET SEA PATROL FAIL")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetLastLiveAnchorInfo ... implementation
|
||||
// [app端关注首页]获取最新一次直播信息
|
||||
func GetLastLiveAnchorInfo(ctx context.Context, roomResult map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo,
|
||||
RoomIDs []int64, RoomID2UID map[int64]int64, ExtraInfo *v2pb.MyIdolExtra) (uid int64, relationPage int64, err error) {
|
||||
if len(roomResult) == 0 || len(RoomIDs) == 0 || len(RoomID2UID) == 0 {
|
||||
return
|
||||
}
|
||||
lastLiveTime, _ := relationT.GetLastLiveTime(ctx, RoomIDs)
|
||||
_, _, sorted := relationV1.GetLastAnchorLiveTime(lastLiveTime)
|
||||
var firstRoom int64
|
||||
var firstValue int64
|
||||
if sorted.Len() > 0 {
|
||||
for _, v := range sorted {
|
||||
firstRoom = int64(v.Key)
|
||||
firstValue = int64(v.Value)
|
||||
break
|
||||
}
|
||||
firstUID := int64(RoomID2UID[firstRoom])
|
||||
tempTime := make(map[int64]int64)
|
||||
if firstValue > 0 {
|
||||
tempTime[firstUID] = firstValue
|
||||
if roomItem, exist := roomResult[firstUID]; exist {
|
||||
ExtraInfo.UnameDesc = roomItem.Uname
|
||||
ExtraInfo.TagsDesc = roomItem.AreaV2Name
|
||||
liveDesc, _ := relationV1.TimeLineRule(tempTime, nil)
|
||||
ExtraInfo.TimeDesc = liveDesc[firstUID]
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetUserInfoData ...
|
||||
// 调用account grpc接口cards获取用户信息
|
||||
func (s *RelationService) GetUserInfoData(ctx context.Context, UIDs []int64) (userResult map[int64]*accountM.Card, err error) {
|
||||
|
||||
rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(relationT.AccountGRPC)
|
||||
params := relationT.ChunkCallInfo{ParamsName: "ufos", URLName: relationT.AccountGRPC, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
|
||||
userResult = make(map[int64]*accountM.Card)
|
||||
lens := len(UIDs)
|
||||
if lens <= 0 {
|
||||
return
|
||||
}
|
||||
// 批次
|
||||
params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
|
||||
chunkResult := make([]map[int64]*accountM.Card, params.ChunkNum)
|
||||
wg, _ := errgroup.WithContext(ctx)
|
||||
|
||||
for i := int64(1); i <= params.ChunkNum; i++ {
|
||||
x := i
|
||||
wg.Go(func() error {
|
||||
chunkUfosIds := make([]int64, 20)
|
||||
if x == params.ChunkNum {
|
||||
chunkUfosIds = UIDs[(x-1)*params.ChunkSize:]
|
||||
} else {
|
||||
chunkUfosIds = UIDs[(x-1)*params.ChunkSize : x*params.ChunkSize]
|
||||
}
|
||||
ret, err := s.accountRPC.Cards3(ctx, &actmdl.ArgMids{Mids: chunkUfosIds})
|
||||
if err != nil {
|
||||
err = errors.WithMessage(ecode.AccountGRPCError, "GET SEA PATROL FAIL")
|
||||
log.Error("Call main.Account.Cards Error.Infos(%+v) error(%+v)", chunkUfosIds, err)
|
||||
}
|
||||
chunkResult[x-1] = ret
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := wg.Wait(); err != nil {
|
||||
erelongInfo := relationT.ErrLogStrut{}
|
||||
erelongInfo.ErrType = "GoRoutingWaitError"
|
||||
erelongInfo.URLName = relationT.AccountGRPC
|
||||
erelongInfo.ErrDesc = relationT.GoRoutingErr
|
||||
erelongInfo.Code = 1003001
|
||||
erelongInfo.RPCTimeout = params.RPCTimeout
|
||||
erelongInfo.ErrorPtr = &err
|
||||
log.Error(erelongInfo.ErrType+"|"+erelongInfo.URLName+"|error:%+v"+"|Code:%d"+"|Msg:%s"+"|RPCTimeout:%d"+"|ChunkSize:%d"+"|ChunkNum:%d"+"|ParamsName:%s",
|
||||
*erelongInfo.ErrorPtr, erelongInfo.Code, erelongInfo.Msg, erelongInfo.RPCTimeout, erelongInfo.ChunkSize, erelongInfo.ChunkNum, params.ParamsName)
|
||||
err = errors.WithMessage(ecode.AccountGRPCFrameError, "GET SEA PATROL FAIL")
|
||||
return nil, err
|
||||
}
|
||||
// 整理数据
|
||||
for _, chunkItemList := range chunkResult {
|
||||
for _, item := range chunkItemList {
|
||||
if item != nil {
|
||||
userResult[item.Mid] = item
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// App536ABTest ... hard code配置
|
||||
// ABTest
|
||||
func (s *IndexService) App536ABTest(mid int64, platform string) (grayType int64) {
|
||||
// 因为ipad屏幕尺寸较大,展示2卡会影响体验,故如果是ipad客户端则使用4卡样式,产品:tianyumo
|
||||
if platform == "ipad" {
|
||||
return 0
|
||||
}
|
||||
mUID := mid % 100
|
||||
if mUID >= 0 && mUID <= 89 {
|
||||
// 4卡
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// 后台配置
|
||||
// // App536ABTest ...
|
||||
// // ABTest
|
||||
// func (s *IndexService) App536ABTest(content string, mid int64) (grayType int64) {
|
||||
// if len(content) == 0 {
|
||||
// grayType = 0
|
||||
// return
|
||||
// }
|
||||
// resultMap := make(map[string]int64)
|
||||
// resultMap["app536_4card_type"] = 0
|
||||
// resultMap["app536_2card_type"] = 1
|
||||
// typeMap := make([]string, 0)
|
||||
// mr := &[]GrayRule{}
|
||||
// if err := json.Unmarshal([]byte(content), mr); err != nil {
|
||||
// grayType = 0
|
||||
// return
|
||||
// }
|
||||
// ruleArr := *mr
|
||||
// scoreMap := make(map[string]int)
|
||||
//
|
||||
// for _, v := range ruleArr {
|
||||
// scoreMap[v.Mark] = int(RParseInt(v.Value, 100))
|
||||
// }
|
||||
// sortedScore := SortMapByValue(scoreMap)
|
||||
// scoreEnd := make([]int, 0)
|
||||
// for _, v := range sortedScore {
|
||||
// scoreEnd = append(scoreEnd, v.Value)
|
||||
// typeMap = append(typeMap, v.Key)
|
||||
// }
|
||||
// score1 := scoreEnd[0]
|
||||
// score2 := 100
|
||||
// section1 := make(map[int]bool)
|
||||
// section2 := make(map[int]bool)
|
||||
// for section1Loop := 0; section1Loop < score1; section1Loop++ {
|
||||
// section1[section1Loop] = true
|
||||
// }
|
||||
// for sectionLoop2 := score1; sectionLoop2 < score2; sectionLoop2++ {
|
||||
// section2[sectionLoop2] = true
|
||||
// }
|
||||
// result := int(mid % 100)
|
||||
// if scoreEnd[0] != 0 {
|
||||
// if _, exist := section1[result]; exist {
|
||||
// grayType = resultMap[typeMap[0]]
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// if scoreEnd[1] != 0 {
|
||||
// if _, exist := section2[result]; exist {
|
||||
// grayType = resultMap[typeMap[1]]
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// grayType = 0
|
||||
// return
|
||||
// }
|
88
app/interface/live/app-interface/service/v2/pic_list.go
Normal file
88
app/interface/live/app-interface/service/v2/pic_list.go
Normal file
@ -0,0 +1,88 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go-common/library/log"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
)
|
||||
|
||||
// 获取分区入口
|
||||
func (s *IndexService) getAreaEntrance(ctx context.Context) (res []*v2pb.MAreaEntrance) {
|
||||
moduleInfoMap := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
listMap := s.getAreaEntranceListMapFromCache(ctx)
|
||||
res = make([]*v2pb.MAreaEntrance, 0)
|
||||
for _, m := range moduleInfoMap[_entranceType] {
|
||||
if l, ok := listMap[m.Id]; ok {
|
||||
res = append(res, &v2pb.MAreaEntrance{
|
||||
ModuleInfo: m,
|
||||
List: l,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// load from cache
|
||||
func (s *IndexService) getAreaEntranceListMapFromCache(ctx context.Context) (res map[int64][]*v2pb.PicItem) {
|
||||
// load
|
||||
i := s.areaEntranceListMap.Load()
|
||||
// assert
|
||||
res, ok := i.(map[int64][]*v2pb.PicItem)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
// 回源&log
|
||||
res = s.getAreaEntranceListMap(ctx)
|
||||
log.Warn("[getAreaEntranceListMapFromCache]memory cache miss!! i:%+v; res:%+v", i, res)
|
||||
return
|
||||
}
|
||||
|
||||
// getAreaEntranceListMap raw
|
||||
func (s *IndexService) getAreaEntranceListMap(ctx context.Context) (listMap map[int64][]*v2pb.PicItem) {
|
||||
moduleIds := s.getIdsFromModuleMap(ctx, []int64{_entranceType})
|
||||
if len(moduleIds) <= 0 {
|
||||
return
|
||||
}
|
||||
areaResult, err := s.roomDao.GetAreaEntrance(ctx, moduleIds)
|
||||
if err != nil {
|
||||
log.Error("[loadAreaEntranceCache]roomDao.GetAreaEntrance get data error: %+v, data: %+v", err, areaResult)
|
||||
return
|
||||
}
|
||||
if len(areaResult) > 0 {
|
||||
listMap = make(map[int64][]*v2pb.PicItem)
|
||||
for moduleId, i := range areaResult {
|
||||
if i != nil && i.List != nil {
|
||||
for _, ii := range i.List {
|
||||
listMap[moduleId] = append(listMap[moduleId], &v2pb.PicItem{
|
||||
Id: ii.Id,
|
||||
Pic: ii.Pic,
|
||||
Link: ii.Link,
|
||||
Title: ii.Title,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ticker
|
||||
func (s *IndexService) areaEntranceProc() {
|
||||
for {
|
||||
time.Sleep(time.Minute * 1)
|
||||
s.loadAreaEntranceCache()
|
||||
}
|
||||
}
|
||||
func (s *IndexService) loadAreaEntranceCache() {
|
||||
areaEntranceListMap := s.getAreaEntranceListMap(context.TODO())
|
||||
if len(areaEntranceListMap) > 0 {
|
||||
s.areaEntranceListMap.Store(areaEntranceListMap)
|
||||
log.Info("[loadAreaEntranceCache]load data success!")
|
||||
}
|
||||
return
|
||||
}
|
180
app/interface/live/app-interface/service/v2/rank.go
Normal file
180
app/interface/live/app-interface/service/v2/rank.go
Normal file
@ -0,0 +1,180 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
bp "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
"go-common/app/interface/live/app-interface/dao"
|
||||
"go-common/app/service/live/room/api/liverpc/v1"
|
||||
accountM "go-common/app/service/main/account/model"
|
||||
"go-common/library/log"
|
||||
"go-common/library/sync/errgroup"
|
||||
)
|
||||
|
||||
type lastHourCache struct {
|
||||
Modules []*bp.MHourRank
|
||||
CTime int64
|
||||
}
|
||||
|
||||
const (
|
||||
_hourRankType = 5
|
||||
)
|
||||
|
||||
var LastHourItemCache atomic.Value
|
||||
|
||||
// 获取首页上小时排行榜
|
||||
func (s *IndexService) getLastHourTop3(ctx context.Context) (resp []*bp.MHourRank, err error) {
|
||||
moduleInfoMaps := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
resp = []*bp.MHourRank{}
|
||||
module, ok := moduleInfoMaps[_hourRankType]
|
||||
if !ok || 0 == len(module) {
|
||||
return
|
||||
}
|
||||
cacheResp, err := getLastHour3FromCache(ctx)
|
||||
|
||||
if 0 != len(cacheResp) && 0 != len(cacheResp[0].List) {
|
||||
resp = cacheResp
|
||||
return
|
||||
}
|
||||
// load
|
||||
resp, err = s.loadLastHourData(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
func setLastHour3Cache(c context.Context, modules []*bp.MHourRank) {
|
||||
cache := &lastHourCache{
|
||||
Modules: modules,
|
||||
CTime: time.Now().Unix(),
|
||||
}
|
||||
LastHourItemCache.Store(cache)
|
||||
return
|
||||
}
|
||||
|
||||
func getLastHour3FromCache(c context.Context) (resp []*bp.MHourRank, err error) {
|
||||
resp = make([]*bp.MHourRank, 0)
|
||||
now := time.Now().Unix()
|
||||
|
||||
resp = []*bp.MHourRank{}
|
||||
cache, ok := LastHourItemCache.Load().(*lastHourCache)
|
||||
if !ok || nil == cache {
|
||||
return
|
||||
}
|
||||
cTime := cache.CTime
|
||||
if now > (cTime + 60) {
|
||||
return
|
||||
}
|
||||
resp = cache.Modules
|
||||
return
|
||||
}
|
||||
|
||||
// loadLastHour 定时存cache
|
||||
func (s *IndexService) loadLastHour() {
|
||||
for {
|
||||
time.Sleep(time.Second * 20)
|
||||
s.loadLastHourData(context.TODO())
|
||||
}
|
||||
}
|
||||
|
||||
// loadLastHourData 获取上小时榜数据
|
||||
func (s *IndexService) loadLastHourData(ctx context.Context) (resp []*bp.MHourRank, err error) {
|
||||
moduleInfoMaps := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
resp = []*bp.MHourRank{}
|
||||
module, ok := moduleInfoMaps[_hourRankType]
|
||||
if !ok || 0 == len(module) {
|
||||
return
|
||||
}
|
||||
// extraInfo format
|
||||
var nowHourName string
|
||||
lastHourName := time.Now().Add(-time.Hour).Format("15")
|
||||
timeNum, _ := strconv.Atoi(lastHourName)
|
||||
lastHourName += ":00"
|
||||
if timeNum > 9 {
|
||||
nowHourName = strconv.Itoa(timeNum + 1)
|
||||
} else {
|
||||
nowHourName = time.Now().Format("15")
|
||||
}
|
||||
nowHourName += ":00"
|
||||
subTitle := lastHourName + "-" + nowHourName + " 总榜排名"
|
||||
|
||||
list := []*bp.HourRankItem{}
|
||||
roomReq := &v1.RoomGetStatusInfoByUidsReq{}
|
||||
roomResp := &v1.RoomGetStatusInfoByUidsResp{}
|
||||
userInfo := map[int64]*accountM.Card{}
|
||||
wg := &errgroup.Group{}
|
||||
// liveRpc call rankdb
|
||||
uids, err := s.rankdbDao.GetLastHourTop3(ctx)
|
||||
if 0 == len(uids) || nil != err {
|
||||
goto formatReturn
|
||||
}
|
||||
|
||||
wg, _ = errgroup.WithContext(ctx)
|
||||
wg.Go(func() error {
|
||||
// liveRpc call room
|
||||
roomReq.Uids = uids
|
||||
roomResp, err = dao.RoomApi.V1Room.GetStatusInfoByUids(ctx, roomReq)
|
||||
return err
|
||||
})
|
||||
wg.Go(func() error {
|
||||
// call account for UserInfo
|
||||
userInfo, err = s.rankdbDao.GetUserInfoData(ctx, uids)
|
||||
return err
|
||||
})
|
||||
|
||||
if err = wg.Wait(); nil != err {
|
||||
goto formatReturn
|
||||
}
|
||||
|
||||
if 0 != roomResp.Code || 0 == len(roomResp.Data) {
|
||||
log.Error("[app-interface][rankDbItem] liveRpc call room return error, code:%d, msg:%s", roomResp.Code, roomResp.Data)
|
||||
goto formatReturn
|
||||
}
|
||||
|
||||
if 0 == len(userInfo) {
|
||||
log.Error("[app-interface][rankDbItem] call account return empty")
|
||||
goto formatReturn
|
||||
}
|
||||
|
||||
for k, v := range uids {
|
||||
detail := &bp.HourRankItem{}
|
||||
if nil != roomResp.Data[v] {
|
||||
detail = &bp.HourRankItem{
|
||||
Roomid: roomResp.Data[v].RoomId,
|
||||
LiveStatus: roomResp.Data[v].LiveStatus,
|
||||
AreaV2ParentId: roomResp.Data[v].AreaV2ParentId,
|
||||
AreaV2Id: roomResp.Data[v].AreaV2Id,
|
||||
AreaV2ParentName: roomResp.Data[v].AreaV2ParentName,
|
||||
AreaV2Name: roomResp.Data[v].AreaV2Name,
|
||||
Uname: userInfo[v].Name,
|
||||
Face: userInfo[v].Face,
|
||||
}
|
||||
}
|
||||
if nil != userInfo[v] {
|
||||
detail.Uname = userInfo[v].Name
|
||||
detail.Face = userInfo[v].Face
|
||||
}
|
||||
detail.Rank = int64(k + 1)
|
||||
detail.Uid = v
|
||||
|
||||
list = append(list, detail)
|
||||
}
|
||||
|
||||
// format return
|
||||
formatReturn:
|
||||
for _, v := range module {
|
||||
if v.Type == _hourRankType {
|
||||
item := &bp.MHourRank{
|
||||
ModuleInfo: v,
|
||||
ExtraInfo: &bp.HourRankExtra{SubTitle: subTitle},
|
||||
List: list,
|
||||
}
|
||||
resp = append(resp, item)
|
||||
break
|
||||
}
|
||||
}
|
||||
moduleCache := resp
|
||||
setLastHour3Cache(ctx, moduleCache)
|
||||
return
|
||||
}
|
215
app/interface/live/app-interface/service/v2/rec_pool.go
Normal file
215
app/interface/live/app-interface/service/v2/rec_pool.go
Normal file
@ -0,0 +1,215 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
"go-common/app/interface/live/app-interface/dao"
|
||||
xrf "go-common/app/service/live/xroom-feed/api"
|
||||
"go-common/library/sync/errgroup"
|
||||
"go-common/library/xstr"
|
||||
|
||||
"context"
|
||||
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const _appModuleType = 1
|
||||
|
||||
// getRecPoolList
|
||||
func (s *IndexService) getRecPoolList(ctx context.Context, module int64, num int64, moduleExists []int64, otherExists []int64) (list map[int64]*xrf.RoomItem) {
|
||||
list = make(map[int64]*xrf.RoomItem)
|
||||
req := &xrf.RecPoolReq{
|
||||
ModuleType: module,
|
||||
PositionNum: num,
|
||||
ModuleExistRooms: xstr.JoinInts(moduleExists),
|
||||
OtherExistRooms: xstr.JoinInts(otherExists),
|
||||
From: "app-interface",
|
||||
}
|
||||
resp, ferr := s.xrfClient.RecPoolClient.GetList(ctx, req)
|
||||
if ferr != nil {
|
||||
log.Error("[rec_pool]GetList from xroom-feed err:%+v", ferr.Error())
|
||||
return
|
||||
}
|
||||
|
||||
list = resp.List
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) getRecPoolAllPosition(ctx context.Context, moduleRoomIDs, otherRoomIDs []int64) (recPool map[int64]*v2pb.CommonRoomItem) {
|
||||
recPool = make(map[int64]*v2pb.CommonRoomItem)
|
||||
|
||||
uids := make([]int64, 0)
|
||||
roomIds := make([]int64, 0)
|
||||
mapRoomIdToUid := make(map[int64]int64)
|
||||
|
||||
roomItem := s.getRecPoolList(ctx, _appModuleType, 6, moduleRoomIDs, otherRoomIDs)
|
||||
if len(roomItem) <= 0 {
|
||||
log.Info("[getRecPoolAllPosition]getRecPoolList roomItem empty")
|
||||
return
|
||||
}
|
||||
|
||||
for i, item := range roomItem {
|
||||
uids = append(uids, item.Uid)
|
||||
roomIds = append(roomIds, item.RoomId)
|
||||
mapRoomIdToUid[item.RoomId] = item.Uid
|
||||
recPool[i] = &v2pb.CommonRoomItem{
|
||||
Roomid: item.RoomId,
|
||||
Title: item.Title,
|
||||
Link: "/" + strconv.Itoa(int(item.RoomId)),
|
||||
AreaV2Id: item.AreaId,
|
||||
AreaV2Name: item.AreaName,
|
||||
AreaV2ParentId: item.ParentAreaId,
|
||||
AreaV2ParentName: item.ParentAreaName,
|
||||
Online: item.PopularityCount,
|
||||
Cover: s.getCover(item.Cover, item.Keyframe),
|
||||
RecType: item.RecType,
|
||||
AcceptQuality: []int64{2, 4},
|
||||
}
|
||||
}
|
||||
|
||||
if len(recPool) <= 0 {
|
||||
return
|
||||
}
|
||||
extraInfo := s.getExtraDataForRoom(ctx, roomIds, uids, mapRoomIdToUid)
|
||||
|
||||
for _, pool := range recPool {
|
||||
if _, ok := extraInfo[pool.Roomid]; ok {
|
||||
pool.Uname = extraInfo[pool.Roomid].UName
|
||||
pool.Face = extraInfo[pool.Roomid].Face
|
||||
pool.PendentRu = extraInfo[pool.Roomid].PendentRu
|
||||
pool.PendentRuPic = extraInfo[pool.Roomid].PendentRuPic
|
||||
pool.PendentRuColor = extraInfo[pool.Roomid].PendentRuColor
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) handleCommonRoomList(ctx context.Context, respMyIdol *v2pb.MMyIdol, respCommonRoomList []*v2pb.MRoomBlock, quality, build int64, platform string, device string) []*v2pb.MRoomBlock {
|
||||
moduleExistIds := make([]int64, 0)
|
||||
otherExistIds := make([]int64, 0)
|
||||
duplicateMap := make(map[int64]bool)
|
||||
for _, idol := range respMyIdol.List {
|
||||
otherExistIds = append(otherExistIds, idol.Roomid)
|
||||
duplicateMap[idol.Roomid] = true
|
||||
}
|
||||
for _, roomBlock := range respCommonRoomList {
|
||||
if roomBlock.ModuleInfo.Type == _recFormType || roomBlock.ModuleInfo.Type == _recSquareType {
|
||||
newRecRoomList := make([]*v2pb.CommonRoomItem, 0)
|
||||
for _, item := range roomBlock.List {
|
||||
if len(newRecRoomList) >= 24 {
|
||||
break
|
||||
}
|
||||
if _, ok := duplicateMap[item.Roomid]; !ok {
|
||||
newRecRoomList = append(newRecRoomList, item)
|
||||
moduleExistIds = append(moduleExistIds, item.Roomid)
|
||||
}
|
||||
}
|
||||
|
||||
// 投放位
|
||||
if device != "pad" {
|
||||
recPool, recPoolRooms := s.fourTimeRecPoolForYumo(ctx, moduleExistIds, otherExistIds)
|
||||
|
||||
log.Info("[handleCommonRoomList]投放位 recPool: %+v, moduleExistIds: %+v, otherExistIds:%+v", recPoolRooms, xstr.JoinInts(moduleExistIds), xstr.JoinInts(otherExistIds))
|
||||
|
||||
duplicateRecMap := make(map[int64]bool)
|
||||
for _, id := range recPoolRooms {
|
||||
duplicateRecMap[id] = true
|
||||
}
|
||||
newRecFilterCommonList := make([]*v2pb.CommonRoomItem, 0)
|
||||
for _, room := range newRecRoomList {
|
||||
if room == nil {
|
||||
continue
|
||||
}
|
||||
if _, ok := duplicateRecMap[room.Roomid]; !ok {
|
||||
newRecFilterCommonList = append(newRecFilterCommonList, room)
|
||||
}
|
||||
}
|
||||
filterList := make([]*v2pb.CommonRoomItem, 0)
|
||||
|
||||
for i := 0; i < 24; i++ {
|
||||
position := int64(i) + 1
|
||||
if item, ok := recPool[position]; ok {
|
||||
filterList = append(filterList, item)
|
||||
continue
|
||||
}
|
||||
if len(newRecFilterCommonList) <= 0 {
|
||||
continue
|
||||
}
|
||||
filterList = append(filterList, newRecFilterCommonList[0:1][0])
|
||||
newRecFilterCommonList = newRecFilterCommonList[1:]
|
||||
}
|
||||
roomBlock.List = filterList
|
||||
} else {
|
||||
roomBlock.List = newRecRoomList
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 拼playurl
|
||||
roomIds := make([]int64, 0)
|
||||
for _, commRoomBlock := range respCommonRoomList {
|
||||
for _, roomList := range commRoomBlock.List {
|
||||
roomIds = append(roomIds, roomList.Roomid)
|
||||
}
|
||||
}
|
||||
changeRoomListPlayURLMap := dao.BvcApi.GetPlayUrlMulti(ctx, roomIds, 0, quality, build, platform)
|
||||
|
||||
for _, v := range respCommonRoomList {
|
||||
for _, vv := range v.List {
|
||||
if changeRoomListPlayURLMap[vv.Roomid] != nil {
|
||||
vv.AcceptQuality = changeRoomListPlayURLMap[vv.Roomid].AcceptQuality
|
||||
vv.CurrentQuality = changeRoomListPlayURLMap[vv.Roomid].CurrentQuality
|
||||
vv.PlayUrl = changeRoomListPlayURLMap[vv.Roomid].Url["h264"]
|
||||
vv.PlayUrlH265 = changeRoomListPlayURLMap[vv.Roomid].Url["h265"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return respCommonRoomList
|
||||
}
|
||||
|
||||
// 一次请求 变为四次请求xroom feed
|
||||
func (s *IndexService) fourTimeRecPoolForYumo(ctx context.Context, moduleExistIds []int64, otherExistIds []int64) (recPool map[int64]*v2pb.CommonRoomItem, recPoolRooms map[int64]int64) {
|
||||
recPool = make(map[int64]*v2pb.CommonRoomItem)
|
||||
recPoolRooms = make(map[int64]int64)
|
||||
pageSize := 6
|
||||
if len(moduleExistIds) < pageSize {
|
||||
return
|
||||
}
|
||||
page := int64(math.Floor(float64(len(moduleExistIds)) / float64(pageSize)))
|
||||
|
||||
result := make([]map[int64]*v2pb.CommonRoomItem, page)
|
||||
wg := errgroup.Group{}
|
||||
var i int64
|
||||
for i = 1; i <= page; i++ {
|
||||
p := i - 1
|
||||
start := p * int64(pageSize)
|
||||
end := start + int64(pageSize)
|
||||
duplicateIds := moduleExistIds[start:end]
|
||||
|
||||
wg.Go(func() (err error) {
|
||||
result[p] = s.getRecPoolAllPosition(ctx, duplicateIds, otherExistIds)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
err := wg.Wait()
|
||||
if err != nil {
|
||||
log.Error("[fourTimeRecPoolForYumo]moduleExistIds: %+v, otherExistIds:%+v", xstr.JoinInts(moduleExistIds), xstr.JoinInts(otherExistIds))
|
||||
return
|
||||
}
|
||||
for page, recPoolMap := range result {
|
||||
for position, item := range recPoolMap {
|
||||
if item == nil {
|
||||
continue
|
||||
}
|
||||
p := position + int64(page*pageSize)
|
||||
recPool[p] = item
|
||||
recPoolRooms[p] = item.Roomid
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
43
app/interface/live/app-interface/service/v2/room_ex.go
Normal file
43
app/interface/live/app-interface/service/v2/room_ex.go
Normal file
@ -0,0 +1,43 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
)
|
||||
|
||||
// 首页banner
|
||||
func (s *IndexService) getIndexBanner(ctx context.Context, platform string, device string, build int64) (resp []*v2pb.MBanner) {
|
||||
bizList := map[int64]int64{
|
||||
0: _bannerType,
|
||||
}
|
||||
moduleList := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
for biz, moduleType := range bizList {
|
||||
for _, moduleInfo := range moduleList[moduleType] {
|
||||
bannerList, err := s.roomexDao.GetBanner(ctx, biz, 0, platform, device, build)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
res := &v2pb.MBanner{}
|
||||
list := make([]*v2pb.PicItem, 0)
|
||||
|
||||
for _, banner := range bannerList {
|
||||
id, _ := strconv.Atoi(banner.Id)
|
||||
list = append(list, &v2pb.PicItem{
|
||||
Id: int64(id),
|
||||
Link: banner.Link,
|
||||
Pic: banner.Pic,
|
||||
Title: banner.Title,
|
||||
Content: "",
|
||||
})
|
||||
}
|
||||
|
||||
res.ModuleInfo = moduleInfo
|
||||
res.List = list
|
||||
|
||||
resp = append(resp, res)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
307
app/interface/live/app-interface/service/v2/room_list.go
Normal file
307
app/interface/live/app-interface/service/v2/room_list.go
Normal file
@ -0,0 +1,307 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
"go-common/app/interface/live/app-interface/dao"
|
||||
roomV2 "go-common/app/service/live/room/api/liverpc/v2"
|
||||
"go-common/library/log"
|
||||
"go-common/library/xstr"
|
||||
)
|
||||
|
||||
type multiModuleInfo struct {
|
||||
areaName string
|
||||
parentAreaId int64
|
||||
areaId int64
|
||||
}
|
||||
|
||||
const _areaModuleLink = "https://live.bilibili.com/app/area?parent_area_id=%d&parent_area_name=%s&area_id=%d&area_name=%s"
|
||||
|
||||
func (s *IndexService) getCommonRoomListForIndex(ctx context.Context, build int64, platform string, quality int64) (respCommonRoomList []*v2pb.MRoomBlock) {
|
||||
respCommonRoomList = make([]*v2pb.MRoomBlock, 0)
|
||||
moduleInfoMap := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
roomModuleIDs := make([]int64, 0)
|
||||
for _, moduleType := range s.commonType {
|
||||
if _, ok := moduleInfoMap[moduleType]; ok {
|
||||
for _, moduleInfo := range moduleInfoMap[moduleType] {
|
||||
respCommonRoomList = append(respCommonRoomList, &v2pb.MRoomBlock{
|
||||
ModuleInfo: moduleInfo,
|
||||
})
|
||||
roomModuleIDs = append(roomModuleIDs, moduleInfo.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
s.getCommonRoomList(ctx, roomModuleIDs, respCommonRoomList)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) getCommonRoomList(ctx context.Context, moduleIds []int64, respCommonRoomList []*v2pb.MRoomBlock) (err error) {
|
||||
if len(moduleIds) <= 0 || len(respCommonRoomList) <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
roomListMap := make(map[int64]*roomV2.AppIndexGetRoomListByIdsResp_RoomList)
|
||||
roomListMap = s.getCommonListFromCache(moduleIds)
|
||||
|
||||
if roomListMap == nil {
|
||||
log.Error("[commonList]GetListByIds error, res:%+v", roomListMap)
|
||||
return
|
||||
}
|
||||
|
||||
for _, moduleInfo := range respCommonRoomList {
|
||||
moduleInfo.List = make([]*v2pb.CommonRoomItem, 0)
|
||||
if _, ok := roomListMap[moduleInfo.ModuleInfo.Id]; ok {
|
||||
for _, roomList := range roomListMap[moduleInfo.ModuleInfo.Id].List {
|
||||
if moduleInfo.ModuleInfo.Type == _parentAreaFormType ||
|
||||
moduleInfo.ModuleInfo.Type == _parentAreaSquareType ||
|
||||
moduleInfo.ModuleInfo.Type == _yunyingRecSquareType ||
|
||||
moduleInfo.ModuleInfo.Type == _yunyingRecFormType {
|
||||
|
||||
if len(moduleInfo.List) >= 4 {
|
||||
break
|
||||
}
|
||||
}
|
||||
moduleInfo.List = append(moduleInfo.List, &v2pb.CommonRoomItem{
|
||||
Roomid: roomList.Roomid,
|
||||
Title: roomList.Title,
|
||||
Uname: roomList.Uname,
|
||||
AreaV2Id: roomList.AreaV2Id,
|
||||
AreaV2Name: roomList.AreaV2Name,
|
||||
AreaV2ParentId: roomList.AreaV2ParentId,
|
||||
AreaV2ParentName: roomList.AreaV2ParentName,
|
||||
Online: roomList.Online,
|
||||
Face: roomList.Face,
|
||||
Cover: roomList.Cover,
|
||||
BroadcastType: roomList.BroadcastType,
|
||||
CurrentQuality: roomList.CurrentQuality,
|
||||
AcceptQuality: roomList.AcceptQuality,
|
||||
RecType: roomList.RecType,
|
||||
PendentRu: roomList.PendentRu,
|
||||
PendentRuColor: roomList.PendentRuColor,
|
||||
PendentRuPic: roomList.PendentRuPic,
|
||||
PlayUrl: roomList.PlayUrl,
|
||||
PlayUrlH265: roomList.PlayUrlH265,
|
||||
PkId: roomList.PkId,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) getCommonRoomListByID(ctx context.Context, moduleID int64, build int64, platform string, quality int64, device string, duplicates []int64) (respCommonRoomList []*v2pb.CommonRoomItem, err error) {
|
||||
respCommonRoomList = make([]*v2pb.CommonRoomItem, 0)
|
||||
duplicatesMap := make(map[int64]bool)
|
||||
|
||||
for _, roomID := range duplicates {
|
||||
duplicatesMap[roomID] = true
|
||||
}
|
||||
moduleExistIds := make([]int64, 0)
|
||||
if moduleID == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
roomListMap, err := s.roomDao.GetListByIds(ctx, []int64{moduleID})
|
||||
if err != nil {
|
||||
log.Error("[commonList]GetAllModuleListByIds error, error:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 24个对关注去重的item
|
||||
if _, ok := roomListMap[moduleID]; ok {
|
||||
list := roomListMap[moduleID].List
|
||||
for _, info := range list {
|
||||
if len(respCommonRoomList) >= 24 {
|
||||
break
|
||||
}
|
||||
if _, ok := duplicatesMap[info.Roomid]; !ok {
|
||||
respCommonRoomList = append(respCommonRoomList, &v2pb.CommonRoomItem{
|
||||
Roomid: info.Roomid,
|
||||
Title: info.Title,
|
||||
Uname: info.Uname,
|
||||
AreaV2Id: info.AreaV2Id,
|
||||
AreaV2Name: info.AreaV2Name,
|
||||
AreaV2ParentId: info.AreaV2ParentId,
|
||||
AreaV2ParentName: info.AreaV2ParentName,
|
||||
Online: info.Online,
|
||||
Face: info.Face,
|
||||
Cover: info.Cover,
|
||||
BroadcastType: info.BroadcastType,
|
||||
CurrentQuality: info.CurrentQuality,
|
||||
AcceptQuality: info.AcceptQuality,
|
||||
RecType: info.RecType,
|
||||
PendentRu: info.PendentRu,
|
||||
PendentRuColor: info.PendentRuColor,
|
||||
PendentRuPic: info.PendentRuPic,
|
||||
PlayUrl: info.PlayUrl,
|
||||
PlayUrlH265: info.PlayUrlH265,
|
||||
PkId: info.PkId,
|
||||
})
|
||||
moduleExistIds = append(moduleExistIds, info.Roomid)
|
||||
}
|
||||
}
|
||||
|
||||
filterList := make([]*v2pb.CommonRoomItem, 0)
|
||||
if device != "pad" {
|
||||
//投放位覆盖
|
||||
recPool, recPoolRooms := s.fourTimeRecPoolForYumo(ctx, moduleExistIds, duplicates)
|
||||
log.Info("[getCommonRoomListByID]投放位 recPool: %+v, moduleExistIds: %+v, otherExistIds:%+v", recPoolRooms, xstr.JoinInts(moduleExistIds), xstr.JoinInts(duplicates))
|
||||
|
||||
duplicateMap := make(map[int64]bool)
|
||||
for _, id := range recPoolRooms {
|
||||
duplicateMap[id] = true
|
||||
}
|
||||
newRecFilterCommonList := make([]*v2pb.CommonRoomItem, 0)
|
||||
for _, room := range respCommonRoomList {
|
||||
if _, ok := duplicateMap[room.Roomid]; !ok {
|
||||
newRecFilterCommonList = append(newRecFilterCommonList, room)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < 24; i++ {
|
||||
position := int64(i) + 1
|
||||
if item, ok := recPool[position]; ok {
|
||||
filterList = append(filterList, item)
|
||||
} else {
|
||||
if len(newRecFilterCommonList) <= 0 {
|
||||
continue
|
||||
}
|
||||
filterList = append(filterList, newRecFilterCommonList[0:1][0])
|
||||
newRecFilterCommonList = newRecFilterCommonList[1:]
|
||||
}
|
||||
}
|
||||
respCommonRoomList = filterList
|
||||
}
|
||||
|
||||
//获取playurl
|
||||
s.getPlayUrl(ctx, respCommonRoomList, quality, build, platform)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) getMultiRoomList(ctx context.Context, myTag []*v2pb.MMyTag, platform string, build int64, quality int64) (respMyTagRoomList []*v2pb.MRoomBlock, existAreaMap map[int64]bool) {
|
||||
// 未登陆
|
||||
respMyTagRoomList = make([]*v2pb.MRoomBlock, 0)
|
||||
existAreaMap = make(map[int64]bool) // for duplicate yunying rec
|
||||
if len(myTag) <= 0 {
|
||||
log.Warn("[getMultiRoomList]my tag empty!")
|
||||
return
|
||||
}
|
||||
|
||||
parentName := map[int64]string{
|
||||
1: "娱乐",
|
||||
2: "游戏",
|
||||
3: "手游",
|
||||
4: "绘画",
|
||||
5: "电台",
|
||||
}
|
||||
areaIds := make([]int64, 0)
|
||||
multiModuleInfos := make([]*multiModuleInfo, 0)
|
||||
for _, tag := range myTag {
|
||||
// 默认tag没有list 跳过
|
||||
if tag.ExtraInfo.IsGray == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, item := range tag.List {
|
||||
if item.AreaV2Id == 0 {
|
||||
// 过滤异常或全部标签
|
||||
continue
|
||||
}
|
||||
areaIds = append(areaIds, item.AreaV2Id)
|
||||
multiModuleInfos = append(multiModuleInfos, &multiModuleInfo{
|
||||
areaId: item.AreaV2Id,
|
||||
areaName: item.AreaV2Name,
|
||||
parentAreaId: item.AreaV2ParentId,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(areaIds) <= 0 {
|
||||
log.Info("[getMultiRoomList]no gray tag, so no room list")
|
||||
return
|
||||
}
|
||||
multiRoomListMap, err := s.roomDao.GetMultiRoomList(ctx, xstr.JoinInts(areaIds), platform)
|
||||
if err != nil {
|
||||
log.Error("[getMultiRoomList]roomDao.GetMultiRoomList get error:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
moduleInfoMap := s.GetAllModuleInfoMapFromCache(ctx)
|
||||
myTagRoomListTypeMap, exist := moduleInfoMap[_myAreaTagListType]
|
||||
if !exist || myTagRoomListTypeMap == nil || len(myTagRoomListTypeMap) <= 0 {
|
||||
log.Info("[getMultiRoomList]my tag room list module not exist, all: %+v", moduleInfoMap)
|
||||
return
|
||||
}
|
||||
roomIds := make([]int64, 0)
|
||||
for index, moduleInfo := range myTagRoomListTypeMap {
|
||||
if len(multiModuleInfos) <= index {
|
||||
// 后台多配的case,防止溢出
|
||||
continue
|
||||
}
|
||||
mInfo := multiModuleInfos[index]
|
||||
if mInfo == nil {
|
||||
continue
|
||||
}
|
||||
moduleInfo.Title = mInfo.areaName
|
||||
moduleInfo.Link = fmt.Sprintf(_areaModuleLink, mInfo.parentAreaId, parentName[mInfo.parentAreaId], mInfo.areaId, mInfo.areaName)
|
||||
item := &v2pb.MRoomBlock{
|
||||
ModuleInfo: moduleInfo,
|
||||
}
|
||||
|
||||
l, ok := multiRoomListMap[mInfo.areaId]
|
||||
if !ok || l == nil {
|
||||
continue
|
||||
}
|
||||
existAreaMap[mInfo.areaId] = true
|
||||
|
||||
innerList := make([]*v2pb.CommonRoomItem, 0)
|
||||
for _, v := range l {
|
||||
roomIds = append(roomIds, v.Roomid)
|
||||
innerList = append(innerList, &v2pb.CommonRoomItem{
|
||||
Roomid: v.Roomid,
|
||||
Title: v.Title,
|
||||
Uname: v.Uname,
|
||||
AreaV2Id: v.AreaV2Id,
|
||||
AreaV2Name: v.AreaV2Name,
|
||||
AreaV2ParentId: v.AreaV2ParentId,
|
||||
AreaV2ParentName: v.AreaV2ParentName,
|
||||
Online: v.Online,
|
||||
Face: v.Face,
|
||||
Cover: v.Cover,
|
||||
BroadcastType: v.BroadcastType,
|
||||
CurrentQuality: v.CurrentQuality,
|
||||
AcceptQuality: v.AcceptQuality,
|
||||
RecType: v.RecType,
|
||||
PendentRu: v.PendentRu,
|
||||
PendentRuColor: v.PendentRuColor,
|
||||
PendentRuPic: v.PendentRuPic,
|
||||
PlayUrl: v.PlayUrl,
|
||||
PlayUrlH265: v.PlayUrlH265,
|
||||
PkId: v.PkId,
|
||||
})
|
||||
}
|
||||
item.List = innerList
|
||||
respMyTagRoomList = append(respMyTagRoomList, item)
|
||||
}
|
||||
|
||||
// 拼playurl
|
||||
changeRoomListPlayURLMap := dao.BvcApi.GetPlayUrlMulti(ctx, roomIds, 0, quality, build, platform)
|
||||
|
||||
for _, v := range respMyTagRoomList {
|
||||
for _, vv := range v.List {
|
||||
if changeRoomListPlayURLMap[vv.Roomid] != nil {
|
||||
vv.AcceptQuality = changeRoomListPlayURLMap[vv.Roomid].AcceptQuality
|
||||
vv.CurrentQuality = changeRoomListPlayURLMap[vv.Roomid].CurrentQuality
|
||||
vv.PlayUrl = changeRoomListPlayURLMap[vv.Roomid].Url["h264"]
|
||||
vv.PlayUrlH265 = changeRoomListPlayURLMap[vv.Roomid].Url["h265"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"go-common/app/interface/live/app-interface/conf"
|
||||
)
|
||||
|
||||
var (
|
||||
s *IndexService
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Set("conf", "../../cmd/test.toml")
|
||||
if err := conf.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
s = NewIndexService(conf.Conf)
|
||||
}
|
74
app/interface/live/app-interface/service/v2/sky_horse.go
Normal file
74
app/interface/live/app-interface/service/v2/sky_horse.go
Normal file
@ -0,0 +1,74 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
v2pb "go-common/app/interface/live/app-interface/api/http/v2"
|
||||
"go-common/app/interface/live/app-interface/dao"
|
||||
"go-common/library/ecode"
|
||||
)
|
||||
|
||||
const (
|
||||
_skyHorseRecTimeOut = 100
|
||||
_recTypeForce = 3
|
||||
_mobileIndexBadgeColorDefault = "#FB9E60"
|
||||
_recTypeSkyHorse = 4
|
||||
)
|
||||
|
||||
func (s *IndexService) getSkyHorseRoomListForIndex(ctx context.Context, respMyIdol *v2pb.MMyIdol, mid int64, buvid string, build int64, platform string, recPage int64, quality int64) (respSkyHorseRoomList []*v2pb.CommonRoomItem, err error) {
|
||||
respSkyHorseRoomList = make([]*v2pb.CommonRoomItem, 0)
|
||||
duplicate := make([]int64, 0)
|
||||
// ctx可以换带cancel或timeout的
|
||||
for _, idol := range respMyIdol.List {
|
||||
duplicate = append(duplicate, idol.Roomid)
|
||||
}
|
||||
respSkyHorseRoomList, err = s.getSkyHorseRoomList(ctx, mid, buvid, build, platform, duplicate, recPage, quality)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *IndexService) getSkyHorseRoomList(ctx context.Context, uid int64, buvid string, build int64, platform string, idolIds []int64, recPage int64, quality int64) (respSkyHorseRoomList []*v2pb.CommonRoomItem, err error) {
|
||||
// 天马对关注去重
|
||||
duplicates := idolIds
|
||||
|
||||
idolDuplicateMap := make(map[int64]bool)
|
||||
|
||||
for _, id := range duplicates {
|
||||
if _, ok := idolDuplicateMap[id]; !ok {
|
||||
idolDuplicateMap[id] = true
|
||||
}
|
||||
}
|
||||
|
||||
strongRecLen := 0
|
||||
//天马不考虑位置好的
|
||||
recPool := s.getRecPoolAllPosition(ctx, nil, duplicates)
|
||||
// 获取强推
|
||||
if len(recPool) > 0 {
|
||||
for _, strongInfo := range recPool {
|
||||
if strongInfo.Roomid == 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := idolDuplicateMap[strongInfo.Roomid]; !ok {
|
||||
duplicates = append(duplicates, strongInfo.Roomid)
|
||||
strongRecLen++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skyHorseRec, skyHorseErr := dao.SkyHorseApi.GetSkyHorseRec(ctx, uid, buvid, build, platform, duplicates, strongRecLen, _skyHorseRecTimeOut)
|
||||
if skyHorseErr != nil {
|
||||
err = errors.WithMessage(ecode.SkyHorseError, "")
|
||||
return
|
||||
}
|
||||
|
||||
roomIds := make([]int64, 0)
|
||||
for _, skyHorseInfo := range skyHorseRec.Data {
|
||||
roomIds = append(roomIds, int64(skyHorseInfo.Id))
|
||||
}
|
||||
|
||||
return s.getRecRoomList(ctx, roomIds, recPool, build, platform, idolDuplicateMap, _recTypeSkyHorse, quality)
|
||||
}
|
208
app/interface/live/app-interface/service/v2/tools.go
Normal file
208
app/interface/live/app-interface/service/v2/tools.go
Normal file
@ -0,0 +1,208 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"go-common/library/net/metadata"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Pair ...
|
||||
// 自定义map排序结构
|
||||
type Pair struct {
|
||||
Key int64
|
||||
Value int64
|
||||
}
|
||||
|
||||
// Gray ...
|
||||
// 自定义灰度策略结构
|
||||
type Gray struct {
|
||||
Key string
|
||||
Value int
|
||||
}
|
||||
|
||||
// GrayRule ...
|
||||
// 自定义灰度策略
|
||||
type GrayRule struct {
|
||||
Name string `json:"name"`
|
||||
Mark string `json:"mark"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// PairList ...
|
||||
// 自定义灰度策略
|
||||
type PairList []Pair
|
||||
|
||||
// GrayList ...
|
||||
// 自定义灰度策略
|
||||
type GrayList []Gray
|
||||
|
||||
// Swap
|
||||
// 自定义排序
|
||||
func (p PairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
// Len
|
||||
// 自定义排序
|
||||
func (p PairList) Len() int { return len(p) }
|
||||
|
||||
// Less
|
||||
// 自定义排序
|
||||
func (p PairList) Less(i, j int) bool { return p[i].Value > p[j].Value }
|
||||
|
||||
// Swap
|
||||
// 自定义排序
|
||||
func (p GrayList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
// Len
|
||||
// 自定义排序
|
||||
func (p GrayList) Len() int { return len(p) }
|
||||
|
||||
// Less
|
||||
// 自定义排序
|
||||
func (p GrayList) Less(i, j int) bool { return p[i].Value < p[j].Value }
|
||||
|
||||
// SortMap ...
|
||||
// 自定义排序
|
||||
func SortMap(input map[int64]int64) (sorted PairList) {
|
||||
|
||||
p := make(PairList, len(input))
|
||||
i := 0
|
||||
for k, v := range input {
|
||||
p[i] = Pair{k, v}
|
||||
i++
|
||||
}
|
||||
sort.Sort(p)
|
||||
sorted = p
|
||||
return
|
||||
}
|
||||
|
||||
// SortMapByValue ...
|
||||
// 自定义排序
|
||||
func SortMapByValue(m map[string]int) GrayList {
|
||||
p := make(GrayList, len(m))
|
||||
i := 0
|
||||
for k, v := range m {
|
||||
p[i] = Gray{k, v}
|
||||
i++
|
||||
}
|
||||
sort.Sort(p)
|
||||
return p
|
||||
}
|
||||
|
||||
// RoleMap ...
|
||||
// 兼容主站个人认证信息
|
||||
// 见 http://info.bilibili.co/pages/viewpage.action?pageId=8742464
|
||||
// 当前与客户端约定为, 0:个人 1:企业 -1:没有
|
||||
func RoleMap(role int8) (changeType int64) {
|
||||
switch role {
|
||||
case 0:
|
||||
{
|
||||
changeType = -1
|
||||
}
|
||||
case 1, 2:
|
||||
{
|
||||
changeType = 0
|
||||
}
|
||||
case 3, 4, 5, 6:
|
||||
{
|
||||
changeType = 1
|
||||
}
|
||||
default:
|
||||
{
|
||||
changeType = -1
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RParseInt ...
|
||||
// 转int
|
||||
func RParseInt(inputStr string, defaultValue int64) (output int64) {
|
||||
if mid, err := strconv.ParseInt(inputStr, 10, 64); err == nil {
|
||||
output = mid
|
||||
} else {
|
||||
output = defaultValue
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// App531ABTest ...
|
||||
// ABTest
|
||||
func (s *IndexService) App531ABTest(ctx context.Context, content string) (grayType int64) {
|
||||
if len(content) == 0 {
|
||||
grayType = 0
|
||||
return
|
||||
}
|
||||
resultMap := make(map[string]int64)
|
||||
resultMap["double_small_card"] = 0
|
||||
resultMap["card_not_auto_play"] = 1
|
||||
resultMap["card_auto_play"] = 2
|
||||
typeMap := make([]string, 0)
|
||||
mr := &[]GrayRule{}
|
||||
if err := json.Unmarshal([]byte(content), mr); err != nil {
|
||||
grayType = 0
|
||||
return
|
||||
}
|
||||
ruleArr := *mr
|
||||
scoreMap := make(map[string]int)
|
||||
|
||||
for _, v := range ruleArr {
|
||||
scoreMap[v.Mark] = int(RParseInt(v.Value, 100))
|
||||
}
|
||||
sortedScore := SortMapByValue(scoreMap)
|
||||
scoreEnd := make([]int, 0)
|
||||
for _, v := range sortedScore {
|
||||
scoreEnd = append(scoreEnd, v.Value)
|
||||
typeMap = append(typeMap, v.Key)
|
||||
}
|
||||
score1 := scoreEnd[0]
|
||||
score2 := scoreEnd[0] + scoreEnd[1]
|
||||
score3 := 100
|
||||
section1 := make(map[int]bool)
|
||||
section2 := make(map[int]bool)
|
||||
section3 := make(map[int]bool)
|
||||
for section1Loop := 0; section1Loop < score1; section1Loop++ {
|
||||
section1[section1Loop] = true
|
||||
}
|
||||
for sectionLoop2 := score1; sectionLoop2 < score2; sectionLoop2++ {
|
||||
section2[sectionLoop2] = true
|
||||
}
|
||||
for sectionLoop3 := score2; sectionLoop3 < score3; sectionLoop3++ {
|
||||
section3[sectionLoop3] = true
|
||||
}
|
||||
mid := GetUIDFromHeader(ctx)
|
||||
result := int(mid % 100)
|
||||
if scoreEnd[0] != 0 {
|
||||
if _, exist := section1[result]; exist {
|
||||
grayType = resultMap[typeMap[0]]
|
||||
return
|
||||
}
|
||||
}
|
||||
if scoreEnd[1] != 0 {
|
||||
if _, exist := section2[result]; exist {
|
||||
grayType = resultMap[typeMap[1]]
|
||||
return
|
||||
}
|
||||
}
|
||||
if scoreEnd[2] != 0 {
|
||||
if _, exist := section3[result]; exist {
|
||||
grayType = resultMap[typeMap[2]]
|
||||
return
|
||||
}
|
||||
}
|
||||
grayType = 0
|
||||
return
|
||||
}
|
||||
|
||||
// GetUIDFromHeader ...
|
||||
// 获取uid
|
||||
func GetUIDFromHeader(ctx context.Context) (uid int64) {
|
||||
midInterface, isUIDSet := metadata.Value(ctx, metadata.Mid).(int64) // 大多使用header里的mid解析, 框架已封装请求的header
|
||||
mid := int64(0)
|
||||
if isUIDSet {
|
||||
mid = midInterface
|
||||
}
|
||||
uid = mid
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user