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

101 lines
2.7 KiB
Go

package vidser
import (
"bytes"
"crypto/sha256"
"errors"
"sort"
"time"
"91porn-server/app/service/vidhelpser"
"91porn-server/models/commod"
"91porn-server/models/v/moduleconfmod"
"91porn-server/models/v/vidmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
var ErrRandomRefreshUnsupported = errors.New("the selected sort does not support random refresh")
func RefreshModuleVideos(uid uint64, subModuleID primitive.ObjectID, req RefreshModuleVideosReq) (RefreshModuleVideosResp, error) {
resp := RefreshModuleVideosResp{
AllVideoInfo: []*vidmod.VideoInfoResp{},
RefreshMode: moduleconfmod.RefreshModeRandomTopN,
RefreshToken: req.RefreshToken,
}
subModule, err := moduleconfmod.GetByID(subModuleID)
if err != nil {
return resp, err
}
if !subModule.IsActiveAt(time.Now()) {
return resp, nil
}
subModule.HaiJiaoStyle.EnsureSortRules()
candidateN := 0
for _, rule := range subModule.HaiJiaoStyle.SortRules {
if rule.Val == commod.SortType(req.ModuleSort) && rule.RefreshMode == moduleconfmod.RefreshModeRandomTopN {
candidateN = rule.RandomCandidateN
break
}
}
if candidateN == 0 {
return resp, ErrRandomRefreshUnsupported
}
pageSize := req.PageSize
if pageSize <= 0 {
pageSize = 20
}
if pageSize > candidateN {
pageSize = candidateN
}
filter := bson.M{
"mId": subModuleID.Hex(),
"status": vidmod.CheckPass,
"newsType": vidmod.SP,
"chosen": false,
}
opt := options.Find().
SetSort(bson.D{
{Key: "liaoBaTopSort", Value: -1},
{Key: "likeCount", Value: -1},
{Key: "reviewAt", Value: -1},
{Key: "_id", Value: -1},
}).
SetLimit(int64(candidateN)).
SetProjection(bson.M{"richText": 0})
videos, err := vidmod.GetVideoListByCond(filter, opt)
if err != nil {
return resp, err
}
resp.CandidateCount = len(videos)
deterministicOrderVideos(videos, subModuleID.Hex()+":"+req.RefreshToken)
if len(videos) > pageSize {
videos = videos[:pageSize]
}
resp.HasNext = hasNextRefreshCandidate(resp.CandidateCount, len(videos))
resp.AllVideoInfo = vidhelpser.NewEncodeVideoInfoNotStatusForUser(uid, videos)
if resp.AllVideoInfo == nil {
resp.AllVideoInfo = []*vidmod.VideoInfoResp{}
}
return resp, nil
}
func hasNextRefreshCandidate(candidateCount, returnedCount int) bool {
return candidateCount > returnedCount
}
func deterministicOrderVideos(videos []*vidmod.VideoModel, seed string) {
sort.SliceStable(videos, func(i, j int) bool {
left := sha256.Sum256([]byte(seed + ":" + videos[i].ID.Hex()))
right := sha256.Sum256([]byte(seed + ":" + videos[j].ID.Hex()))
cmp := bytes.Compare(left[:], right[:])
if cmp == 0 {
return videos[i].ID.Hex() < videos[j].ID.Hex()
}
return cmp < 0
})
}