Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+227
View File
@@ -0,0 +1,227 @@
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
}