123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928 |
- package v1
- import (
- "context"
- "math"
- "strconv"
- "time"
- "go-common/library/sync/errgroup"
- "github.com/pkg/errors"
- v1pb "go-common/app/interface/live/app-interface/api/http/v1"
- "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"
- relationV1 "go-common/app/service/live/relation/api/liverpc/v1"
- roomV1 "go-common/app/service/live/room/api/liverpc/v1"
- roomExV1 "go-common/app/service/live/room_ex/api/liverpc/v1"
- playurlbvc "go-common/app/service/live/third_api/bvc"
- userExV1 "go-common/app/service/live/userext/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"
- "go-common/library/net/rpc/liverpc"
- liveConText "go-common/library/net/rpc/liverpc/context"
- rpcCtx "go-common/library/net/rpc/liverpc/context"
- )
- // RelationService struct
- type RelationService struct {
- conf *conf.Config
- accountRPC *account.Service3
- // optionally add other properties here, such as dao
- // dao *dao.Dao
- }
- // NewRelationService init
- func NewRelationService(c *conf.Config) (s *RelationService) {
- s = &RelationService{
- conf: c,
- accountRPC: account.New3(nil),
- }
- return s
- }
- const (
- // RoomStatusLive ...
- RoomStatusLive = 1
- // MobileIndexBadgeColorDefault ...
- MobileIndexBadgeColorDefault = "#FB9E60"
- )
- // UnliveAnchor ... implementation
- // 直播二级页暂未开播接口
- func (s *RelationService) UnliveAnchor(ctx context.Context, req *v1pb.UnLiveAnchorReq) (resp *v1pb.UnLiveAnchorResp, err error) {
- resp = &v1pb.UnLiveAnchorResp{}
- config := conf.GetDummyUidConf()
- if config == relationT.DummyUIDEnable {
- dummyHeader := &liverpc.Header{Uid: relationT.RParseInt(req.Buyaofangqizhiliao, relationT.SelfUID)}
- ctx = liveConText.WithHeader(ctx, dummyHeader)
- }
- MakeUnLiveDefaultResult(resp)
- uid := relationT.GetUIDFromHeader(ctx)
- if uid <= 0 && config == 0 {
- return
- }
- wg, _ := errgroup.WithContext(ctx)
- pass, page, pageSize, uid, err := CheckUnLiveAnchorParams(ctx, req)
- if !pass {
- log.Error("[UnLiveAnchor]CheckParamsError,page:%d,pageSize:%d,uid:%d", page, pageSize, uid)
- return
- }
- relationInfo, groupList, mapUfos2Rolaids, mapRolaids2Ufos, setRolaids, err := GetAttentionListAndGroup(ctx)
- if err != nil {
- log.Error("[LiveAnchor]get_attentionList_rpc_error")
- return
- }
- // 获取有效(曾经直播过)主播,剪枝roomIDs
- lastLiveTime, _ := relationT.GetLastLiveTime(ctx, setRolaids)
- alienableRolaids, liberateInfo, sorted := FilterEverLived(lastLiveTime)
- alienableUfos := GetUID(mapRolaids2Ufos, alienableRolaids)
- roomExReq := &roomExV1.RoomNewsMultiGetReq{RoomIds: alienableRolaids, IsDecoded: 1}
- roomParams := &roomV1.RoomGetStatusInfoByUidsReq{Uids: groupList["all"], FilterOffline: 0}
- userInfo := make(map[int64]*accountM.Card)
- roomResp := make(map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo)
- roomExResp := make(map[int64]*roomExV1.RoomNewsMultiGetResp_Data)
- userfcResp := make(map[int64]*relationV1.FeedGetUserFcBatchResp_RelationList)
- // room
- wg.Go(func() error {
- roomResp, err = relationT.GetRoomInfo(ctx, roomParams)
- return err
- })
- // user信息
- wg.Go(func() error {
- userInfo, err = s.GetUserInfoData(ctx, alienableUfos)
- return err
- })
- // roomEx
- wg.Go(func() error {
- roomExResp, err = relationT.GetRoomNewsInfo(ctx, roomExReq)
- return err
- })
- // fansNum
- wg.Go(func() error {
- userfcResp, err = GetUserFc(ctx, alienableUfos)
- return err
- })
- waitErr := wg.Wait()
- if waitErr != nil {
- log.Error("[UnLiveAnchor][step2] rpc error: %s", waitErr)
- return
- }
- mapSp := make(map[int64]bool)
- normalSp := make(map[int64]bool)
- for _, v := range groupList["special"] {
- mapSp[v] = true
- }
- for _, v := range groupList["normal"] {
- normalSp[v] = true
- }
- specialRoomed, normalRoomed := s.GroupByRule(ctx, mapSp, normalSp, liberateInfo, sorted, mapRolaids2Ufos)
- specialUID := GetUID(mapRolaids2Ufos, specialRoomed)
- normalUID := GetUID(mapRolaids2Ufos, normalRoomed)
- liveDesc, newsDesc := CalcTimeLine(liberateInfo, roomExResp)
- LiveCount := CountLiveRooms(roomResp)
- resp.Rooms = AdaptField(roomResp, userfcResp, userInfo, roomExResp, relationInfo, specialUID, normalUID, mapUfos2Rolaids, liveDesc, newsDesc)
- resp.TotalCount = int64(len(resp.Rooms))
- resp.NoRoomCount = int64(len(setRolaids) - int(resp.TotalCount) - int(LiveCount))
- resp.Rooms = UnLiveAnchorSlice(resp.Rooms, page, pageSize)
- if (page * pageSize) >= resp.TotalCount {
- resp.HasMore = 0
- } else {
- resp.HasMore = 1
- }
- return
- }
- // CountLiveRooms 计算正在直播数目
- func CountLiveRooms(input map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo) (count int) {
- if len(input) <= 0 {
- count = 0
- return
- }
- for _, v := range input {
- if v.LiveStatus == RoomStatusLive {
- count++
- }
- }
- return
- }
- // CheckUnLiveAnchorParams implementation
- // 入参校验
- func CheckUnLiveAnchorParams(ctx context.Context, req *v1pb.UnLiveAnchorReq) (pass bool, page int64, pageSize int64, uid int64, err error) {
- if req == nil {
- pass = false
- return
- }
- config := conf.GetDummyUidConf()
- uid = relationT.GetUIDFromHeader(ctx)
- if uid == 0 && config == 0 {
- err = errors.WithMessage(ecode.NeedLogIn, "GET SEA PATROL FAIL")
- pass = false
- return
- }
- page = req.Page
- pageSize = req.Pagesize
- if page <= 0 || pageSize <= 0 {
- pass = false
- log.Error("CallRelationUnLiveAnchorParamsCheckError|page:%d,pageSize:%d", page, pageSize)
- err = errors.WithMessage(ecode.UnliveAnchorReqParamsError, "GET SEA PATROL FAIL")
- return
- }
- pass = true
- return
- }
- // CheckLiveAnchorParams implementation
- // 入参校验
- func CheckLiveAnchorParams(ctx context.Context, req *v1pb.LiveAnchorReq) (sortRule int64, filterRule int64, uid int64, err error) {
- if req == nil {
- err = ecode.LiveAnchorReqParamsNil
- return
- }
- sortRule = req.SortRule
- filterRule = req.FilterRule
- uid = relationT.GetUIDFromHeader(ctx)
- config := conf.GetDummyUidConf()
- if uid == 0 && config == 0 {
- err = errors.WithMessage(ecode.NeedLogIn, "GET SEA PATROL FAIL")
- return
- }
- if sortRule < 0 || filterRule < 0 {
- log.Error("CallRelationLiveAnchorParamsCheckError|page:%d,pageSize:%d", sortRule, filterRule)
- err = errors.WithMessage(ecode.LiveAnchorReqParamsError, "GET SEA PATROL FAIL")
- return
- }
- return
- }
- // UnLiveAnchorSlice implementation
- // 分页逻辑
- func UnLiveAnchorSlice(req []*v1pb.UnLiveAnchorResp_Rooms, page int64, pageSize int64) (resp []*v1pb.UnLiveAnchorResp_Rooms) {
- resp = make([]*v1pb.UnLiveAnchorResp_Rooms, 0)
- start := (page - 1) * pageSize
- end := start + pageSize
- length := int64(len(req))
- if start >= length {
- return
- }
- if end >= length {
- resp = req[start:]
- } else {
- resp = req[start:end]
- }
- return
- }
- // MakeUnLiveDefaultResult implementation
- // 缺省返回
- func MakeUnLiveDefaultResult(resp *v1pb.UnLiveAnchorResp) {
- if resp != nil {
- resp.HasMore = 0
- resp.NoRoomCount = 0
- resp.TotalCount = 0
- resp.Rooms = make([]*v1pb.UnLiveAnchorResp_Rooms, 0)
- }
- }
- // GroupByRule implementation
- // 按照规则排序,组间按照特别关注优先,组内按照上次关播时间倒序
- func (s *RelationService) GroupByRule(ctx context.Context, special map[int64]bool, normal map[int64]bool,
- liberate map[int64]int64, sorted relationT.PairList, mapRolaids2Ufos map[int64]int64) (specialRoomed []int64, normalRoomed []int64) {
- specialRoomed = make([]int64, 0)
- normalRoomed = make([]int64, 0)
- if len(liberate) == 0 || liberate == nil {
- return
- }
- for _, v := range sorted {
- if _, ok := special[mapRolaids2Ufos[v.Key]]; ok {
- specialRoomed = append(specialRoomed, v.Key)
- } else {
- normalRoomed = append(normalRoomed, v.Key)
- }
- }
- return
- }
- // AdaptField implementation
- // 填充逻辑
- func AdaptField(roomInfo map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo,
- fansInfo map[int64]*relationV1.FeedGetUserFcBatchResp_RelationList,
- userResult map[int64]*accountM.Card,
- roomedInfo map[int64]*roomExV1.RoomNewsMultiGetResp_Data,
- relationInfo map[int64]*relationV1.BaseInfoGetFollowTypeResp_UidInfo,
- specialUID []int64, normalUID []int64,
- mapUfos2Rolaids map[int64]int64, liveDesc map[int64]string, newsDesc map[int64]string) (resp []*v1pb.UnLiveAnchorResp_Rooms) {
- var item []*v1pb.UnLiveAnchorResp_Rooms
- resp = make([]*v1pb.UnLiveAnchorResp_Rooms, 0)
- if len(specialUID) > 0 {
- item = FireField(roomInfo, fansInfo, userResult, roomedInfo, relationInfo, specialUID, mapUfos2Rolaids, liveDesc, newsDesc)
- resp = append(resp, item...)
- }
- if len(normalUID) > 0 {
- item = FireField(roomInfo, fansInfo, userResult, roomedInfo, relationInfo, normalUID, mapUfos2Rolaids, liveDesc, newsDesc)
- resp = append(resp, item...)
- }
- return
- }
- // CalcTimeLine ...
- // 计算时间规则
- func CalcTimeLine(liberateInfo map[int64]int64,
- roomNewsInfo map[int64]*roomExV1.RoomNewsMultiGetResp_Data) (liveDesc map[int64]string, newsDesc map[int64]string) {
- liveDesc, newsDesc = TimeLineRule(liberateInfo, roomNewsInfo)
- return
- }
- // TimeLineRule ...
- // 计算时间规则
- func TimeLineRule(liberateInfo map[int64]int64, roomNewsInfo map[int64]*roomExV1.RoomNewsMultiGetResp_Data) (liveDesc map[int64]string, newsDesc map[int64]string) {
- liveDesc = make(map[int64]string)
- newsDesc = make(map[int64]string)
- if len(liberateInfo) <= 0 {
- return
- }
- for livedRoomed, lastLiveTime := range liberateInfo {
- now := time.Now()
- currentYear, currentMonth, currentDay := now.Date()
- currentLocation := now.Location()
- firstOfMonth := time.Date(currentYear, 1, 1, 0, 0, 0, 0, currentLocation)
- thisYearUnixTimeStamp := firstOfMonth.Unix()
- todayUnixTimeStamp := time.Date(currentYear, currentMonth, currentDay, 0, 0, 0, 0, currentLocation).Unix()
- today24 := math.Abs(float64(todayUnixTimeStamp - lastLiveTime))
- liveTime := math.Abs(float64(now.Unix() - lastLiveTime))
- if lastLiveTime == 0 {
- liveDesc[livedRoomed] = "上次"
- }
- if liveTime < 60 {
- liveDesc[livedRoomed] = "刚刚"
- } else if liveTime >= 60 && liveTime < 3600 {
- text := int(math.Floor(liveTime / 60))
- liveDesc[livedRoomed] = strconv.Itoa(text) + "分钟前"
- } else if liveTime >= 3600 && liveTime < 86400 {
- text := int(math.Floor(liveTime / 3600))
- liveDesc[livedRoomed] = strconv.Itoa(text) + "小时前"
- } else if liveTime >= 86400 && today24 <= 86400 {
- liveDesc[livedRoomed] = "昨天"
- } else if liveTime >= 86400 && lastLiveTime >= thisYearUnixTimeStamp {
- tm := time.Unix(lastLiveTime, 0)
- text := tm.Format("1-2")
- liveDesc[livedRoomed] = text
- } else {
- if lastLiveTime < thisYearUnixTimeStamp && liveTime >= 86400 {
- tm := time.Unix(lastLiveTime, 0)
- text := tm.Format("2006-1-2")
- liveDesc[livedRoomed] = text
- } else {
- tm := time.Unix(lastLiveTime, 0)
- text := tm.Format("2006-1-2")
- liveDesc[livedRoomed] = text
- }
- }
- }
- if len(roomNewsInfo) <= 0 {
- return
- }
- for livedRoomed, lastNewsTime := range roomNewsInfo {
- lastLiveTimeStr := lastNewsTime.Ctime
- now := time.Now()
- timeFmt, _ := time.ParseInLocation("2006-01-02 15:04:05", lastLiveTimeStr, time.Local)
- lastLiveTime := timeFmt.Unix()
- currentYear, currentMonth, currentDay := now.Date()
- currentLocation := now.Location()
- todayUnixTimeStamp := time.Date(currentYear, currentMonth, currentDay, 0, 0, 0, 0, currentLocation).Unix()
- today24 := math.Abs(float64(todayUnixTimeStamp - lastLiveTime))
- liveTime := math.Abs(float64(now.Unix() - lastLiveTime))
- if lastLiveTime == 0 {
- newsDesc[livedRoomed] = ""
- }
- if liveTime < 60 {
- newsDesc[livedRoomed] = "刚刚"
- } else if liveTime >= 60 && liveTime < 3600 {
- text := int(math.Floor(liveTime / 60))
- newsDesc[livedRoomed] = strconv.Itoa(text) + "分钟前"
- } else if liveTime >= 3600 && liveTime < 86400 {
- text := int(math.Floor(liveTime / 3600))
- newsDesc[livedRoomed] = strconv.Itoa(text) + "小时前"
- } else if liveTime >= 86400 && today24 <= 86400 {
- newsDesc[livedRoomed] = "昨天"
- }
- }
- return
- }
- // FireField ...
- // 适配返回值
- func FireField(roomInfo map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo,
- fansInfo map[int64]*relationV1.FeedGetUserFcBatchResp_RelationList,
- userResult map[int64]*accountM.Card,
- roomedInfo map[int64]*roomExV1.RoomNewsMultiGetResp_Data,
- relationInfo map[int64]*relationV1.BaseInfoGetFollowTypeResp_UidInfo,
- ufos []int64,
- mapUfos2Rolaids map[int64]int64, liveDesc map[int64]string, newsDesc map[int64]string) (resp []*v1pb.UnLiveAnchorResp_Rooms) {
- for _, v := range ufos {
- item := v1pb.UnLiveAnchorResp_Rooms{}
- roomID, roomIDExist := mapUfos2Rolaids[v]
- if !roomIDExist {
- continue
- }
- roomItem := roomInfo[v]
- userItem := userResult[v]
- fansItem := fansInfo[v]
- relationItem := relationInfo[v]
- roomedItem := roomedInfo[roomID]
- roomNewsDesc := newsDesc[roomID]
- liveDescItem := liveDesc[roomID]
- roomNewsContent := ""
- roomNewsDescText := ""
- if roomItem == nil || userItem == nil || relationItem == nil {
- continue
- }
- if roomItem.LiveStatus == RoomStatusLive {
- continue
- }
- if roomedItem != nil {
- roomNewsContent = roomedItem.NewsContent
- roomNewsDescText = roomNewsDesc
- }
- item.Roomid = roomItem.RoomId
- item.Uid = roomItem.Uid
- item.Uname = userItem.Name
- item.Face = userItem.Face
- item.LiveStatus = roomItem.LiveStatus
- 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(relationT.RoleMap(userItem.Official.Role))
- item.Attentions = fansItem.Fc
- item.SpecialAttention = relationItem.Special
- item.AnnouncementContent = roomNewsContent
- item.AnnouncementTime = roomNewsDescText
- item.LiveDesc = liveDescItem
- resp = append(resp, &item)
- }
- return
- }
- // LiveFireField ...
- // 适配返回值
- 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]*playurlbvc.PlayUrlItem,
- relationInfo map[int64]*relationV1.BaseInfoGetFollowTypeResp_UidInfo,
- ufos []int64, mapUfos2Rolaids map[int64]int64) (resp []*v1pb.LiveAnchorResp_Rooms) {
- for _, v := range ufos {
- item := v1pb.LiveAnchorResp_Rooms{}
- 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
- }
- if PendentRuColor == "" {
- PendentRuColor = MobileIndexBadgeColorDefault
- }
- 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.AcceptQuality = PlayURLAcc
- item.CurrentQuality = int64(PlayURLCur)
- item.PkId = pkItem
- item.Area = roomItem.Area
- item.AreaName = roomItem.AreaName
- item.AreaV2Id = roomItem.AreaV2Id
- item.PlayUrlH265 = PlayURL265
- 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(relationT.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
- }
- // GroupUfos ...
- // 按照关注类型分组
- func GroupUfos(input map[int64]*relationV1.BaseInfoGetFollowTypeResp_UidInfo) (resp map[string][]int64, err error) {
- if input == nil {
- return nil, nil
- }
- resp = make(map[string][]int64)
- for k, v := range input {
- if v.Special == 0 {
- resp["normal"] = append(resp["normal"], k)
- } else {
- resp["special"] = append(resp["special"], k)
- }
- resp["all"] = append(resp["all"], k)
- }
- return resp, nil
- }
- // GetUID ...
- // 获取uid
- func GetUID(idsMap map[int64]int64, input []int64) (resp []int64) {
- if idsMap == nil || input == nil {
- return nil
- }
- for _, v := range input {
- resp = append(resp, idsMap[int64(v)])
- }
- return resp
- }
- // FilterEverLived ...
- // 过滤未开播
- func FilterEverLived(lastLiveTime map[string]string) (rolaids []int64, lifetime map[int64]int64, sorted relationT.PairList) {
- rolaids = make([]int64, 0)
- lifetime = make(map[int64]int64)
- for roomed, v := range lastLiveTime {
- timeFmt, _ := time.ParseInLocation("2006-01-02 15:04:05", v, time.Local)
- if !timeFmt.IsZero() {
- if mid, err := strconv.ParseInt(roomed, 10, 64); err == nil {
- lifetime[mid] = timeFmt.Unix()
- rolaids = append(rolaids, mid)
- }
- }
- }
- sorted = make([]relationT.Pair, 0)
- sorted = relationT.SortMap(lifetime)
- return rolaids, lifetime, sorted
- }
- // GetLastAnchorLiveTime ...
- // 获取上一个主播信息
- func GetLastAnchorLiveTime(lastLiveTime map[string]string) (rolaids []int64, lifetime map[int64]int64, sorted relationT.PairList) {
- rolaids = make([]int64, 0)
- lifetime = make(map[int64]int64)
- for roomed, v := range lastLiveTime {
- timeFmt, _ := time.ParseInLocation("2006-01-02 15:04:05", v, time.Local)
- if mid, err := strconv.ParseInt(roomed, 10, 64); err == nil {
- lifetime[mid] = timeFmt.Unix()
- rolaids = append(rolaids, mid)
- }
- }
- sorted = make([]relationT.Pair, 0)
- sorted = relationT.SortMap(lifetime)
- return rolaids, lifetime, sorted
- }
- // MakeLiveAnchorDefaultResult ...
- // 正在直播默认返回
- func MakeLiveAnchorDefaultResult(resp *v1pb.LiveAnchorResp) {
- if resp != nil {
- resp.TotalCount = 0
- // [历史原因]cardType只能为1,否则客户端报错,见 https://www.tapd.cn/20082211/prong/stories/view/1120082211001086997
- resp.CardType = relationT.App533CardType
- resp.BigCardType = 0
- resp.Rooms = make([]*v1pb.LiveAnchorResp_Rooms, 0)
- }
- }
- // GetAttentionListAndGroup ...
- // 关注分组
- func GetAttentionListAndGroup(ctx context.Context) (relationInfo map[int64]*relationV1.BaseInfoGetFollowTypeResp_UidInfo, groupList map[string][]int64,
- mapUfos2Rolaids map[int64]int64, mapRolaids2Ufos map[int64]int64, setRolaids []int64, attentionErr error) {
- relationTimeout := conf.GetTimeout("relation", 200)
- attentionErr = nil
- attentionData, attentionErr := dao.RelationApi.V1BaseInfo.GetFollowType(
- rpcCtx.WithTimeout(ctx, time.Duration(relationTimeout)*time.Millisecond),
- &relationV1.BaseInfoGetFollowTypeReq{})
- if attentionErr != nil || attentionData == nil {
- attentionErr = ecode.AttentionListRPCError
- return
- }
- relationInfo = attentionData.Data
- groupList, _ = GroupUfos(attentionData.Data)
- // 转换ids
- mapUfos2Rolaids, err := relationT.UIDs2roomIDs(ctx, groupList["all"])
- if err != nil {
- attentionErr = ecode.RoomGetRoomIDCodeRPCError
- return
- }
- mapRolaids2Ufos, setRolaids = TransRoomedUUID(mapUfos2Rolaids)
- return
- }
- // TransRoomedUUID ...
- // 转换ids
- func TransRoomedUUID(mapUfos2Rolaids map[int64]int64) (mapRolaids2Ufos map[int64]int64, setRolaids []int64) {
- mapRolaids2Ufos = make(map[int64]int64)
- for k, v := range mapUfos2Rolaids {
- mapRolaids2Ufos[v] = k
- }
- setRolaids = make([]int64, 0)
- for _, v := range mapUfos2Rolaids {
- setRolaids = append(setRolaids, v)
- }
- return
- }
- // AdaptLivingField ...
- // 填充逻辑
- func AdaptLivingField(roomInfo map[int64]*roomV1.RoomGetStatusInfoByUidsResp_RoomInfo,
- roomPendentInfo map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result,
- userResult map[int64]*accountM.Card,
- relationInfo map[int64]*relationV1.BaseInfoGetFollowTypeResp_UidInfo,
- pkIDInfo map[string]int64, playURLInfo map[int64]*playurlbvc.PlayUrlItem, specialUID []int64, normalUID []int64,
- mapUfos2Rolaids map[int64]int64) (resp []*v1pb.LiveAnchorResp_Rooms) {
- var item []*v1pb.LiveAnchorResp_Rooms
- resp = make([]*v1pb.LiveAnchorResp_Rooms, 0)
- normalResp := make([]*v1pb.LiveAnchorResp_Rooms, 0)
- if len(specialUID) > 0 {
- item = LiveFireField(roomInfo, roomPendentInfo, userResult, pkIDInfo, playURLInfo, relationInfo, specialUID, mapUfos2Rolaids)
- tempResp := &v1pb.LiveAnchorResp{}
- tempResp.Rooms = item
- resp = relationT.AppSortRuleOnline(tempResp)
- }
- if len(normalUID) > 0 {
- item = LiveFireField(roomInfo, roomPendentInfo, userResult, pkIDInfo, playURLInfo, relationInfo, normalUID, mapUfos2Rolaids)
- tempResp := &v1pb.LiveAnchorResp{}
- tempResp.Rooms = item
- normalResp = relationT.AppSortRuleOnline(tempResp)
- }
- if len(normalResp) > 0 {
- resp = append(resp, normalResp...)
- }
- return
- }
- // LiveAnchor implementation
- // [app端关注二级页][全量]正在直播接口
- func (s *RelationService) LiveAnchor(ctx context.Context, req *v1pb.LiveAnchorReq) (resp *v1pb.LiveAnchorResp, err error) {
- resp = &v1pb.LiveAnchorResp{}
- MakeLiveAnchorDefaultResult(resp)
- sortRule, filterRule, uid, err := CheckLiveAnchorParams(ctx, req)
- wg, _ := errgroup.WithContext(ctx)
- if err != nil {
- log.Error("[LiveAnchor]CheckParamsError,page:%d,pageSize:%d,uid:%d", sortRule, filterRule, uid)
- return
- }
- relationInfo, groupList, mapUfos2Rolaids, _, _, err := GetAttentionListAndGroup(ctx)
- if err != nil {
- log.Error("[LiveAnchor]get_attentionList_rpc_error")
- return
- }
- // 获取有效(正在直播中)主播,剪枝roomIDs
- roomParams := &roomV1.RoomGetStatusInfoByUidsReq{Uids: groupList["all"], FilterOffline: 1, NeedBroadcastType: 1}
- // room
- roomResp, err := relationT.GetRoomInfo(ctx, roomParams)
- if err != nil {
- log.Error("[LiveAnchor]get_room_rpc_error")
- return
- }
- livingUfos := make([]int64, 0)
- livingRolaids := make([]int64, 0)
- // 没有人直播
- if len(roomResp) == 0 {
- return
- }
- for k, v := range roomResp {
- livingUfos = append(livingUfos, k)
- livingRolaids = append(livingRolaids, v.RoomId)
- }
- userResp := make(map[int64]*accountM.Card)
- roomCornerResp := make(map[int64]*roomV1.RoomPendantGetPendantByIdsResp_Result)
- pkResp := make(map[string]int64)
- attentionRoomListPlayURLMap := make(map[int64]*playurlbvc.PlayUrlItem)
- build, _ := strconv.ParseInt(req.Build, 10, 64)
- roomPendentParams := &roomV1.RoomPendantGetPendantByIdsReq{Ids: livingRolaids, Type: relationT.PendentMobileBadge, Position: relationT.PendentPosition}
- pkParams := &avV1.PkGetPkIdsByRoomIdsReq{RoomIds: livingRolaids, Platform: req.Platform}
- if err != nil {
- log.Error("[LiveAnchor]get_roomPendant_rpc_error")
- return
- }
- // user信息
- wg.Go(func() error {
- userResp, err = s.GetUserInfoData(ctx, livingUfos)
- return err
- })
- // room
- wg.Go(func() error {
- roomCornerResp, err = relationT.GetRoomPendantInfo(ctx, roomPendentParams)
- return err
- })
- // pk_id
- wg.Go(func() error {
- pkResp, err = relationT.GetPkID(ctx, pkParams)
- return err
- })
- quality := req.Quality
- if quality <= 0 {
- quality = 4
- }
- // playurl
- wg.Go(func() error {
- attentionRoomListPlayURLMap = dao.BvcApi.GetPlayUrlMulti(ctx, livingRolaids, 0, quality, build, req.Platform)
- return err
- })
- waitErr := wg.Wait()
- if waitErr != nil {
- log.Error("[LiveAnchor][step2] rpc error: %s", waitErr)
- return
- }
- // 下游数据收集完成
- mapSp := make([]int64, 0)
- normalSp := make([]int64, 0)
- mapSp = append(mapSp, groupList["special"]...)
- normalSp = append(normalSp, groupList["normal"]...)
- resp.Rooms = AdaptLivingField(roomResp, roomCornerResp, userResp, relationInfo, pkResp, attentionRoomListPlayURLMap, mapSp, normalSp, mapUfos2Rolaids)
- resp.TotalCount = int64(len(resp.Rooms))
- userExtParams := &userExV1.GrayRuleGetByMarkReq{Mark: relationT.App531GrayRule}
- grayRule, err := relationT.GetGrayRule(ctx, userExtParams)
- if err != nil {
- log.Error("[LiveAnchor]get_GrayRule_rpc_error")
- resp.BigCardType = 0
- } else if grayRule != nil {
- resp.BigCardType = relationT.App531ABTest(ctx, grayRule.Content, req.Build, req.Platform)
- }
- FilterType(ctx, livingUfos, resp, filterRule)
- SortType(ctx, resp, sortRule)
- return
- }
- // FilterType implementation
- // [app端关注二级页]按照规则过滤结果集
- func FilterType(ctx context.Context, targetUIDs []int64, originResult *v1pb.LiveAnchorResp, filterType int64) {
- if originResult == nil || len(originResult.Rooms) == 0 {
- return
- }
- switch filterType {
- case relationT.AppFilterDefault:
- {
- }
- case relationT.AppFilterFansMedal:
- {
- filteredRooms, _ := relationT.AppFilterRuleFansMedal(ctx, originResult, targetUIDs)
- originResult.Rooms = filteredRooms
- originResult.TotalCount = int64(len(originResult.Rooms))
- }
- case relationT.AppFilterGoldType:
- {
- filteredRooms, _ := relationT.AppFilterGold(ctx, originResult)
- originResult.Rooms = filteredRooms
- originResult.TotalCount = int64(len(originResult.Rooms))
- }
- }
- }
- // SortType implementation
- // [app端关注二级页]按照规则排序结果集
- // 规则见https://www.tapd.cn/20082211/prong/stories/view/1120082211001067961
- func SortType(ctx context.Context, originResult *v1pb.LiveAnchorResp, sortType int64) (resp *v1pb.LiveAnchorResp, err error) {
- if originResult == nil || len(originResult.Rooms) == 0 {
- return
- }
- switch sortType {
- // 组间特别关注、组内人气值
- case relationT.AppSortDefaultT:
- {
- }
- case relationT.AppSortRuleLiveTimeT:
- {
- originResult.Rooms = relationT.AppSortRuleLiveTime(originResult)
- }
- case relationT.AppSortRuleOnlineT:
- {
- originResult.Rooms = relationT.AppSortRuleOnline(originResult)
- }
- case relationT.AppSortRuleGoldT:
- {
- originResult.Rooms = relationT.AppSortRuleGold(ctx, originResult)
- }
- default:
- }
- 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
- }
- // GetUserFc ...
- // 获取用户粉丝
- func GetUserFc(ctx context.Context, UIDs []int64) (userResult map[int64]*relationV1.FeedGetUserFcBatchResp_RelationList, err error) {
- rpcChunkSize, RPCTimeout, err := relationT.GetChunkInfo(relationT.FansNum)
- params := relationT.ChunkCallInfo{ParamsName: "ufos", URLName: relationT.FansNum, ChunkSize: rpcChunkSize, RPCTimeout: RPCTimeout}
- userResult = make(map[int64]*relationV1.FeedGetUserFcBatchResp_RelationList)
- lens := len(UIDs)
- if lens <= 0 {
- return
- }
- // 批次
- params.ChunkNum = int64(math.Ceil(float64(lens) / float64(params.ChunkSize)))
- chunkResult := make([]map[int64]*relationV1.FeedGetUserFcBatchResp_RelationList, 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 := dao.RelationApi.V1Feed.GetUserFcBatch(ctx, &relationV1.FeedGetUserFcBatchReq{Uids: 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.Data
- return nil
- })
- }
- if err := wg.Wait(); err != nil {
- erelongInfo := relationT.ErrLogStrut{}
- erelongInfo.ErrType = "GoRoutingWaitError"
- erelongInfo.URLName = relationT.FansNum
- 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
- }
|