go-common/app/interface/main/tv/model/search/wild.go
2019-04-22 18:49:16 +08:00

648 lines
19 KiB
Go
Raw 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"
"fmt"
"regexp"
"strconv"
"strings"
v1 "go-common/app/service/main/archive/api"
xtime "go-common/library/time"
)
// default .
const (
GotoBangumi = "bangumi"
GotoAv = "av"
GotoWeb = "web"
GotoMovie = "movie"
GotoBangumiWeb = "bangumi_web"
GotoSp = "sp"
GotoLive = "live"
GotoGame = "game"
GotoAuthor = "author"
GotoClip = "clip"
GotoAlbum = "album"
GotoArticle = "article"
GotoAudio = "audio"
GotoSpecial = "special"
GotoBanner = "banner"
GotoSpecialS = "special_s"
GotoConverge = "converge"
GotoPGC = "pgc"
GotoChannel = "channel"
GotoEP = "ep"
GotoTwitter = "twitter"
CoverIng = "即将上映"
CoverPay = "付费观看"
CoverFree = "免费观看"
CoverVipFree = "付费观看"
CoverVipOnly = "专享"
CoverVipFirst = "抢先"
)
// UserSearch user search request .
type UserSearch struct {
SearchType string `form:"search_type" validate:"required"`
Order string `form:"order"`
Category int `form:"category"`
Platform string `form:"platform"`
Build string `form:"build"`
MobiAPP string `form:"mobi_app"`
Device string `form:"device"`
Keyword string `form:"keyword" validate:"required"`
Page int `form:"page" validate:"required,min=1"`
Pagesize int `form:"pagesize"`
UserType int `form:"user_type"`
Highlight int `form:"highlight"`
OrderSort int `form:"order_sort"`
FromSource string `form:"from_source"`
Buvid string `form:"buvid"`
Duration int `form:"duration"` // 视频时长
// 传递参数给到dao用
SeasonNum int `form:"season_num"`
MovieNum int `form:"movie_num"`
RID int `form:"rid"`
MID int64 `form:"mid"`
}
// User struct res .
type User struct {
Type string `json:"type"`
Mid int64 `json:"mid,omitempty"`
Name string `json:"uname,omitempty"`
Usign string `json:"usign,omitempty"`
Fans int `json:"fans,omitempty"`
Videos int `json:"videos,omitempty"`
Pic string `json:"upic,omitempty"`
VerifyInfo string `json:"verify_info"`
Level int `json:"level,omitempty"`
Gender int `json:"gender"`
IsUpuser int `json:"is_upuser,omitempty"`
IsLive int `json:"is_live,omitempty"`
RoomID int64 `json:"room_id,omitempty"`
Res []*struct {
Aid int64 `json:"aid,omitempty"`
Title string `json:"title,omitempty"`
Pubdate int64 `json:"pubdate,omitempty"`
ArcURL string `json:"arcurl,omitempty"`
Pic string `json:"pic,omitempty"`
Play interface{} `json:"play,omitempty"`
Danmaku int `json:"dm,omitempty"`
Coin int `json:"coin"`
Fav int `json:"fav"`
Desc string `json:"desc"`
Duration string `json:"duration,omitempty"`
} `json:"res,omitempty"`
OfficialVerify *OfficialVerify `json:"official_verify,omitempty"`
*ResultResponse
}
// OfficialVerify struct .
type OfficialVerify struct {
Type int `json:"type"`
Desc string `json:"desc,omitempty"`
}
// Search all .
type Search struct {
Code int `json:"code,omitempty"`
Trackid string `json:"seid,omitempty"`
Page int `json:"page,omitempty"`
PageSize int `json:"pagesize,omitempty"`
Total int `json:"total,omitempty"`
NumResults int `json:"numResults,omitempty"`
NumPages int `json:"numPages,omitempty"`
SuggestKeyword string `json:"suggest_keyword,omitempty"`
Attribute int32 `json:"exp_bits,omitempty"`
PageInfo struct {
Bangumi *Page `json:"bangumi,omitempty"`
UpUser *Page `json:"upuser,omitempty"`
BiliUser *Page `json:"bili_user,omitempty"`
User *Page `json:"user,omitempty"`
Movie *Page `json:"movie,omitempty"`
Film *Page `json:"pgc,omitempty"`
MediaBangumi *Page `json:"media_bangumi,omitempty"`
MediaFt *Page `json:"media_ft,omitempty"`
} `json:"pageinfo,omitempty"`
Result struct {
Bangumi []*Bangumi `json:"bangumi,omitempty"`
UpUser []*User `json:"upuser,omitempty"`
BiliUser []*User `json:"bili_user,omitempty"`
User []*User `json:"user,omitempty"`
Movie []*Movie `json:"movie,omitempty"`
Video []*Video `json:"video,omitempty"`
MediaBangumi []*Media `json:"media_bangumi,omitempty"`
MediaFt []*Media `json:"media_ft,omitempty"`
} `json:"result,omitempty"`
}
// Media struct .
type Media struct {
MediaID int64 `json:"media_id,omitempty"`
SeasonID int64 `json:"season_id,omitempty"`
Title string `json:"title,omitempty"`
OrgTitle string `json:"org_title,omitempty"`
Styles string `json:"styles,omitempty"`
Cover string `json:"cover,omitempty"`
PlayState int `json:"play_state,omitempty"`
MediaScore *struct {
Score float64 `json:"score,omitempty"`
UserCount int `json:"user_count,omitempty"`
} `json:"media_score,omitempty"`
MediaType int `json:"media_type,omitempty"`
CV string `json:"cv,omitempty"`
Staff string `json:"staff,omitempty"`
Areas string `json:"areas,omitempty"`
GotoURL string `json:"goto_url,omitempty"`
Pubtime xtime.Time `json:"pubtime,omitempty"`
HitColumns []string `json:"hit_columns,omitempty"`
}
// Movie struct .
type Movie struct {
Title string `json:"title"`
SpID string `json:"spid"`
Type string `json:"type"`
Aid int64 `json:"aid"`
Desc string `json:"description"`
Actors string `json:"actors"`
Staff string `json:"staff"`
Cover string `json:"cover"`
Pic string `json:"pic"`
ScreenDate string `json:"screenDate"`
Area string `json:"area"`
Status int `json:"status"`
Length int `json:"length"`
Pages int `json:"numPages"`
}
// Video struct .
type Video struct {
ID int64 `json:"id"`
Author string `json:"author"`
Title string `json:"title"`
Pic string `json:"pic"`
Desc string `json:"description"`
Play interface{} `json:"play"`
Danmaku int `json:"video_review"`
Duration string `json:"duration"`
Pages int `json:"numPages"`
ViewType string `json:"view_type"`
RecTags []string `json:"rec_tags"`
}
// ResultAll struct .
type ResultAll 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"` // 混排的数据(未用到)
Attribute int32 `json:"attribute"` // 实验中开关
}
// ResultItems struct .
type ResultItems struct {
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"`
}
// 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"`
}
// 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"`
// media bangumi and mdeia ft
Prompt string `json:"prompt,omitempty"`
Episodes []*Item `json:"episodes,omitempty"`
Label string `json:"label,omitempty"`
// bangumi season
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"`
// user
Face string `json:"face,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"`
}
// Bangumi struct .
type Bangumi struct {
Name string `json:"name,omitempty"`
SeasonID int `json:"season_id,omitempty"`
Title string `json:"title,omitempty"`
Cover string `json:"cover,omitempty"`
Evaluate string `json:"evaluate,omitempty"`
NewestEpID int `json:"newest_ep_id,omitempty"`
NewestEpIndex string `json:"newest_ep_index,omitempty"`
IsFinish int `json:"is_finish,omitempty"`
IsStarted int `json:"is_started,omitempty"`
NewestCat string `json:"newest_cat,omitempty"`
NewestSeason string `json:"newest_season,omitempty"`
TotalCount int `json:"total_count,omitempty"`
Pages int `json:"numPages,omitempty"`
CatList *struct {
TV int `json:"tv"`
Movie int `json:"movie"`
Ova int `json:"ova"`
} `json:"catlist,omitempty"`
}
// TypeSearch struct .
type TypeSearch struct {
TrackID string `json:"trackid"`
Pages int `json:"pages"`
Total int `json:"total"`
Items []*Item `json:"items,omitempty"`
}
// Card for bangumi .
type Card struct {
SeasonID int64 `json:"season_id"`
IsFollow int `json:"is_follow"`
IsSelection int `json:"is_selection"`
Badge string `json:"badge"`
BadgeType int `json:"badge_type"`
Episodes []*Episode `json:"episodes"`
}
// Episode for bangumi card .
type Episode struct {
ID int64 `json:"id"`
Badge string `json:"badge"`
BadgeType int `json:"badge_type"`
Status int `json:"status"`
Cover string `json:"cover"`
Index string `json:"index"`
IndexTitle string `json:"index_title"`
}
// StatusMark cover status mark .
func StatusMark(status int) string {
if status == 0 {
return CoverIng
} else if status == 1 {
return CoverPay
} else if status == 2 {
return CoverFree
} else if status == 3 {
return CoverVipFree
} else if status == 4 {
return CoverVipOnly
} else if status == 5 {
return CoverVipFirst
}
return ""
}
// FillURI deal app schema .
func FillURI(gt, param string, f func(uri string) string) (uri string) {
switch gt {
case GotoAv, "":
uri = "bilibili://video/" + param
case GotoLive:
uri = "bilibili://live/" + param
case GotoBangumi:
uri = "bilibili://bangumi/season/" + param
case GotoBangumiWeb:
uri = "http://bangumi.bilibili.com/anime/" + param
case GotoGame:
uri = "bilibili://game_center/detail?id=" + param + "&sourceType=adPut"
case GotoSp:
uri = "bilibili://splist/" + param
case GotoAuthor:
uri = "bilibili://author/" + param
case GotoClip:
uri = "bilibili://clip/" + param
case GotoAlbum:
uri = "bilibili://album/" + param
case GotoArticle:
uri = "bilibili://article/" + param
case GotoWeb:
uri = param
case GotoPGC:
uri = "https://www.bilibili.com/bangumi/play/ss" + param
case GotoChannel:
uri = "bilibili://pegasus/channel/" + param + "/"
case GotoEP:
uri = "https://www.bilibili.com/bangumi/play/ep" + param
case GotoTwitter:
uri = "bilibili://pictureshow/detail/" + param
}
if f != nil {
uri = f(uri)
}
return
}
// search const
var getHightLight = regexp.MustCompile(`<em.*?em>`)
var (
// AvHandler .
AvHandler = func(a *v1.Arc) func(uri string) string {
return func(uri string) string {
if a == nil {
return uri
}
if a.Dimension.Height != 0 || a.Dimension.Width != 0 {
return fmt.Sprintf("%s?player_width=%d&player_height=%d&player_rotate=%d", uri, a.Dimension.Width, a.Dimension.Height, a.Dimension.Rotate)
}
return uri
}
}
)
// FromSeason .
func (i *Item) FromSeason(b *Bangumi, bangumi string) {
i.Title = b.Title
i.Cover = b.Cover
i.Goto = GotoBangumi
i.Param = strconv.Itoa(int(b.SeasonID))
i.URI = 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]*v1.Arc) {
i.Title = u.Name
i.Cover = u.Pic
i.Goto = GotoAuthor
i.OfficialVerify = u.OfficialVerify
i.Param = strconv.Itoa(int(u.Mid))
i.URI = FillURI(i.Goto, i.Param, nil)
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 = GotoAv
vi.Param = strconv.Itoa(int(v.Aid))
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)
}
}
// FromUser form func .
func (i *Item) FromUser(u *User, as map[int64]*v1.Arc) {
i.Title = u.Name
i.Cover = u.Pic
i.Goto = GotoAuthor
i.OfficialVerify = u.OfficialVerify
i.Param = strconv.Itoa(int(u.Mid))
i.URI = FillURI(i.Goto, i.Param, nil)
i.Sign = u.Usign
i.Fans = u.Fans
i.Level = u.Level
i.Arcs = u.Videos
i.AvItems = make([]*Item, 0, len(u.Res))
if u.IsUpuser == 1 {
for _, v := range u.Res {
vi := &Item{}
vi.Title = v.Title
vi.Cover = v.Pic
vi.Goto = GotoAv
vi.Param = strconv.Itoa(int(v.Aid))
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
}
}
// FromMovie form func .
func (i *Item) FromMovie(m *Movie, as map[int64]*v1.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 = GotoAv
i.URI = FillURI(i.Goto, i.Param, AvHandler(as[m.Aid]))
i.CoverMark = StatusMark(m.Status)
} else if m.Type == "special" {
i.Param = m.SpID
i.Goto = GotoSp
i.URI = 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 *v1.Arc) {
i.Title = v.Title
i.Cover = v.Pic
i.Author = v.Author
i.Param = strconv.Itoa(int(v.ID))
i.Goto = GotoAv
if a != nil {
i.Face = a.Author.Face
i.URI = FillURI(i.Goto, i.Param, AvHandler(a))
i.Play = int(a.Stat.View)
i.Danmaku = int(a.Stat.Danmaku)
} else {
i.URI = 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
}
// FromMedia form func .
func (i *Item) FromMedia(m *Media, prompt string, gt string, bangumis map[string]*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.SeasonID))
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 == GotoBangumi {
i.Label = fmt.Sprintf("声优: %v...", v[0])
break
} else if gt == 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 .
ssID := strconv.Itoa(int(m.SeasonID))
if bgm, ok := bangumis[ssID]; ok {
for _, v := range bgm.Episodes {
tmp := &Item{
Param: strconv.Itoa(int(v.ID)),
Index: v.Index,
BadgeType: v.BadgeType,
}
tmp.URI = FillURI(GotoEP, tmp.Param, nil)
i.Episodes = append(i.Episodes, tmp)
}
}
}