Files
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

228 lines
6.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package officialWebsiteser
import (
"91porn-server/common"
"91porn-server/common/stderr"
"91porn-server/models/v/officialWebsitemod"
"91porn-server/models/v/vidmod"
"sync"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
type VideoListReq struct {
Type int64 `json:"type" form:"type"` // 1: 全量,2:专辑ID3:演员ID, 4: TagID
ID string `json:"id" form:"id"` // 专辑ID或者演员ID,根据Type决定
Sort int64 `json:"sort" form:"sort"` // 1:热度,2:创建时间,3: 播放量,4:点赞量,5:评论量,6:收藏量
PageNumber int64 `json:"pageNumber" form:"pageNumber"`
PageSize int64 `json:"pageSize" form:"pageSize"`
}
type VideoListResp struct {
HasNext bool `json:"hasNext"`
List []*VideoResp `json:"list"`
}
type VideoResp struct {
ID string `json:"id"`
Title string `json:"title"`
SeoSlug string `json:"seoSlug"`
Cover string `json:"cover"`
IsHot bool `json:"isHot"`
Tags []VideoTagResp `json:"tags"`
}
type VideoTagResp struct {
ID string `json:"id"`
Name string `json:"name"`
}
func VideoList(req *VideoListReq) (resp VideoListResp, err error) {
var sort interface{}
switch req.Sort {
case 2:
sort = bson.D{{Key: "createdAt", Value: -1}}
case 3:
sort = bson.D{{Key: "watchCount", Value: -1}}
case 4:
sort = bson.D{{Key: "likeCount", Value: -1}}
case 5:
sort = bson.D{{Key: "commentCount", Value: -1}}
case 6:
sort = bson.D{{Key: "collectCount", Value: -1}}
default:
sort = bson.D{{Key: "isHot", Value: -1}, {Key: "createdAt", Value: -1}}
}
var filter = bson.M{}
objID, err := primitive.ObjectIDFromHex(req.ID)
if err != nil && req.Type != 1 {
err = stderr.ErrParamError
return
}
switch req.Type {
case 2:
filter["albumId"] = objID
case 3:
filter["heroId"] = objID
case 4:
filter["tags._id"] = objID
}
filter["isActive"] = true
var skip, limit = transPageAndPageNumber(req.PageSize, req.PageNumber)
var ops = options.Find().SetSort(sort).SetSkip(skip).SetLimit(limit + 1)
videosData, err := (&officialWebsitemod.Video{}).FindMany(filter, ops)
if err != nil {
return
}
resp = VideoListResp{
HasNext: len(videosData) > int(limit),
List: make([]*VideoResp, 0),
}
for _, v := range videosData {
var videoResp = &VideoResp{
ID: v.ID.Hex(),
Title: v.Title,
SeoSlug: v.SeoSlug,
Cover: v.Cover,
IsHot: v.IsHot,
Tags: make([]VideoTagResp, 0),
}
for _, tag := range v.Tags {
videoResp.Tags = append(videoResp.Tags, VideoTagResp{
ID: tag.ID.Hex(),
Name: tag.Name,
})
}
resp.List = append(resp.List, videoResp)
}
if resp.HasNext {
resp.List = resp.List[:len(resp.List)-1]
}
return
}
type VideoDetailReq struct {
ID string `uri:"id" binding:"required"`
}
type VideoDetailResp struct {
ID string `json:"id"`
Title string `json:"title"`
SeoSlug string `json:"seoSlug"`
Description string `json:"description"`
Cover string `json:"cover"`
Url string `json:"url"`
PlayTime uint `json:"playTime"` // 视频播放时长(秒)
IsHot bool `json:"isHot"`
Tags []VideoTagResp `json:"tags"`
WatchCount int64 `json:"watchCount"`
LikeCount int64 `json:"likeCount"`
CommentCount int64 `json:"commentCount"`
CollectCount int64 `json:"collectCount"`
RelatedVideos []VideoResp `json:"relatedVideos"`
CreatedAt time.Time `json:"createdAt"`
}
func VideoDetail(req *VideoDetailReq) (resp VideoDetailResp, err error) {
// 兼容 id 与 seoSlug24 位 hex 按 _id 查,否则按 seoSlug 查
filter := bson.M{"isActive": true}
if id, e := primitive.ObjectIDFromHex(req.ID); e == nil {
filter["_id"] = id
} else {
filter["seoSlug"] = req.ID
}
video := &officialWebsitemod.Video{}
err = video.FindOne(filter)
if err != nil {
return
}
if video.ID == primitive.NilObjectID {
err = stderr.OfficialWebsiteVideoNotExist
return
}
resp = VideoDetailResp{
ID: video.ID.Hex(),
Title: video.Title,
SeoSlug: video.SeoSlug,
Description: video.Description,
Cover: video.Cover,
Url: video.Url,
IsHot: video.IsHot,
Tags: make([]VideoTagResp, 0),
WatchCount: video.WatchCount,
LikeCount: video.LikeCount,
CommentCount: video.CommentCount,
CollectCount: video.CollectCount,
CreatedAt: video.CreatedAt,
}
// 播放时长:官网视频复用了视频库(vidmod)的视频 ID,按 ID 反查视频库获取
if vid, e := vidmod.GetVideoByID(video.ID); e == nil && vid != nil {
resp.PlayTime = vid.PlayTime
}
for _, tag := range video.Tags {
resp.Tags = append(resp.Tags, VideoTagResp{
ID: tag.ID.Hex(),
Name: tag.Name,
})
}
var tagsID = make([]primitive.ObjectID, 0)
for _, tag := range video.Tags {
tagsID = append(tagsID, tag.ID)
}
var videoTags []officialWebsitemod.Video
var videoNormal []officialWebsitemod.Video
var wg = &sync.WaitGroup{}
wg.Add(2)
common.Go(func() {
defer wg.Done()
if len(tagsID) == 0 {
return
}
filterTags := bson.M{"tags.id": bson.M{"$in": tagsID}, "isActive": true}
videoTags, _ = (&officialWebsitemod.Video{}).FindMany(filterTags,
options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "createdAt", Value: -1}}).SetLimit(10))
})
common.Go(func() {
defer wg.Done()
filterNormal := bson.M{"isActive": true}
videoNormal, _ = (&officialWebsitemod.Video{}).FindMany(filterNormal,
options.Find().SetSort(bson.D{{Key: "isHot", Value: -1}, {Key: "createdAt", Value: -1}}).SetLimit(10))
})
wg.Wait()
var relatedVideosData []officialWebsitemod.Video
if len(videoTags) > 0 {
relatedVideosData = videoTags
} else {
relatedVideosData = videoNormal
}
resp.RelatedVideos = make([]VideoResp, 0)
for _, v := range relatedVideosData {
var videoResp = VideoResp{
ID: v.ID.Hex(),
Title: v.Title,
SeoSlug: v.SeoSlug,
Cover: v.Cover,
IsHot: v.IsHot,
Tags: make([]VideoTagResp, 0),
}
for _, tag := range v.Tags {
videoResp.Tags = append(videoResp.Tags, VideoTagResp{
ID: tag.ID.Hex(),
Name: tag.Name,
})
}
resp.RelatedVideos = append(resp.RelatedVideos, videoResp)
}
return
}