You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
350 lines
8.7 KiB
350 lines
8.7 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"go-common/app/service/bbq/common" |
|
"go-common/library/conf/env" |
|
"go-common/library/ecode" |
|
"time" |
|
|
|
"go-common/app/interface/bbq/app-bbq/api/http/v1" |
|
"go-common/app/interface/bbq/app-bbq/model" |
|
"go-common/app/interface/bbq/app-bbq/model/grpc" |
|
rec "go-common/app/service/bbq/recsys/api/grpc/v1" |
|
user "go-common/app/service/bbq/user/api" |
|
video "go-common/app/service/bbq/video/api/grpc/v1" |
|
"go-common/library/log" |
|
"go-common/library/net/trace" |
|
) |
|
|
|
// SvList 短视屏推荐列表 |
|
func (s *Service) SvList(c context.Context, pageSize int64, mid int64, base *v1.Base, deviceID string) (res []*v1.VideoResponse, err error) { |
|
var ( |
|
svids []int64 |
|
svRes map[int64]*v1.VideoResponse |
|
) |
|
res = make([]*v1.VideoResponse, 0) |
|
//推荐列表 |
|
svids, err = s.dao.RawRecList(c, pageSize, mid, base.BUVID) |
|
if err != nil || len(svids) == 0 || env.DeployEnv == env.DeployEnvUat { |
|
log.Warnv(c, log.KV("log", fmt.Sprintf("s.dao.GetList err[%v]", err))) |
|
// 降级 |
|
svids, _ = s.dao.GetList(c, pageSize) |
|
} |
|
svRes, err = s.svInfos(c, svids, mid, false) |
|
for _, id := range svids { |
|
if sv, ok := svRes[id]; ok { |
|
if common.IsRecommendSvStateAvailable(int64(sv.State)) { |
|
res = append(res, sv) |
|
} else { |
|
log.Warnw(c, "log", "get error svid in recommend list", "svid", id, "mid", mid, "sv", sv) |
|
} |
|
} |
|
} |
|
return |
|
} |
|
|
|
// svPlays 批量获取playurl(相对地址方法) |
|
func (s *Service) svPlays(c context.Context, svids []int64) map[int64]*v1.VideoPlay { |
|
var ( |
|
relAddr []string |
|
err error |
|
bvcUrls map[string]*grpc.VideoKeyItem |
|
bvcKeys map[int64][]*model.SVBvcKey |
|
) |
|
playMap := make(map[int64]*v1.VideoPlay) |
|
bvcKeys, err = s.dao.RawSVBvcKey(c, svids) |
|
if err != nil { |
|
log.Error("s.dao.RawSVBvcKey err[%v]", err) |
|
} |
|
for id, keys := range bvcKeys { |
|
playMap[id] = &v1.VideoPlay{ |
|
SVID: id, |
|
} |
|
for k, v := range keys { |
|
if k == 0 { |
|
playMap[id].Quality = int64(v.CodeRate) |
|
} |
|
fi := &v1.FileInfo{ |
|
TimeLength: v.Duration, |
|
FileSize: v.FileSize, |
|
Path: v.Path, |
|
} |
|
playMap[id].FileInfo = append(playMap[id].FileInfo, fi) |
|
playMap[id].SupportQuality = append(playMap[id].SupportQuality, int64(v.CodeRate)) |
|
relAddr = append(relAddr, v.Path) |
|
} |
|
} |
|
bvcUrls, err = s.dao.RelPlayURLs(c, relAddr) |
|
if err != nil { |
|
log.Error("s.dao.RelPlayURLs err[%v]", err) |
|
} |
|
//拼装playurl |
|
for _, svid := range svids { |
|
if play, ok := playMap[svid]; ok { |
|
for fk, f := range play.FileInfo { |
|
if urls, ok := bvcUrls[f.Path]; ok { |
|
playMap[svid].ExpireTime = int64(urls.Etime) |
|
playMap[svid].CurrentTime = time.Now().Unix() |
|
for _, u := range urls.URL { |
|
if playMap[svid].FileInfo[fk].URL == "" { |
|
playMap[svid].FileInfo[fk].URL = u |
|
if playMap[svid].URL == "" { |
|
playMap[svid].URL = u |
|
} |
|
continue |
|
} |
|
if playMap[svid].FileInfo[fk].URLBc == "" { |
|
playMap[svid].FileInfo[fk].URLBc = u |
|
break |
|
} |
|
} |
|
} else { |
|
delete(playMap, svid) |
|
break |
|
} |
|
} |
|
playMap[svid] = play |
|
} |
|
} |
|
return playMap |
|
} |
|
|
|
// SvStatistics 视频统计服务 |
|
func (s *Service) SvStatistics(c context.Context, mid int64, svids []int64) (res []*v1.SvStatRes, err error) { |
|
var ( |
|
stMap map[int64]*model.SvStInfo |
|
ulike map[int64]bool |
|
upIDs []int64 |
|
) |
|
svInfos, _ := s.dao.RawVideos(c, svids) |
|
for _, sv := range svInfos { |
|
upIDs = append(upIDs, sv.MID) |
|
} |
|
stMap, err = s.dao.RawVideoStatistic(c, svids) |
|
if err != nil { |
|
log.Error("s.dao.RawVideoStatistic err[%v]", err) |
|
} |
|
//点赞状态 |
|
ulike, err = s.dao.CheckUserLike(c, mid, svids) |
|
if err != nil { |
|
log.Error("s.dao.CheckUserLike err[%v]", err) |
|
} |
|
uflw, _ := s.dao.BatchUserInfo(c, mid, upIDs, false, false, true) |
|
if err != nil { |
|
log.Error("s.dao.IsFollow err[%v]", err) |
|
} |
|
for _, id := range svids { |
|
rp := &v1.SvStatRes{} |
|
rp.SVID = id |
|
if st, ok := stMap[id]; ok { |
|
rp.Like = st.Like |
|
rp.Share = st.Share |
|
rp.Play = st.Play |
|
rp.Subtitles = st.Subtitles |
|
rp.Reply = st.Reply |
|
} |
|
if l, ok := ulike[id]; ok { |
|
rp.IsLike = l |
|
} |
|
if sv, ok := svInfos[id]; ok { |
|
if f, ok2 := uflw[sv.MID]; ok2 { |
|
rp.FollowState = f.FollowState |
|
} |
|
} |
|
res = append(res, rp) |
|
} |
|
return |
|
} |
|
|
|
// SvCPlays 批量拉取playurl |
|
func (s *Service) SvCPlays(c context.Context, svids []int64, mid int64) (res []*v1.VideoPlay, err error) { |
|
res = make([]*v1.VideoPlay, 0) |
|
|
|
//视频列表 |
|
svRes, err := s.dao.RawVideos(c, svids) |
|
if err != nil { |
|
log.Error("s.dao.RawVideos err[%v]", err) |
|
return |
|
} |
|
|
|
avaliableSvids := make([]int64, 0) |
|
for _, v := range svRes { |
|
if (mid == 0 || v.MID != mid) && common.IsSvStateGuestAvailable(int64(v.State)) { |
|
avaliableSvids = append(avaliableSvids, v.SVID) |
|
} else if v.MID == mid && common.IsSvStateOwnerAvailable(int64(v.State)) { |
|
avaliableSvids = append(avaliableSvids, v.SVID) |
|
} |
|
} |
|
|
|
playMap := s.svPlays(c, avaliableSvids) |
|
for _, svid := range avaliableSvids { |
|
var play *v1.VideoPlay |
|
if p, ok := playMap[svid]; !ok { |
|
log.Warn("play不存在 svid[%d]", svid) |
|
continue |
|
} else { |
|
play = p |
|
} |
|
res = append(res, play) |
|
} |
|
return |
|
} |
|
|
|
// SvDetail 单条sv的视频详情,暂时只用于评论中转页 |
|
func (s *Service) SvDetail(c context.Context, svid int64, mid int64) (res *v1.VideoResponse, err error) { |
|
_, err = s.dao.VideoBase(c, mid, svid) |
|
if err != nil { |
|
return |
|
} |
|
|
|
svInfos, err := s.svInfos(c, []int64{svid}, mid, true) |
|
if err != nil { |
|
return |
|
} |
|
|
|
if val, exists := svInfos[svid]; exists { |
|
res = val |
|
} else { |
|
err = ecode.VideoUnExists |
|
log.Infow(c, "log", "not sv info", "svid", svid) |
|
} |
|
|
|
return |
|
} |
|
|
|
// svInfos 批量获取视频信息 |
|
// @params allowState 可放出状态,传空为app整体可露出状态 |
|
// @params needStInfo 是否需要视频统计数据 |
|
func (s *Service) svInfos(c context.Context, ids []int64, mid int64, needStInfo bool) (res map[int64]*v1.VideoResponse, err error) { |
|
var ( |
|
mids []int64 |
|
svRes map[int64]*model.SvInfo |
|
ulike map[int64]bool |
|
stMap map[int64]*model.SvStInfo |
|
) |
|
res = make(map[int64]*v1.VideoResponse) |
|
stMap = make(map[int64]*model.SvStInfo) |
|
|
|
//视频列表 |
|
svRes, err = s.dao.RawVideos(c, ids) |
|
if err != nil { |
|
log.Error("s.dao.RawVideos err[%v]", err) |
|
return |
|
} |
|
for _, v := range svRes { |
|
mids = append(mids, v.MID) |
|
} |
|
if mid != 0 { |
|
ulike, err = s.dao.CheckUserLike(c, mid, ids) |
|
if err != nil { |
|
log.Error("s.dao.CheckUserLike err[%v]", err) |
|
} |
|
} |
|
// query id |
|
tracer, _ := trace.FromContext(c) |
|
queryID := fmt.Sprintf("%s", tracer) |
|
//账号 |
|
var userMap map[int64]*user.UserBase |
|
userMap, err = s.dao.JustGetUserBase(c, mids) |
|
if err != nil { |
|
log.Error("s.dao.UserBase err[%v]", err) |
|
} |
|
// play信息 |
|
playMap := s.svPlays(c, ids) |
|
if needStInfo { |
|
stMap, err = s.dao.RawVideoStatistic(c, ids) |
|
if err != nil { |
|
log.Error("s.dao.RawVideoStatistic err[%v]", err) |
|
} |
|
} |
|
// extension信息 |
|
extensions, tmpErr := s.getExtension(c, ids) |
|
if tmpErr != nil { |
|
log.Warnw(c, "log", "get extension fail") |
|
} |
|
|
|
for _, v := range svRes { |
|
if common.IsSvStateAvailable(int64(v.State)) { |
|
sv := &v1.VideoResponse{} |
|
if acc, ok := userMap[v.MID]; ok { |
|
sv.UserInfo = *acc |
|
} |
|
if lk, ok := ulike[v.SVID]; ok { |
|
sv.IsLike = lk |
|
} |
|
sv.SVID = v.SVID |
|
sv.Title = v.Title |
|
sv.Content = v.Content |
|
sv.MID = v.MID |
|
sv.Duration = v.Duration |
|
sv.Pubtime = v.Pubtime |
|
sv.Ctime = v.Ctime |
|
sv.AVID = v.AVID |
|
sv.CID = v.CID |
|
sv.From = v.From |
|
sv.CoverURL = v.CoverURL |
|
sv.CoverHeight = v.CoverHeight |
|
sv.CoverWidth = v.CoverWidth |
|
sv.QueryID = queryID |
|
sv.State = v.State |
|
if play, ok := playMap[v.SVID]; ok { |
|
sv.Play = *play |
|
res[v.SVID] = sv |
|
} else { |
|
log.Warn("play不存在 svid[%d],此条记录直接舍弃", v.SVID) |
|
} |
|
if st, ok := stMap[v.SVID]; ok { |
|
sv.SvStInfo = *st |
|
} |
|
if extension, exists := extensions[v.SVID]; exists { |
|
sv.Extension = extension.Extension |
|
} |
|
|
|
res[v.SVID] = sv |
|
} |
|
} |
|
|
|
return |
|
} |
|
|
|
// SvRelRec 相关推荐服务 |
|
func (s *Service) SvRelRec(c context.Context, data *v1.SvRelReq) (res map[string]interface{}, err error) { |
|
res = make(map[string]interface{}) |
|
var svMap map[int64]*v1.VideoResponse |
|
list := make([]*v1.VideoResponse, 0) |
|
relReq := &rec.RecsysRequest{ |
|
SVID: data.SVID, |
|
Offset: data.Offset, |
|
Limit: data.Limit, |
|
QueryID: data.QueryID, |
|
App: data.APP, |
|
AppVersion: data.APPVersion, |
|
BUVID: data.BUVID, |
|
MID: data.MID, |
|
} |
|
IDList, err := s.dao.RelRecList(c, relReq) |
|
if err != nil { |
|
err = nil |
|
return |
|
} |
|
svMap, err = s.svInfos(c, IDList, data.MID, false) |
|
if err != nil { |
|
err = nil |
|
return |
|
} |
|
for _, id := range IDList { |
|
if sv, ok := svMap[id]; ok { |
|
list = append(list, sv) |
|
} |
|
|
|
} |
|
res["list"] = list |
|
return |
|
} |
|
|
|
// SvDel 视频删除 |
|
func (s *Service) SvDel(c context.Context, in *video.VideoDeleteRequest) (interface{}, error) { |
|
return s.dao.SvDel(c, in) |
|
}
|
|
|