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.
601 lines
16 KiB
601 lines
16 KiB
package search |
|
|
|
import ( |
|
"bytes" |
|
"fmt" |
|
|
|
// "hash/crc32" |
|
"regexp" |
|
"strconv" |
|
"strings" |
|
|
|
"go-common/app/interface/main/app-intl/model" |
|
bgmmdl "go-common/app/interface/main/app-intl/model/bangumi" |
|
article "go-common/app/interface/openplatform/article/model" |
|
"go-common/app/service/main/archive/api" |
|
xtime "go-common/library/time" |
|
) |
|
|
|
// search const |
|
var getHightLight = regexp.MustCompile(`<em.*?em>`) |
|
|
|
// Result struct |
|
type Result struct { |
|
Trackid string `json:"trackid,omitempty"` |
|
Page int `json:"page,omitempty"` |
|
NavInfo []*NavInfo `json:"nav,omitempty"` |
|
Item []*Item `json:"item,omitempty"` |
|
Array int `json:"array,omitempty"` |
|
Attribute int32 `json:"attribute"` |
|
EasterEgg *EasterEgg `json:"easter_egg,omitempty"` |
|
} |
|
|
|
// NavInfo struct |
|
type NavInfo struct { |
|
Name string `json:"name"` |
|
Total int `json:"total"` |
|
Pages int `json:"pages"` |
|
Type int `json:"type"` |
|
Show int `json:"show_more,omitempty"` |
|
} |
|
|
|
// TypeSearch struct |
|
type TypeSearch struct { |
|
TrackID string `json:"trackid"` |
|
Pages int `json:"pages"` |
|
Total int `json:"total"` |
|
Items []*Item `json:"items,omitempty"` |
|
} |
|
|
|
// Suggestion struct |
|
type Suggestion struct { |
|
TrackID string `json:"trackid"` |
|
UpUser interface{} `json:"upuser,omitempty"` |
|
Bangumi interface{} `json:"bangumi,omitempty"` |
|
Suggest []string `json:"suggest,omitempty"` |
|
} |
|
|
|
// SuggestionResult3 struct |
|
type SuggestionResult3 struct { |
|
TrackID string `json:"trackid"` |
|
List []*Item `json:"list,omitempty"` |
|
} |
|
|
|
// NoResultRcndResult struct |
|
type NoResultRcndResult struct { |
|
TrackID string `json:"trackid"` |
|
Title string `json:"title,omitempty"` |
|
Pages int `json:"pages"` |
|
Items []*Item `json:"items,omitempty"` |
|
} |
|
|
|
// EasterEgg struct |
|
type EasterEgg struct { |
|
ID int64 `json:"id,omitempty"` |
|
ShowCount int `json:"show_count,omitempty"` |
|
} |
|
|
|
// Item struct |
|
type Item struct { |
|
TrackID string `json:"trackid,omitempty"` |
|
LinkType string `json:"linktype,omitempty"` |
|
Position int `json:"position,omitempty"` |
|
SuggestKeyword string `json:"suggest_keyword,omitempty"` |
|
Title string `json:"title,omitempty"` |
|
Name string `json:"name,omitempty"` |
|
Cover string `json:"cover,omitempty"` |
|
URI string `json:"uri,omitempty"` |
|
Param string `json:"param,omitempty"` |
|
Goto string `json:"goto,omitempty"` |
|
// av |
|
Play int `json:"play,omitempty"` |
|
Danmaku int `json:"danmaku,omitempty"` |
|
Author string `json:"author,omitempty"` |
|
ViewType string `json:"view_type,omitempty"` |
|
PTime xtime.Time `json:"ptime,omitempty"` |
|
RecTags []string `json:"rec_tags,omitempty"` |
|
// bangumi season |
|
SeasonID int64 `json:"season_id,omitempty"` |
|
SeasonType int `json:"season_type,omitempty"` |
|
Finish int8 `json:"finish,omitempty"` |
|
Started int8 `json:"started,omitempty"` |
|
Index string `json:"index,omitempty"` |
|
NewestCat string `json:"newest_cat,omitempty"` |
|
NewestSeason string `json:"newest_season,omitempty"` |
|
CatDesc string `json:"cat_desc,omitempty"` |
|
TotalCount int `json:"total_count,omitempty"` |
|
MediaType int `json:"media_type,omitempty"` |
|
PlayState int `json:"play_state,omitempty"` |
|
Style string `json:"style,omitempty"` |
|
CV string `json:"cv,omitempty"` |
|
Rating float64 `json:"rating,omitempty"` |
|
Vote int `json:"vote,omitempty"` |
|
RatingCount int `json:"rating_count,omitempty"` |
|
BadgeType int `json:"badge_type,omitempty"` |
|
// upper |
|
Sign string `json:"sign,omitempty"` |
|
Fans int `json:"fans,omitempty"` |
|
Level int `json:"level,omitempty"` |
|
Desc string `json:"desc,omitempty"` |
|
OfficialVerify *OfficialVerify `json:"official_verify,omitempty"` |
|
AvItems []*Item `json:"av_items,omitempty"` |
|
Item []*Item `json:"item,omitempty"` |
|
CTime int64 `json:"ctime,omitempty"` |
|
IsUp bool `json:"is_up,omitempty"` |
|
LiveURI string `json:"live_uri,omitempty"` |
|
// movie |
|
ScreenDate string `json:"screen_date,omitempty"` |
|
Area string `json:"area,omitempty"` |
|
CoverMark string `json:"cover_mark,omitempty"` |
|
// arc and sp |
|
Arcs int `json:"archives,omitempty"` |
|
// arc and movie |
|
Duration string `json:"duration,omitempty"` |
|
DurationInt int64 `json:"duration_int,omitempty"` |
|
Actors string `json:"actors,omitempty"` |
|
Staff string `json:"staff,omitempty"` |
|
Length int `json:"length,omitempty"` |
|
Status int `json:"status,omitempty"` |
|
// live |
|
RoomID int64 `json:"roomid,omitempty"` |
|
Mid int64 `json:"mid,omitempty"` |
|
Type string `json:"type,omitempty"` |
|
Attentions int `json:"attentions,omitempty"` |
|
LiveStatus int `json:"live_status,omitempty"` |
|
Tags string `json:"tags,omitempty"` |
|
Region int `json:"region,omitempty"` |
|
Online int `json:"online,omitempty"` |
|
ShortID int `json:"short_id,omitempty"` |
|
CateName string `json:"area_v2_name,omitempty"` |
|
IsSelection int `json:"is_selection,omitempty"` |
|
// article |
|
ID int64 `json:"id,omitempty"` |
|
TemplateID int `json:"template_id,omitempty"` |
|
ImageUrls []string `json:"image_urls,omitempty"` |
|
View int `json:"view,omitempty"` |
|
Like int `json:"like,omitempty"` |
|
Reply int `json:"reply,omitempty"` |
|
// special |
|
Badge string `json:"badge,omitempty"` |
|
RcmdReason *RcmdReason `json:"rcmd_reason,omitempty"` |
|
// media bangumi and mdeia ft |
|
Prompt string `json:"prompt,omitempty"` |
|
Episodes []*Item `json:"episodes,omitempty"` |
|
Label string `json:"label,omitempty"` |
|
// game |
|
Reserve string `json:"reserve,omitempty"` |
|
// user |
|
Face string `json:"face,omitempty"` |
|
// suggest |
|
From string `json:"from,omitempty"` |
|
KeyWord string `json:"keyword,omitempty"` |
|
CoverSize float64 `json:"cover_size,omitempty"` |
|
SugType string `json:"sug_type,omitempty"` |
|
TermType int `json:"term_type,omitempty"` |
|
// rcmd query |
|
List []*Item `json:"list,omitempty"` |
|
FromSource string `json:"from_source,omitempty"` |
|
// live master |
|
UCover string `json:"ucover,omitempty"` |
|
VerifyType int `json:"verify_type,omitempty"` |
|
VerifyDesc string `json:"verify_desc,omitempty"` |
|
LevelColor int64 `json:"level_color,omitempty"` |
|
IsAttention int `json:"is_atten,omitempty"` |
|
CateParentName string `json:"cate_parent_name,omitempty"` |
|
CateNameNew string `json:"cate_name,omitempty"` |
|
Glory *Glory `json:"glory_info,omitempty"` |
|
// twitter |
|
Covers []string `json:"covers,omitempty"` |
|
CoverCount int `json:"cover_count,omitempty"` |
|
} |
|
|
|
// Glory live struct |
|
type Glory struct { |
|
Title string `json:"title,omitempty"` |
|
Total int `json:"total"` |
|
Items []*Item `json:"items,omitempty"` |
|
} |
|
|
|
// RcmdReason struct |
|
type RcmdReason struct { |
|
Content string `json:"content,omitempty"` |
|
} |
|
|
|
// UserResult struct |
|
type UserResult struct { |
|
Items []*Item `json:"items,omitempty"` |
|
} |
|
|
|
// DefaultWords struct |
|
type DefaultWords struct { |
|
Trackid string `json:"trackid,omitempty"` |
|
Param string `json:"param,omitempty"` |
|
Show string `json:"show,omitempty"` |
|
Word string `json:"word,omitempty"` |
|
} |
|
|
|
// FromSeason form func |
|
func (i *Item) FromSeason(b *Bangumi, bangumi string) { |
|
i.Title = b.Title |
|
i.Cover = b.Cover |
|
i.Goto = model.GotoBangumi |
|
i.Param = strconv.Itoa(int(b.SeasonID)) |
|
i.URI = model.FillURI(bangumi, i.Param, nil) |
|
i.Finish = int8(b.IsFinish) |
|
i.Started = int8(b.IsStarted) |
|
i.Index = b.NewestEpIndex |
|
i.NewestCat = b.NewestCat |
|
i.NewestSeason = b.NewestSeason |
|
i.TotalCount = b.TotalCount |
|
var buf bytes.Buffer |
|
if b.CatList.TV != 0 { |
|
buf.WriteString(`TV(`) |
|
buf.WriteString(strconv.Itoa(b.CatList.TV)) |
|
buf.WriteString(`) `) |
|
} |
|
if b.CatList.Movie != 0 { |
|
buf.WriteString(`剧场版(`) |
|
buf.WriteString(strconv.Itoa(b.CatList.Movie)) |
|
buf.WriteString(`) `) |
|
} |
|
if b.CatList.Ova != 0 { |
|
buf.WriteString(`OVA/OAD/SP(`) |
|
buf.WriteString(strconv.Itoa(b.CatList.Ova)) |
|
buf.WriteString(`)`) |
|
} |
|
i.CatDesc = buf.String() |
|
} |
|
|
|
// FromUser form func |
|
func (i *Item) FromUser(u *User, as map[int64]*api.Arc) { |
|
i.Title = u.Name |
|
i.Cover = u.Pic |
|
i.Goto = model.GotoAuthor |
|
i.OfficialVerify = u.OfficialVerify |
|
i.Param = strconv.Itoa(int(u.Mid)) |
|
i.URI = model.FillURI(i.Goto, i.Param, nil) |
|
i.Mid = u.Mid |
|
i.Sign = u.Usign |
|
i.Fans = u.Fans |
|
i.Level = u.Level |
|
i.Arcs = u.Videos |
|
i.AvItems = make([]*Item, 0, len(u.Res)) |
|
i.RoomID = u.RoomID |
|
if u.IsUpuser == 1 { |
|
for _, v := range u.Res { |
|
vi := &Item{} |
|
vi.Title = v.Title |
|
vi.Cover = v.Pic |
|
vi.Goto = model.GotoAv |
|
vi.Param = strconv.Itoa(int(v.Aid)) |
|
vi.URI = model.FillURI(vi.Goto, vi.Param, model.AvHandler(as[v.Aid], "", nil)) |
|
a, ok := as[v.Aid] |
|
if ok { |
|
vi.Play = int(a.Stat.View) |
|
vi.Danmaku = int(a.Stat.Danmaku) |
|
} else { |
|
switch play := v.Play.(type) { |
|
case float64: |
|
vi.Play = int(play) |
|
case string: |
|
vi.Play, _ = strconv.Atoi(play) |
|
} |
|
vi.Danmaku = v.Danmaku |
|
} |
|
vi.CTime = v.Pubdate |
|
vi.Duration = v.Duration |
|
i.AvItems = append(i.AvItems, vi) |
|
} |
|
i.IsUp = true |
|
} |
|
} |
|
|
|
// FromUpUser form func |
|
func (i *Item) FromUpUser(u *User, as map[int64]*api.Arc) { |
|
i.Title = u.Name |
|
i.Cover = u.Pic |
|
i.Goto = model.GotoAuthor |
|
i.OfficialVerify = u.OfficialVerify |
|
i.Param = strconv.Itoa(int(u.Mid)) |
|
i.URI = model.FillURI(i.Goto, i.Param, nil) |
|
i.Mid = u.Mid |
|
i.Sign = u.Usign |
|
i.Fans = u.Fans |
|
i.Level = u.Level |
|
i.Arcs = u.Videos |
|
i.AvItems = make([]*Item, 0, len(u.Res)) |
|
for _, v := range u.Res { |
|
vi := &Item{} |
|
vi.Title = v.Title |
|
vi.Cover = v.Pic |
|
vi.Goto = model.GotoAv |
|
vi.Param = strconv.Itoa(int(v.Aid)) |
|
vi.URI = model.FillURI(vi.Goto, vi.Param, model.AvHandler(as[v.Aid], "", nil)) |
|
a, ok := as[v.Aid] |
|
if ok { |
|
vi.Play = int(a.Stat.View) |
|
vi.Danmaku = int(a.Stat.Danmaku) |
|
} else { |
|
switch play := v.Play.(type) { |
|
case float64: |
|
vi.Play = int(play) |
|
case string: |
|
vi.Play, _ = strconv.Atoi(play) |
|
} |
|
vi.Danmaku = v.Danmaku |
|
} |
|
vi.CTime = v.Pubdate |
|
vi.Duration = v.Duration |
|
i.AvItems = append(i.AvItems, vi) |
|
} |
|
i.RoomID = u.RoomID |
|
i.IsUp = u.IsUpuser == 1 |
|
} |
|
|
|
// FromMovie form func |
|
func (i *Item) FromMovie(m *Movie, as map[int64]*api.Arc) { |
|
i.Title = m.Title |
|
i.Desc = m.Desc |
|
if m.Type == "movie" { |
|
i.Cover = m.Cover |
|
i.Param = strconv.Itoa(int(m.Aid)) |
|
i.Goto = model.GotoAv |
|
i.URI = model.FillURI(i.Goto, i.Param, model.AvHandler(as[m.Aid], "", nil)) |
|
i.CoverMark = model.StatusMark(m.Status) |
|
} else if m.Type == "special" { |
|
i.Param = m.SpID |
|
i.Goto = model.GotoSp |
|
i.URI = model.FillURI(i.Goto, i.Param, nil) |
|
i.Cover = m.Pic |
|
} |
|
i.Staff = m.Staff |
|
i.Actors = m.Actors |
|
i.Area = m.Area |
|
i.Length = m.Length |
|
i.Status = m.Status |
|
i.ScreenDate = m.ScreenDate |
|
} |
|
|
|
// FromVideo form func |
|
func (i *Item) FromVideo(v *Video, a *api.Arc) { |
|
i.Title = v.Title |
|
i.Cover = v.Pic |
|
i.Author = v.Author |
|
i.Param = strconv.Itoa(int(v.ID)) |
|
i.Goto = model.GotoAv |
|
if a != nil { |
|
i.Face = a.Author.Face |
|
i.URI = model.FillURI(i.Goto, i.Param, model.AvHandler(a, "", nil)) |
|
i.Play = int(a.Stat.View) |
|
i.Danmaku = int(a.Stat.Danmaku) |
|
} else { |
|
i.URI = model.FillURI(i.Goto, i.Param, nil) |
|
switch play := v.Play.(type) { |
|
case float64: |
|
i.Play = int(play) |
|
case string: |
|
i.Play, _ = strconv.Atoi(play) |
|
} |
|
i.Danmaku = v.Danmaku |
|
} |
|
i.Desc = v.Desc |
|
i.Duration = v.Duration |
|
i.ViewType = v.ViewType |
|
i.RecTags = v.RecTags |
|
} |
|
|
|
// FromOperate form func |
|
func (i *Item) FromOperate(o *Operate, gt string) { |
|
i.Title = o.Title |
|
i.Cover = o.Cover |
|
i.URI = o.RedirectURL |
|
i.Param = strconv.FormatInt(o.ID, 10) |
|
i.Desc = o.Desc |
|
i.Badge = o.Corner |
|
i.Goto = gt |
|
if o.RecReason != "" { |
|
i.RcmdReason = &RcmdReason{Content: o.RecReason} |
|
} |
|
} |
|
|
|
// FromConverge form func |
|
func (i *Item) FromConverge(o *Operate, am map[int64]*api.Arc, artm map[int64]*article.Meta) { |
|
const _convergeMinCount = 2 |
|
cis := make([]*Item, 0, len(o.ContentList)) |
|
for _, c := range o.ContentList { |
|
ci := &Item{} |
|
switch c.Type { |
|
case 0: |
|
if a, ok := am[c.ID]; ok && a.IsNormal() { |
|
ci.Title = a.Title |
|
ci.Cover = a.Pic |
|
ci.Goto = model.GotoAv |
|
ci.Param = strconv.FormatInt(a.Aid, 10) |
|
ci.URI = model.FillURI(ci.Goto, ci.Param, model.AvHandler(a, "", nil)) |
|
ci.fillArcStat(a) |
|
cis = append(cis, ci) |
|
} |
|
case 2: |
|
if art, ok := artm[c.ID]; ok { |
|
ci.Title = art.Title |
|
ci.Desc = art.Summary |
|
if len(art.ImageURLs) != 0 { |
|
ci.Cover = art.ImageURLs[0] |
|
} |
|
ci.Goto = model.GotoArticle |
|
ci.Param = strconv.FormatInt(art.ID, 10) |
|
ci.URI = model.FillURI(ci.Goto, ci.Param, nil) |
|
if art.Stats != nil { |
|
ci.fillArtStat(art) |
|
} |
|
ci.Badge = "文章" |
|
cis = append(cis, ci) |
|
} |
|
} |
|
} |
|
if len(cis) < _convergeMinCount { |
|
return |
|
} |
|
i.Item = cis |
|
i.Title = o.Title |
|
i.Cover = o.Cover |
|
i.URI = o.RedirectURL |
|
i.Param = strconv.FormatInt(o.ID, 10) |
|
i.Desc = o.Desc |
|
i.Badge = o.Corner |
|
i.Goto = model.GotoConverge |
|
if o.RecReason != "" { |
|
i.RcmdReason = &RcmdReason{Content: o.RecReason} |
|
} |
|
} |
|
|
|
// FromMedia form func |
|
func (i *Item) FromMedia(m *Media, prompt string, gt string, bangumis map[string]*bgmmdl.Card) { |
|
i.Title = m.Title |
|
if i.Title == "" { |
|
i.Title = m.OrgTitle |
|
} |
|
i.Cover = m.Cover |
|
i.Goto = gt |
|
i.Param = strconv.Itoa(int(m.MediaID)) |
|
i.URI = m.GotoURL |
|
i.MediaType = m.MediaType |
|
i.PlayState = m.PlayState |
|
i.Style = m.Styles |
|
i.CV = m.CV |
|
i.Staff = m.Staff |
|
if m.MediaScore != nil { |
|
i.Rating = m.MediaScore.Score |
|
i.Vote = m.MediaScore.UserCount |
|
} |
|
i.PTime = m.Pubtime |
|
areas := strings.Split(m.Areas, "、") |
|
if len(areas) != 0 { |
|
i.Area = areas[0] |
|
} |
|
i.Prompt = prompt |
|
var hit string |
|
for _, v := range m.HitColumns { |
|
if v == "cv" { |
|
hit = v |
|
break |
|
} else if v == "staff" { |
|
hit = v |
|
} |
|
} |
|
if hit == "cv" { |
|
for _, v := range getHightLight.FindAllStringSubmatch(m.CV, -1) { |
|
if gt == model.GotoBangumi { |
|
i.Label = fmt.Sprintf("声优: %v...", v[0]) |
|
break |
|
} else if gt == model.GotoMovie { |
|
i.Label = fmt.Sprintf("演员: %v...", v[0]) |
|
break |
|
} |
|
} |
|
} else if hit == "staff" { |
|
for _, v := range getHightLight.FindAllStringSubmatch(m.Staff, -1) { |
|
i.Label = fmt.Sprintf("制作人员: %v...", v[0]) |
|
break |
|
} |
|
} |
|
// get from PGC API. |
|
i.SeasonID = m.SeasonID |
|
ssID := strconv.Itoa(int(m.SeasonID)) |
|
if bgm, ok := bangumis[ssID]; ok { |
|
i.IsAttention = bgm.IsFollow |
|
i.IsSelection = bgm.IsSelection |
|
i.SeasonType = bgm.SeasonType |
|
for _, v := range bgm.Episodes { |
|
tmp := &Item{ |
|
Param: strconv.Itoa(int(v.ID)), |
|
Index: v.Index, |
|
} |
|
tmp.URI = model.FillURI(model.GotoEP, tmp.Param, nil) |
|
i.Episodes = append(i.Episodes, tmp) |
|
} |
|
} |
|
} |
|
|
|
// FromArticle form func |
|
func (i *Item) FromArticle(a *Article) { |
|
i.ID = a.ID |
|
i.Mid = a.Mid |
|
i.TemplateID = a.TemplateID |
|
i.Title = a.Title |
|
i.Desc = a.Desc |
|
i.ImageUrls = a.ImageUrls |
|
i.View = a.View |
|
i.Play = a.View |
|
i.Like = a.Like |
|
i.Reply = a.Reply |
|
i.Goto = model.GotoArticle |
|
i.Param = strconv.Itoa(int(a.ID)) |
|
i.URI = model.FillURI(i.Goto, i.Param, nil) |
|
} |
|
|
|
// FromChannel form func |
|
func (i *Item) FromChannel(c *Channel) { |
|
i.ID = c.TagID |
|
i.Title = c.TagName |
|
i.Cover = c.Cover |
|
i.Param = strconv.FormatInt(c.TagID, 10) |
|
i.Goto = model.GotoChannel |
|
i.URI = model.FillURI(i.Goto, i.Param, nil) |
|
i.Type = c.Type |
|
i.Attentions = c.AttenCount |
|
} |
|
|
|
// FromQuery form func |
|
func (i *Item) FromQuery(qs []*Query) { |
|
i.Goto = model.GotoRecommendWord |
|
for _, q := range qs { |
|
i.List = append(i.List, &Item{Param: strconv.FormatInt(q.ID, 10), Title: q.Name, Type: q.Type, FromSource: q.FromSource}) |
|
} |
|
} |
|
|
|
// FromTwitter form twitter |
|
func (i *Item) FromTwitter(t *Twitter) { |
|
i.Title = t.Content |
|
i.Covers = t.Cover |
|
i.CoverCount = t.CoverCount |
|
i.Param = strconv.FormatInt(t.ID, 10) |
|
i.Goto = model.GotoTwitter |
|
i.URI = model.FillURI(i.Goto, strconv.FormatInt(t.PicID, 10), nil) |
|
} |
|
|
|
// fillArcStat fill func |
|
func (i *Item) fillArcStat(a *api.Arc) { |
|
if a.Access == 0 { |
|
i.Play = int(a.Stat.View) |
|
} |
|
i.Danmaku = int(a.Stat.Danmaku) |
|
i.Reply = int(a.Stat.Reply) |
|
i.Like = int(a.Stat.Like) |
|
} |
|
|
|
// fillArtStat fill func |
|
func (i *Item) fillArtStat(m *article.Meta) { |
|
i.Play = int(m.Stats.View) |
|
i.Reply = int(m.Stats.Reply) |
|
} |
|
|
|
// FromSuggest3 form func |
|
func (i *Item) FromSuggest3(st *Sug, as map[int64]*api.Arc) { |
|
i.From = "search" |
|
i.Title = st.ShowName |
|
i.KeyWord = st.Term |
|
i.Position = st.Pos |
|
i.Cover = st.Cover |
|
i.CoverSize = st.CoverSize |
|
i.SugType = st.SubType |
|
i.TermType = st.TermType |
|
if st.TermType == SuggestionJump { |
|
switch st.SubType { |
|
case SuggestionAV: |
|
i.Goto = model.GotoAv |
|
i.URI = model.FillURI(i.Goto, strconv.Itoa(int(st.Ref)), model.AvHandler(as[st.Ref], "", nil)) |
|
i.SugType = "视频" |
|
} |
|
} |
|
}
|
|
|