package search import ( "91porn-server/app/proto" "91porn-server/app/service/searcher" "91porn-server/app/service/searcher/tagsearcher" "91porn-server/app/service/searcher/tonesearcher" "91porn-server/app/service/searcher/usersearcher" "91porn-server/app/service/searcher/vidhkwsearcher" "91porn-server/app/service/searcher/vidhotsearcher" "91porn-server/app/service/searcher/vidpcountsearcher" "91porn-server/app/service/searcher/vidrichsearcher" "91porn-server/app/service/searcher/vidsearcher" "91porn-server/app/service/vidhelpser" "91porn-server/common" "91porn-server/common/constant" "91porn-server/common/log" sli "91porn-server/common/slice" "91porn-server/models/commod" "91porn-server/models/v/tagmod" "91porn-server/models/v/vidmod" "errors" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" "strings" "sync" "time" ) type ( NewsKeywordSearchReq struct { Realm constant.RealmType `form:"realm" json:"realm" binding:"required"` // SP:长视频 SHORT:短视频 COVER:图文帖子 PIC:图集帖子 SEED_LINK:种子/黄油帖子 KeyWords []string `form:"keyWords" json:"keyWords" binding:"required"` // 关键字 SortType int `form:"sortType" json:"sortType"` // 1最多观看 2最新上架 3最多收藏 commod.Page } NewsKeywordSearchRep struct { List any `json:"list"` // 数据列表(ACG和帖子不同格式) TagID string `json:"tagID"` // 帖子搜索时附带的tagID TagVidList []*vidmod.VideoInfo `json:"tagVidList"` // 搜索时tag相关的帖子 HasNext bool `json:"hasNext"` // 是否还有下一页 } ) func (req *NewsKeywordSearchReq) Search(uid uint64) (rep NewsKeywordSearchRep, err error) { var search searcher.Searcher switch req.Realm { case constant.SearchComplex: search = vidrichsearcher.NewVidRichSearcher(uid) case constant.SearchUser: search = usersearcher.NewUserSearcher(uid) case constant.SearchSP, constant.SearchShort, constant.SearchCover, constant.SearchPic: search = vidsearcher.NewVidSearcher(uid, req.Realm, req.SortType) case constant.SearchTag: search = tagsearcher.NewTagSearcher(&uid) default: return rep, errors.New("search Realm is invaild") } kw := &searcher.Keyword{Word: strings.Join(req.KeyWords, "|")} opt := (&searcher.Option{}).SetSkip(req.Skip64()).SetLimit(req.Limit64()) result, err := search.Search(kw, opt) if err != nil { return rep, err } rep.List = result.Data() rep.HasNext = result.HasNext() if req.Realm == constant.SearchSP || req.Realm == constant.SearchShort { // 额外获取TAG相关信息 tagId, err := tagmod.GetTagIDByName(req.KeyWords[0]) if err != nil || tagId.IsZero() { return rep, nil } // 6-最多收藏 limit := int64(4) if req.Realm == constant.SearchShort { limit = 6 } filter := bson.M{"tags": tagId, "status": 1, "newsType": req.Realm} sort := bson.D{{"collectCount", -1}, {"reviewAt", -1}} opts := options.Find().SetLimit(limit).SetSort(sort) tagVideos, _, err := vidmod.FindList(filter, opts) if err != nil { return rep, err } rep.TagID = tagId.Hex() rep.TagVidList = vidhelpser.EncodeVideoInfoForSearch(uid, tagVideos) } return rep, nil } // GetHome // 热点视屏 通过hOpt设置 // 最热视屏 通过hsOpt设置 // 音色入口 固定7个 func GetHome(uid uint64, hOpt, hsOpt searcher.Opter) Home { //热点 vidHKWSearcher := vidhkwsearcher.NewVidHKWSearcher(uid, (&searcher.Option{}).SetLimit(1)) //最热视屏 vidHotSearcher := vidhotsearcher.NewVidHotSearcher(uid) //音色 toneSearcher := tonesearcher.NewToneSearcher() now := time.Now() var ( home Home sumDate = searcher.NewSumDate(now) hVidRes, hsVidRes, toneRes searcher.Resulter wg = sync.WaitGroup{} ) wg.Add(3) common.Go(func() { //热点 defer wg.Done() res, err := vidHKWSearcher.Search(sumDate, hOpt) if err != nil { log.Error("vidHKWSearcher search faild!", log.E(err)) return } hVidRes = res if res.Count() >= hOpt.Limit() { //查找出来的视屏数量足够 不用替换视屏 return } //查找出来的视屏数量不够,用最多播放视屏替换 res, err = vidpcountsearcher.NewVidPlayCountSearcher(uid).Search(nil, hOpt) if err != nil { log.Error("vidpcountsearcher search faild!", log.E(err)) return } hVidRes = res }) common.Go(func() { //最热视屏 defer wg.Done() res, err := vidHotSearcher.Search(nil, hsOpt) if err != nil { log.Error("vidHotSearcher search faild!", log.E(err)) //失败 返回原始搜索结果 return } hsVidRes = res }) common.Go(func() { //音色 defer wg.Done() res, err := toneSearcher.Search(nil, nil) if err != nil { log.Error("toneSearcher search faild!", log.E(err)) //失败 返回原始搜索结果 return } toneRes = res }) wg.Wait() //热点 if hVidRes != nil { home.HVidList = hVidRes.Data().([]vidhkwsearcher.VideoRes) } //今日最热视屏 if hsVidRes != nil { home.HSVidList = hsVidRes.Data().([]vidhotsearcher.VideoRes) } //音色 if toneRes != nil { home.ToneList = toneRes.Data().([]tonesearcher.ToneRes) } return home } func GetWonderTagList(skip, limit int64) ([]vidmod.TagInfo, bool, error) { limitEx1 := limit + 1 tags, err := tagmod.WonderTags(skip, limitEx1) if err != nil { return nil, false, err } hasNext := false if len(tags) > int(limit) { hasNext = true tags = tags[:limit] } log.Debug("GetWonderTagList", log.Any("skip", skip), log.Any("limit", limit), log.Any("hasNext", hasNext)) return tags, hasNext, nil } func GetHotTag() ([]interface{}, error) { tags, _, err := tagmod.GetTagListMostPlayed(commod.Page{ PageNumber: 1, PageSize: 10, }) if err != nil { return nil, err } data := make([]interface{}, len(tags)) for i := range tags { data[i] = proto.Tag{ ID: tags[i].ID, Name: tags[i].TagName, Hot: tags[i].TPlayCount, } } sli.Shuffle(data) return data, nil }