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 }) }