2019-04-22 02:59:20 +00:00

1319 lines
36 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package search
import (
"bytes"
"encoding/json"
"fmt"
// "hash/crc32"
"math"
"regexp"
"strconv"
"strings"
"go-common/app/interface/main/app-interface/model"
bangumimdl "go-common/app/interface/main/app-interface/model/bangumi"
"go-common/app/interface/main/app-interface/model/bplus"
"go-common/app/interface/main/app-interface/model/live"
tagmdl "go-common/app/interface/main/app-interface/model/tag"
article "go-common/app/interface/openplatform/article/model"
account "go-common/app/service/main/account/model"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
seasongrpc "go-common/app/service/openplatform/pgc-season/api/grpc/season/v1"
"go-common/library/log"
xtime "go-common/library/time"
)
var (
getHightLight = regexp.MustCompile(`<em.*?em>`)
payBadge = &model.ReasonStyle{Text: "付费",
TextColor: "#FFFFFFFF",
TextColorNight: "#E5E5E5",
BgColor: "#FAAB4B",
BgColorNight: "#BA833F",
BorderColor: "#FAAB4B",
BorderColorNight: "#BA833F",
BgStyle: BgStyleFill,
}
cooperationBadge = &model.ReasonStyle{Text: "合作",
TextColor: "#FFFFFFFF",
TextColorNight: "#E5E5E5",
BgColor: "#FB7299",
BgColorNight: "#BB5B76",
BorderColor: "#FB7299",
BorderColorNight: "#BB5B76",
BgStyle: BgStyleFill,
}
videoStrongStyle = &model.ReasonStyle{
TextColor: "#FFFFFFFF",
TextColorNight: "#E5E5E5",
BgColor: "#FAAB4B",
BgColorNight: "#BA833F",
BorderColor: "#FAAB4B",
BorderColorNight: "#BA833F",
BgStyle: BgStyleFill,
}
videoWeekStyle = &model.ReasonStyle{
TextColor: "#FAAB4B",
TextColorNight: "#BA833F",
BgColor: "",
BgColorNight: "",
BorderColor: "#FAAB4B",
BorderColorNight: "#BA833F",
BgStyle: BgStyleStroke,
}
)
// search const
const (
_emptyLiveCover = "https://static.hdslb.com/images/transparent.gif"
_emptyLiveCover2 = "https://i0.hdslb.com/bfs/live/0477300d2adf65062a3d1fb7ef92122b82213b0f.png"
StarSpace = 1
StarChannel = 2
BgStyleFill = int8(1)
BgStyleStroke = int8(2)
BgStyleFillAndStroke = int8(3)
BgStyleNoFillAndNoStroke = int8(4)
)
// Result struct
type Result struct {
Trackid string `json:"trackid,omitempty"`
Page int `json:"page,omitempty"`
NavInfo []*NavInfo `json:"nav,omitempty"`
Items ResultItems `json:"items,omitempty"`
Item []*Item `json:"item,omitempty"`
Array int `json:"array,omitempty"`
Attribute int32 `json:"attribute"`
EasterEgg *EasterEgg `json:"easter_egg,omitempty"`
}
// ResultItems struct
type ResultItems struct {
SuggestKeyWord *Item `json:"suggest_keyword,omitempty"`
Operation []*Item `json:"operation,omitempty"`
Season2 []*Item `json:"season2,omitempty"`
Season []*Item `json:"season,omitempty"`
Upper []*Item `json:"upper,omitempty"`
Movie2 []*Item `json:"movie2,omitempty"`
Movie []*Item `json:"movie,omitempty"`
Archive []*Item `json:"archive,omitempty"`
LiveRoom []*Item `json:"live_room,omitempty"`
LiveUser []*Item `json:"live_user,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"`
}
// TypeSearchLiveAll struct
type TypeSearchLiveAll struct {
TrackID string `json:"trackid"`
Pages int `json:"pages"`
Total int `json:"total"`
Master *TypeSearch `json:"live_master,omitempty"`
Room *TypeSearch `json:"live_room,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"`
}
// Suggestion2 struct
type Suggestion2 struct {
TrackID string `json:"trackid"`
List []*Item `json:"list,omitempty"`
}
// SuggestionResult3 struct
type SuggestionResult3 struct {
TrackID string `json:"trackid"`
List []*Item `json:"list,omitempty"`
}
// RecommendResult struct
type RecommendResult struct {
TrackID string `json:"trackid"`
Title string `json:"title,omitempty"`
Pages int `json:"pages"`
Items []*Item `json:"list,omitempty"`
}
// DefaultWordResult struct
type DefaultWordResult struct {
TrackID string `json:"trackid"`
Title string `json:"title,omitempty"`
Pages int `json:"pages"`
Items []*Item `json:"items,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"`
}
// RecommendPreResult struct
type RecommendPreResult struct {
TrackID string `json:"trackid"`
Total int `json:"total"`
Items []*Item `json:"items,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"`
IsPay int `json:"is_pay,omitempty"`
NewRecTags []*model.ReasonStyle `json:"new_rec_tags,omitempty"`
// bangumi season
SeasonID int64 `json:"season_id,omitempty"`
SeasonType int `json:"season_type,omitempty"`
SeasonTypeName string `json:"season_type_name,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"`
Styles string `json:"styles,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"`
OutName string `json:"out_name,omitempty"`
OutIcon string `json:"out_icon,omitempty"`
OutURL string `json:"out_url,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"`
Upper *Item `json:"upper,omitempty"`
State *Item `json:"stat,omitempty"`
// star
TagItems []*Item `json:"tag_items,omitempty"`
TagID int64 `json:"tag_id,omitempty"`
URIType int `json:"uri_type,omitempty"`
// ticket
ShowTime string `json:"show_time,omitempty"`
City string `json:"city,omitempty"`
Venue string `json:"venue,omitempty"`
Price int `json:"price,omitempty"`
PriceComplete string `json:"price_complete,omitempty"`
PriceType int `json:"price_type,omitempty"`
ReqNum int `json:"required_number,omitempty"`
// product
ShopName string `json:"shop_name,omitempty"`
// specialer_guide
Phone string `json:"phone,omitempty"`
Badges []*model.ReasonStyle `json:"badges,omitempty"`
ComicURL string `json:"comic_url,omitempty"`
// suggest_keyword
SugKeyWordType int `json:"sugKeyWord_type,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"`
ShowFront int `json:"show_front,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()
}
// FromUpUser form func
func (i *Item) FromUpUser(u *User, as map[int64]*api.Arc, lv *live.RoomInfo) {
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(archive.BuildArchive3(as[v.Aid])))
a, ok := as[v.Aid]
if ok {
vi.Play = int(a.Stat.View)
vi.Danmaku = int(a.Stat.Danmaku)
if a.Rights.UGCPay == 1 {
vi.Badges = append(vi.Badges, payBadge)
}
if a.Rights.IsCooperation == 1 {
vi.Badges = append(vi.Badges, cooperationBadge)
}
} else {
switch play := v.Play.(type) {
case float64:
vi.Play = int(play)
case string:
vi.Play, _ = strconv.Atoi(play)
}
vi.Danmaku = v.Danmaku
}
vi.IsPay = v.IsPay
vi.CTime = v.Pubdate
vi.Duration = v.Duration
i.AvItems = append(i.AvItems, vi)
}
i.LiveStatus = u.IsLive
i.RoomID = u.RoomID
i.IsUp = u.IsUpuser == 1
if i.RoomID != 0 {
i.LiveURI = model.FillURI(model.GotoLive, strconv.Itoa(int(u.RoomID)), model.LiveHandler(lv))
}
}
// FromUser form func
func (i *Item) FromUser(u *User, as map[int64]*api.Arc, lv *live.RoomInfo) {
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.LiveStatus = u.IsLive
i.RoomID = u.RoomID
if i.RoomID != 0 {
i.LiveURI = model.FillURI(model.GotoLive, strconv.Itoa(int(u.RoomID)), model.LiveHandler(lv))
}
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(archive.BuildArchive3(as[v.Aid])))
a, ok := as[v.Aid]
if ok {
vi.Play = int(a.Stat.View)
vi.Danmaku = int(a.Stat.Danmaku)
if a.Rights.UGCPay == 1 {
vi.Badges = append(vi.Badges, payBadge)
}
if a.Rights.IsCooperation == 1 {
vi.Badges = append(vi.Badges, cooperationBadge)
}
} else {
switch play := v.Play.(type) {
case float64:
vi.Play = int(play)
case string:
vi.Play, _ = strconv.Atoi(play)
}
vi.Danmaku = v.Danmaku
}
vi.IsPay = v.IsPay
vi.CTime = v.Pubdate
vi.Duration = v.Duration
i.AvItems = append(i.AvItems, vi)
}
i.IsUp = true
}
}
// 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(archive.BuildArchive3(as[m.Aid])))
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, cooperation bool) {
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(archive.BuildArchive3(a)))
i.Play = int(a.Stat.View)
i.Danmaku = int(a.Stat.Danmaku)
i.Mid = a.Author.Mid
if a.Rights.UGCPay == 1 {
i.Badges = append(i.Badges, payBadge)
}
if a.Rights.IsCooperation == 1 {
i.Badges = append(i.Badges, cooperationBadge)
if i.Author != "" && cooperation {
i.Author += " 等联合创作"
}
}
} 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.IsPay = v.IsPay
i.Desc = v.Desc
i.Duration = v.Duration
i.ViewType = v.ViewType
i.RecTags = v.RecTags
for _, r := range v.NewRecTags {
if r.Name != "" {
switch r.Style {
case BgStyleFill:
videoStrongStyle.Text = r.Name
i.NewRecTags = append(i.NewRecTags, videoStrongStyle)
case BgStyleStroke:
videoWeekStyle.Text = r.Name
i.NewRecTags = append(i.NewRecTags, videoWeekStyle)
}
}
}
}
// FromLive form func
func (i *Item) FromLive(l *Live, lv *live.RoomInfo) {
i.RoomID = l.RoomID
i.Mid = l.UID
i.Title = l.Title
i.Type = l.Type
if l.Cover == "" {
i.Cover = l.Uface
} else {
i.Cover = l.Cover
}
i.Name = l.Uname
i.Online = l.Online
i.Attentions = l.Attentions
i.Goto = model.GotoLive
if i.Type == "live_user" {
i.Param = strconv.Itoa(int(i.Mid))
} else {
i.Param = strconv.Itoa(int(i.RoomID))
}
i.URI = model.FillURI(i.Goto, i.Param, model.LiveHandler(lv))
i.Tags = l.Tags
i.Region = l.Area
i.Badge = "直播"
}
// FromLive2 form func
func (i *Item) FromLive2(l *Live, lv *live.RoomInfo) {
i.RoomID = l.RoomID
i.Mid = l.UID
i.Title = l.Title
i.Type = l.Type
if l.UserCover != "" && l.UserCover != _emptyLiveCover {
i.Cover = l.UserCover
} else if l.Cover != "" && l.Cover != _emptyLiveCover {
i.Cover = l.Cover
} else {
i.Cover = _emptyLiveCover2
}
i.Name = l.Uname
i.Online = l.Online
i.Attentions = l.Attentions
i.Goto = model.GotoLive
if i.Type == "live_user" {
i.Param = strconv.Itoa(int(i.Mid))
} else {
i.Param = strconv.Itoa(int(i.RoomID))
}
i.URI = model.FillURI(i.Goto, i.Param, model.LiveHandler(lv))
i.Tags = l.Tags
i.Region = l.Area
i.Badge = "直播"
i.ShortID = l.ShortID
i.CateName = l.CateName
i.LiveStatus = l.LiveStatus
}
// FromArticle form func
func (i *Item) FromArticle(a *Article, acc *account.Info) {
i.ID = a.ID
i.Mid = a.Mid
if acc != nil {
i.Author = acc.Name
}
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.Badge = "专栏"
i.Goto = model.GotoArticle
i.Param = strconv.Itoa(int(a.ID))
i.URI = model.FillURI(i.Goto, i.Param, nil)
}
// 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, rm map[int64]*live.Room, 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(archive.BuildArchive3(a)))
ci.fillArcStat(a)
cis = append(cis, ci)
}
case 1:
if r, ok := rm[c.ID]; ok {
if r.LiveStatus == 0 {
continue
}
ci.Title = r.Title
ci.Cover = r.Cover
ci.Goto = model.GotoLive
ci.Param = strconv.FormatInt(r.RoomID, 10)
ci.Online = r.Online
ci.URI = model.FillURI(ci.Goto, ci.Param, nil) + "?broadcast_type=" + strconv.Itoa(r.BroadcastType)
ci.Badge = "直播"
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]*bangumimdl.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
i.OutName = m.AllNetName
i.OutIcon = m.AllNetIcon
i.OutURL = m.AllNetURL
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 m.MediaType == 7 {
i.Label = fmt.Sprintf("嘉宾: %v...", v[0])
break
}
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
}
} else if hit == "" {
i.Label = FormPGCLabel(m.MediaType, m.Styles, m.Staff, m.CV)
}
// get from PGC API.
i.SeasonID = m.SeasonID
ssID := strconv.Itoa(int(m.SeasonID))
if bgm, ok := bangumis[ssID]; ok {
i.Badge = model.FormMediaType(bgm.SeasonType)
i.SeasonTypeName = bgm.SeasonTypeName
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,
Badges: v.Badges,
}
tmp.URI = model.FillURI(model.GotoEP, tmp.Param, nil)
i.Episodes = append(i.Episodes, tmp)
}
}
var (
badges []*model.ReasonStyle
err error
)
err = json.Unmarshal(m.DisplayInfo, &badges)
if err != nil {
log.Error("%v", err)
return
}
i.Badges = badges
}
// FromGame form func
func (i *Item) FromGame(g *Game) {
i.Title = g.Title
i.Cover = g.Cover
i.Desc = g.Desc
i.Rating = g.View
var reserve string
if g.Status == 1 || g.Status == 2 {
if g.Like < 10000 {
reserve = strconv.FormatInt(g.Like, 10) + "人预约"
} else {
reserve = strconv.FormatFloat(float64(g.Like)/10000, 'f', 1, 64) + "万人预约"
}
}
i.Reserve = reserve
i.Goto = model.GotoGame
i.Param = strconv.FormatInt(g.ID, 10)
i.URI = g.RedirectURL
}
// 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)
}
// FromSuggest form func
func (i *Item) FromSuggest(st *SuggestTag) {
i.From = "search"
if st.SpID == SuggestionJump {
switch st.Type {
case SuggestionAV:
i.Title = st.Value
i.Goto = model.GotoAv
i.URI = model.FillURI(i.Goto, strconv.Itoa(int(st.Ref)), nil)
case SuggestionLive:
i.Title = st.Value
i.Goto = model.GotoLive
i.URI = model.FillURI(i.Goto, strconv.Itoa(int(st.Ref)), nil)
}
} else {
i.Title = st.Value
}
}
// FromSuggest2 form func
func (i *Item) FromSuggest2(st *SuggestTag, as map[int64]*api.Arc, ls map[int64]*live.RoomInfo) {
i.From = "search"
if st.SpID == SuggestionJump {
switch st.Type {
case SuggestionAV:
i.Title = st.Value
i.Goto = model.GotoAv
i.URI = model.FillURI(i.Goto, strconv.Itoa(int(st.Ref)), model.AvHandler(archive.BuildArchive3(as[st.Ref])))
case SuggestionLive:
var (
l *live.RoomInfo
ok bool
)
i.Title = st.Value
i.Goto = model.GotoLive
if l, ok = ls[st.Ref]; !ok {
for _, v := range ls {
if v.ShortID == st.Ref {
l = v
break
}
}
}
i.URI = model.FillURI(i.Goto, strconv.Itoa(int(st.Ref)), model.LiveHandler(l))
if strings.Contains(i.URI, "broadcast_type") {
i.URI += "&extra_jump_from=23004"
} else {
i.URI += "?extra_jump_from=23004"
}
}
} else {
i.Title = st.Value
}
}
// FromSuggest3 form func
func (i *Item) FromSuggest3(st *Sug, as map[int64]*api.Arc, ls map[int64]*live.RoomInfo) {
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(archive.BuildArchive3(as[st.Ref])))
i.SugType = "视频"
case SuggestionLive:
var (
l *live.RoomInfo
ok bool
)
i.Goto = model.GotoLive
if l, ok = ls[st.Ref]; !ok {
for _, v := range ls {
if v.ShortID == st.Ref {
l = v
break
}
}
}
i.URI = model.FillURI(i.Goto, strconv.Itoa(int(st.Ref)), model.LiveHandler(l))
if strings.Contains(i.URI, "broadcast_type") {
i.URI += "&extra_jump_from=23004"
} else {
i.URI += "?extra_jump_from=23004"
}
i.SugType = "直播"
case SuggestionArticle:
i.Goto = model.GotoArticle
i.URI = model.FillURI(i.Goto, strconv.Itoa(int(st.Ref)), nil)
if !strings.Contains(i.URI, "column_from") {
i.URI += "?column_from=search"
}
i.SugType = "专栏"
}
} else if st.TermType == SuggestionJumpUser && st.User != nil {
i.Title = st.User.Name
i.Cover = st.User.Face
i.Goto = model.GotoAuthor
i.OfficialVerify = &OfficialVerify{Type: st.User.OfficialVerifyType}
i.Param = strconv.Itoa(int(st.User.Mid))
i.URI = model.FillURI(i.Goto, i.Param, nil)
i.Mid = st.User.Mid
i.Fans = st.User.Fans
i.Level = st.User.Level
i.Arcs = st.User.Videos
} else if st.TermType == SuggestionJumpPGC && st.PGC != nil {
var styles []string
i.Title = st.PGC.Title
i.Cover = st.PGC.Cover
i.PTime = st.PGC.Pubtime
i.URI = st.PGC.GotoURL
if pt := i.PTime.Time().Format("2006"); pt != "" {
styles = append(styles, pt)
}
i.SeasonTypeName = model.FormMediaType(st.PGC.MediaType)
if i.SeasonTypeName != "" {
styles = append(styles, i.SeasonTypeName)
}
i.Goto = model.GotoPGC
i.Param = strconv.Itoa(int(st.PGC.MediaID))
i.Area = st.PGC.Areas
if i.Area != "" {
styles = append(styles, i.Area)
}
i.Style = st.PGC.Styles
if len(styles) > 0 {
i.Styles = strings.Join(styles, "|")
}
i.Label = FormPGCLabel(st.PGC.MediaType, st.PGC.Styles, st.PGC.Staff, st.PGC.CV)
i.Rating = st.PGC.MediaScore
i.Vote = st.PGC.MediaUserCount
i.Badges = st.PGC.Badges
}
}
// 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})
}
}
func (i *Item) FromComic(c *Comic) {
i.ID = c.ID
i.Title = c.Title
if len(c.Author) > 0 {
i.Name = fmt.Sprintf("作者: %v", strings.Join(c.Author, "、"))
}
i.Style = c.Styles
i.Cover = c.Cover
i.URI = c.URL
i.ComicURL = c.ComicURL
i.Param = strconv.FormatInt(c.ID, 10)
i.Goto = model.GotoComic
i.Badge = "漫画"
}
// FromLiveMaster form func
func (i *Item) FromLiveMaster(l *Live, lv *live.RoomInfo) {
i.Type = l.Type
i.Name = l.Uname
i.UCover = l.Uface
i.Attentions = l.Fans
i.VerifyType = l.VerifyType
i.VerifyDesc = l.VerifyDesc
i.Title = l.Title
if l.Cover != "" && l.Cover != _emptyLiveCover {
i.Cover = l.Cover
} else {
i.Cover = _emptyLiveCover2
}
i.Goto = model.GotoLive
i.Mid = l.UID
i.RoomID = l.RoomID
i.Param = strconv.Itoa(int(i.RoomID))
i.URI = model.FillURI(i.Goto, i.Param, model.LiveHandler(lv))
i.Online = l.Online
i.LiveStatus = l.LiveStatus
i.CateParentName = l.CateParentName
i.CateNameNew = l.CateName
}
// FromChannel form func
func (i *Item) FromChannel(c *Channel, avm map[int64]*api.Arc, bangumis map[int32]*seasongrpc.CardInfoProto, lm map[int64]*live.RoomInfo, tagMyInfos []*tagmdl.Tag) {
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
i.Desc = c.Desc
for _, myInfo := range tagMyInfos {
if myInfo != nil && myInfo.TagID == c.TagID {
i.IsAttention = myInfo.IsAtten
break
}
}
var (
item []*Item
cooperation bool
)
for _, v := range c.Values {
ii := &Item{TrackID: v.TrackID, LinkType: v.LinkType, Position: v.Position}
switch v.Type {
case TypeVideo:
ii.FromVideo(v.Video, avm[v.Video.ID], cooperation)
//case TypeLive:
// ii.FromLive(v.Live, lm[v.Live.RoomID])
//case TypeMediaBangumi, TypeMediaFt:
// if bangumi, ok := bangumis[int32(v.Media.SeasonID)]; ok {
// ii.FromTagPGC(v.Media, bangumi)
// }
//case TypeTicket:
// ii.FromTicket(v.Ticket)
//case TypeProduct:
// ii.FromProduct(v.Product)
//case TypeArticle:
// ii.FromArticle(v.Article, nil)
}
if ii.Goto != "" {
item = append(item, ii)
}
}
i.Item = item
}
// FromTwitter form twitter
func (i *Item) FromTwitter(t *Twitter, details map[int64]*bplus.Detail, isUP, isCount, isNew bool) {
var (
gt, id string
)
i.Title = t.Content
i.Covers = t.Cover
i.CoverCount = t.CoverCount
i.Param = strconv.FormatInt(t.ID, 10)
i.Goto = model.GotoTwitter
if isNew {
gt = model.GotoDynamic
id = i.Param
} else {
gt = model.GotoTwitter
id = strconv.FormatInt(t.PicID, 10)
}
i.URI = model.FillURI(gt, id, nil)
if detail, ok := details[t.ID]; ok {
if isUP {
ii := &Item{
Mid: detail.Mid,
Title: detail.NickName,
Cover: detail.FaceImg,
}
i.Upper = ii
}
if isCount {
ii := &Item{
Play: detail.ViewCount,
Like: detail.LikeCount,
Reply: detail.CommentCount,
}
i.State = ii
}
}
}
// FromRcmdPre from rcmd pre.
func (i *Item) FromRcmdPre(id int64, a *api.Arc, bangumi *seasongrpc.CardInfoProto) {
if a != nil {
i.Title = a.Title
i.Cover = a.Pic
i.Author = a.Author.Name
i.Param = strconv.Itoa(int(id))
i.Goto = model.GotoAv
i.URI = model.FillURI(i.Goto, i.Param, model.AvHandler(archive.BuildArchive3(a)))
i.fillArcStat(a)
i.Desc = a.Desc
i.DurationInt = a.Duration
} else if bangumi != nil {
i.Title = bangumi.Title
i.Cover = bangumi.Cover
i.Param = strconv.Itoa(int(id))
i.Goto = model.GotoPGC
i.URI = model.FillURI(i.Goto, i.Param, nil)
i.Badge = bangumi.SeasonTypeName
i.Started = int8(bangumi.IsStarted)
i.Play = int(bangumi.Stat.View)
if bangumi.Rating != nil {
i.Rating = float64(bangumi.Rating.Score)
i.RatingCount = int(bangumi.Rating.Count)
}
i.MediaType = int(bangumi.SeasonType) // 1番剧2电影3纪录片4国漫5电视剧
if bangumi.Stat != nil {
i.Attentions = int(bangumi.Stat.Follow)
}
if bangumi.NewEp != nil {
i.Label = bangumi.NewEp.IndexShow
}
}
}
// FromStar form func
func (i *Item) FromStar(s *Star) {
var cooperation bool
i.Title = s.Title
i.Cover = s.Cover
i.Desc = s.Desc
if i.URIType == StarSpace {
i.URI = model.FillURI(model.GotoSpace, strconv.Itoa(int(s.MID)), nil)
} else if i.URIType == StarChannel {
i.URI = model.FillURI(model.GotoChannel, strconv.Itoa(int(s.TagID)), nil)
}
i.Param = strconv.Itoa(int(s.ID))
i.Goto = model.GotoStar
i.Mid = s.MID
i.TagID = s.TagID
i.TagItems = make([]*Item, 0, len(s.TagList))
for _, v := range s.TagList {
if v == nil {
continue
}
vi := &Item{}
vi.Title = v.TagName
vi.KeyWord = v.KeyWord
vi.Item = make([]*Item, 0, len(v.ValueList))
for _, vv := range v.ValueList {
if vv == nil || vv.Video == nil {
continue
}
vvi := &Item{}
vvi.FromVideo(vv.Video, nil, cooperation)
vi.Item = append(vi.Item, vvi)
}
i.TagItems = append(i.TagItems, vi)
}
}
// FromTicket from ticket
func (i *Item) FromTicket(t *Ticket) {
i.ID = t.ID
i.Param = strconv.Itoa(int(t.ID))
i.Goto = model.GotoTicket
i.Badge = "展演"
i.Title = t.Title
i.Cover = t.Cover
i.ShowTime = t.ShowTime
i.City = t.CityName
i.Venue = t.VenueName
i.Price = int(math.Ceil(float64(t.PriceLow) / 100))
i.PriceComplete = strconv.FormatFloat(float64(t.PriceLow)/100, 'f', -1, 64)
i.PriceType = t.PriceType
i.ReqNum = t.ReqNum
i.URI = t.URL
}
// FromProduct from ticket
func (i *Item) FromProduct(p *Product) {
i.ID = p.ID
i.Param = strconv.Itoa(int(p.ID))
i.Goto = model.GotoProduct
i.Badge = "商品"
i.Title = p.Title
i.Cover = p.Cover
i.ShopName = p.ShopName
i.Price = int(math.Ceil(float64(p.Price) / 100))
i.PriceComplete = strconv.FormatFloat(float64(p.Price)/100, 'f', -1, 64)
i.PriceType = p.PriceType
i.ReqNum = p.ReqNum
i.URI = p.URL
}
// FromSpecialerGuide from ticket
func (i *Item) FromSpecialerGuide(sg *SpecialerGuide) {
i.ID = sg.ID
i.Param = strconv.Itoa(int(sg.ID))
i.Goto = model.GotoSpecialerGuide
i.Title = sg.Title
i.Cover = sg.Cover
i.Desc = sg.Desc
i.Phone = sg.Tel
}
func (i *Item) FromTagPGC(m *Media, bangumi *seasongrpc.CardInfoProto) {
if m.SeasonID == 0 {
return
}
ssid := strconv.Itoa(int(m.SeasonID))
i.Title = bangumi.Title
i.Cover = bangumi.Cover
i.Param = strconv.Itoa(int(m.MediaID))
i.Goto = model.GotoPGC
i.URI = model.FillURI(i.Goto, ssid, nil)
i.Badge = bangumi.SeasonTypeName
i.Started = int8(bangumi.IsStarted)
i.Play = int(bangumi.Stat.View)
if bangumi.Rating != nil {
i.Rating = float64(bangumi.Rating.Score)
i.RatingCount = int(bangumi.Rating.Count)
}
i.MediaType = int(bangumi.SeasonType) // 1番剧2电影3纪录片4国漫5电视剧
if bangumi.Stat != nil {
i.Attentions = int(bangumi.Stat.Follow)
}
if bangumi.NewEp != nil {
i.Label = bangumi.NewEp.IndexShow
}
}
// flowTest form func
// func flowTest(buvid string) (ok bool) {
// id := crc32.ChecksumIEEE([]byte(reverseString(buvid))) % 2
// if id%2 > 0 {
// ok = true
// }
// return
// }
// reverseString form func
// func reverseString(s string) string {
// runes := []rune(s)
// for from, to := 0, len(runes)-1; from < to; from, to = from+1, to-1 {
// runes[from], runes[to] = runes[to], runes[from]
// }
// return string(runes)
// }
func FormPGCLabel(mediaType int, styles, staff, cv string) (label string) {
switch mediaType {
case 1: // 演员
label = strings.Replace(styles, "\n", "、", -1)
case 2: // 电影
label = "演员:" + strings.Replace(cv, "\n", "、", -1)
case 3: // 纪录片
label = strings.Replace(staff, "\n", "、", -1)
case 4: // 国创
label = strings.Replace(styles, "\n", "、", -1)
case 5: // 电视剧
label = "演员:" + strings.Replace(cv, "\n", "、", -1)
case 7: // 综艺
label = strings.Replace(cv, "\n", "、", -1)
case 123: // 电视剧
label = "演员:" + strings.Replace(cv, "\n", "、", -1)
case 124: // 综艺
label = strings.Replace(cv, "\n", "、", -1)
case 125: // 纪录片
label = strings.Replace(staff, "\n", "、", -1)
case 126: // 电影
label = "演员:" + strings.Replace(cv, "\n", "、", -1)
case 127: // 动漫
label = strings.Replace(styles, "\n", "、", -1)
default:
label = strings.Replace(cv, "\n", "、", -1)
}
return
}