2886 lines
86 KiB
Go
2886 lines
86 KiB
Go
package vidser
|
|
|
|
import (
|
|
"91porn-server/app/service/mediaser"
|
|
"91porn-server/app/service/searchaccessser"
|
|
"91porn-server/app/service/shortrecommendser"
|
|
"91porn-server/app/service/sys_config"
|
|
"91porn-server/common/cachev2"
|
|
"91porn-server/common/redis"
|
|
topser "91porn-server/common/top"
|
|
"91porn-server/common/top/weektop"
|
|
"91porn-server/models/cache/viddata"
|
|
"91porn-server/models/v/mediamod"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"net/http"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
goredis "github.com/go-redis/redis"
|
|
|
|
"github.com/vmihailenco/msgpack/v5"
|
|
|
|
"91porn-server/app/appg"
|
|
"91porn-server/app/proto"
|
|
"91porn-server/app/service/activityclient"
|
|
"91porn-server/app/service/searcher"
|
|
"91porn-server/app/service/searcher/vidhkwsearcher"
|
|
"91porn-server/app/service/searcher/vidhotsearcher"
|
|
"91porn-server/app/service/vidhelpser"
|
|
"91porn-server/common"
|
|
"91porn-server/common/constant"
|
|
"91porn-server/common/constant/redisconst"
|
|
"91porn-server/common/httputil"
|
|
"91porn-server/common/log"
|
|
sli "91porn-server/common/slice"
|
|
"91porn-server/common/stderr"
|
|
"91porn-server/common/timeutil"
|
|
"91porn-server/models/commod"
|
|
"91porn-server/models/l/payvidlgmod"
|
|
"91porn-server/models/l/playlgmod"
|
|
"91porn-server/models/s/hotstatmod"
|
|
"91porn-server/models/s/sectionstatmod"
|
|
"91porn-server/models/v/freeVidmod"
|
|
"91porn-server/models/v/imagetopmod"
|
|
"91porn-server/models/v/locmod"
|
|
"91porn-server/models/v/moduleconfmod"
|
|
"91porn-server/models/v/modulesectionmod"
|
|
"91porn-server/models/v/modulevidmod"
|
|
"91porn-server/models/v/productmod"
|
|
"91porn-server/models/v/tagmod"
|
|
"91porn-server/models/v/useractmod"
|
|
"91porn-server/models/v/usermod"
|
|
"91porn-server/models/v/userwatchrecordmod"
|
|
"91porn-server/models/v/videoactivitymod"
|
|
"91porn-server/models/v/videodiscountmod"
|
|
"91porn-server/models/v/vidmod"
|
|
"91porn-server/models/v/vidpopmod"
|
|
"91porn-server/models/v/walletmod"
|
|
|
|
"github.com/jinzhu/now"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
const (
|
|
h5FirstPlay = "1"
|
|
|
|
timeout = 5 * time.Second
|
|
)
|
|
|
|
var defaultLocation, _ = primitive.ObjectIDFromHex("5dbeb23790b3d9aa3756912f") //默认城市ID 广州
|
|
|
|
func getCityByIP(ip string) string {
|
|
return vidhelpser.GetLocationByIP(ip)
|
|
}
|
|
|
|
// GetLocationList 获取附近位置的视频
|
|
func GetLocationList(uid uint64, ip string, city string, page, size uint64, typ string) (stderr.Code, interface{}) {
|
|
if len(city) == 0 {
|
|
city = getCityByIP(ip)
|
|
}
|
|
lid, err := locmod.GetLocationIDByCity(city)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
if lid.IsZero() {
|
|
return stderr.Success, vidmod.LocVideoResp{List: []*vidmod.VideoInfo{}, HasNext: false}
|
|
}
|
|
var videos []*vidmod.VideoModel
|
|
if typ == vidmod.SP {
|
|
if videos, err = vidmod.GetVideoListByLocation(lid, int64(page), int64(size+1)); err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
}
|
|
if typ == vidmod.COVER {
|
|
if videos, err = vidmod.GetImageListByLocation(lid, int64(page), int64(size+1)); err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
}
|
|
hasNext := false
|
|
if uint64(len(videos)) > size {
|
|
videos = videos[:size]
|
|
hasNext = true
|
|
}
|
|
return stderr.Success, vidmod.LocVideoResp{List: vidhelpser.EncodeVideoInfo(uid, videos), HasNext: hasNext}
|
|
}
|
|
|
|
// GetLocationHot 获取热门城市
|
|
func GetLocationHot() (code stderr.Code, data interface{}) {
|
|
citys, err := locmod.GetHotCity()
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
back := make([]locmod.CityResp, len(citys))
|
|
for i, c := range citys {
|
|
back[i] = locmod.CityResp{ID: c.ID.Hex(), City: c.City, Province: c.Province, Hot: c.SortKey}
|
|
}
|
|
return stderr.Success, back
|
|
}
|
|
|
|
// GetInfo 获取视频详情
|
|
func GetInfo(uid uint64, videoID string) (code stderr.Code, data interface{}) {
|
|
return GetInfoWithSearchAccess(uid, videoID, "")
|
|
}
|
|
|
|
// GetInfoWithSearchAccess 获取视频详情;失效亚模块的视频必须携带搜索结果签发的访问凭证。
|
|
func GetInfoWithSearchAccess(uid uint64, videoID, searchAccessToken string) (code stderr.Code, data interface{}) {
|
|
v, err := vidmod.GetVideoInfo(videoID)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
blockedModules, err := moduleconfmod.BlockedOutsideSearchModuleIDs([]string{v.MID}, time.Now())
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
_, searchOnly := blockedModules[v.MID]
|
|
if searchOnly && !searchaccessser.Validate(searchAccessToken, uid, videoID, time.Now()) {
|
|
return stderr.CodeEmptyData, nil
|
|
}
|
|
var infos []*vidmod.VideoInfo
|
|
if searchOnly {
|
|
infos = vidhelpser.EncodeVideoInfoForSearch(uid, []*vidmod.VideoModel{&v})
|
|
} else {
|
|
infos = vidhelpser.EncodeVideoInfo(uid, []*vidmod.VideoModel{&v})
|
|
}
|
|
if len(infos) == 0 {
|
|
return stderr.UnkonwErr, ""
|
|
}
|
|
info := infos[0]
|
|
if info.NewsType == constant.COVER {
|
|
user, _ := usermod.FindUserByUID(uid)
|
|
wallet, _ := walletmod.GetWallet(uid)
|
|
info.RichText = activityclient.ReplaceActivityDomainInHTML(info.RichText, user, wallet)
|
|
}
|
|
return stderr.Success, info
|
|
}
|
|
|
|
// SubmitBase 提交基本信息
|
|
func SubmitBase(uid uint64, req vidmod.SubmitReq, clientIP string) (code stderr.Code, vid primitive.ObjectID) {
|
|
if uid == 0 {
|
|
uid = req.UID
|
|
}
|
|
tags := make([]primitive.ObjectID, 0, len(req.Tags))
|
|
for _, t := range req.Tags {
|
|
oid, err := primitive.ObjectIDFromHex(t)
|
|
if err != nil {
|
|
log.Warn("SubmitBase error", log.Any("uid", uid), log.Any("req", req), log.E(err))
|
|
continue
|
|
}
|
|
if sli.PrimitiveObjIDIsExist(tags, oid) {
|
|
continue
|
|
}
|
|
tags = append(tags, oid)
|
|
// 标签视频数计数
|
|
if err = tagmod.IncreaseTagVidCount(oid, 1); err != nil {
|
|
log.Warn("SubmitBase2 error", log.Any("uid", uid), log.Any("req", req), log.E(err))
|
|
continue
|
|
}
|
|
}
|
|
l := locmod.Location{
|
|
Longitude: req.Location.Longitude,
|
|
Latitude: req.Location.Latitude,
|
|
Country: req.Location.Country,
|
|
CountryCode: req.Location.CountryCode,
|
|
Province: req.Location.Province,
|
|
ProvinceCode: req.Location.ProvinceCode,
|
|
City: req.Location.City,
|
|
CityCode: req.Location.CityCode,
|
|
Address: req.Location.Address,
|
|
Visit: 0,
|
|
}
|
|
isHideLocation := false
|
|
if len(l.City) == 0 {
|
|
l.City = getCityByIP(clientIP)
|
|
isHideLocation = true
|
|
}
|
|
var lid primitive.ObjectID
|
|
if err := locmod.InsertLocationInfo(l); err != nil {
|
|
lid = defaultLocation
|
|
} else {
|
|
lid, err = locmod.GetLocationIDByCity(l.City)
|
|
if err != nil {
|
|
user, userError := usermod.FindUserByUID(uid)
|
|
if userError != nil || user.Region == "" {
|
|
lid = defaultLocation
|
|
} else {
|
|
var locErr error
|
|
lid, locErr = locmod.GetLocationIDByCity(user.Region)
|
|
if locErr != nil || lid.IsZero() {
|
|
lid = defaultLocation
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//为了不影响用户上传体验,对于sourceID为"0000..."情况的视频,允许上传成功,但默认为审核不通过
|
|
var status int
|
|
sourceID := req.SourceID
|
|
oid, oidErr := primitive.ObjectIDFromHex(req.SourceID)
|
|
if (req.NewsType == vidmod.SP || req.NewsType == vidmod.SHORT) && (oidErr != nil || oid.IsZero()) {
|
|
oid = primitive.NewObjectID()
|
|
sourceID = oid.Hex()
|
|
status = 2
|
|
}
|
|
series := []string{}
|
|
if len(req.SeriesCover) != 0 {
|
|
series = req.SeriesCover
|
|
}
|
|
//视频高度不能低于640
|
|
var width, height int
|
|
resolutions := strings.Split(req.Resolution, "*")
|
|
if len(resolutions) >= 2 {
|
|
width, _ = strconv.Atoi(resolutions[0])
|
|
height, _ = strconv.Atoi(resolutions[1])
|
|
}
|
|
if width > 0 && height > 0 && height < 640 {
|
|
return stderr.ResolutionNotEnough, primitive.NilObjectID
|
|
}
|
|
ok, err := vidmod.IsSubmitByPublisherID(uid)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, primitive.NilObjectID
|
|
}
|
|
if !ok {
|
|
appg.Redis.Incr("creatorNumber")
|
|
}
|
|
v := vidmod.VideoModel{
|
|
ID: oid,
|
|
PublisherID: uid,
|
|
NewsType: req.NewsType,
|
|
Title: req.Title,
|
|
Content: req.Content,
|
|
Tags: tags,
|
|
SourceID: sourceID,
|
|
SourceURL: req.SourceURL,
|
|
MimeType: req.MimeType,
|
|
Activity: []primitive.ObjectID{},
|
|
Filename: req.Filename,
|
|
PlayTime: req.PlayTime,
|
|
Cover: req.Cover,
|
|
CoverThumb: req.CoverThumb,
|
|
SeriesCover: series,
|
|
SeriesNum: len(series),
|
|
Via: req.Via,
|
|
Rating: 0,
|
|
PlayCount: 0,
|
|
LikeCount: 0,
|
|
CommentCount: 0,
|
|
ShareCount: 0,
|
|
Status: status,
|
|
Location: lid,
|
|
FreeTime: req.FreeTime,
|
|
Coins: req.Coins,
|
|
Size: req.Size,
|
|
Resolution: req.Resolution,
|
|
Ratio: req.Ratio,
|
|
MD5: req.MD5,
|
|
Actor: req.Actor,
|
|
IsHideLocation: isHideLocation,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
if req.IsActivity {
|
|
videoActivity, err := videoactivitymod.QueryDocumentByStatus(videoactivitymod.Enable)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, primitive.NilObjectID
|
|
}
|
|
v.ActivityID = videoActivity.ID
|
|
}
|
|
|
|
if v.PlayTime > 0 || v.NewsType == vidmod.SP {
|
|
if v.PlayTime < 300 {
|
|
v.NewsType = vidmod.SHORT
|
|
} else {
|
|
v.NewsType = vidmod.SP
|
|
}
|
|
}
|
|
|
|
if vid, err = vidmod.InsertBase(v); err != nil {
|
|
if mongo.IsDuplicateKeyError(err) {
|
|
return stderr.ErrUploadExistVideo, primitive.NilObjectID
|
|
}
|
|
return stderr.ErrNetWorkBusy, primitive.NilObjectID
|
|
}
|
|
return stderr.Success, vid
|
|
}
|
|
|
|
// PlayRecord 用户播放行为记录
|
|
// 视频播放、标签播放、地理位置播放++
|
|
// 播放日志记录
|
|
// 播放率统计
|
|
func PlayRecord(uid uint64, req vidmod.PlayReq) (code stderr.Code, data interface{}) {
|
|
oid, err := primitive.ObjectIDFromHex(req.VideoID)
|
|
if err != nil {
|
|
log.Error("PlayRecord error", log.Any("uid", uid), log.Any("req", req), log.E(err))
|
|
return stderr.ErrParamError, nil
|
|
}
|
|
var tid primitive.ObjectID
|
|
if len(req.TagID) != 0 {
|
|
tid, err = primitive.ObjectIDFromHex(req.TagID)
|
|
if err != nil {
|
|
log.Error("PlayRecord tid error", log.Any("uid", uid), log.Any("req", req), log.E(err))
|
|
return stderr.ErrParamError, nil
|
|
}
|
|
}
|
|
now := time.Now()
|
|
common.Go(func() {
|
|
if req.Publisher <= 0 {
|
|
return
|
|
}
|
|
weektop.Incr(topser.TypeRecommendUser, fmt.Sprintf("%v", req.Publisher), 1)
|
|
})
|
|
common.Go(func() {
|
|
ok, err := userwatchrecordmod.IsExist(uid, oid)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if ok {
|
|
if err = userwatchrecordmod.Refresh(uid, oid); err != nil {
|
|
return
|
|
}
|
|
} else {
|
|
if err = userwatchrecordmod.Insert(uid, oid); err != nil {
|
|
return
|
|
}
|
|
}
|
|
p := playlgmod.PlayLog{
|
|
UID: uid,
|
|
VideoID: oid,
|
|
Longer: req.Longer,
|
|
Progress: req.Progress,
|
|
Via: req.Via,
|
|
PlayWay: req.PlayWay,
|
|
TagID: tid,
|
|
Publisher: req.Publisher,
|
|
CreatedAt: now,
|
|
}
|
|
_ = playlgmod.InsertPlayRecord(p)
|
|
isValid := req.Longer >= 5
|
|
_ = vidhelpser.IncreaseTag(req.VideoID, tid, isValid)
|
|
popCfg, err := vidpopmod.FindVidPopCfg()
|
|
if err != nil {
|
|
log.Error("vidpopmod.FindVidPopCfg", log.E(err))
|
|
}
|
|
_ = vidmod.IncPlayCount(oid, req, popCfg)
|
|
})
|
|
common.Go(func() {
|
|
_ = setHotPubliser(now, req.Publisher)
|
|
})
|
|
return stderr.Success, nil
|
|
}
|
|
|
|
func setHotPubliser(d time.Time, publishserUID uint64) error {
|
|
d = timeutil.BeginningOfDay(d)
|
|
reidsKey := redisconst.PlayLeaderboardKey("publiser", d.Unix())
|
|
_, err := appg.Redis.ZIncrBy(reidsKey, 1, strconv.FormatUint(publishserUID, 10))
|
|
return err
|
|
}
|
|
|
|
// SendBaseInfo2FS 上传基本文件信息到aws
|
|
func SendBaseInfo2FS(req vidmod.SubmitReq) (code stderr.Code) {
|
|
info := vidmod.BaseVid4Aws{
|
|
ID: req.SourceID,
|
|
CheckSum: req.MD5,
|
|
Title: req.Title,
|
|
Actors: []string{req.Actor},
|
|
AddedTime: time.Now().Format("2006-01-02"),
|
|
PlayTime: uint64(req.PlayTime),
|
|
Size: req.Size,
|
|
Via: "q1",
|
|
Filename: req.Filename,
|
|
Type: "sp",
|
|
}
|
|
var tags []string
|
|
reqTagsLen := len(req.Tags)
|
|
if reqTagsLen > 0 {
|
|
tags = make([]string, 0, reqTagsLen)
|
|
for _, v := range req.Tags {
|
|
tagID, err := primitive.ObjectIDFromHex(v)
|
|
if err != nil {
|
|
log.Warn("SendBaseInfo2FS error", log.Any("req", req), log.E(err))
|
|
continue
|
|
}
|
|
tagData, err := tagmod.FindOneTagByID(tagID)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
tags = append(tags, tagData.TagName)
|
|
}
|
|
}
|
|
info.Tags = tags
|
|
c, cancle := context.WithTimeout(context.Background(), timeout)
|
|
defer cancle()
|
|
params, _ := common.ToJsonM(info)
|
|
respBody := commod.Resp{}
|
|
httpStatus, err := httputil.DefaultClientPostJsonWithRespWithCtx(c, &respBody, appg.Conf.URL.FileInfoUrl, nil, params)
|
|
log.Info("http method SendBaseInfo2FS response code ==>", log.Any("httpStatus", httpStatus), log.Any("respCode", respBody.Code))
|
|
if err != nil {
|
|
log.Error("SendBaseInfo2FS POSTJsonWithJResp error", log.Any("req", req), log.E(err))
|
|
return stderr.ErrConnectToFs
|
|
}
|
|
if respBody.Code != http.StatusOK {
|
|
log.Error("SendBaseInfo2FS status error", log.Any("req", req), log.Any("respBody.Code", respBody.Code), log.E(err))
|
|
return stderr.ErrFsServerFile
|
|
}
|
|
return stderr.Success
|
|
}
|
|
|
|
// SendCoverInfo2FS 上传基本图集信息到aws
|
|
func SendCoverInfo2FS(req vidmod.SubmitReq) (code stderr.Code) {
|
|
info := vidmod.CoverInfo4Aws{
|
|
Type: "SP",
|
|
Title: req.Title,
|
|
Tags: req.Tags,
|
|
CoverImg: req.Cover,
|
|
SeriesCover: req.SeriesCover,
|
|
Status: "",
|
|
MimeType: req.MimeType,
|
|
Via: "q1",
|
|
Topic: []string{},
|
|
NewUpdateAt: time.Now().Format("2006-01-02"),
|
|
Desc: "",
|
|
}
|
|
var tags []string
|
|
reqTagsLen := len(req.Tags)
|
|
if reqTagsLen > 0 {
|
|
tags = make([]string, 0, reqTagsLen)
|
|
for _, v := range req.Tags {
|
|
tagID, err := primitive.ObjectIDFromHex(v)
|
|
if err != nil {
|
|
log.Warn("SendCoverInfo2FS error", log.Any("req", req), log.E(err))
|
|
continue
|
|
}
|
|
tagData, err := tagmod.FindOneTagByID(tagID)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
tags = append(tags, tagData.TagName)
|
|
}
|
|
}
|
|
info.Tags = tags
|
|
c, cancle := context.WithTimeout(context.Background(), timeout)
|
|
defer cancle()
|
|
params, _ := common.ToJsonM(info)
|
|
respBody := commod.Resp{}
|
|
httpStatus, err := httputil.DefaultClientPostJsonWithRespWithCtx(c, &respBody, appg.Conf.URL.CoverInfoUrl, nil, params)
|
|
log.Info("http method SendCoverInfo2FS response code ==>", log.Any("httpStatus", httpStatus), log.Any("respCode", respBody.Code))
|
|
if err != nil {
|
|
log.Error("SendCoverInfo2FS POSTJsonWithJResp error", log.Any("req", req), log.E(err))
|
|
return stderr.ErrConnectToFs
|
|
}
|
|
if respBody.Code != http.StatusOK {
|
|
log.Error("SendCoverInfo2FS status error", log.Any("req", req), log.Any("respBody.Code", respBody.Code), log.E(err))
|
|
return stderr.ErrFsServerFile
|
|
}
|
|
return stderr.Success
|
|
}
|
|
|
|
// GetLocation 通过id获取地理位置
|
|
func GetLocation(uid uint64, id string) (code stderr.Code, data interface{}) {
|
|
oid, err := primitive.ObjectIDFromHex(id)
|
|
if err != nil {
|
|
log.Error("GetLocation error", log.Any("uid", uid), log.Any("id", id), log.E(err))
|
|
return stderr.ErrParamError, nil
|
|
}
|
|
l, err := locmod.GetLocationInfoByID(oid)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
if err = locmod.IncVisit(oid); err != nil {
|
|
return stderr.ErrDbUpdateError, nil
|
|
}
|
|
return stderr.Success, vidmod.LocResp{LocInfo: vidmod.LocInfo{
|
|
ID: l.ID,
|
|
City: l.City,
|
|
Cover: l.Cover,
|
|
Visit: l.FakeVisit,
|
|
CreatedAt: l.CreatedAt,
|
|
}}
|
|
}
|
|
|
|
// 总数固定10次 看完之后不再恢复
|
|
func GetWatchCount(uid uint64, oid primitive.ObjectID, first string) (isCan bool, watchCount uint64) {
|
|
totalCount := TotalFreeWatchCount()
|
|
var playWay uint64 = 0
|
|
duration := now.BeginningOfDay()
|
|
u, err := usermod.FindUserByUID(uid)
|
|
if u == nil || err != nil {
|
|
isCan = false
|
|
return
|
|
}
|
|
//是否是vip VIP可免费观看
|
|
isFree := IsFreeWatch(uid)
|
|
if isFree {
|
|
isCan = true
|
|
return
|
|
}
|
|
info, err := vidmod.GetVideoInfo(oid.Hex())
|
|
if err != nil {
|
|
return false, u.WatchCount
|
|
}
|
|
//判断是否是自己的视频或免费的视频或收费的视频
|
|
if info.PublisherID == uid || info.FreeArea || info.Coins > 0 {
|
|
return true, u.WatchCount
|
|
}
|
|
//当前视频在当天是否观看过 如果观看过 则可以继续观看
|
|
result := useractmod.IsViewTodayByNoVip(uid, oid, duration)
|
|
if result {
|
|
isCan = true
|
|
return
|
|
}
|
|
watchCount = u.WatchCount
|
|
if watchCount > totalCount {
|
|
watchCount = totalCount
|
|
}
|
|
//当观看次数为0时 分两种情况
|
|
if watchCount == 0 {
|
|
//判断当天是否观看过 如果没有观看过 则设置为10
|
|
// cnt := useractmod.ActCount(uid, duration)
|
|
// if cnt == 0 {
|
|
// watchCount = vidmod.TotalWatchCount
|
|
// _, _ = usermod.UpdateUserWatchCount(uid, int64(vidmod.TotalWatchCount))
|
|
// }
|
|
isCan = false
|
|
}
|
|
if 0 < watchCount && watchCount <= totalCount {
|
|
isCan = true
|
|
if first == h5FirstPlay {
|
|
return isCan, watchCount
|
|
}
|
|
_ = useractmod.UserActInsert(useractmod.UserAct{
|
|
VID: oid,
|
|
PlayWay: playWay,
|
|
UID: uid,
|
|
CreatedAt: time.Now(),
|
|
DailyDate: duration,
|
|
})
|
|
wCount := int64(watchCount - 1)
|
|
_, _ = usermod.UpdateUserWatchCount(uid, wCount)
|
|
}
|
|
return isCan, watchCount
|
|
}
|
|
|
|
// TotalFreeWatchCount 返回系统配置的免费观看总次数。
|
|
func TotalFreeWatchCount() uint64 {
|
|
return sys_config.GetTotalWatchCount()
|
|
}
|
|
|
|
func FreshCount(uid uint64) uint64 {
|
|
u, err := usermod.FindUserByUID(uid)
|
|
if u == nil || err != nil {
|
|
return 0
|
|
}
|
|
return u.WatchCount
|
|
}
|
|
|
|
func IsFreeWatch(uid uint64) bool {
|
|
u, err := usermod.FindUserByUID(uid)
|
|
if err != nil || u == nil {
|
|
return false
|
|
}
|
|
return !u.VipExpireDate.Before(time.Now())
|
|
}
|
|
|
|
func GetHotList(uid uint64, skip, limit int64) (list interface{}, hasNext bool, err error) {
|
|
opt := (&searcher.Option{}).
|
|
SetSkip(skip).
|
|
SetLimit(limit)
|
|
hotResult, err := vidhotsearcher.NewVidHotSearcher(uid).Search(nil, opt)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
return hotResult.Data(), hotResult.HasNext(), nil
|
|
}
|
|
|
|
func GetHotKWList(uid uint64, skip, limit int64) (list interface{}, hasNext bool, err error) {
|
|
//每个关键字平均取视屏
|
|
//如:需要12个视屏 用6个关键字搜素 每个关键字最多查询2个视屏
|
|
const keywordCount = 6
|
|
vidLimitPer := limit / keywordCount
|
|
vidOpt := (&searcher.Option{}).
|
|
SetSkip(limit * vidLimitPer).
|
|
SetLimit(limit)
|
|
hkwOpt := (&searcher.Option{}).SetLimit(keywordCount) //搜索排名前keywordCount的关键字
|
|
hkwResult, err := vidhkwsearcher.NewVidHKWSearcher(uid, vidOpt).Search(nil, hkwOpt)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
if hkwResult.Count() >= limit { //不用补充视屏
|
|
return hkwResult.Data(), hkwResult.HasNext(), nil
|
|
}
|
|
//热搜视屏代替
|
|
hotOpt := (&searcher.Option{}).
|
|
SetSkip(skip).
|
|
SetLimit(limit)
|
|
hotResult, err := vidhotsearcher.NewVidHotSearcher(uid).Search(nil, hotOpt)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
return hotResult.Data(), hotResult.HasNext(), nil
|
|
}
|
|
|
|
// DeleteManyByTTL 删除自己的视频 被删除的视屏归属为officialUID,未审核或审核未通过的视屏通过TTL删除,其余视屏保留
|
|
func DeleteManyByTTL(uid uint64, ids ...primitive.ObjectID) (code stderr.Code, data interface{}) {
|
|
//redis清除视频id
|
|
mats := []vidmod.Matcher{
|
|
(&vidmod.PublisherIDMatch{PublisherID: &uid}).New(),
|
|
(&vidmod.IDInMatch{IDs: ids}).New(),
|
|
}
|
|
list, err := vidmod.FindMany(mats...)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
//removeIDs-转移到官方账号 并置为审核不通过
|
|
//fakeRemoveIDs-审核通过的金币视频,如果有人购买,做逻辑删除
|
|
//deleteIDs-物理删除
|
|
listLen := len(list)
|
|
removeIDs, fakeRemoveIDs, deleteIDs := make([]primitive.ObjectID, 0, listLen), make([]primitive.ObjectID, 0, listLen), make([]primitive.ObjectID, 0, listLen)
|
|
for _, v := range list {
|
|
if v.Status == 1 || v.Status == 3 { //状态,0 未审核 1通过 2审核失败 3视为免费 默认为0
|
|
if v.Status == 1 && v.Coins > 0 {
|
|
isBePay := payvidlgmod.IsVidIfBePay(v.ID) //判断是否当前视频是否购买过
|
|
if isBePay {
|
|
fakeRemoveIDs = append(fakeRemoveIDs, v.ID)
|
|
} else {
|
|
removeIDs = append(removeIDs, v.ID)
|
|
}
|
|
} else {
|
|
removeIDs = append(removeIDs, v.ID)
|
|
}
|
|
}
|
|
if v.Status == 0 || v.Status == 2 { //状态,0 未审核 1通过 2审核失败 3视为免费 默认为0
|
|
deleteIDs = append(deleteIDs, v.ID)
|
|
}
|
|
}
|
|
rmSetDoc := (&vidmod.SetDoc{}).SetPublisherID(constant.DeleteUID).SetStatus(vidmod.CheckFailure)
|
|
logicRmSetDoc := (&vidmod.SetDoc{}).SetPublisherID(constant.DeleteUID).SetStatus(vidmod.IsDeleted)
|
|
if _, err = vidmod.ModifyMany(removeIDs, *rmSetDoc); err != nil {
|
|
return stderr.ErrDbUpdateError, nil
|
|
}
|
|
if _, err = vidmod.ModifyMany(fakeRemoveIDs, *logicRmSetDoc); err != nil {
|
|
return stderr.ErrDbUpdateError, nil
|
|
}
|
|
|
|
if len(deleteIDs) != 0 {
|
|
_ = vidmod.DelVideo(deleteIDs)
|
|
}
|
|
return stderr.Success, nil
|
|
}
|
|
|
|
// GetNewestNewsList 获取最新帖子
|
|
func GetNewestNewsList(uid, page, size uint64, head []*vidmod.VideoModel, reqDate time.Time) (
|
|
code stderr.Code, data interface{}) {
|
|
infos, hasNext, err := vidhelpser.GetNewestNews(page, size, reqDate)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
if len(head) > 0 {
|
|
head = append(head, infos...)
|
|
head = RemoveRep(head)
|
|
} else {
|
|
head = infos
|
|
}
|
|
newInfos := vidhelpser.EncodeVideoInfo(uid, head)
|
|
data = vidmod.NewsListResp{List: newInfos, HasNext: hasNext}
|
|
return stderr.Success, data
|
|
}
|
|
|
|
// GetNewestNewsList 获取最新帖子
|
|
func GetNewestNewsList_old(uid, page, size uint64, head []*vidmod.VideoModel, subType int) (stderr.Code, interface{}) {
|
|
var infos []*vidmod.VideoModel
|
|
var hasNext bool
|
|
var err error
|
|
if subType == 1 { // 1 只取短视频
|
|
infos, hasNext, err = vidhelpser.GetNewestShortVideo(page, size)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
} else {
|
|
infos, hasNext, err = vidhelpser.GetNewestNews_old(page, size)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
}
|
|
if len(head) > 0 {
|
|
head = append(head, infos...)
|
|
head = RemoveRep(head)
|
|
} else {
|
|
head = infos
|
|
}
|
|
return stderr.Success, vidmod.NewsListResp{List: vidhelpser.EncodeVideoInfo(uid, head), HasNext: hasNext}
|
|
}
|
|
|
|
// GetHotestNewsList 获取最热帖子
|
|
func GetHotestNewsList(uid uint64, subType int, page, size uint64) (code stderr.Code, data interface{}) {
|
|
//优先获取撩吧推荐置顶的
|
|
top := make([]*vidmod.VideoModel, 0)
|
|
if page == 1 {
|
|
var err error
|
|
top, err = vidmod.GetLiaoBaTop()
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
size = size - uint64(len(top))
|
|
}
|
|
//置顶排序
|
|
sort.Sort(vidmod.VideoModelSort(top))
|
|
var ids []primitive.ObjectID
|
|
hasNext := false
|
|
var err error
|
|
if subType == vidmod.TodayRank {
|
|
ids, hasNext, err = hotstatmod.GetHotValueToday(page, size)
|
|
}
|
|
if subType == vidmod.WeekRank {
|
|
ids, hasNext, err = hotstatmod.GetHotValueWeek(page, size)
|
|
}
|
|
if subType == vidmod.MonthRank {
|
|
ids, hasNext, err = hotstatmod.GetHotValueMonth(page, size)
|
|
}
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
mInfos, err := vidmod.GetNewsByIDs2M(ids)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
topLen := len(top)
|
|
sortInfos := make([]*vidmod.VideoModel, 0, len(ids)+topLen)
|
|
if topLen > 0 {
|
|
sortInfos = append(sortInfos, top...)
|
|
}
|
|
for _, v := range ids {
|
|
if mInfos[v] != nil {
|
|
sortInfos = append(sortInfos, mInfos[v])
|
|
}
|
|
}
|
|
newInfos := vidhelpser.EncodeVideoInfo(uid, sortInfos)
|
|
data = vidmod.NewsListResp{List: newInfos, HasNext: hasNext}
|
|
return stderr.Success, data
|
|
}
|
|
|
|
// DoUnlikeVideo 不感兴趣
|
|
func DoUnlikeVideo(uid uint64, vid string) (code stderr.Code, data interface{}) {
|
|
oid, err := primitive.ObjectIDFromHex(vid)
|
|
if err != nil {
|
|
return stderr.ErrParamError, nil
|
|
}
|
|
fmt.Println(oid)
|
|
return stderr.Success, nil
|
|
}
|
|
|
|
// GetNewsCoinsList 金币专区
|
|
func GetNewsCoinsList(uid uint64, subType int, page, size uint64, head []*vidmod.VideoModel) (stderr.Code, interface{}) {
|
|
infos, hasNext, err := vidmod.GetCoinsNews(page, size, subType)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
if len(head) > 0 {
|
|
head = append(head, infos...)
|
|
head = RemoveRep(head)
|
|
} else {
|
|
head = infos
|
|
}
|
|
return stderr.Success, vidmod.NewsListResp{List: vidhelpser.EncodeVideoInfo(uid, head), HasNext: hasNext}
|
|
}
|
|
|
|
// GetOriginalList 新版原创专区
|
|
func GetOriginalList(uid uint64, subType int, page, size uint64) (code stderr.Code, data interface{}) {
|
|
/** TODO:
|
|
1.获取博主排序
|
|
2.获取博主前三则视频
|
|
*/
|
|
users, hasNext, err := usermod.OfficialCertList(page, size, subType)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, err
|
|
}
|
|
var (
|
|
lids []primitive.ObjectID
|
|
vids []primitive.ObjectID
|
|
wg sync.WaitGroup
|
|
m sync.Map
|
|
self *usermod.User
|
|
mLocation = make(map[primitive.ObjectID]locmod.Location)
|
|
mFree = make(map[uint64]bool)
|
|
videoDiscLog videodiscountmod.VideoDiscountLog
|
|
now = time.Now()
|
|
largestDiscount int
|
|
)
|
|
wg.Add(len(users))
|
|
for _, v := range users {
|
|
go func(u *usermod.User) {
|
|
defer wg.Done()
|
|
infos, err := GetUserTopWork(u.UID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if len(infos) == 0 {
|
|
return
|
|
}
|
|
var lidOk bool
|
|
vidInfos := make([]*vidmod.VideoInfo, len(infos))
|
|
for i, v := range infos {
|
|
if !lidOk {
|
|
lids = append(lids, v.Location)
|
|
lidOk = true
|
|
}
|
|
vids = append(vids, v.ID)
|
|
newType := vidmod.SP
|
|
if len(v.NewsType) != 0 {
|
|
newType = v.NewsType
|
|
}
|
|
vidInfos[i] = &vidmod.VideoInfo{
|
|
VideoBase: vidmod.VideoBase{
|
|
ID: v.ID,
|
|
NewsType: newType,
|
|
Title: v.Title,
|
|
PlayTime: v.PlayTime,
|
|
Cover: v.Cover,
|
|
CoverThumb: v.CoverThumb,
|
|
SeriesCover: v.SeriesCover,
|
|
PlayCount: v.FakePlayCount,
|
|
LikeCount: v.FakeLikeCount,
|
|
CommentCount: v.CommentCount,
|
|
ShareCount: v.FakeShareCount,
|
|
Coins: v.Coins,
|
|
Size: v.Size,
|
|
Resolution: v.Resolution,
|
|
Ratio: v.Ratio,
|
|
PurchaseCount: v.PurchaseCount,
|
|
CreatedAt: v.CreatedAt,
|
|
ReviewAt: v.ReviewAt,
|
|
FreeTime: v.FreeTime,
|
|
Status: v.Status,
|
|
Reason: v.Reason,
|
|
SourceURL: v.SourceURL,
|
|
H265Url: vidhelpser.H265URLForApp(v),
|
|
LinkUrl: v.LinkUrl,
|
|
IsHideLocation: v.IsHideLocation,
|
|
FreeArea: v.FreeArea,
|
|
IsTopping: v.IsTopping,
|
|
IsChoosen: v.IsChoosen,
|
|
IsRecommend: v.IsRecommend,
|
|
Rewarded: v.Rewarded.Add(v.FakeRewarded),
|
|
OriginCoins: v.Coins,
|
|
},
|
|
UInfo: vidmod.Publisher{
|
|
UInfo: usermod.BaseInfoVip{
|
|
UID: u.UID,
|
|
Name: u.Name,
|
|
Gender: u.Gender,
|
|
Portrait: u.Portrait,
|
|
HasLocked: u.HasLocked,
|
|
HasBanned: u.HasBanned,
|
|
VipLevel: u.VipLevel,
|
|
IsVip: u.IsVIP(time.Now()),
|
|
SuperUser: u.SuperUser,
|
|
ActiveValue: u.ActiveValue,
|
|
OfficialCert: u.OfficialCert,
|
|
Age: u.Age(),
|
|
},
|
|
},
|
|
Location: vidmod.LocInfo{ID: v.Location},
|
|
}
|
|
}
|
|
m.Store(u.UID, vidInfos)
|
|
}(v)
|
|
}
|
|
wg.Wait()
|
|
wg.Add(4)
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
self, err = usermod.FindUserByUID(uid)
|
|
if err != nil {
|
|
log.Error("usermod.FindUserByUID", log.Any("uid", uid), log.E(err))
|
|
}
|
|
if !self.IsVIP(now) {
|
|
largestDiscount, err = productmod.GetLargestDiscountVIPCard()
|
|
if err != nil {
|
|
log.Error("GetLargestDiscountVIPCard", log.Any("uid", uid), log.E(err))
|
|
}
|
|
}
|
|
})
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
// 查询地理位置
|
|
mLocation, err = locmod.GetLocationInfoByIDs(lids)
|
|
if err != nil {
|
|
log.Error("usermod.FindUserByUID", log.Any("uid", uid), log.E(err))
|
|
}
|
|
})
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
mFree = freeVidmod.GetFreeVideoMapByUID(uid)
|
|
})
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
videoDiscLog, err = videodiscountmod.GetByUID(uid)
|
|
if err != nil {
|
|
log.Error("videodiscountmod.GetByUID", log.Any("uid", uid), log.E(err))
|
|
}
|
|
})
|
|
wg.Wait()
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, err
|
|
}
|
|
//查询购买信息
|
|
mPay, _ := payvidlgmod.IsPay4Videos(uid, vids)
|
|
// 排序
|
|
out := make([][]*vidmod.VideoInfo, len(users))
|
|
freeTrialContext := vidhelpser.FreeTrialBadgeContextForUser(uid, self)
|
|
for i, v := range users {
|
|
if infos, ok := m.Load(v.UID); ok {
|
|
for i, info := range infos.([]*vidmod.VideoInfo) {
|
|
if item, ok := mLocation[info.Location.ID]; ok {
|
|
info.Location = vidmod.LocInfo{
|
|
ID: item.ID,
|
|
City: item.City,
|
|
Cover: item.Cover,
|
|
Visit: item.Visit,
|
|
CreatedAt: item.CreatedAt,
|
|
}
|
|
}
|
|
//是否购买
|
|
infos.([]*vidmod.VideoInfo)[i].VidStatus = vidmod.VideoStatus{
|
|
HasPaid: mPay[info.ID],
|
|
}
|
|
//计算折扣后视频金币数
|
|
infos.([]*vidmod.VideoInfo)[i].Coins = vidhelpser.CalcVideoCoins(info.Coins, v.UID, self, mFree,
|
|
videoDiscLog, largestDiscount, nil)
|
|
}
|
|
vidhelpser.ApplyFreeTrialBadgeToVideoInfos(freeTrialContext, infos.([]*vidmod.VideoInfo))
|
|
out[i] = infos.([]*vidmod.VideoInfo)
|
|
}
|
|
}
|
|
return stderr.Success, vidmod.OriginalInfo{List: out, HasNext: hasNext, Version: vidmod.Version}
|
|
}
|
|
|
|
// GetHeadNews 获取置顶、力荐、加精
|
|
func GetHeadNews(typ int, lid primitive.ObjectID, isMadou bool) ([]*vidmod.VideoModel, error) {
|
|
topping := []*vidmod.VideoModel{}
|
|
recomm := []*vidmod.VideoModel{}
|
|
chosen := []*vidmod.VideoModel{}
|
|
var wg sync.WaitGroup
|
|
wg.Add(3)
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
topping, _ = vidmod.GetTopping(typ, lid, isMadou)
|
|
})
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
recomm, _ = vidmod.GetReco(typ, lid, isMadou)
|
|
})
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
chosen, _ = vidmod.GetChosen(typ, lid, isMadou)
|
|
})
|
|
wg.Wait()
|
|
toppingLen := len(topping)
|
|
recommLen := len(recomm)
|
|
chosenLen := len(chosen)
|
|
head := make([]*vidmod.VideoModel, toppingLen, toppingLen+recommLen+chosenLen)
|
|
mFlag := make(map[primitive.ObjectID]bool)
|
|
for i, v := range topping {
|
|
mFlag[v.ID] = true
|
|
head[i] = v
|
|
}
|
|
for _, v := range recomm {
|
|
if !mFlag[v.ID] {
|
|
mFlag[v.ID] = true
|
|
head = append(head, v)
|
|
}
|
|
}
|
|
for _, v := range chosen {
|
|
if !mFlag[v.ID] {
|
|
mFlag[v.ID] = true
|
|
head = append(head, v)
|
|
}
|
|
}
|
|
return head, nil
|
|
}
|
|
|
|
func GetVIPVideo(uid, page, size uint64) (stderr.Code, interface{}) {
|
|
infos, hasNext, err := vidmod.GetVipList(page, size)
|
|
if err != nil {
|
|
return stderr.ErrDbQueryError, nil
|
|
}
|
|
newInfos := vidhelpser.EncodeVideoInfo(uid, infos)
|
|
data := vidmod.NewsListResp{List: newInfos, HasNext: hasNext}
|
|
return stderr.Success, data
|
|
}
|
|
|
|
func GetVideosUnderSubModuleNew(subModuleID primitive.ObjectID, uid uint64, req VideoUnderSubModuleReq) (data *VideoUnderSubModuleResp, err error) {
|
|
defer func() {
|
|
applyFreeTrialBadgeToSubModule(uid, data)
|
|
}()
|
|
ret := VideoUnderSubModuleResp{
|
|
HasNext: false,
|
|
AllVideoInfo: []*vidmod.VideoInfoResp{},
|
|
AllSection: []Section{},
|
|
}
|
|
subModule, err := moduleconfmod.GetByID(subModuleID)
|
|
if err != nil {
|
|
return &ret, err
|
|
}
|
|
|
|
if subModule.ID.IsZero() {
|
|
return &ret, err
|
|
}
|
|
if !subModule.IsActiveAt(time.Now()) {
|
|
return &ret, nil
|
|
}
|
|
|
|
switch subModule.Type {
|
|
case moduleconfmod.HomePage:
|
|
cachev2.Classes().CacheTime(time.Minute*5).AutoListKey("91PORN-HomePage").ResBind(&ret).Cache(HandleHomePage, subModule, req)
|
|
case moduleconfmod.DeepWeb:
|
|
cachev2.Classes().CacheTime(time.Minute*5).AutoListKey("91PORN-DeepWeb").ResBind(&ret).Cache(HandleHaijiaoList, subModule, req)
|
|
case moduleconfmod.Cartoon, moduleconfmod.Comics, moduleconfmod.Novel:
|
|
cachev2.Classes().CacheTime(time.Minute*5).AutoListKey("91PORN-ACG").ResBind(&ret).Cache(HandleAcg, subModule, req)
|
|
case moduleconfmod.Community: //, moduleconfmod.PrivateCircle:
|
|
cachev2.Classes().CacheTime(time.Minute*5).AutoListKey("91PORN-Community").ResBind(&ret).Cache(HandleCommunity, subModule, req)
|
|
case moduleconfmod.Game, moduleconfmod.Pics:
|
|
cachev2.Classes().CacheTime(time.Minute*5).AutoListKey("91PORN-CommunityPicGame").ResBind(&ret).Cache(HandleCommunityPICAndGame, subModule, req)
|
|
default:
|
|
return
|
|
}
|
|
return &ret, nil
|
|
|
|
}
|
|
|
|
func HandleAcg(subModule moduleconfmod.ModuleConf, req VideoUnderSubModuleReq) (data VideoUnderSubModuleResp) {
|
|
switch subModule.ShowType {
|
|
case moduleconfmod.AllSectionShowType:
|
|
// 专题样式
|
|
data = HandleAcgSectionList(subModule, req)
|
|
default:
|
|
// 海角样式
|
|
data = HandleAcgHaiJiao(subModule, req)
|
|
}
|
|
return
|
|
}
|
|
|
|
func HandleAcgHaiJiao(subModule moduleconfmod.ModuleConf, req VideoUnderSubModuleReq) (data VideoUnderSubModuleResp) {
|
|
if subModule.Type == moduleconfmod.Cartoon || subModule.Type == moduleconfmod.Comics {
|
|
allSection, err := modulesectionmod.GetAllBySubModuleID(subModule.ID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, s := range allSection {
|
|
sec := Section{
|
|
SectionID: s.ID.Hex(),
|
|
SectionName: s.SectionName,
|
|
Hot: s.Hot,
|
|
}
|
|
if s.SectionCover != nil {
|
|
sec.SectionCover = *s.SectionCover
|
|
}
|
|
data.AllSection = append(data.AllSection, sec)
|
|
}
|
|
}
|
|
topIds := []primitive.ObjectID{}
|
|
topList := []*mediamod.Media{}
|
|
var err error
|
|
// 判断当前排序规则是否存在置顶排序
|
|
for _, v := range subModule.HaiJiaoStyle.SortRules {
|
|
if v.Val == commod.SortType(req.ModuleSort) && v.Top == true {
|
|
// 通过模块id获取acg动漫列表
|
|
topList, _, err = mediamod.GetList(bson.M{
|
|
"mId": subModule.ID,
|
|
"sortCode": bson.M{"$gt": 0},
|
|
}, 0, 10, bson.D{
|
|
{Key: "sortCode", Value: -1},
|
|
})
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("HandleAcgHaiJiao mediamod.GetList err:%v", err))
|
|
return
|
|
}
|
|
for _, vi := range topList {
|
|
topIds = append(topIds, vi.ID)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
filter := bson.M{"mId": subModule.ID, "isDelete": false, "status": 1}
|
|
if len(topIds) > 0 {
|
|
filter["_id"] = bson.M{"$nin": topIds}
|
|
}
|
|
sort := acgMediaSort(req.ModuleSort)
|
|
switch commod.SortType(req.ModuleSort) {
|
|
case commod.New:
|
|
// 最新排序已由 acgMediaSort 统一处理。
|
|
case commod.MostHot:
|
|
// 最热(热门推荐)
|
|
sort = bson.D{{Key: "countLike", Value: -1}, {"createdAt", -1}}
|
|
case commod.MostWatch: // 最多观看
|
|
sort = bson.D{{Key: "countBrowse", Value: -1}, {"createdAt", -1}}
|
|
case commod.MostCollect: // 最多收藏
|
|
sort = bson.D{{"countCollect", -1}, {"createdAt", -1}}
|
|
case commod.HotComment: // 热评
|
|
sort = bson.D{{Key: "hot", Value: -1}, {"createdAt", -1}}
|
|
default:
|
|
// 最新
|
|
sort = bson.D{{"createdAt", -1}}
|
|
}
|
|
// 通过模块id获取acg动漫列表
|
|
list, hasNext, err := mediamod.GetList(filter, int64(req.Skip()), int64(req.Limit()), sort)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("HandleAcgHaiJiao mediamod.GetList err:%v", err))
|
|
return
|
|
}
|
|
if req.PageNumber == 1 && len(topList) > 0 {
|
|
list = append(topList, list...)
|
|
}
|
|
data.HasNext = hasNext
|
|
data.AllMediaInfo = mediaser.FillNotStatusMedias(list, false)
|
|
return data
|
|
}
|
|
|
|
func acgMediaSort(moduleSort int) bson.D {
|
|
if commod.SortType(moduleSort) == commod.New {
|
|
return bson.D{
|
|
{Key: "latestPublishedAt", Value: -1},
|
|
{Key: "contentUpdateTime", Value: -1},
|
|
{Key: "createdAt", Value: -1},
|
|
{Key: "_id", Value: -1},
|
|
}
|
|
}
|
|
return bson.D{{Key: "createdAt", Value: -1}}
|
|
}
|
|
|
|
func HandleAcgSectionList(subModule moduleconfmod.ModuleConf, req VideoUnderSubModuleReq) (resp VideoUnderSubModuleResp) {
|
|
page := commod.Page{
|
|
PageNumber: req.PageNumber,
|
|
PageSize: req.PageSize,
|
|
Sort: []commod.Sorts{
|
|
{SortKey: "sort", SortVal: -1},
|
|
{SortKey: "createdAt", SortVal: -1},
|
|
},
|
|
}
|
|
sections, hasNext, err := modulesectionmod.GetBySubModuleID(subModule.ID, page)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("HandleCartoonSingleSection modulesectionmod.GetBySubModuleID err:%v", err))
|
|
return resp
|
|
}
|
|
if len(sections) < 0 {
|
|
return resp
|
|
}
|
|
resp.HasNext = hasNext
|
|
wg := &sync.WaitGroup{}
|
|
sectionResult := make(chan Section, len(sections))
|
|
for _, v := range sections {
|
|
section := v
|
|
// 如果是猜你喜欢专题(ACG不存在这个,直接忽略)
|
|
if section.ShowType == modulesectionmod.GuessYouLike {
|
|
continue
|
|
}
|
|
wg.Add(1)
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
num, ok := modulesectionmod.ACGShowTypeHashVale[section.ShowType]
|
|
// 兼容旧版本找不到新类型的情况
|
|
if !ok {
|
|
// 默认 一大四小
|
|
num = modulesectionmod.ACGShowTypeHashVale[modulesectionmod.FourGrid]
|
|
section.ShowType = modulesectionmod.FourGrid
|
|
}
|
|
secVidMap := Section{
|
|
SectionID: section.ID.Hex(),
|
|
SectionTitle: section.SectionTitle,
|
|
ShowType: section.ShowType,
|
|
SectionName: section.SectionName,
|
|
}
|
|
if section.Sort != nil {
|
|
secVidMap.Sort = *section.Sort
|
|
}
|
|
if section.SectionCover != nil {
|
|
secVidMap.SectionCover = *section.SectionCover
|
|
}
|
|
//op := options.Find().SetLimit(int64(num)).SetSort(bson.D{{Key: "sortCode", Value: -1}, {Key: "createdAt", Value: -1}})
|
|
op := options.Find().SetLimit(int64(num)).SetSort(bson.D{{Key: "sectionSort", Value: -1}, {Key: "createdAt", Value: -1}})
|
|
mediaBases, err := mediamod.SectionVideosBySectionID(section.ID, op)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("mediamod SectionVideos By SectionID:%v, err:%v", section.ID, err))
|
|
sectionResult <- secVidMap
|
|
return
|
|
}
|
|
|
|
if len(mediaBases) == 0 {
|
|
log.Warn("mediamod.SectionVideos no video info")
|
|
sectionResult <- secVidMap
|
|
return
|
|
}
|
|
secVidMap.AllMediaInfo = mediaser.FillNotStatusMedias(mediaBases, false)
|
|
sectionResult <- secVidMap
|
|
})
|
|
}
|
|
wg.Wait()
|
|
close(sectionResult)
|
|
for section := range sectionResult {
|
|
resp.AllSection = append(resp.AllSection, section)
|
|
}
|
|
sort.Slice(resp.AllSection, func(i, j int) bool {
|
|
// 正序排
|
|
return resp.AllSection[i].Sort < resp.AllSection[j].Sort
|
|
})
|
|
return resp
|
|
}
|
|
|
|
func HandleHomePage(subModule moduleconfmod.ModuleConf, req VideoUnderSubModuleReq) (data VideoUnderSubModuleResp) {
|
|
switch subModule.ShowType {
|
|
//case moduleconfmod.NewPageShowType:
|
|
// // 首页最新/推荐展示类型
|
|
// return HandleHomePageNew(subModule, req)
|
|
case moduleconfmod.HJShowType:
|
|
// 海角系 专题+列表
|
|
return HandleHaijiaoList(subModule, req)
|
|
case moduleconfmod.AllSectionShowType:
|
|
// 专题展示样式
|
|
return HandleSectionList(subModule, req)
|
|
default:
|
|
return HandleHaijiaoList(subModule, req)
|
|
}
|
|
return
|
|
}
|
|
|
|
func HandleHaijiaoList(subModule moduleconfmod.ModuleConf, req VideoUnderSubModuleReq) (data VideoUnderSubModuleResp) {
|
|
var (
|
|
videos []*vidmod.VideoModel
|
|
topVideos []*vidmod.VideoInfoResp
|
|
chosenVideos []*vidmod.VideoInfoResp
|
|
)
|
|
// 展示专题
|
|
if subModule.HaiJiaoStyle.SectionStyle > 0 {
|
|
allSection, err := modulesectionmod.HomePageGetBySubModuleID(subModule.ID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, s := range allSection {
|
|
sec := Section{
|
|
SectionID: s.ID.Hex(),
|
|
SectionName: s.SectionName,
|
|
Hot: s.Hot,
|
|
}
|
|
if s.SectionCover != nil {
|
|
sec.SectionCover = *s.SectionCover
|
|
}
|
|
data.AllSection = append(data.AllSection, sec)
|
|
}
|
|
}
|
|
|
|
wg := &sync.WaitGroup{}
|
|
|
|
if subModule.HaiJiaoStyle.ShowChosenVideo == 1 {
|
|
wg.Add(1)
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
// 获取推荐的数据
|
|
filter := bson.M{"mId": subModule.ID.Hex(), "newsType": vidmod.SP, "status": vidmod.CheckPass, "chosen": true}
|
|
sort := bson.D{{"isTopping", -1}, {"chosenDate", -1}}
|
|
opt := options.Find().
|
|
SetSort(sort).
|
|
SetLimit(20).
|
|
SetProjection(bson.M{"richText": 0})
|
|
|
|
// 首页精选视频
|
|
list, err := vidmod.GetVideoListByCond(filter, opt) // 获取视频详情
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("HandleAllList vidmod.GetVideoListByCond err:%v", err))
|
|
return
|
|
}
|
|
chosenVideos = vidhelpser.NewEncodeVideoInfoNotStatus(list)
|
|
})
|
|
}
|
|
|
|
topIds := []primitive.ObjectID{}
|
|
// 判断当前排序规则是否存在置顶排序
|
|
for _, v := range subModule.HaiJiaoStyle.SortRules {
|
|
if v.Val == commod.SortType(req.ModuleSort) && v.Top == true {
|
|
// 获取置顶数据
|
|
wg.Add(1)
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
// 获取置顶的数据
|
|
filter := bson.M{"mId": subModule.ID.Hex(), "liaoBaTopSort": bson.M{"$gt": 0}, "chosen": false}
|
|
sort := bson.D{{"liaoBaTopSort", -1}}
|
|
opt := options.Find().
|
|
SetSort(sort).
|
|
SetLimit(10).
|
|
SetProjection(bson.M{"richText": 0})
|
|
|
|
// 首页精选视频
|
|
list, err := vidmod.GetVideoListByCond(filter, opt) // 获取视频详情
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("HandleAllList vidmod.GetVideoListByCond err:%v", err))
|
|
return
|
|
}
|
|
topVideos = vidhelpser.NewEncodeVideoInfoNotStatus(list)
|
|
for _, video := range topVideos {
|
|
topIds = append(topIds, video.ID)
|
|
}
|
|
})
|
|
break
|
|
}
|
|
}
|
|
wg.Wait()
|
|
// 首页
|
|
filter := bson.M{
|
|
"mId": subModule.ID.Hex(),
|
|
"status": vidmod.CheckPass,
|
|
"newsType": vidmod.SP,
|
|
"chosen": false,
|
|
}
|
|
if len(topIds) > 0 {
|
|
filter["_id"] = bson.M{"$nin": topIds}
|
|
}
|
|
sort := bson.D{{"reviewAt", -1}}
|
|
switch commod.SortType(req.ModuleSort) {
|
|
case commod.New:
|
|
// 最新
|
|
sort = bson.D{{"reviewAt", -1}}
|
|
case commod.MostHot:
|
|
// 最热(热门推荐)
|
|
sort = bson.D{{"liaoBaTopSort", -1}, {Key: "likeCount", Value: -1}, {"reviewAt", -1}}
|
|
case commod.MostWatch:
|
|
// 最多观看
|
|
sort = bson.D{{Key: "playCount", Value: -1}, {"reviewAt", -1}}
|
|
case commod.MostCollect:
|
|
// 最多收藏
|
|
sort = bson.D{{"collectCount", -1}, {"reviewAt", -1}}
|
|
case commod.HotComment: // 热度值
|
|
sort = bson.D{{"hot", -1}, {"reviewAt", -1}}
|
|
default:
|
|
// 最新
|
|
sort = bson.D{{"reviewAt", -1}}
|
|
}
|
|
opt := options.Find().SetSort(sort).SetSkip(req.Skip64()).SetLimit(req.Limit64() + 1).SetProjection(bson.M{"richText": 0})
|
|
var err error
|
|
videos, err = vidmod.GetVideoListByCond(filter, opt) // 获取视频详情
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("vidmod.GetVideoListByCond err:%v", err))
|
|
return
|
|
}
|
|
if len(videos) > int(req.Limit()) {
|
|
data.HasNext = true
|
|
videos = videos[:req.Limit()]
|
|
}
|
|
data.AllVideoInfo = vidhelpser.NewEncodeVideoInfoNotStatus(videos)
|
|
if req.PageNumber == 1 && len(topVideos) > 0 {
|
|
// 第一页,直接插入到最前面
|
|
data.AllVideoInfo = append(topVideos, data.AllVideoInfo...)
|
|
}
|
|
data.ChosenVideoInfo = chosenVideos
|
|
return
|
|
}
|
|
|
|
func HandleSectionList(subModule moduleconfmod.ModuleConf, req VideoUnderSubModuleReq) (resp VideoUnderSubModuleResp) {
|
|
page := commod.Page{
|
|
PageNumber: req.PageNumber,
|
|
PageSize: req.PageSize,
|
|
Sort: []commod.Sorts{
|
|
{SortKey: "sort", SortVal: -1},
|
|
{SortKey: "createdAt", SortVal: -1},
|
|
},
|
|
}
|
|
sections, hasNext, err := modulesectionmod.GetBySubModuleID(subModule.ID, page)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("HandleSectionList modulesectionmod.GetBySubModuleID err:%v", err))
|
|
return resp
|
|
}
|
|
if len(sections) < 0 {
|
|
return resp
|
|
}
|
|
resp.HasNext = hasNext
|
|
wg := &sync.WaitGroup{}
|
|
sectionResult := make(chan Section, len(sections))
|
|
for _, v := range sections {
|
|
section := v
|
|
wg.Add(1)
|
|
common.Go(func() {
|
|
defer wg.Done()
|
|
num := modulesectionmod.ShowTypeHashVale[section.ShowType]
|
|
if num == 0 {
|
|
num = int(req.PageSize)
|
|
}
|
|
num = num + 2 // 满足ab测需求,额外多返回2个
|
|
secVidMap := Section{
|
|
SectionID: section.ID.Hex(),
|
|
SectionTitle: section.SectionTitle,
|
|
ShowType: section.ShowType,
|
|
SectionName: section.SectionName,
|
|
Hot: section.Hot,
|
|
}
|
|
if section.Sort != nil {
|
|
secVidMap.Sort = *section.Sort
|
|
}
|
|
if section.SectionCover != nil {
|
|
secVidMap.SectionCover = *section.SectionCover
|
|
}
|
|
if section.ShowType == modulesectionmod.GuessYouLike {
|
|
sectionResult <- secVidMap
|
|
return
|
|
}
|
|
var (
|
|
sectionVideos []modulevidmod.SectionVideo
|
|
videos []*vidmod.VideoModel
|
|
)
|
|
opt := options.Find().SetSort(bson.D{{Key: "sortCode", Value: -1}, {Key: "videoReviewedAt", Value: -1}}).SetLimit(int64(num))
|
|
sectionVideos, err = modulevidmod.SectionVideosBySectionID(section.ID, opt)
|
|
if err != nil {
|
|
log.Error("GetSectionVideosBySectionID", log.Any("sectionID", section.ID), log.E(err))
|
|
return
|
|
}
|
|
if len(sectionVideos) == 0 {
|
|
log.Warn("modulevidmod.SectionVideosBySectionID empty video list", log.Any("sectionID", section.ID))
|
|
return
|
|
}
|
|
videoIDs := make([]primitive.ObjectID, len(sectionVideos))
|
|
for i, v := range sectionVideos {
|
|
videoIDs[i] = v.VideoID
|
|
}
|
|
// 获取视频详情
|
|
if videos, err = vidmod.GetVideoListByIDs(videoIDs); err != nil {
|
|
log.Error("vidmod.GetVideoListByIDs", log.Any("videoIDs", videoIDs), log.E(err))
|
|
return
|
|
}
|
|
if len(videos) == 0 {
|
|
log.Warn("vidmod.GetVideoListByIDs no video info", log.Any("videosIDs", videoIDs))
|
|
return
|
|
}
|
|
// 根据专题中的重新排序
|
|
sortVideos := []*vidmod.VideoModel{}
|
|
videoMap := make(map[primitive.ObjectID]*vidmod.VideoModel)
|
|
for _, video := range videos {
|
|
videoMap[video.ID] = video
|
|
}
|
|
for _, video := range sectionVideos {
|
|
vi, ok := videoMap[video.VideoID]
|
|
if ok {
|
|
sortVideos = append(sortVideos, vi)
|
|
}
|
|
}
|
|
videoList := vidhelpser.NewEncodeVideoInfoNotStatus(sortVideos)
|
|
secVidMap.AllVideoInfo = videoList
|
|
sectionResult <- secVidMap
|
|
})
|
|
}
|
|
wg.Wait()
|
|
close(sectionResult)
|
|
for section := range sectionResult {
|
|
resp.AllSection = append(resp.AllSection, section)
|
|
}
|
|
sort.Slice(resp.AllSection, func(i, j int) bool {
|
|
// 正序排
|
|
return resp.AllSection[i].Sort < resp.AllSection[j].Sort
|
|
})
|
|
return
|
|
}
|
|
|
|
func HandleCommunity(subModule moduleconfmod.ModuleConf, req VideoUnderSubModuleReq) (data VideoUnderSubModuleResp) {
|
|
var (
|
|
videos []*vidmod.VideoModel
|
|
videoTagIds []primitive.ObjectID
|
|
err error
|
|
next bool
|
|
)
|
|
|
|
allSection, err := modulesectionmod.GetAllBySubModuleID(subModule.ID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, s := range allSection {
|
|
var allTag []Tag
|
|
if s.Tags != nil && len(*s.Tags) > 0 && s.TagIds != nil && len(*s.TagIds) > 0 {
|
|
videoTagIds = append(videoTagIds, *s.TagIds...)
|
|
tags, err := tagmod.FindOneTagByIds(*s.TagIds)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if tags != nil && len(tags) > 0 {
|
|
for _, t := range tags {
|
|
allTag = append(allTag, Tag{
|
|
ID: t.ID,
|
|
TagName: t.TagName,
|
|
CoverImg: t.CoverImg,
|
|
VideoCount: t.VideoCount,
|
|
HotMark: t.HotMark,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
sec := Section{
|
|
SectionID: s.ID.Hex(),
|
|
SectionName: s.SectionName,
|
|
AllTags: allTag,
|
|
}
|
|
if s.SectionCover != nil {
|
|
sec.SectionCover = *s.SectionCover
|
|
}
|
|
data.AllSection = append(data.AllSection, sec)
|
|
}
|
|
tagId, _ := primitive.ObjectIDFromHex(req.TagId)
|
|
if !tagId.IsZero() {
|
|
videoTagIds = []primitive.ObjectID{tagId}
|
|
}
|
|
if len(videoTagIds) == 0 {
|
|
return data
|
|
}
|
|
|
|
var (
|
|
topVideos []*vidmod.VideoModel
|
|
now = time.Now()
|
|
filter = bson.M{}
|
|
sort = bson.D{}
|
|
opt = options.Find().SetSkip(req.Skip64()).SetLimit(req.Limit64()).SetProjection(bson.M{"richText": 0})
|
|
)
|
|
|
|
// 社区置顶,第一页查询置顶数据,没有时间限制
|
|
if req.ModuleSort == 7 && req.PageNumber == 1 {
|
|
topFilter := bson.M{
|
|
"tags": bson.M{"$in": videoTagIds},
|
|
"status": vidmod.CheckPass,
|
|
"liaoBaTopSort": bson.M{"$gt": 0},
|
|
}
|
|
topSort := bson.D{
|
|
{"liaoBaTopSort", -1},
|
|
{"reviewAt", -1},
|
|
}
|
|
|
|
topOpt := options.Find().
|
|
SetLimit(10).
|
|
SetSort(topSort).
|
|
SetProjection(bson.M{"richText": 0})
|
|
|
|
topVideos, _, err = vidmod.FindList(topFilter, topOpt) // 获取视频详情
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("vidmod.FindList get top vid err:%v", err))
|
|
return
|
|
}
|
|
}
|
|
|
|
//帖子排序
|
|
//最新:最新上架的 sortType = 1
|
|
//最热:收藏量 10-120天 sortType = 2
|
|
//推荐: 收藏量 14天内 sortType = 7
|
|
//热评:hot排序 1年内 sortType = 9
|
|
|
|
filter = bson.M{"tags": bson.M{"$in": videoTagIds}, "status": vidmod.CheckPass}
|
|
switch req.ModuleSort {
|
|
case 2: // 精选/最多喜欢 // x天内点赞最多的
|
|
filter["reviewAt"] = bson.M{"$gte": now.AddDate(0, -4, 0), "$lt": now.AddDate(0, -1, 0)}
|
|
sort = bson.D{{"collectCount", -1}, {"reviewAt", -1}}
|
|
|
|
case 3: // 推荐
|
|
filter["reviewAt"] = bson.M{"$gte": now.Add(-time.Hour * 24 * 30)}
|
|
sort = bson.D{{"playCount", -1}, {"reviewAt", -1}}
|
|
|
|
case 6: // 社区视频 x天内观看最多(视频)
|
|
filter["reviewAt"] = bson.M{"$gte": now.Add(-time.Hour * 24 * 30)}
|
|
filter["newsType"] = vidmod.SP
|
|
sort = bson.D{{"playCount", -1}, {"reviewAt", -1}}
|
|
|
|
case 7: // 推荐/最多收藏 x天内收藏最多
|
|
filter["reviewAt"] = bson.M{"$gte": now.Add(-time.Hour * 24 * 14)}
|
|
filter["liaoBaTopSort"] = 0
|
|
sort = bson.D{{"collectCount", -1}, {"reviewAt", -1}}
|
|
case 9: // 热评
|
|
filter["reviewAt"] = bson.M{"$gte": now.AddDate(-1, 0, 0)}
|
|
sort = bson.D{{"hot", -1}, {"reviewAt", -1}}
|
|
|
|
case 1: // 最新
|
|
fallthrough
|
|
default:
|
|
sort = bson.D{{"reviewAt", -1}}
|
|
}
|
|
|
|
opt = opt.SetSort(sort)
|
|
|
|
videos, next, err = vidmod.FindList(filter, opt) // 获取视频详情
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("vidmod.GetVideoListByCond err:%v", err))
|
|
return
|
|
}
|
|
if len(topVideos) > 0 {
|
|
videos = append(topVideos, videos...)
|
|
}
|
|
if len(videos) == 0 {
|
|
log.Warn(fmt.Sprintf("vidmod.GetVideoListByCond is null, subModuleID:%v", subModule.ID.Hex()))
|
|
return
|
|
}
|
|
|
|
data.HasNext = next
|
|
data.AllVideoInfo = vidhelpser.NewEncodeVideoInfoNotStatus(videos)
|
|
|
|
// tagId 不为空,找出video的tag, 只返回一个,前端统一
|
|
if !tagId.IsZero() {
|
|
var tag vidmod.TagInfo
|
|
for _, video := range data.AllVideoInfo {
|
|
if tag.ID.IsZero() {
|
|
for _, t := range video.Tags {
|
|
if t.ID == tagId {
|
|
tag = t
|
|
}
|
|
}
|
|
}
|
|
video.Tags = append(video.Tags[0:0], tag)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func HandleCommunityPICAndGame(subModule moduleconfmod.ModuleConf, req VideoUnderSubModuleReq) (data VideoUnderSubModuleResp) {
|
|
var (
|
|
err error
|
|
videos []*vidmod.VideoModel
|
|
next bool
|
|
)
|
|
var (
|
|
filter = bson.M{}
|
|
sort = bson.D{}
|
|
someTimeAgo = time.Now().AddDate(-3, 0, 0) // 给个默认时间统一走索引
|
|
opt = options.Find().SetSkip(req.Skip64()).SetLimit(req.Limit64()).SetProjection(bson.M{"richText": 0})
|
|
)
|
|
// 黄油 (本项目没用到)
|
|
//最热:根据点赞量排序 sortType = 2
|
|
//最新:根据上架时间排序 sortType = 1
|
|
//畅销:根据解锁次数排序 sortType = 8
|
|
|
|
//图集
|
|
//最多观看:观看量最多 sortType = 3
|
|
//最新发布:根据上架时间排序 sortType = 1
|
|
//最多收藏:根据收藏量排序 sortType = 7
|
|
|
|
filter = bson.M{"mId": subModule.ID.Hex(), "status": vidmod.CheckPass}
|
|
switch req.ModuleSort {
|
|
case 2: // 精选/最多喜欢 // x天内点赞最多的
|
|
filter["reviewAt"] = bson.M{"$gte": someTimeAgo}
|
|
sort = bson.D{{"liaoBaTopSort", -1}, {"likeCount", -1}, {"reviewAt", -1}}
|
|
case 3: // 最热/最多播放 x天内观看量
|
|
filter["reviewAt"] = bson.M{"$gte": someTimeAgo}
|
|
sort = bson.D{{"playCount", -1}, {"reviewAt", -1}}
|
|
|
|
case 7: // 推荐/最多收藏 x天内收藏最多
|
|
filter["reviewAt"] = bson.M{"$gte": someTimeAgo}
|
|
sort = bson.D{{"collectCount", -1}, {"reviewAt", -1}}
|
|
|
|
case 8: // 购买人数
|
|
filter["reviewAt"] = bson.M{"$gte": someTimeAgo}
|
|
sort = bson.D{{"purchaseCount", -1}, {"reviewAt", -1}}
|
|
case 1: // 最新
|
|
fallthrough
|
|
default:
|
|
sort = bson.D{{"reviewAt", -1}}
|
|
}
|
|
|
|
videos, next, err = vidmod.FindList(filter, opt.SetSort(sort)) // 获取视频详情
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("vidmod.GetVideoListByCond err:%v", err))
|
|
return
|
|
}
|
|
if len(videos) == 0 {
|
|
log.Warn(fmt.Sprintf("vidmod.GetVideoListByCond is null, subModuleID:%v", subModule.ID.Hex()))
|
|
return
|
|
}
|
|
|
|
data.HasNext = next
|
|
data.AllVideoInfo = vidhelpser.NewEncodeVideoInfoNotStatus(videos)
|
|
return
|
|
}
|
|
|
|
// GetCommunityRecommend 社区-图集和黄油推荐
|
|
func GetCommunityRecommend(req CommunityRecommendReq) (data *VideoUnderSubModuleResp, err error) {
|
|
ret := VideoUnderSubModuleResp{
|
|
HasNext: false,
|
|
AllVideoInfo: []*vidmod.VideoInfoResp{},
|
|
AllSection: []Section{},
|
|
}
|
|
excluded, err := moduleconfmod.ExcludedVideoModuleIDs(time.Now(), true)
|
|
if err != nil {
|
|
return &ret, err
|
|
}
|
|
if len(excluded) > 0 {
|
|
result := HandleHotRecommend(req)
|
|
return &result, nil
|
|
}
|
|
expire := time.Minute * 5
|
|
_, err = cachev2.Classes().CacheTime(expire).AutoListKey("CommunityRecommend").ResBind(&ret).Cache(HandleHotRecommend, req)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return &ret, nil
|
|
}
|
|
|
|
// HandleHotRecommend 社区热门推荐
|
|
func HandleHotRecommend(req CommunityRecommendReq) (resp VideoUnderSubModuleResp) {
|
|
var (
|
|
sort bson.D
|
|
someTimeAgo = time.Now().AddDate(0, -3, 0)
|
|
filter = bson.M{"newsType": req.NewsType, "status": vidmod.CheckPass, "reviewAt": bson.M{"$gte": someTimeAgo}}
|
|
opt = options.Find().SetSkip(int64(req.Skip())).SetLimit(int64(req.Limit())).SetProjection(bson.M{"richText": 0})
|
|
)
|
|
excluded, err := moduleconfmod.ExcludedVideoModuleIDs(time.Now(), true)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if len(excluded) > 0 {
|
|
filter["mId"] = bson.M{"$nin": excluded}
|
|
}
|
|
|
|
// 黄油 90天内的帖子
|
|
//最热:根据点赞量排序 sortType = 2
|
|
//最新:根据上架时间排序 sortType = 1
|
|
//畅销:根据解锁次数排序 sortType = 8
|
|
//图集 90天内的帖子
|
|
//最多观看:观看量最多 sortType = 3
|
|
//最新发布:根据上架时间排序 sortType = 1
|
|
//最多收藏:根据收藏量排序 sortType = 7
|
|
|
|
switch req.SortType {
|
|
case 2: // 精选/最多喜欢 // x天内点赞最多的
|
|
filter["reviewAt"] = bson.M{"$gte": someTimeAgo}
|
|
sort = bson.D{{"likeCount", -1}, {"reviewAt", -1}}
|
|
|
|
case 3: // 最热/最多播放 x天内观看量
|
|
filter["reviewAt"] = bson.M{"$gte": someTimeAgo}
|
|
sort = bson.D{{"playCount", -1}, {"reviewAt", -1}}
|
|
|
|
case 7: // 推荐/最多收藏 x天内收藏最多
|
|
filter["reviewAt"] = bson.M{"$gte": someTimeAgo}
|
|
sort = bson.D{{"liaoBaTopSort", -1}, {"collectCount", -1}, {"reviewAt", -1}}
|
|
|
|
case 8: // 购买人数
|
|
filter["reviewAt"] = bson.M{"$gte": someTimeAgo}
|
|
sort = bson.D{{"purchaseCount", -1}, {"reviewAt", -1}}
|
|
|
|
case 1: // 最新
|
|
fallthrough
|
|
default:
|
|
sort = bson.D{{"reviewAt", -1}}
|
|
}
|
|
|
|
videos, next, err := vidmod.FindList(filter, opt.SetSort(sort)) // 获取视频详情
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("vidmod.GetVideoListByCond err:%v", err))
|
|
return
|
|
}
|
|
if len(videos) == 0 {
|
|
return
|
|
}
|
|
|
|
resp.HasNext = next
|
|
resp.AllVideoInfo = vidhelpser.NewEncodeVideoInfoNotStatusForRecommend(videos)
|
|
|
|
return resp
|
|
}
|
|
|
|
// IncSectionHits 增加专题点击量
|
|
func IncSectionHits(ctx context.Context, sectionID primitive.ObjectID) error {
|
|
now := time.Now()
|
|
date := now.Add(-12 * time.Hour).Local().Format("2006-01-02")
|
|
return sectionstatmod.UpsertSectionHits(sectionID, date)
|
|
}
|
|
|
|
// GetBloggerVideos 获取某一原创博主的视频列表
|
|
func GetBloggerVideos(uid, bloggerID uint64, page commod.Page) (resp VideoUnderSectionResp, err error) {
|
|
videos, hasNext, err := vidmod.GetBloggerVideos(bloggerID, int64(page.Skip()), int64(page.Limit()))
|
|
if err != nil {
|
|
return
|
|
}
|
|
resp.HasNext = hasNext
|
|
bloggerInfo, err := getOriginalBloggerInfo([]uint64{bloggerID})
|
|
if err != nil {
|
|
return
|
|
}
|
|
resp.OriginalBloggerInfo = bloggerInfo[bloggerID]
|
|
resp.Videos = vidhelpser.NewEncodeVideoInfo(uid, videos)
|
|
sort.Slice(resp.Videos, func(i, j int) bool {
|
|
return resp.Videos[i].CreatedAt.After(resp.Videos[j].CreatedAt)
|
|
})
|
|
return
|
|
}
|
|
|
|
func GetSectionVideos(uid uint64, sectionID primitive.ObjectID, page commod.Page, sortType string, playTimeType int) (
|
|
out VideoUnderSectionResp, err error,
|
|
) {
|
|
var sectionVideos []modulevidmod.SectionVideo
|
|
defer func() {
|
|
vidhelpser.ApplyFreeTrialBadgeToVideoInfoResps(vidhelpser.LoadFreeTrialBadgeContext(uid), out.Videos)
|
|
}()
|
|
section, err := modulesectionmod.GetBySectionByID(sectionID)
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
if section.ID.IsZero() {
|
|
return out, errors.New("section not found")
|
|
}
|
|
active, err := moduleconfmod.CanBrowseModule(section.SubModuleID, time.Now())
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
if !active {
|
|
return out, nil
|
|
}
|
|
key := redisconst.SectionVideoInfoCacheKey(sectionID.Hex(), sortType, int64(page.PageSize), int64(page.PageNumber))
|
|
str, err := appg.Redis.Get(key)
|
|
if err != nil {
|
|
log.Warn(fmt.Sprintf("用户ID:%d;缓存获取视频列表信息异常:%v", uid, err))
|
|
}
|
|
|
|
if str != nil {
|
|
if err = msgpack.Unmarshal([]byte(*str), &out); err == nil {
|
|
return out, nil
|
|
}
|
|
log.Warn(fmt.Sprintf("用户ID:%d;解析缓存数据异常:%v", uid, err))
|
|
}
|
|
limit100 := false
|
|
skip := page.Skip()
|
|
if strings.TrimSpace(section.SectionName) == "最新" { // "最新"栏最多返回100条
|
|
limit100 = true
|
|
if skip >= 100 {
|
|
return out, nil
|
|
}
|
|
}
|
|
// 默认专题排序
|
|
if sortType == "" && playTimeType == 0 {
|
|
opts := options.Find().SetLimit(int64(page.PageSize + 1)).SetSkip(int64((page.PageNumber - 1) * page.PageSize)).
|
|
SetSort(bson.D{{Key: "sortCode", Value: -1}, {Key: "videoReviewedAt", Value: -1}})
|
|
sectionVideos, err = modulevidmod.Find(bson.M{"sectionID": sectionID}, opts)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("用户ID:%d;专题ID:%v;获取专题视频异常:%v", uid, sectionID, err))
|
|
return out, err
|
|
}
|
|
out.HasNext = false
|
|
if uint64(len(sectionVideos)) > page.PageSize {
|
|
sectionVideos = sectionVideos[:page.PageSize]
|
|
out.HasNext = true
|
|
}
|
|
} else {
|
|
sectionVideos, err = modulevidmod.GetSectionVideosBySectionID(sectionID)
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
}
|
|
videoIDs := make([]primitive.ObjectID, len(sectionVideos))
|
|
for i, v := range sectionVideos {
|
|
videoIDs[i] = v.VideoID
|
|
}
|
|
if len(videoIDs) == 0 {
|
|
out.Videos = []*vidmod.VideoInfoResp{}
|
|
return out, nil
|
|
}
|
|
cond := bson.M{"_id": bson.M{"$in": videoIDs}, "status": 1}
|
|
/* 19porn used sort
|
|
热门推荐:一个月内视频按点赞量排序 支持运营手动设置推荐
|
|
最新上架:根据发布的时间顺序进行排序,无限下滑
|
|
最新热评:按照用户评论排序。优先级在置顶排序后边,按天刷新
|
|
*/
|
|
var s bson.D
|
|
switch sortType {
|
|
case "watch":
|
|
s = bson.D{{Key: "playCount", Value: -1}, {Key: "reviewAt", Value: -1}, {Key: "_id", Value: -1}}
|
|
case "new", "":
|
|
s = bson.D{{Key: "reviewAt", Value: -1}, {Key: "_id", Value: -1}}
|
|
case "collect":
|
|
s = bson.D{{Key: "collectCount", Value: -1}, {"reviewAt", -1}, {Key: "_id", Value: -1}}
|
|
case "like":
|
|
s = bson.D{{Key: "likeCount", Value: -1}, {"reviewAt", -1}, {Key: "_id", Value: -1}}
|
|
case "comment": // hot comment, sort value , from task timed statistics of 'SKD' server got it
|
|
s = bson.D{{Key: "hot", Value: -1}, {"reviewAt", -1}, {Key: "_id", Value: -1}}
|
|
default: //兼容旧版,传入参数为其他值
|
|
s = bson.D{{"reviewAt", -1}, {Key: "_id", Value: -1}}
|
|
}
|
|
videos, total, err := vidmod.GetvideoListByMapCond(cond, s, page.PageNumber, page.PageSize)
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
var newVideos []*vidmod.VideoModel
|
|
if playTimeType == 0 && sortType == "" {
|
|
newVideos = make([]*vidmod.VideoModel, 0, len(sectionVideos))
|
|
for _, sv := range sectionVideos {
|
|
for _, v := range videos {
|
|
if sv.VideoID == v.ID {
|
|
newVideos = append(newVideos, v)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
newVideos = videos
|
|
}
|
|
if int64(page.PageNumber*page.PageSize) < total {
|
|
out.HasNext = true
|
|
}
|
|
if newVideosLen := uint64(len(newVideos)); limit100 && skip+newVideosLen >= 100 {
|
|
out.HasNext = false
|
|
newVideos = newVideos[:100-skip]
|
|
}
|
|
out.Videos = vidhelpser.NewEncodeVideoInfo(uid, newVideos)
|
|
|
|
common.Go(func() {
|
|
if out.Videos != nil || len(out.Videos) > 0 {
|
|
d, err := msgpack.Marshal(out)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if err = appg.Redis.Set(key, d, 10*time.Minute); err != nil {
|
|
log.Warn(fmt.Sprintf("用户ID:%d;保存缓存数据异常:%v", uid, err))
|
|
}
|
|
}
|
|
})
|
|
return out, nil
|
|
}
|
|
|
|
func GetVideosUnderSection(uid uint64, sectionID primitive.ObjectID, page commod.Page, sortType string, playTimeType int) (
|
|
resp VideoUnderSectionResp, err error) {
|
|
section, err := modulesectionmod.GetBySectionByID(sectionID)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
active, err := moduleconfmod.CanBrowseModule(section.SubModuleID, time.Now())
|
|
if err != nil || !active {
|
|
return resp, err
|
|
}
|
|
sectionVideos, err := modulevidmod.GetSectionVideosBySectionID(sectionID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
videoIDs := make([]primitive.ObjectID, len(sectionVideos))
|
|
for i, v := range sectionVideos {
|
|
videoIDs[i] = v.VideoID
|
|
}
|
|
cond := bson.M{"status": 1, "_id": bson.M{"$in": videoIDs}}
|
|
switch playTimeType {
|
|
case 1:
|
|
cond["playTime"] = bson.M{"$gte": 60 * 10}
|
|
case 2:
|
|
cond["playTime"] = bson.M{"$lt": 60 * 10}
|
|
}
|
|
var s bson.D
|
|
switch sortType {
|
|
case "hot":
|
|
videos, _, hasNext, err := vidmod.GetHotList(int64((page.PageNumber-1)*page.PageSize), int64(page.PageSize), cond)
|
|
vInfos := vidhelpser.NewEncodeVideoInfo(uid, videos)
|
|
resp.Videos = vInfos
|
|
resp.HasNext = hasNext
|
|
return resp, err
|
|
case "watch":
|
|
s = bson.D{{Key: "playCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
case "like":
|
|
s = bson.D{{Key: "likeCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
case "new", "":
|
|
s = bson.D{{Key: "reviewAt", Value: -1}}
|
|
default: //兼容旧版,传入参数为其他值
|
|
s = bson.D{{Key: "playCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
}
|
|
videos, total, err := vidmod.GetvideoListByMapCond(cond, s, page.PageNumber, page.PageSize)
|
|
if err != nil {
|
|
return resp, err
|
|
}
|
|
videoInfo := vidhelpser.NewEncodeVideoInfo(uid, videos)
|
|
resp.Videos = videoInfo
|
|
if int64(page.PageNumber*page.PageSize) < total {
|
|
resp.HasNext = true
|
|
}
|
|
resp.OriginalBloggerInfo = OriginalBloggerInfo{}
|
|
return
|
|
}
|
|
|
|
type HotVideoRes struct {
|
|
List []*vidmod.VideoInfo `json:"data"`
|
|
HasNext bool `json:"hasNext"`
|
|
}
|
|
|
|
// GetHotVideo 获取最热视频
|
|
func GetHotVideo(page, size int64, t int) (res HotVideoRes, err error) {
|
|
key := fmt.Sprintf("hot-videos:page%d:size%d:t%d", page, size, t)
|
|
expire := time.Minute * 10
|
|
s, err := appg.Redis.Get(key)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if s != nil && *s != "" {
|
|
_ = json.Unmarshal([]byte(*s), &res)
|
|
}
|
|
if len(res.List) == 0 {
|
|
start := time.Now().AddDate(0, 0, -7)
|
|
end := time.Now()
|
|
switch t {
|
|
case 1: // 本月最热
|
|
start = time.Now().AddDate(0, -1, 0)
|
|
case 2: // 上月最热
|
|
start = time.Now().AddDate(0, -2, 0)
|
|
end = time.Now().AddDate(0, -1, 0)
|
|
}
|
|
|
|
var videos []*vidmod.VideoModel
|
|
videos, res.HasNext, err = vidmod.GetHotVideoByOnlineTimeRange(start, end, page, size)
|
|
if err != nil {
|
|
return HotVideoRes{}, err
|
|
}
|
|
|
|
res.List = vidhelpser.EncodeVideoInfoNoUID(videos)
|
|
common.Go(func() {
|
|
b, _ := json.Marshal(res)
|
|
_ = appg.Redis.Set(key, string(b), expire)
|
|
})
|
|
}
|
|
return
|
|
}
|
|
|
|
func GetHotPublisher(uid uint64) (data []*proto.HotPublisher, err error) {
|
|
data = make([]*proto.HotPublisher, 0)
|
|
return
|
|
key := "getHotpublisher:vidser"
|
|
expaire := time.Minute * 10
|
|
s, err := appg.Redis.Get(key)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if s != nil && *s != "" {
|
|
_ = json.Unmarshal([]byte(*s), &data)
|
|
}
|
|
if len(data) == 0 {
|
|
now := time.Now()
|
|
d := timeutil.BeginningOfDay(now)
|
|
reidsKey := redisconst.PlayLeaderboardKey("publiser", d.Unix())
|
|
var publiserSli []string
|
|
publiserSli, err = appg.Redis.ZRange(reidsKey, 0, 20)
|
|
if err != nil {
|
|
return
|
|
}
|
|
//数据量少用头一天的
|
|
if len(publiserSli) < 20 {
|
|
reidsKey = redisconst.PlayLeaderboardKey("publiser", d.Add(-time.Hour*24).Unix())
|
|
publiserSli, err = appg.Redis.ZRange(reidsKey, 0, 20)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
publiserUIDs := make([]uint64, len(publiserSli))
|
|
for i := range publiserSli {
|
|
publiserUIDs[i], err = strconv.ParseUint(publiserSli[i], 10, 64)
|
|
if err != nil {
|
|
publiserUIDs[i] = 0
|
|
}
|
|
}
|
|
data = make([]*proto.HotPublisher, 0, len(publiserUIDs))
|
|
for _, v := range publiserUIDs {
|
|
if v == 0 {
|
|
continue
|
|
}
|
|
hotPublisherVid := proto.HotPublisher{
|
|
BaseInfo: usermod.BaseInfo{},
|
|
List: make([]*vidmod.VideoInfo, 0),
|
|
}
|
|
var u *usermod.User
|
|
u, err = usermod.FindUserByUID(v)
|
|
if err != nil || u == nil {
|
|
return
|
|
}
|
|
hotPublisherVid.BaseInfo = usermod.BaseInfo{
|
|
UID: u.UID,
|
|
Name: u.Name,
|
|
Gender: u.Gender,
|
|
Portrait: u.Portrait,
|
|
HasLocked: u.HasLocked,
|
|
HasBanned: u.HasBanned,
|
|
}
|
|
var vidMods []*vidmod.VideoModel
|
|
vidMods, _, _, err = vidmod.GetVideoListByPublishers([]uint64{v}, 1, 4)
|
|
if err != nil || len(vidMods) <= 0 {
|
|
return
|
|
}
|
|
hotPublisherVid.List = vidhelpser.EncodeVideoInfo(uid, vidMods)
|
|
data = append(data, &hotPublisherVid)
|
|
}
|
|
common.Go(func() {
|
|
b, _ := json.Marshal(data)
|
|
_ = appg.Redis.Set(key, string(b), expaire)
|
|
})
|
|
}
|
|
return
|
|
}
|
|
|
|
func getOriginalBloggerInfo(uids []uint64) (info map[uint64]OriginalBloggerInfo, err error) {
|
|
users, err := usermod.FindUsersByUID(uids)
|
|
if err != nil {
|
|
return
|
|
}
|
|
info = make(map[uint64]OriginalBloggerInfo)
|
|
for _, user := range users {
|
|
info[user.UID] = OriginalBloggerInfo{
|
|
UID: user.UID,
|
|
Name: user.Name,
|
|
Portrait: user.Portrait,
|
|
OfficialCert: user.OfficialCert,
|
|
Summary: user.Summary,
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// List 新版视频列表
|
|
func List(uid uint64, req *vidmod.AppListReq) (interface{}, stderr.Code) {
|
|
var (
|
|
head []*vidmod.VideoModel
|
|
err error
|
|
)
|
|
data, _ := json.Marshal(req)
|
|
log.Info(fmt.Sprintf("新版视频列表请求参数:%s", string(data)))
|
|
filter, err := req.Filter(uid)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("获取视频列表 发生错误:%v", err), log.Any("uid", uid), log.Any("params", req))
|
|
return nil, stderr.ErrParamError
|
|
}
|
|
log.Info("---", log.Any("filter", filter))
|
|
hasNext := false
|
|
if req.Type == vidmod.Image && req.Model == vidmod.HappinessPlaza {
|
|
head, err = getImageTopList(req.FilterType, filter, req.Options())
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("获取幸福广场列表 发生错误:%v", err), log.Any("uid", uid), log.Any("params", req))
|
|
return nil, stderr.ErrDbQueryError
|
|
}
|
|
startIndex, endIndex := common.SlicePage(req.PageNumber, req.PageSize, uint64(len(head)))
|
|
head = head[startIndex:endIndex]
|
|
if len(head) >= int(req.PageSize) {
|
|
hasNext = true
|
|
}
|
|
newInfos := vidhelpser.EncodeVideoInfo(uid, head)
|
|
return vidmod.NewsListResp{List: newInfos, HasNext: hasNext}, stderr.Success
|
|
}
|
|
// 首先从redis缓存内获取相关信息
|
|
redisKey := req.RedisKey(uid)
|
|
if redisKey != "" {
|
|
ct, err := appg.Redis.Get(redisKey)
|
|
if err != nil && ct != nil && *ct != "" {
|
|
if err = json.Unmarshal([]byte(*ct), &head); err == nil {
|
|
if len(head) > int(req.PageSize) {
|
|
hasNext = true
|
|
head = head[:req.PageSize]
|
|
}
|
|
newInfos := vidhelpser.EncodeVideoInfo(uid, head)
|
|
return vidmod.NewsListResp{List: newInfos, HasNext: hasNext}, stderr.Success
|
|
}
|
|
}
|
|
}
|
|
list, err := vidmod.GetList(filter, req.Options())
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("获取视频列表 发生错误:%v", err), log.Any("uid", uid), log.Any("params", req))
|
|
return nil, stderr.ErrDbQueryError
|
|
}
|
|
// 设置/刷新redis缓存
|
|
if redisKey != "" {
|
|
go func() {
|
|
bts, err := json.Marshal(list)
|
|
if err != nil {
|
|
return
|
|
}
|
|
_ = appg.Redis.Set(redisKey, string(bts), time.Minute*3)
|
|
}()
|
|
}
|
|
head = list
|
|
if len(list) > int(req.PageSize) {
|
|
hasNext = true
|
|
head = list[:req.PageSize]
|
|
}
|
|
newInfos := vidhelpser.EncodeVideoInfo(uid, head)
|
|
return vidmod.NewsListResp{List: newInfos, HasNext: hasNext}, stderr.Success
|
|
}
|
|
|
|
func AllVideosOfModule(subModuleID primitive.ObjectID, uid uint64, req AllVideosOfModuleReq) (AllVideosOfModuleResp, error) {
|
|
ret := AllVideosOfModuleResp{
|
|
HasNext: false,
|
|
Videos: make([]*vidmod.VideoInfo, 0),
|
|
}
|
|
active, err := moduleconfmod.CanBrowseModule(subModuleID, time.Now())
|
|
if err != nil || !active {
|
|
return ret, err
|
|
}
|
|
sections, err := modulesectionmod.GetAllBySubModuleID(subModuleID)
|
|
if err != nil {
|
|
return ret, err
|
|
}
|
|
sectionIds := make([]primitive.ObjectID, len(sections))
|
|
for i, v := range sections {
|
|
sectionIds[i] = v.ID
|
|
}
|
|
sectionVideos, err := modulevidmod.GetVideosBySectionIDs(sectionIds)
|
|
if err != nil {
|
|
return ret, err
|
|
}
|
|
vids := make([]primitive.ObjectID, len(sectionVideos))
|
|
for i, v := range sectionVideos {
|
|
vids[i] = v.VideoID
|
|
}
|
|
cond := bson.M{"status": 1, "_id": bson.M{"$in": vids}}
|
|
switch req.PlayTimeType {
|
|
case 1:
|
|
cond["playTime"] = bson.M{"$gte": 60 * 10}
|
|
case 2:
|
|
cond["playTime"] = bson.M{"$lt": 60 * 10}
|
|
}
|
|
var sort bson.D
|
|
switch req.SortType {
|
|
case "hot":
|
|
videos, _, hasNext, err := vidmod.GetHotList(int64((req.PageNumber-1)*req.PageSize), int64(req.PageSize), cond)
|
|
ret.Videos = vidhelpser.EncodeVideoInfo(uid, videos)
|
|
ret.HasNext = hasNext
|
|
return ret, err
|
|
case "watch":
|
|
sort = bson.D{{Key: "playCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
case "like":
|
|
sort = bson.D{{Key: "likeCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
case "new", "":
|
|
sort = bson.D{{Key: "reviewAt", Value: -1}}
|
|
default: //兼容旧版,传入参数为其他值
|
|
sort = bson.D{{Key: "playCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
}
|
|
videos, total, err := vidmod.GetvideoListByMapCond(cond, sort, req.PageNumber, req.PageSize)
|
|
if err != nil {
|
|
return ret, err
|
|
}
|
|
vInfos := vidhelpser.EncodeVideoInfo(uid, videos)
|
|
ret.Videos = vInfos
|
|
if int64(req.PageNumber*req.PageSize) < total {
|
|
ret.HasNext = true
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
// 获取幸福广场置顶帖子
|
|
func getImageTopList(topType uint, filter1 bson.M, opts *options.FindOptions) ([]*vidmod.VideoModel, error) {
|
|
key := fmt.Sprintf(redisconst.ImageTopKey, topType)
|
|
//读取缓存
|
|
s, err := appg.Redis.Get(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if s != nil && *s != "" {
|
|
vidModels := make([]*vidmod.VideoModel, 0)
|
|
if err = json.Unmarshal([]byte(*s), &vidModels); err != nil {
|
|
return nil, err
|
|
}
|
|
return vidModels, nil
|
|
}
|
|
filter := bson.M{}
|
|
var opt *options.FindOptions
|
|
switch topType {
|
|
case 1:
|
|
filter["recommendEndTime"] = bson.M{"$gt": time.Now()}
|
|
opt = options.Find().SetSort(bson.D{{Key: "recommendSort", Value: -1}})
|
|
case 2:
|
|
filter["newEndTime"] = bson.M{"$gt": time.Now()}
|
|
opt = options.Find().SetSort(bson.D{{Key: "createdAt", Value: -1}})
|
|
default:
|
|
filter["newEndTime"] = bson.M{"$gt": time.Now()}
|
|
opt = options.Find().SetSort(bson.D{{Key: "newSort", Value: -1}})
|
|
}
|
|
imageTops, err := imagetopmod.GetImageTopList(filter, opt)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("获取置顶帖子列表 发生错误:%v", err), log.Any("params", topType))
|
|
return nil, err
|
|
}
|
|
//查询所有的幸福社区的帖子
|
|
filter1["happinessPlazaTop"] = bson.M{"$ne": 1}
|
|
list, _ := vidmod.GetList(filter1, opts)
|
|
//根据置顶帖子查询过滤出来视频id
|
|
imageTopsLen := len(imageTops)
|
|
vidModels := make([]*vidmod.VideoModel, imageTopsLen, imageTopsLen+len(list))
|
|
for i, info := range imageTops {
|
|
videoInfo, err := vidmod.GetVideoByID(info.ImageId)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("获取置顶帖子列表 发生错误:%v", err), log.Any("params", topType))
|
|
return nil, err
|
|
}
|
|
vidModels[i] = videoInfo
|
|
}
|
|
vidModels = append(vidModels, list...)
|
|
//设置缓存
|
|
common.Go(func() {
|
|
b, _ := json.Marshal(vidModels)
|
|
_ = appg.Redis.Set(key, string(b), redisconst.ImageTopExpire)
|
|
})
|
|
return vidModels, nil
|
|
}
|
|
|
|
func GetValidSections() ([]SectionResp, error) {
|
|
sections, err := modulesectionmod.AllSections()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sectionsLen := len(sections)
|
|
if sectionsLen == 0 {
|
|
return nil, nil
|
|
}
|
|
sort.Slice(sections, func(i, j int) bool {
|
|
if sections[i].Sort == nil {
|
|
return true
|
|
}
|
|
if sections[j].Sort == nil {
|
|
return false
|
|
}
|
|
return *sections[i].Sort < *sections[j].Sort
|
|
})
|
|
srs := make([]SectionResp, sectionsLen)
|
|
for i := range sections {
|
|
srs[i].ID = sections[i].ID
|
|
srs[i].SectionName = sections[i].SectionName
|
|
}
|
|
return srs, nil
|
|
}
|
|
|
|
func GetVidPlayRecommand(uid uint64, vid primitive.ObjectID) (*RecommandResp, error) {
|
|
svs, err := modulevidmod.GetSectionsByVideoId(vid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
svsLen := len(svs)
|
|
if svsLen == 0 {
|
|
return GetSearchRecommand(uid)
|
|
}
|
|
sectionIDs := make([]primitive.ObjectID, svsLen)
|
|
for i, sv := range svs {
|
|
sectionIDs[i] = sv.SectionID
|
|
}
|
|
svs, err = modulevidmod.GetVideosBySectionIDs(sectionIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
svsLen = len(svs)
|
|
if svsLen == 0 {
|
|
return GetSearchRecommand(uid)
|
|
}
|
|
vids := make([]primitive.ObjectID, 0, svsLen)
|
|
for _, sv := range svs {
|
|
if sv.VideoID == vid || sv.VideoID.IsZero() {
|
|
continue
|
|
}
|
|
vids = append(vids, sv.VideoID)
|
|
}
|
|
if len(vids) == 0 {
|
|
return GetSearchRecommand(uid)
|
|
}
|
|
videos, err := vidmod.GetVideosRecommandInVids(vids)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(videos) == 0 {
|
|
return GetSearchRecommand(uid)
|
|
}
|
|
return &RecommandResp{
|
|
Videos: vidhelpser.EncodeVideoInfoForRecommend(uid, videos),
|
|
HasNext: false,
|
|
}, nil
|
|
}
|
|
|
|
func GetVidPlayRecommand_new(uid uint64, vid primitive.ObjectID) (data *RecommandResp, err error) {
|
|
excludedModules, err := moduleconfmod.ExcludedVideoModuleIDs(time.Now(), true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
useCache := len(excludedModules) == 0
|
|
svs, err := modulevidmod.GetSectionsByVideoId(vid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
svsLen := len(svs)
|
|
if svsLen == 0 {
|
|
return GetSearchRecommand(uid)
|
|
}
|
|
sectionIDs := make([]primitive.ObjectID, svsLen)
|
|
for i, sv := range svs {
|
|
sectionIDs[i] = sv.SectionID
|
|
}
|
|
//加一个搜索缓存
|
|
var key string
|
|
if len(sectionIDs) > 0 {
|
|
key = fmt.Sprintf("GetVidPlayRecommand_new%v", sectionIDs[0])
|
|
}
|
|
expaire := time.Minute * 5
|
|
if useCache {
|
|
s, cacheErr := appg.Redis.Get(key)
|
|
if cacheErr != nil {
|
|
return nil, cacheErr
|
|
}
|
|
if s != nil && *s != "" {
|
|
if cacheErr = json.Unmarshal([]byte(*s), &data); cacheErr != nil {
|
|
return nil, cacheErr
|
|
}
|
|
return data, nil
|
|
}
|
|
}
|
|
fmt.Println("--------------------1")
|
|
var videos []*vidmod.VideoModel
|
|
if data == nil {
|
|
svs, err = modulevidmod.GetVideosBySectionIDs(sectionIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
svsLen = len(svs)
|
|
if svsLen == 0 {
|
|
return GetSearchRecommand(uid)
|
|
}
|
|
vids := make([]primitive.ObjectID, 0, svsLen)
|
|
fmt.Println("--------------------2")
|
|
for _, sv := range svs {
|
|
if sv.VideoID == vid || sv.VideoID.IsZero() {
|
|
continue
|
|
}
|
|
vids = append(vids, sv.VideoID)
|
|
}
|
|
if len(vids) == 0 {
|
|
return GetSearchRecommand(uid)
|
|
}
|
|
fmt.Println("----------------------------vids", vids)
|
|
videos, err = vidmod.GetVideosRecommandInVids(vids)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(videos) == 0 {
|
|
return GetSearchRecommand(uid)
|
|
}
|
|
fmt.Println("--------------------3")
|
|
data = &RecommandResp{Videos: vidhelpser.EncodeVideoInfoForRecommend(uid, videos), HasNext: false}
|
|
if useCache {
|
|
common.Go(func() {
|
|
b, _ := json.Marshal(data)
|
|
_ = appg.Redis.Set(key, string(b), expaire)
|
|
})
|
|
}
|
|
}
|
|
return data, nil
|
|
}
|
|
|
|
func GetSearchRecommand(uid uint64) (*RecommandResp, error) {
|
|
videos, err := vidmod.GetSearchRecommand()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &RecommandResp{
|
|
Videos: vidhelpser.EncodeVideoInfoForRecommend(uid, videos),
|
|
HasNext: false,
|
|
}, nil
|
|
}
|
|
|
|
// GetVideosByTagID 通过标签id获取视频列表信息
|
|
func GetVideosByTagID(tid primitive.ObjectID, newsType string, sort int, skip, limit uint64) (list []vidmod.RecoVideoModel, err error) {
|
|
redisKey := redisconst.GetTagSortVideoKey(tid.Hex(), newsType, sort, skip, limit)
|
|
if !appg.Redis.Exists(redisKey) {
|
|
list, err = vidmod.VideoListByTagIDSort(tid, newsType, sort, skip, limit)
|
|
if err != nil {
|
|
return
|
|
}
|
|
go func() {
|
|
b, _ := json.Marshal(list)
|
|
_ = appg.Redis.Set(redisKey, string(b), redisconst.GetTagSortVideoExpire())
|
|
}()
|
|
return
|
|
}
|
|
strP, err := appg.Redis.Get(redisKey)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if strP != nil {
|
|
err = json.Unmarshal([]byte(*strP), &list)
|
|
} else {
|
|
err = errors.New("redis GetVideosByTagID get nil")
|
|
}
|
|
return
|
|
}
|
|
|
|
func GetRecommendList(uid uint64, tagId string, newsType string, page commod.Page) (list []*vidmod.VideoInfo, hasNext bool, err error) {
|
|
tagObjId, _ := primitive.ObjectIDFromHex(tagId)
|
|
filter := bson.M{"status": 1, "newsType": newsType}
|
|
if !tagObjId.IsZero() {
|
|
filter["tags"] = tagObjId
|
|
}
|
|
res, hasNext, err := viddata.GetListFromCache(filter, int64(page.Skip()), int64(page.Limit()),
|
|
bson.D{{Key: "likeCount", Value: -1}, {Key: "reviewAt", Value: -1}})
|
|
if err != nil {
|
|
return
|
|
}
|
|
list = vidhelpser.EncodeVideoInfoForRecommend(uid, res)
|
|
return list, hasNext, nil
|
|
}
|
|
|
|
// -------- 查询亚模块下的所有视屏列表 ---------
|
|
|
|
type SubModuleAllVideoListReq struct {
|
|
commod.Page
|
|
Type int `form:"type"` // 0 最多观看 1 最新上架 3 最多收藏
|
|
}
|
|
|
|
func SubModuleAllVideoList(uid uint64, subModuleId primitive.ObjectID, req SubModuleAllVideoListReq) (resp VideoUnderSubModuleResp, err error) {
|
|
active, err := moduleconfmod.CanBrowseModule(subModuleId, time.Now())
|
|
if err != nil || !active {
|
|
return resp, err
|
|
}
|
|
expire := time.Minute * 10
|
|
var videos []*vidmod.VideoModel
|
|
_, err = cachev2.Classes().CacheTime(expire).AutoListKey("HomePage:MaybeYouLike").ResBind(&videos).Cache(findAllVideoByModuleId, subModuleId, req)
|
|
if err != nil || len(videos) == 0 {
|
|
return resp, err
|
|
}
|
|
|
|
if uint64(len(videos)) > req.PageSize {
|
|
resp.HasNext = true
|
|
videos = videos[:req.PageSize]
|
|
}
|
|
vInfos := vidhelpser.NewEncodeVideoInfoNotStatusForUser(uid, videos)
|
|
resp.AllVideoInfo = vInfos
|
|
|
|
return resp, nil
|
|
}
|
|
func findAllVideoByModuleId(subModuleId primitive.ObjectID, req SubModuleAllVideoListReq) []*vidmod.VideoModel {
|
|
subModule, err := moduleconfmod.GetByID(subModuleId)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if !subModule.IsActiveAt(time.Now()) {
|
|
return nil
|
|
}
|
|
var (
|
|
skip = int64((req.PageNumber - 1) * req.PageSize)
|
|
sort bson.D
|
|
)
|
|
switch req.Type {
|
|
case 1:
|
|
sort = bson.D{{"reviewAt", -1}, {"_id", -1}}
|
|
case 3:
|
|
sort = bson.D{{"collectCount", -1}, {"reviewAt", -1}, {"_id", -1}}
|
|
default: // 0
|
|
sort = bson.D{{"playCount", -1}, {"reviewAt", -1}, {"_id", -1}}
|
|
}
|
|
|
|
filter := bson.M{"mId": subModule.ID.Hex(), "status": 1}
|
|
videos, err := vidmod.GetList(filter, options.Find().SetSkip(skip).SetLimit(int64(req.PageSize+1)).SetSort(sort))
|
|
if err != nil {
|
|
log.Error("findAllVideoByModuleId vidmod.GetVideosByIDs", log.E(err))
|
|
return nil
|
|
}
|
|
return videos
|
|
}
|
|
|
|
type (
|
|
HandleShortVideoUnderSubModuleReq struct {
|
|
commod.Page
|
|
UID uint64 `json:"-" form:"-"`
|
|
Context context.Context `json:"-" form:"-"`
|
|
RequestID string `json:"-" form:"-"`
|
|
Err error `json:"-" form:"-"`
|
|
}
|
|
HandleShortVideoUnderSubModuleRep VideoUnderSubModuleResp
|
|
)
|
|
|
|
func (req *HandleShortVideoUnderSubModuleReq) Do() (data VideoUnderSubModuleResp) {
|
|
if req.UID > 0 {
|
|
return req.get()
|
|
}
|
|
excluded, err := moduleconfmod.ExcludedVideoModuleIDs(time.Now(), true)
|
|
if err != nil || len(excluded) > 0 {
|
|
return req.get()
|
|
}
|
|
cachev2.Classes().CacheTime(time.Minute * 5).AutoListKey("ShortVideoRecoList").ResBind(&data).Cache(req.get)
|
|
return data
|
|
}
|
|
func (req *HandleShortVideoUnderSubModuleReq) get() (data VideoUnderSubModuleResp) {
|
|
if req.UID > 0 && appg.Conf.ShortRecommendEnabled() {
|
|
ctx := req.Context
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
fetchCtx, cancel := context.WithTimeout(ctx, appg.Conf.ShortRecommendRequestTimeout())
|
|
result, fetchErr := shortrecommendser.FetchScoped(
|
|
fetchCtx, req.UID, int(req.PageSize), req.RequestID, "module-short-all",
|
|
)
|
|
cancel()
|
|
if result.QueueVersion != "" {
|
|
if fetchErr != nil && len(result.Videos) == 0 {
|
|
log.Error("short module recommend fetch failed after reservation",
|
|
log.E(fetchErr),
|
|
log.Any("uid", req.UID),
|
|
log.Any("queueVersion", result.QueueVersion),
|
|
log.Any("queueLength", result.QueueLength),
|
|
log.Any("scanned", result.Scanned),
|
|
log.Any("batches", result.Batches))
|
|
req.Err = fetchErr
|
|
return data
|
|
}
|
|
if fetchErr != nil || result.BudgetExceeded || result.Filtered > 0 {
|
|
log.Warn("short module recommend fetch completed with filtering",
|
|
log.E(fetchErr),
|
|
log.Any("uid", req.UID),
|
|
log.Any("queueVersion", result.QueueVersion),
|
|
log.Any("queueLength", result.QueueLength),
|
|
log.Any("requested", req.PageSize),
|
|
log.Any("returned", len(result.Videos)),
|
|
log.Any("scanned", result.Scanned),
|
|
log.Any("filtered", result.Filtered),
|
|
log.Any("batches", result.Batches),
|
|
log.Any("budgetExceeded", result.BudgetExceeded))
|
|
}
|
|
data.AllVideoInfo = vidhelpser.NewEncodeVideoInfoNotStatusForUser(req.UID, result.Videos)
|
|
data.HasNext = result.QueueLength > 0
|
|
return data
|
|
}
|
|
if fetchErr != nil {
|
|
if errors.Is(fetchErr, context.Canceled) ||
|
|
errors.Is(fetchErr, context.DeadlineExceeded) {
|
|
return data
|
|
}
|
|
log.Error("short module recommend fetch failed, fallback random set",
|
|
log.E(fetchErr), log.Any("uid", req.UID))
|
|
}
|
|
}
|
|
excluded, err := moduleconfmod.ExcludedVideoModuleIDs(time.Now(), true)
|
|
if err != nil {
|
|
return data
|
|
}
|
|
excludedSet := make(map[string]struct{}, len(excluded))
|
|
for _, moduleID := range excluded {
|
|
excludedSet[moduleID] = struct{}{}
|
|
}
|
|
totalSize, err := appg.Redis.SCard(redisconst.ShortVideosRecoCacheKey)
|
|
if err != nil {
|
|
log.Error("GetVidList SCard err", log.E(err))
|
|
return data
|
|
}
|
|
if totalSize == 0 {
|
|
return data
|
|
}
|
|
|
|
if totalSize <= int64(req.PageSize) {
|
|
data.HasNext = false
|
|
} else {
|
|
data.HasNext = math.Ceil(float64(totalSize)/float64(req.PageSize)) > float64(req.PageNumber)
|
|
}
|
|
|
|
sampleSize := int64(req.PageSize * 5)
|
|
if sampleSize > totalSize {
|
|
sampleSize = totalSize
|
|
}
|
|
pushVid, err := redis.Handler.SRandMemberN(redisconst.ShortVideosRecoCacheKey, sampleSize)
|
|
if err != nil {
|
|
return data
|
|
}
|
|
vids := common.String2ObjectID(pushVid)
|
|
vList, err := vidmod.GetVideosByIDs(vids)
|
|
if err != nil {
|
|
return data
|
|
}
|
|
allowed := make([]*vidmod.VideoModel, 0, req.PageSize)
|
|
for _, video := range vList {
|
|
if video == nil {
|
|
continue
|
|
}
|
|
if _, blocked := excludedSet[video.MID]; blocked {
|
|
continue
|
|
}
|
|
allowed = append(allowed, video)
|
|
if uint64(len(allowed)) == req.PageSize {
|
|
break
|
|
}
|
|
}
|
|
data.AllVideoInfo = vidhelpser.NewEncodeVideoInfoNotStatusForUser(req.UID, allowed)
|
|
return data
|
|
}
|
|
|
|
// GetChangeVideos 获取换一批的视频列表
|
|
func GetChangeVideos(in *vidmod.ChangeVideoSectionReq, uid uint64) (resp VideoUnderSectionResp, err error) {
|
|
sectionID, err := primitive.ObjectIDFromHex(in.SectionID)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("GetChangeVideos primitive objectIDFromHex err:%v", err))
|
|
return
|
|
}
|
|
// 获专题信息
|
|
section, err := modulesectionmod.GetBySectionByID(sectionID)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("GetChangeVideos modulesectionmod getBySectionByID err:%v", err))
|
|
return
|
|
}
|
|
if section.ID.IsZero() {
|
|
return
|
|
}
|
|
active, err := moduleconfmod.CanBrowseModule(section.SubModuleID, time.Now())
|
|
if err != nil || !active {
|
|
return resp, err
|
|
}
|
|
|
|
// 获取专题下视频信息
|
|
filter := bson.M{"sectionID": sectionID}
|
|
op := options.Find().SetSort(bson.M{"createdAt": -1}).SetLimit(300)
|
|
sectionVideos, err := modulevidmod.Find(filter, op)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if len(sectionVideos) < 0 {
|
|
return
|
|
}
|
|
|
|
var vIds []primitive.ObjectID
|
|
for _, v := range sectionVideos {
|
|
vIds = append(vIds, v.VideoID)
|
|
}
|
|
// 根据样式判断随机数据
|
|
num := modulesectionmod.ShowTypeHashVale[section.ShowType]
|
|
if len(vIds) < num {
|
|
return
|
|
}
|
|
if num == 0 {
|
|
num = 9
|
|
}
|
|
rp := common.NewRandomPicker()
|
|
pickElements, err := rp.PickElements(vIds, num)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
objectIDs := make([]primitive.ObjectID, len(pickElements))
|
|
for i, v := range pickElements {
|
|
objectIDs[i] = v.(primitive.ObjectID)
|
|
}
|
|
|
|
// 获取视频详情
|
|
var videos []*vidmod.VideoModel
|
|
if videos, err = vidmod.GetVideoListByIDsPublish(objectIDs); err != nil {
|
|
log.Error("vidmod.GetVideoListByIDsPublish", log.Any("videoIDs", vIds), log.E(err))
|
|
return
|
|
}
|
|
if videos == nil || len(videos) == 0 {
|
|
log.Warn("vidmod.GetVideoListByIDsPublish no video info", log.Any("videosIDs", vIds))
|
|
return
|
|
}
|
|
|
|
resp.Videos = vidhelpser.NewEncodeVideoInfoNotStatusForUser(uid, videos)
|
|
return
|
|
}
|
|
|
|
// GetChangeMedias 获取换一批的视频列表
|
|
func GetChangeMedias(in *vidmod.ChangeVideoSectionReq, uid uint64) (resp VideoUnderSectionResp, err error) {
|
|
sectionID, err := primitive.ObjectIDFromHex(in.SectionID)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("GetChangeVideos primitive objectIDFromHex err:%v", err))
|
|
return
|
|
}
|
|
// 获专题信息
|
|
section, err := modulesectionmod.GetBySectionByID(sectionID)
|
|
if err != nil {
|
|
log.Error(fmt.Sprintf("GetChangeVideos modulesectionmod getBySectionByID err:%v", err))
|
|
return
|
|
}
|
|
if section.ID.IsZero() {
|
|
return
|
|
}
|
|
active, err := moduleconfmod.CanBrowseModule(section.SubModuleID, time.Now())
|
|
if err != nil || !active {
|
|
return resp, err
|
|
}
|
|
|
|
// 获取专题下视频信息
|
|
sort := bson.D{{Key: "sectionSort", Value: -1}, {Key: "createdAt", Value: -1}}
|
|
list, _, err := mediamod.GetList(bson.M{"sId": section.ID, "isDelete": false, "status": 1}, 0, 200, sort)
|
|
|
|
if len(list) < 0 {
|
|
return
|
|
}
|
|
// 根据样式判断随机数据
|
|
num := modulesectionmod.ShowTypeHashVale[section.ShowType]
|
|
if len(list) < num {
|
|
return
|
|
}
|
|
if num == 0 {
|
|
num = 9
|
|
}
|
|
rp := common.NewRandomPicker()
|
|
pickElements, err := rp.PickElements(list, num)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
mediaList := []*mediamod.Media{}
|
|
for _, v := range pickElements {
|
|
item, ok := v.(*mediamod.Media)
|
|
if !ok {
|
|
continue
|
|
}
|
|
mediaList = append(mediaList, item)
|
|
}
|
|
|
|
resp.Medias = mediaser.FillNotStatusMedias(mediaList, false)
|
|
return
|
|
}
|
|
|
|
func MostNewModuleVideoList(uid uint64, req vidmod.HomeMostNewModuleVideoListReq) (ret AllVideosOfModuleResp, err error) {
|
|
defer func() {
|
|
vidhelpser.ApplyFreeTrialBadgeToVideoInfos(vidhelpser.LoadFreeTrialBadgeContext(uid), ret.Videos)
|
|
}()
|
|
now := time.Now()
|
|
excludedModules, excludeErr := moduleconfmod.ExcludedVideoModuleIDs(now, false)
|
|
if excludeErr != nil {
|
|
return ret, excludeErr
|
|
}
|
|
useCache := len(excludedModules) == 0
|
|
if useCache {
|
|
key := redisconst.GetMostNewModuleVideoListKey(req.SortType, req.PageNumber, req.PageSize)
|
|
err = appg.Redis.GetWithJson2Any(key, &ret)
|
|
if err == nil {
|
|
return
|
|
}
|
|
if !errors.Is(err, goredis.Nil) {
|
|
log.Error("appg.Redis.GetWithJson2Any error", log.E(err))
|
|
}
|
|
defer func() {
|
|
appg.Redis.SetWithAny2Json(key, ret, redisconst.MostNewModuleVideoListExpire)
|
|
}()
|
|
}
|
|
// 获取暗网标签
|
|
tag, _ := tagmod.FindOneTagByName("暗网")
|
|
cond := bson.M{"status": 1, "newsType": vidmod.SP}
|
|
if len(excludedModules) > 0 {
|
|
cond["mId"] = bson.M{"$nin": excludedModules}
|
|
}
|
|
if !tag.ID.IsZero() {
|
|
cond["tags"] = bson.M{"$ne": tag.ID}
|
|
}
|
|
var sort bson.D
|
|
switch req.SortType {
|
|
case 1: // 最新强制 在2年内的帖子
|
|
if req.PageNumber > 100 {
|
|
return
|
|
}
|
|
cond["reviewAt"] = bson.M{"$gte": now.AddDate(-2, 0, 0)}
|
|
sort = bson.D{{Key: "reviewAt", Value: -1}}
|
|
case 2: // 本周 15天内上架 播放数
|
|
cond["reviewAt"] = bson.M{"$gte": now.AddDate(0, 0, -15)}
|
|
sort = bson.D{{Key: "playCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
case 3: // 月度
|
|
cond["reviewAt"] = bson.M{"$lt": now.AddDate(0, 0, -15), "$gte": now.AddDate(0, -1, -15)}
|
|
sort = bson.D{{Key: "playCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
case 4: // 年度
|
|
cond["reviewAt"] = bson.M{"$lt": now.AddDate(0, -1, -15), "$gte": now.AddDate(0, -9, 0)}
|
|
sort = bson.D{{Key: "playCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
default:
|
|
cond["reviewAt"] = bson.M{"$lt": now.AddDate(0, -1, -15), "$gte": now.AddDate(0, -9, 0)}
|
|
sort = bson.D{{Key: "playCount", Value: -1}, {Key: "reviewAt", Value: -1}}
|
|
}
|
|
opt := options.Find().SetSort(sort).SetSkip(req.Skip64()).SetLimit(req.Limit64())
|
|
videos, next, err := vidmod.FindList(cond, opt)
|
|
if err != nil {
|
|
return ret, err
|
|
}
|
|
vInfos := vidhelpser.EncodeVideoInfoNoUID(videos)
|
|
ret.Videos = vInfos
|
|
ret.HasNext = next
|
|
|
|
return ret, nil
|
|
}
|