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
@@ -0,0 +1,37 @@
package vidhkwsearcher
import (
"91porn-server/app/service/searcher"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type M = bson.M
type VideoRes = searcher.VideoRes
type ObjectID = primitive.ObjectID
type Video = searcher.VideoInfo
type Result struct {
dat []VideoRes
hasNext bool
}
func (*Result) Types() searcher.ResultTypes {
return searcher.VidHotKeywordSearchResult
}
func (r *Result) Data() interface{} {
return r.dat
}
func (r *Result) Count() int64 {
return int64(len(r.dat))
}
func (r *Result) HasNext() bool {
return r.hasNext
}
@@ -0,0 +1,112 @@
package vidhkwsearcher
import (
"91porn-server/common/constant"
"errors"
"fmt"
"time"
"91porn-server/app/service/searcher"
"91porn-server/app/service/searcher/vidsearcher"
"91porn-server/common"
"91porn-server/common/log"
"91porn-server/models/s/kwrankmod"
)
// VidHKWSearcher VidHKWSearcher
type VidHKWSearcher struct {
uid uint64
vidOpt searcher.Opter
}
// NewVidHKWSearcher NewVidHKWSearcher
func NewVidHKWSearcher(uid uint64, vidOpt searcher.Opter) searcher.Searcher {
return &VidHKWSearcher{
uid: uid,
vidOpt: vidOpt,
}
}
type pair struct {
Word string
Result searcher.Resulter
}
const timeout = 3 * time.Second
const gorouCountMax = 20
// Search Search
func (v *VidHKWSearcher) Search(unuse searcher.KeyWorder, opt searcher.Opter) (result searcher.Resulter, err error) {
limitEx1 := opt.Limit() + 1
//获取热词
words, err := kwrankmod.RecentRanking(limitEx1)
if err != nil {
return nil, errors.New("vidhkwsearcher RecentRanking error")
}
//没有热词
if len(words) == 0 {
return &Result{[]VideoRes{}, false}, nil
}
hasNext := false
if len(words) > int(opt.Limit()) {
words = words[:opt.Limit()]
hasNext = true
}
gorouCount := opt.Limit()
if gorouCount > gorouCountMax {
gorouCount = gorouCountMax
}
ch := make(chan pair, gorouCount)
err_ch := make(chan error)
for _, w := range words {
word := w.KeyWord
common.Go(func() {
k := &searcher.Keyword{Word: word}
result, err := vidsearcher.NewVidSearcher(v.uid, constant.SearchSP, 0).Search(k, v.vidOpt)
if err != nil {
err_ch <- err
return
}
pair := pair{
Word: word,
Result: result,
}
ch <- pair
})
}
count := len(words)
resultMap := make(map[string]searcher.Resulter, count)
timer := time.NewTimer(timeout)
for i := 0; i < count; i++ {
timer.Reset(timeout)
select {
case pair := <-ch:
resultMap[pair.Word] = pair.Result
if i == count-1 {
return toResult(words, v.vidOpt.Limit(), resultMap, hasNext), nil
}
case err := <-err_ch: //获取出错前搜索到的视屏
log.Error(fmt.Sprintf("VidKWSearcher error:%+v\n", err))
return toResult(words, v.vidOpt.Limit(), resultMap, hasNext), nil
case <-timer.C: //获取超时前搜索到的视屏
log.Warn(fmt.Sprintf("VidKWSearcher timeout::%+v\n", timeout))
return toResult(words, v.vidOpt.Limit(), resultMap, hasNext), nil
}
}
return &Result{[]VideoRes{}, false}, nil
}
func toResult(words []kwrankmod.Keyword, vidCountPer int64, resultMap map[string]searcher.Resulter, hasNext bool) searcher.Resulter {
resList := make([]VideoRes, 0, vidCountPer)
//还原视屏的排序
for _, w := range words {
word := w.KeyWord
result, ok := resultMap[word]
if !ok {
continue
}
videoList := result.Data().([]VideoRes)
resList = append(resList, videoList...)
}
return &Result{resList, hasNext}
}