You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
330 lines
8.0 KiB
330 lines
8.0 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"encoding/json" |
|
"go-common/app/interface/bbq/app-bbq/api/http/v1" |
|
"go-common/app/interface/bbq/app-bbq/model" |
|
"go-common/app/service/bbq/common" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
|
|
"github.com/json-iterator/go" |
|
) |
|
|
|
const ( |
|
searchTypeVideo = "bbq_video" |
|
searchTypeUser = "bbq_user" |
|
suggestType = "bbq" |
|
suggestVer = "v4" |
|
searchLen = 20 |
|
) |
|
|
|
// SearchCursor . |
|
type SearchCursor struct { |
|
Offset int64 `json:"offset"` // 默认为0,数据从1开始 |
|
} |
|
|
|
func parseSearchCursor(c context.Context, cursorPrev, cursorNext string) (cursor *SearchCursor, directionNext bool, err error) { |
|
cursor = new(SearchCursor) |
|
// 判断是向前还是向后查询 |
|
directionNext = true |
|
cursorStr := cursorNext |
|
if len(cursorNext) == 0 && len(cursorPrev) > 0 { |
|
directionNext = false |
|
cursorStr = cursorPrev |
|
} |
|
// 解析 |
|
if len(cursorStr) != 0 { |
|
var cursorData = []byte(cursorStr) |
|
err = json.Unmarshal(cursorData, &cursor) |
|
if err != nil { |
|
err = ecode.ReqParamErr |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
//HotWord . |
|
func (s *Service) HotWord(c context.Context, req *v1.HotWordRequest) (res *v1.HotWordResponse, err error) { |
|
res = new(v1.HotWordResponse) |
|
res.List = append(res.List, "小姐姐") |
|
res.List = append(res.List, "舞蹈") |
|
res.List = append(res.List, "MMD") |
|
return |
|
} |
|
|
|
// VideoSearch 视频搜索 |
|
func (s *Service) VideoSearch(c context.Context, arg *v1.BaseSearchReq) (res *v1.VideoSearchRes, err error) { |
|
res = new(v1.VideoSearchRes) |
|
var ( |
|
sres []*model.VideoSearchResult |
|
searchRes *model.RawSearchRes |
|
relids []int32 |
|
svids []int64 |
|
svidMap map[int64]int64 |
|
) |
|
|
|
// 0. check |
|
|
|
// 1. 生成请求,会根据请求参数 |
|
// v2接口 |
|
reqPage := int64(1) |
|
firstItemOffset := int64(0) |
|
var cursor *SearchCursor |
|
var directionNext bool |
|
if arg.Page == 0 { |
|
cursor, directionNext, err = parseSearchCursor(c, arg.CursorPrev, arg.CursorNext) |
|
if err != nil { |
|
log.Warnw(c, "log", "parse search cursor fail", "prev", arg.CursorPrev, "next", arg.CursorNext) |
|
return |
|
} |
|
firstItemOffset = cursor.Offset - 1 |
|
if directionNext { |
|
firstItemOffset = cursor.Offset + 1 |
|
} |
|
reqPage = (firstItemOffset-1)/searchLen + 1 |
|
log.V(1).Infow(c, "log", "v2 request", "next", arg.CursorNext, "prev", arg.CursorPrev) |
|
} else { |
|
reqPage = arg.Page |
|
} |
|
|
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary |
|
sp := &model.SearchBaseReq{ |
|
KeyWord: arg.Key, |
|
Type: searchTypeVideo, |
|
Page: reqPage, |
|
PageSize: searchLen, |
|
Highlight: int64(arg.Highlight), |
|
} |
|
// 相信搜索结果返回的就是searchLen |
|
searchRes, err = s.dao.SearchBBQ(c, sp) |
|
if searchRes.Res == nil { |
|
return |
|
} |
|
if err = json.Unmarshal(searchRes.Res, &sres); err != nil { |
|
return |
|
} |
|
for _, v := range sres { |
|
relids = append(relids, v.ID) |
|
} |
|
if len(relids) == 0 { |
|
log.Infov(c, log.KV("log", "search ret empty")) |
|
return |
|
} |
|
ids := s.dao.ParseRel2ID(relids) |
|
svidMap, err = s.dao.ConvID2SVID(c, ids) |
|
if err != nil { |
|
log.Error("ConvID2SVID err [%v]", err) |
|
err = nil |
|
return |
|
} |
|
for _, svid := range svidMap { |
|
svids = append(svids, svid) |
|
} |
|
svMap, _ := s.svInfos(c, svids, 0, false) |
|
|
|
for index, sinfo := range sres { |
|
id := s.dao.ParseRel2ID([]int32{sinfo.ID}) |
|
if id[0] == 0 { |
|
continue |
|
} |
|
if svid, ok := svidMap[id[0]]; ok { |
|
if sv, ok := svMap[svid]; ok { |
|
if common.IsSearchSvStateAvailable(int64(sv.State)) { |
|
r := new(v1.VideoSearchList) |
|
r.VideoResponse = *sv |
|
r.SVID = svid |
|
r.HitColumns = sinfo.HitColumns |
|
r.TitleHighlight = sinfo.Title |
|
r.Offset = (reqPage-1)*int64(searchLen) + int64(index) + 1 |
|
res.List = append(res.List, r) |
|
} else { |
|
log.Warnw(c, "log", "get error svid in search list", "svid", svid, "sv", sv) |
|
} |
|
} |
|
} |
|
} |
|
|
|
res.NumPage = searchRes.PageNum |
|
res.Page = searchRes.Page |
|
|
|
res.HasMore = false |
|
if arg.Page == 0 { |
|
if (directionNext && searchRes.PageNum > searchRes.Page) || (!directionNext && searchRes.Page > 1) { |
|
res.HasMore = true |
|
} |
|
|
|
var list []*v1.VideoSearchList |
|
if directionNext { |
|
for _, item := range res.List { |
|
if item.Offset < firstItemOffset { |
|
continue |
|
} |
|
list = append(list, item) |
|
} |
|
} else { |
|
if firstItemOffset >= int64(len(res.List)) { |
|
firstItemOffset = int64(len(res.List)) - 1 |
|
} |
|
for i := firstItemOffset - 1; i >= 0; i-- { |
|
list = append(list, res.List[i]) |
|
} |
|
} |
|
res.List = list |
|
} |
|
|
|
var cursorValue SearchCursor |
|
for _, item := range res.List { |
|
cursorValue.Offset = item.Offset |
|
data, _ := json.Marshal(cursorValue) |
|
item.CursorValue = string(data) |
|
} |
|
|
|
return |
|
} |
|
|
|
// UserSearch 用户搜索 |
|
func (s *Service) UserSearch(c context.Context, mid int64, arg *v1.BaseSearchReq) (res *v1.UserSearchRes, err error) { |
|
res = new(v1.UserSearchRes) |
|
var ( |
|
sres []*model.UserSearchResult |
|
searchRes *model.RawSearchRes |
|
mids []int64 |
|
) |
|
|
|
// 1. 生成请求,会根据请求参数 |
|
// v2接口 |
|
reqPage := int64(1) |
|
firstItemOffset := int64(0) |
|
var cursor *SearchCursor |
|
var directionNext bool |
|
if arg.Page == 0 { |
|
cursor, directionNext, err = parseSearchCursor(c, arg.CursorPrev, arg.CursorNext) |
|
if err != nil { |
|
log.Warnw(c, "log", "parse search cursor fail", "prev", arg.CursorPrev, "next", arg.CursorNext) |
|
return |
|
} |
|
firstItemOffset = cursor.Offset - 1 |
|
if directionNext { |
|
firstItemOffset = cursor.Offset + 1 |
|
} |
|
reqPage = (firstItemOffset-1)/searchLen + 1 |
|
log.V(1).Infow(c, "log", "v2 request", "next", arg.CursorNext, "prev", arg.CursorPrev) |
|
} else { |
|
reqPage = arg.Page |
|
} |
|
|
|
sp := &model.SearchBaseReq{ |
|
KeyWord: arg.Key, |
|
Type: searchTypeUser, |
|
Page: reqPage, |
|
PageSize: searchLen, |
|
Highlight: int64(arg.Highlight), |
|
} |
|
searchRes, err = s.dao.SearchBBQ(c, sp) |
|
if searchRes.Res == nil { |
|
return |
|
} |
|
if err = json.Unmarshal(searchRes.Res, &sres); err != nil { |
|
return |
|
} |
|
for _, v := range sres { |
|
mids = append(mids, v.ID) |
|
} |
|
if len(mids) == 0 { |
|
log.Infov(c, log.KV("log", "search ret empty")) |
|
return |
|
} |
|
uMap, _ := s.dao.BatchUserInfo(c, mid, mids, false, true, true) |
|
for index, sinfo := range sres { |
|
if u, ok := uMap[sinfo.ID]; ok { |
|
r := &v1.UserSearchList{ |
|
UserInfo: *u, |
|
} |
|
st := new(v1.UserStatic) |
|
st.Fan = u.Fan |
|
st.Follow = u.Follow |
|
st.Like = u.Like |
|
st.Liked = u.Liked |
|
st.FollowState = u.FollowState |
|
r.UserStatic = st |
|
r.HitColumns = sinfo.HitColumns |
|
r.UnameHighlight = sinfo.Uname |
|
r.Offset = (reqPage-1)*int64(searchLen) + int64(index) + 1 |
|
res.List = append(res.List, r) |
|
} |
|
} |
|
res.NumPage = searchRes.PageNum |
|
res.Page = searchRes.Page |
|
|
|
res.HasMore = false |
|
if arg.Page == 0 { |
|
if (directionNext && searchRes.PageNum > searchRes.Page) || (!directionNext && searchRes.Page > 1) { |
|
res.HasMore = true |
|
} |
|
|
|
var list []*v1.UserSearchList |
|
if directionNext { |
|
for _, item := range res.List { |
|
if item.Offset < firstItemOffset { |
|
continue |
|
} |
|
list = append(list, item) |
|
} |
|
} else { |
|
if firstItemOffset >= int64(len(res.List)) { |
|
firstItemOffset = int64(len(res.List)) - 1 |
|
} |
|
for i := firstItemOffset - 1; i >= 0; i-- { |
|
list = append(list, res.List[i]) |
|
} |
|
} |
|
res.List = list |
|
} |
|
|
|
var cursorValue SearchCursor |
|
for _, item := range res.List { |
|
cursorValue.Offset = item.Offset |
|
data, _ := json.Marshal(cursorValue) |
|
item.CursorValue = string(data) |
|
} |
|
|
|
return |
|
} |
|
|
|
// BBQSug BBQSUG服务 |
|
func (s *Service) BBQSug(c context.Context, arg *v1.SugReq) (res []*v1.SugTag, err error) { |
|
var ( |
|
sres []*model.RawSugTag |
|
data json.RawMessage |
|
) |
|
sp := &model.SugBaseReq{ |
|
Term: arg.KeyWord, |
|
SuggestType: suggestType, |
|
MainVer: suggestVer, |
|
SugNum: arg.PageSize, |
|
Highlight: int64(arg.Highlight), |
|
} |
|
data, err = s.dao.SugBBQ(c, sp) |
|
if err != nil { |
|
log.Error("s.dao.SugBBQ err[%v] data [%s]", err, string(data)) |
|
return |
|
} |
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary |
|
if err = json.Unmarshal(data, &sres); err != nil { |
|
log.Error("json.Unmarshal err[%v] data [%s]", err, string(data)) |
|
return |
|
} |
|
for _, sinfo := range sres { |
|
r := new(v1.SugTag) |
|
name := sinfo.Name |
|
r.Name = name |
|
r.Value = sinfo.Value |
|
r.Type = sinfo.Type |
|
r.Ref = sinfo.Ref |
|
res = append(res, r) |
|
} |
|
return |
|
}
|
|
|