1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213 |
- package feed
- import (
- "encoding/json"
- "strconv"
- "strings"
- cdm "go-common/app/interface/main/app-card/model"
- "go-common/app/interface/main/app-card/model/card/ai"
- "go-common/app/interface/main/app-card/model/card/audio"
- "go-common/app/interface/main/app-card/model/card/bangumi"
- "go-common/app/interface/main/app-card/model/card/banner"
- "go-common/app/interface/main/app-card/model/card/cm"
- "go-common/app/interface/main/app-card/model/card/live"
- "go-common/app/interface/main/app-card/model/card/operate"
- "go-common/app/interface/main/app-card/model/card/rank"
- "go-common/app/interface/main/app-card/model/card/show"
- "go-common/app/interface/main/app-feed/model"
- "go-common/app/interface/main/app-feed/model/dislike"
- livemdl "go-common/app/interface/main/app-feed/model/live"
- bustag "go-common/app/interface/main/tag/model"
- tag "go-common/app/interface/main/tag/model"
- article "go-common/app/interface/openplatform/article/model"
- account "go-common/app/service/main/account/model"
- "go-common/app/service/main/archive/model/archive"
- feed "go-common/app/service/main/feed/model"
- relation "go-common/app/service/main/relation/model"
- episodegrpc "go-common/app/service/openplatform/pgc-season/api/grpc/episode/v1"
- xtime "go-common/library/time"
- )
- const (
- _rankTitle = "全站排行榜"
- _rankURI = "http://www.bilibili.com/index/rank/all-03.json"
- _rankCount = 3
- _convergeMinCount = 2
- _bangumiRcmdUpdates = 99
- )
- // Item is feed item, contains av, bangumi, live, banner, feed...
- type Item struct {
- Title string `json:"title,omitempty"`
- Subtitle string `json:"subtitle,omitempty"`
- Cover string `json:"cover,omitempty"`
- URI string `json:"uri,omitempty"`
- Redirect string `json:"redirect,omitempty"`
- Param string `json:"param,omitempty"`
- Goto string `json:"goto,omitempty"`
- Desc string `json:"desc,omitempty"`
- Play int `json:"play,omitempty"`
- Danmaku int `json:"danmaku,omitempty"`
- Reply int `json:"reply,omitempty"`
- Fav int `json:"favorite,omitempty"`
- Coin int `json:"coin,omitempty"`
- Share int `json:"share,omitempty"`
- Like int `json:"like,omitempty"`
- Dislike int `json:"dislike,omitempty"`
- Duration int64 `json:"duration,omitempty"`
- Count int `json:"count,omitempty"`
- Status int8 `json:"status,omitempty"`
- Type int8 `json:"type,omitempty"`
- Badge string `json:"badge,omitempty"`
- StatType int8 `json:"stat_type,omitempty"`
- RcmdReason *RcmdReason `json:"rcmd_reason,omitempty"`
- Item []*Item `json:"item,omitempty"`
- // sortedset index
- Idx int64 `json:"idx,omitempty"`
- // av
- Cid int64 `json:"cid,omitempty"`
- Rid int32 `json:"tid,omitempty"`
- TName string `json:"tname,omitempty"`
- Tag *Tag `json:"tag,omitempty"`
- Button *Button `json:"button,omitempty"`
- DisklikeReasons []*dislike.DisklikeReason `json:"dislike_reasons,omitempty"`
- CTime xtime.Time `json:"ctime,omitempty"`
- Autoplay int32 `json:"autoplay,omitempty"`
- // upper
- Mid int64 `json:"mid,omitempty"`
- Name string `json:"name,omitempty"`
- Face string `json:"face,omitempty"`
- IsAtten int8 `json:"is_atten,omitempty"`
- Fans int64 `json:"fans,omitempty"`
- RecCnt int `json:"recent_count,omitempty"`
- Recent []*Item `json:"recent,omitempty"`
- Official *OfficialInfo `json:"official,omitempty"`
- // live
- Online int `json:"online,omitempty"`
- Area string `json:"area,omitempty"`
- AreaID int `json:"area_id,omitempty"`
- Area2 *Area2 `json:"area2,omitempty"`
- // bangumi
- Index string `json:"index,omitempty"`
- IndexTitle string `json:"index_title,omitempty"`
- CoverMark string `json:"cover_mark,omitempty"`
- Finish bool `json:"finish,omitempty"`
- LatestIndex string `json:"last_index,omitempty"`
- // bangumi ai
- Updates int `json:"updates,omitempty"`
- // live or bangumi
- From int8 `json:"from,omitempty"`
- // adviertisement
- RequestID string `json:"request_id,omitempty"`
- CreativeID int64 `json:"creative_id,omitempty"`
- SrcID int `json:"src_id,omitempty"`
- IsAd bool `json:"is_ad,omitempty"`
- IsAdLoc bool `json:"is_ad_loc,omitempty"`
- AdCb string `json:"ad_cb,omitempty"`
- ShowURL string `json:"show_url,omitempty"`
- ClickURL string `json:"click_url,omitempty"`
- ClientIP string `json:"client_ip,omitempty"`
- CmMark int64 `json:"cm_mark,omitempty"`
- AdIndex int `json:"ad_index,omitempty"`
- Extra json.RawMessage `json:"extra,omitempty"`
- CardIndex int `json:"card_index,omitempty"`
- // tag
- Tags []*tag.Tag `json:"tags,omitempty"`
- // rank
- Cover1 string `json:"cover1,omitempty"`
- Cover2 string `json:"cover2,omitempty"`
- Cover3 string `json:"cover3,omitempty"`
- // banner
- BannerItem []*banner.Banner `json:"banner_item,omitempty"`
- Hash string `json:"hash,omitempty"`
- // article
- Covers []string `json:"covers,omitempty"`
- Template int `json:"template,omitempty"`
- Temple int `json:"temple,omitempty"`
- Category *Category `json:"category,omitempty"`
- BannerURL string `json:"banner_url,omitempty"`
- // game download
- Download int32 `json:"download,omitempty"`
- BigCover string `json:"big_cover,omitempty"`
- // special
- HideBadge bool `json:"hide_badge,omitempty"`
- Ratio float64 `json:"ratio,omitempty"`
- // shopping
- City string `json:"city,omitempty"`
- PType string `json:"ptype,omitempty"`
- Price string `json:"price,omitempty"`
- Square string `json:"square,omitempty"`
- STime string `json:"stime,omitempty"`
- ETime string `json:"etime,omitempty"`
- // news
- Content string `json:"content,omitempty"`
- // subscribe
- Kind string `json:"kind,omitempty"`
- // audio
- SongTitle string `json:"song_title,omitempty"`
- // bigdata source
- Source string `json:"-"`
- AvFeature json.RawMessage `json:"-"`
- // common
- GotoOrg string `json:"-"`
- // rank score
- Score string `json:"score,omitempty"`
- // ai recommend
- AI *ai.Item `json:"-"`
- // abtest
- AutoplayCard int `json:"autoplay_card,omitempty"`
- }
- type Dimension struct {
- Width int64 `json:"width,omitempty"`
- Height int64 `json:"height,omitempty"`
- Rotate int64 `json:"rotate,omitempty"`
- }
- type Button struct {
- Name string `json:"name,omitempty"`
- URI string `json:"uri,omitempty"`
- RedirectURI string `json:"redirect_uri,omitempty"`
- }
- type RcmdReason struct {
- ID int `json:"id,omitempty"`
- Content string `json:"content,omitempty"`
- BgColor string `json:"bg_color,omitempty"`
- IconLocation string `json:"icon_location,omitempty"`
- Message string `json:"message,omitempty"`
- }
- type Category struct {
- ID int64 `json:"id,omitempty"`
- Name string `json:"name,omitempty"`
- Children *Category `json:"children,omitempty"`
- }
- type Area2 struct {
- ID int64 `json:"id,omitempty"`
- Name string `json:"name,omitempty"`
- Children *Area2 `json:"children,omitempty"`
- }
- type Tag struct {
- // new
- ID int64 `json:"id,omitempty"`
- Name string `json:"name,omitempty"`
- Face string `json:"face,omitempty"`
- Fans int `json:"fans,omitempty"`
- IsAtten int8 `json:"is_atten,omitempty"`
- URI string `json:"uri,omitempty"`
- // old
- TagID int64 `json:"tag_id,omitempty"`
- TagName string `json:"tag_name,omitempty"`
- Count *TagCount `json:"count,omitempty"`
- }
- type TagCount struct {
- Atten int `json:"atten,omitempty"`
- }
- type OfficialInfo struct {
- Role int8 `json:"role,omitempty"`
- Title string `json:"title,omitempty"`
- Desc string `json:"desc,omitempty"`
- }
- type IndexParam struct {
- Build int `form:"build"`
- Platform string `form:"platform"`
- MobiApp string `form:"mobi_app"`
- Device string `form:"device"`
- Network string `form:"network"`
- // idx, err := strconv.ParseInt(idxStr, 10, 64)
- // if err != nil || idx < 0 {
- // idx = 0
- // }
- Idx int64 `form:"idx" default:"0"`
- // pull, err := strconv.ParseBool(pullStr)
- // if err != nil {
- // pull = true
- // }
- Pull bool `form:"pull" default:"true"`
- Column cdm.ColumnStatus `form:"column"`
- // loginEvent, err := strconv.Atoi(loginEventStr)
- // if err != nil {
- // loginEvent = 0
- // }
- LoginEvent int `form:"login_event" default:"0"`
- OpenEvent string `form:"open_event"`
- BannerHash string `form:"banner_hash"`
- AdExtra string `form:"ad_extra"`
- Qn int `form:"qn" default:"0"`
- Interest string `form:"interest"`
- Flush int `form:"flush"`
- AutoPlayCard int `form:"autoplay_card"`
- Fnver int `form:"fnver" default:"0"`
- Fnval int `form:"fnval" default:"0"`
- DeviceType int `form:"device_type"`
- ParentMode int `form:"parent_mode"`
- ForceHost int `form:"force_host"`
- RecsysMode int `form:"recsys_mode"`
- }
- type ConvergeParam struct {
- ID int64 `form:"id" validate:"required,min=1"`
- MobiApp string `form:"mobi_app"`
- Device string `form:"device"`
- Build int `form:"build"`
- Qn int `form:"qn" default:"0"`
- Fnver int `form:"fnver" default:"0"`
- Fnval int `form:"fnval" default:"0"`
- ForceHost int `form:"force_host"`
- }
- func (i *Item) FromRcmd(r *ai.Item) {
- i.Title = r.Name
- i.Param = strconv.FormatInt(r.ID, 10)
- if r.Goto == "" {
- r.Goto = model.GotoAv
- }
- i.From = r.From
- i.Source = r.Source
- i.AvFeature = r.AvFeature
- if r.Config != nil {
- i.Title = r.Config.Title
- i.Cover = r.Config.Cover
- i.URI = r.Config.URI
- }
- i.StatType = r.StatType
- i.GotoOrg = r.Goto
- }
- type Infoc struct {
- UserFeature json.RawMessage
- IsRcmd bool
- NewUser bool
- Code int
- AutoPlayInfoc string
- }
- type Config struct {
- Column cdm.ColumnStatus `json:"column"`
- AutoplayCard int8 `json:"autoplay_card"`
- FeedCleanAbtest int8 `json:"feed_clean_abtest"`
- FollowMode *FollowMode `json:"follow_mode,omitempty"`
- }
- type FollowMode struct {
- Title string `json:"title,omitempty"`
- Option []*Option `json:"option,omitempty"`
- Card *Card `json:"-"`
- ToastMessage string `json:"toast_message,omitempty"`
- }
- type Option struct {
- Title string `json:"title,omitempty"`
- Desc string `json:"desc,omitempty"`
- Value int8 `json:"value"`
- }
- type Card struct {
- Title string `json:"-"`
- Desc string `json:"-"`
- Button []string `json:"-"`
- }
- func (i *Item) FromAv(a *archive.ArchiveWithPlayer) {
- if i.Title == "" {
- i.Title = a.Title
- }
- if i.Cover == "" {
- i.Cover = model.CoverURLHTTPS(a.Pic)
- } else {
- i.Cover = model.CoverURLHTTPS(i.Cover)
- }
- i.Param = strconv.FormatInt(a.Aid, 10)
- i.Goto = model.GotoAv
- i.URI = model.FillURI(i.Goto, i.Param, 0, 0, model.AvPlayHandler(a.Archive3, a.PlayerInfo))
- i.Cid = a.FirstCid
- i.Rid = a.TypeID
- i.TName = a.TypeName
- i.Desc = strconv.Itoa(int(a.Stat.Danmaku)) + "弹幕"
- i.fillArcStat(a.Archive3)
- i.Duration = a.Duration
- i.Mid = a.Author.Mid
- i.Name = a.Author.Name
- i.Face = a.Author.Face
- i.CTime = a.PubDate
- i.Autoplay = a.Rights.Autoplay
- }
- func (i *Item) FromLive(r *live.Room) {
- if r.LiveStatus != 1 || r.Title == "" || r.Cover == "" {
- return
- }
- i.Title = r.Title
- i.Cover = r.Cover
- i.Goto = model.GotoLive
- i.Param = strconv.FormatInt(r.RoomID, 10)
- i.URI = model.FillURI(i.Goto, i.Param, 0, 0, model.LiveRoomHandler(r))
- i.Name = r.Uname
- i.Mid = r.UID
- i.Face = r.Face
- i.Online = int(r.Online)
- i.Autoplay = 1
- // i.Area = r.Area
- // i.AreaID = r.AreaID
- i.Area2 = &Area2{ID: r.AreaV2ParentID, Name: r.AreaV2ParentName, Children: &Area2{ID: r.AreaV2ID, Name: r.AreaV2Name}}
- i.Autoplay = 1
- }
- func (i *Item) FromSeason(b *bangumi.Season) {
- if i.Title == "" {
- i.Title = b.Title
- }
- if i.Cover == "" {
- i.Cover = b.Cover
- }
- i.Goto = model.GotoBangumi
- i.Param = b.EpisodeID
- i.URI = model.FillURI(i.Goto, i.Param, 0, 0, nil)
- i.Play = int(b.PlayCount)
- i.Fav = int(b.Favorites)
- i.Type = b.SeasonType
- i.Badge = b.TypeBadge
- i.Desc = b.UpdateDesc
- i.Face = b.SeasonCover
- i.Square = b.SeasonCover
- }
- func (i *Item) FromPGCSeason(s *episodegrpc.EpisodeCardsProto) {
- if i.Title == "" {
- i.Title = s.Season.Title
- }
- if i.Cover == "" {
- i.Cover = s.Cover
- }
- i.Goto = model.GotoBangumi
- i.Param = strconv.Itoa(int(s.EpisodeId))
- i.URI = model.FillURI(model.GotoBangumi, i.Param, 0, 0, nil)
- i.Index = s.Title
- i.IndexTitle = s.LongTitle
- i.Status = int8(s.Season.SeasonStatus)
- i.CoverMark = s.Season.Badge
- i.Play = int(s.Season.Stat.View)
- i.Fav = int(s.Season.Stat.Follow)
- i.Type = int8(s.Season.SeasonType)
- i.Badge = s.Season.SeasonTypeName
- if s.Season.IsFinish == 1 {
- i.Finish = true
- }
- i.Count = int(s.Season.TotalCount)
- i.LatestIndex = s.Title
- i.Desc = s.Season.NewEpShow
- i.Face = s.Season.Cover
- i.Square = s.Season.Cover
- }
- func (i *Item) FromLogin() {
- if i.Param == "0" {
- i.Param = "1"
- }
- i.Goto = model.GotoLogin
- }
- func (i *Item) FromAdAv(adInfo *cm.AdInfo, a *archive.ArchiveWithPlayer) {
- // ad
- i.RequestID = adInfo.RequestID
- i.CreativeID = adInfo.CreativeID
- i.SrcID = adInfo.Source
- i.IsAdLoc = adInfo.IsAdLoc
- i.IsAd = adInfo.IsAd
- i.AdCb = adInfo.AdCb
- i.CmMark = adInfo.CmMark
- i.AdIndex = adInfo.Index
- c := adInfo.CreativeContent
- i.Title = c.Title
- i.Desc = c.Desc
- i.Cover = c.ImageURL
- i.Goto = model.GotoAdAv
- i.Name = a.Author.Name
- i.Face = c.LogURL
- i.ShowURL = c.ShowURL
- i.ClickURL = c.ClickURL
- // archive
- i.Param = strconv.FormatInt(a.Aid, 10)
- i.URI = model.FillURI(i.Goto, i.Param, 0, 0, model.AvPlayHandler(a.Archive3, a.PlayerInfo))
- if a.TypeName != "广告" {
- i.TName = a.TypeName
- }
- i.fillArcStat(a.Archive3)
- i.Duration = a.Duration
- i.Mid = a.Author.Mid
- if i.Name == "" {
- i.Name = a.Author.Name
- }
- if i.Face == "" {
- i.Face = a.Author.Face
- }
- i.CTime = a.Ctime
- i.Extra = adInfo.Extra
- i.CardIndex = adInfo.CardIndex
- }
- func (i *Item) FromAdWeb(adInfo *cm.AdInfo) {
- i.RequestID = adInfo.RequestID
- i.CreativeID = adInfo.CreativeID
- i.SrcID = adInfo.Source
- i.IsAdLoc = adInfo.IsAdLoc
- i.IsAd = adInfo.IsAd
- i.AdCb = adInfo.AdCb
- i.CmMark = adInfo.CmMark
- i.AdIndex = adInfo.Index
- c := adInfo.CreativeContent
- i.Title = c.Title
- i.Desc = c.Desc
- i.Cover = c.ImageURL
- i.Goto = model.GotoAdWeb
- i.URI = model.FillURI(i.Goto, c.URL, 0, 0, nil)
- i.ShowURL = c.ShowURL
- i.ClickURL = c.ClickURL
- i.Extra = adInfo.Extra
- i.CardIndex = adInfo.CardIndex
- }
- func (i *Item) FromAdLarge(adInfo *cm.AdInfo) {
- i.RequestID = adInfo.RequestID
- i.CreativeID = adInfo.CreativeID
- i.SrcID = adInfo.Source
- i.IsAdLoc = adInfo.IsAdLoc
- i.IsAd = adInfo.IsAd
- i.AdCb = adInfo.AdCb
- i.CmMark = adInfo.CmMark
- i.AdIndex = adInfo.Index
- c := adInfo.CreativeContent
- i.Title = c.Title
- i.Desc = c.Desc
- i.Goto = model.GotoAdLarge
- i.URI = model.FillURI(i.Goto, c.URL, 0, 0, nil)
- i.ShowURL = c.ShowURL
- i.ClickURL = c.ClickURL
- i.Extra = adInfo.Extra
- i.CardIndex = adInfo.CardIndex
- }
- func (i *Item) FromAdWebS(adInfo *cm.AdInfo) {
- i.RequestID = adInfo.RequestID
- i.CreativeID = adInfo.CreativeID
- i.SrcID = adInfo.Source
- i.IsAdLoc = adInfo.IsAdLoc
- i.IsAd = adInfo.IsAd
- i.AdCb = adInfo.AdCb
- i.CmMark = adInfo.CmMark
- i.AdIndex = adInfo.Index
- c := adInfo.CreativeContent
- i.Title = c.Title
- i.Desc = c.Desc
- i.Cover = c.ImageURL
- i.Goto = model.GotoAdWebS
- i.URI = model.FillURI(i.Goto, c.URL, 0, 0, nil)
- i.ShowURL = c.ShowURL
- i.ClickURL = c.ClickURL
- i.Extra = adInfo.Extra
- i.CardIndex = adInfo.CardIndex
- }
- func (i *Item) FromSpecial(id int64, title, cover, desc, url string, typ int, badge string, size string) {
- if title == "" || cover == "" {
- return
- }
- i.Title = title
- i.Cover = cover
- i.Goto = model.GotoSpecial
- i.URI = model.FillURI(model.OperateType[typ], url, 0, 0, nil)
- i.Redirect = model.FillRedirect(i.Goto, typ)
- i.Desc = desc
- i.Param = strconv.FormatInt(id, 10)
- i.HideBadge = true
- i.Badge = badge
- var ratio float64
- if size == "1020x300" {
- ratio = 34
- } else if size == "1020x378" {
- ratio = 27
- }
- i.Ratio = ratio
- }
- func (i *Item) FromSpecialS(id int64, title, cover, square, desc, url string, typ int, badge string) {
- if title == "" || cover == "" {
- return
- }
- i.Title = title
- i.Cover = cover
- // 活不过一个版的单列封面
- if square != "" {
- i.Square = square
- } else {
- i.Square = cover
- }
- i.Goto = model.GotoSpecialS
- i.URI = model.FillURI(model.OperateType[typ], url, 0, 0, nil)
- i.Redirect = model.FillRedirect(i.Goto, typ)
- i.Desc = desc
- i.Param = strconv.FormatInt(id, 10)
- i.Badge = badge
- }
- func (i *Item) FromRank(ranks []*rank.Rank, am map[int64]*archive.ArchiveWithPlayer) {
- if len(ranks) < _rankCount {
- return
- }
- if a, ok := am[ranks[0].Aid]; ok {
- i.Cover1 = a.Pic
- } else {
- return
- }
- if a, ok := am[ranks[1].Aid]; ok {
- i.Cover2 = a.Pic
- } else {
- return
- }
- if a, ok := am[ranks[2].Aid]; ok {
- i.Cover3 = a.Pic
- } else {
- return
- }
- ris := make([]*Item, 0, _rankCount)
- for _, rank := range ranks[:_rankCount] {
- if a, ok := am[rank.Aid]; ok {
- ri := &Item{
- Title: a.Title,
- Cover: a.Pic,
- Goto: model.GotoAv,
- Param: strconv.FormatInt(a.Aid, 10),
- }
- ri.fillArcStat(a.Archive3)
- ri.Duration = a.Duration
- ri.URI = model.FillURI(ri.Goto, ri.Param, 0, 0, model.AvPlayHandler(a.Archive3, a.PlayerInfo))
- score := int64(rank.Score)
- if score < 10000 {
- ri.Score = model.Rounding(score, 0)
- } else if score >= 10000 && score < 100000000 {
- ri.Score = model.Rounding(score, 10000) + "万"
- } else if score >= 100000000 {
- ri.Score = model.Rounding(score, 100000000) + "亿"
- }
- if ri.Score != "" {
- ri.Score = "综合评分:" + ri.Score
- } else {
- ri.Score = "综合评分:-"
- }
- ris = append(ris, ri)
- } else {
- return
- }
- }
- i.Title = _rankTitle
- i.Goto = model.GotoRank
- i.Item = ris
- i.Param = "0"
- i.URI = model.FillURI(i.Goto, _rankURI, 0, 0, nil)
- }
- func (i *Item) FromBangumiRcmd(u *bangumi.Update) {
- i.Cover = u.SquareCover
- i.Goto = model.GotoBangumiRcmd
- i.Desc = u.Title
- if u.Updates > _bangumiRcmdUpdates {
- i.Updates = _bangumiRcmdUpdates
- } else {
- i.Updates = u.Updates
- }
- }
- func (i *Item) FromBanner(bs []*banner.Banner, hash string) {
- i.Goto = model.GotoBanner
- i.Hash = hash
- i.BannerItem = bs
- }
- func (i *Item) FromPlayer(a *archive.ArchiveWithPlayer) {
- if a.Archive3 == nil || !a.IsNormal() {
- return
- }
- title := i.Title
- if title == "" {
- title = a.Title
- }
- cover := i.Cover
- if cover == "" {
- cover = a.Pic
- }
- item := &Item{Title: title, Cover: cover, Param: strconv.FormatInt(a.Aid, 10), Goto: model.GotoAv}
- item.URI = model.FillURI(item.Goto, item.Param, 0, 0, model.AvPlayHandler(a.Archive3, a.PlayerInfo))
- item.fillArcStat(a.Archive3)
- i.Item = []*Item{item}
- i.Cid = a.FirstCid
- i.Rid = a.TypeID
- i.TName = a.TypeName
- i.Mid = a.Author.Mid
- i.Goto = model.GotoPlayer
- i.Name = a.Author.Name
- i.Face = a.Author.Face
- i.Duration = a.Duration
- i.Autoplay = a.Rights.Autoplay
- }
- func (i *Item) FromPlayerLive(r *live.Room) {
- if r.LiveStatus != 1 || r.Title == "" || r.Cover == "" {
- return
- }
- i.Name = r.Uname
- i.Mid = r.UID
- i.Face = r.Face
- item := &Item{Title: r.Title, Cover: r.Cover, Param: strconv.FormatInt(r.RoomID, 10), Goto: model.GotoLive}
- item.URI = model.FillURI(item.Goto, item.Param, 0, 0, model.LiveRoomHandler(r))
- item.Online = int(r.Online)
- item.Area2 = &Area2{ID: r.AreaV2ParentID, Name: r.AreaV2ParentName, Children: &Area2{ID: r.AreaV2ID, Name: r.AreaV2Name}}
- i.Item = []*Item{item}
- i.Goto = model.GotoPlayer
- i.Autoplay = 1
- }
- func (i *Item) FromRcmdReason(r *ai.RcmdReason) {
- if r != nil {
- if r.Style != 0 {
- i.RcmdReason = &RcmdReason{ID: r.Style, Content: r.Content, BgColor: r.Grounding, IconLocation: r.Position}
- if r.Style == 3 {
- i.RcmdReason.Message = i.Name
- }
- } else {
- i.RcmdReason = &RcmdReason{ID: r.ID, Content: r.Content}
- }
- }
- }
- func (i *Item) FromGameDownloadS(d *operate.Download, plat int8, build int) {
- i.Title = d.Title
- i.Cover = d.DoubleCover
- i.BigCover = d.Cover
- i.Goto = model.GotoGameDownloadS
- i.Desc = d.Desc
- // TODO fuck game
- i.URI = model.FillURI(model.OperateType[d.URLType], d.URLValue, plat, build, nil)
- i.Redirect = model.FillRedirect(i.Goto, d.URLType)
- i.Face = d.Icon
- i.Param = strconv.FormatInt(d.ID, 10)
- i.Download = d.Number
- if d.Icon != "" {
- i.Square = d.Icon
- } else {
- i.Square = d.Cover
- }
- }
- func (i *Item) FromShoppingS(c *show.Shopping) {
- if c.Name == "" || c.URL == "" {
- return
- }
- i.Title = c.Name
- i.STime = c.STime
- i.ETime = c.ETime
- i.City = c.CityName
- if len(c.Tags) != 0 {
- i.PType = c.Tags[0].TagName
- }
- i.Param = strconv.FormatInt(c.ID, 10)
- // 双列封面
- if strings.HasPrefix(c.PerformanceImage, "http:") || strings.HasPrefix(c.PerformanceImage, "https:") {
- i.Cover = c.PerformanceImage
- } else {
- i.Cover = "http:" + c.PerformanceImage
- }
- // 单列封面
- if strings.HasPrefix(c.PerformanceImageP, "http:") || strings.HasPrefix(c.PerformanceImageP, "https:") {
- i.Square = c.PerformanceImageP
- } else {
- i.Square = "http:" + c.PerformanceImageP
- }
- if i.Cover == "" {
- i.Cover = i.Square
- }
- if i.Cover == "" {
- return
- }
- i.Goto = model.GotoShoppingS
- i.URI = model.FillURI(i.Goto, c.URL, 0, 0, nil)
- i.Type = c.Type
- i.Subtitle = c.Subname
- // 漫展需加羊角符
- if i.Type == 1 {
- i.Price = "¥" + c.Pricelt
- } else {
- i.Price = c.Pricelt
- }
- i.Desc = c.Want
- }
- func (i *Item) FromAudio(a *audio.Audio) {
- i.Title = a.Title
- i.Cover = a.CoverURL
- i.Param = strconv.FormatInt(a.MenuID, 10)
- i.Goto = model.GotoAudio
- i.URI = model.FillURI(i.Goto, i.Param, 0, 0, model.AudioHandler)
- i.Play = int(a.PlayNum)
- i.Count = a.RecordNum
- i.Fav = int(a.FavoriteNum)
- i.Face = a.Face
- // old
- titles := make([]string, 0, len(a.Songs))
- for index, song := range a.Songs {
- if song != nil || song.Title != "" {
- titles = append(titles, song.Title)
- if index == 0 {
- i.SongTitle = song.Title
- }
- }
- }
- i.Desc = strings.Join(titles, ",")
- // new
- for _, ctg := range a.Ctgs {
- tag := &tag.Tag{ID: ctg.ItemID, Name: ctg.ItemVal}
- i.Tags = append(i.Tags, tag)
- if len(i.Tags) == 2 {
- break
- }
- }
- // new
- if len(a.Ctgs) != 0 {
- id := a.Ctgs[0].ItemID
- name := a.Ctgs[0].ItemVal
- if len(a.Ctgs) > 1 {
- id = a.Ctgs[1].ItemID
- name += "·" + a.Ctgs[1].ItemVal
- }
- i.Tag = &Tag{Name: name, URI: model.FillURI(model.GotoAudioTag, strconv.FormatInt(id, 10), 0, 0, model.AudioHandler)}
- }
- if a.Type == 5 {
- i.Badge = "专辑"
- i.Type = 2
- } else {
- i.Badge = "歌单"
- i.Type = 1
- }
- i.CTime = xtime.Time(a.PaTime)
- }
- func (i *Item) FromConverge(c *operate.Converge, am map[int64]*archive.ArchiveWithPlayer, rm map[int64]*live.Room, artm map[int64]*article.Meta) {
- if len(c.Items) < _convergeMinCount {
- return
- }
- cis := make([]*Item, 0, len(c.Items))
- for _, content := range c.Items {
- ci := &Item{Title: content.Title}
- switch content.Goto {
- case model.GotoAv:
- if a, ok := am[content.Pid]; ok && a.Archive3 != nil && a.IsNormal() {
- if ci.Title == "" {
- 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, 0, 0, model.AvPlayHandler(a.Archive3, a.PlayerInfo))
- ci.fillArcStat(a.Archive3)
- ci.Duration = a.Duration
- cis = append(cis, ci)
- }
- case model.GotoLive:
- if r, ok := rm[content.Pid]; ok {
- if r.LiveStatus == 0 || r.Title == "" || r.Cover == "" {
- continue
- }
- if ci.Title == "" {
- ci.Title = r.Title
- }
- ci.Cover = r.Cover
- ci.Goto = model.GotoLive
- ci.Param = strconv.FormatInt(r.RoomID, 10)
- ci.Online = int(r.Online)
- ci.URI = model.FillURI(ci.Goto, ci.Param, 0, 0, model.LiveRoomHandler(r))
- ci.Badge = "直播"
- cis = append(cis, ci)
- }
- case model.GotoArticle:
- if art, ok := artm[content.Pid]; 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, 0, 0, nil)
- if art.Stats != nil {
- ci.fillArtStat(art)
- }
- ci.Badge = "文章"
- cis = append(cis, ci)
- }
- }
- }
- if len(cis) < _convergeMinCount {
- return
- }
- i.Item = cis
- i.Goto = model.GotoConverge
- i.URI = model.FillURI(model.OperateType[c.ReType], c.ReValue, 0, 0, nil)
- i.Redirect = model.FillRedirect(i.Goto, c.ReType)
- i.Title = c.Title
- i.Cover = c.Cover
- i.Param = strconv.FormatInt(c.ID, 10)
- }
- func (i *Item) FromUpBangumi(p *feed.Bangumi) {
- i.Title = p.Title
- i.Cover = p.NewEp.Cover
- i.Goto = model.GotoUpBangumi
- i.Param = strconv.FormatInt(p.SeasonID, 10)
- i.URI = model.FillURI(i.Goto, i.Param, 0, 0, nil)
- i.Status = int8(p.IsFinish)
- i.Index = p.NewEp.Index
- i.IndexTitle = p.NewEp.IndexTitle
- i.Play = int(p.NewEp.Play)
- i.Danmaku = int(p.NewEp.Dm)
- i.Type = int8(p.BgmType)
- i.Count = int(p.TotalCount)
- i.Updates = int(p.NewEp.EpisodeID)
- i.CTime = xtime.Time(p.Ts)
- }
- func (i *Item) FromUpLive(f *livemdl.Feed) {
- i.Cover = f.Face
- i.Param = strconv.FormatInt(f.RoomID, 10)
- i.URI = model.FillURI(model.GotoLive, i.Param, 0, 0, nil)
- }
- func (i *Item) FromUpArticle(m *article.Meta) {
- i.Title = m.Title
- i.Desc = m.Summary
- i.Covers = m.ImageURLs
- i.Goto = model.GotoUpArticle
- i.Param = strconv.FormatInt(m.ID, 10)
- i.URI = model.FillURI(i.Goto, i.Param, 0, 0, nil)
- if m.Author != nil {
- i.Mid = m.Author.Mid
- i.Name = m.Author.Name
- i.Face = m.Author.Face
- }
- if m.Category != nil {
- i.Category = &Category{ID: m.Category.ID, Name: m.Category.Name}
- }
- if m.Stats != nil {
- i.fillArtStat(m)
- }
- i.Temple = int(m.TemplateID)
- if i.Temple == 4 {
- i.Temple = 1
- }
- i.Template = int(m.TemplateID)
- i.BannerURL = m.BannerURL
- i.CTime = m.PublishTime
- }
- func (i *Item) FromArticleS(m *article.Meta) {
- if m.State < 0 {
- return
- }
- i.Title = m.Title
- i.Desc = m.Summary
- i.Covers = m.ImageURLs
- i.Goto = model.GotoArticleS
- i.Param = strconv.FormatInt(m.ID, 10)
- i.URI = model.FillURI(i.Goto, i.Param, 0, 0, nil)
- if m.Author != nil {
- i.Mid = m.Author.Mid
- i.Name = m.Author.Name
- i.Face = m.Author.Face
- }
- if len(m.Categories) >= 2 && m.Categories[0] != nil && m.Categories[1] != nil {
- i.Category = &Category{ID: m.Categories[0].ID, Name: m.Categories[0].Name}
- i.Category.Children = &Category{ID: m.Categories[1].ID, Name: m.Categories[1].Name}
- }
- if m.Stats != nil {
- i.fillArtStat(m)
- }
- i.Temple = int(m.TemplateID)
- if i.Temple == 4 {
- i.Temple = 1
- }
- i.Template = int(m.TemplateID)
- i.BannerURL = m.BannerURL
- i.CTime = m.PublishTime
- }
- func (i *Item) FromLiveUpRcmd(id int64, cs []*live.Card, card map[int64]*account.Card) {
- if len(cs) < 2 {
- return
- }
- is := make([]*Item, 0, 2)
- for _, c := range cs[:2] {
- if c.LiveStatus != 1 {
- return
- }
- it := &Item{}
- it.Title = c.Title
- it.Cover = c.ShowCover
- it.Goto = model.GotoLive
- it.Param = strconv.FormatInt(c.RoomID, 10)
- it.URI = model.FillURI(it.Goto, it.Param, 0, 0, model.LiveUpHandler(c))
- it.Fans = int64(c.Online)
- it.Mid = c.UID
- it.Name = c.Uname
- it.Badge = "直播"
- if card, ok := card[it.Mid]; ok {
- if card.Official.Role != 0 {
- it.Official = &OfficialInfo{Role: card.Official.Role, Title: card.Official.Title, Desc: card.Official.Desc}
- }
- }
- is = append(is, it)
- }
- i.Item = is
- i.Goto = model.GotoLiveUpRcmd
- i.Param = strconv.FormatInt(id, 10)
- }
- func (i *Item) FromWeb(title, cover, uri string) {
- i.Title = title
- i.Cover = cover
- i.Goto = model.GotoWeb
- i.URI = model.FillURI(i.Goto, uri, 0, 0, nil)
- i.Redirect = model.FillRedirect(i.Goto, 0)
- }
- func (i *Item) FromDislikeReason(plat int8, build int) {
- const (
- _seasonNoSeason = 1
- _seasonRegion = 2
- _seasonTag = 3
- _seasonUpper = 4
- _channelIPhone = 6720
- _channelAndroid = 5270000
- )
- var reasonName string
- if (plat == model.PlatIPhone && build > _channelIPhone) || (plat == model.PlatAndroid && build >= _channelAndroid) || plat == model.PlatIPhoneB {
- reasonName = "频道:"
- } else {
- reasonName = "标签:"
- }
- if i.Tag != nil {
- i.DisklikeReasons = []*dislike.DisklikeReason{
- &dislike.DisklikeReason{ReasonID: _seasonUpper, ReasonName: "UP主:" + i.Name},
- &dislike.DisklikeReason{ReasonID: _seasonRegion, ReasonName: "分区:" + i.TName},
- &dislike.DisklikeReason{ReasonID: _seasonTag, ReasonName: reasonName + i.Tag.TagName},
- &dislike.DisklikeReason{ReasonID: _seasonNoSeason, ReasonName: "不感兴趣"},
- }
- } else {
- i.DisklikeReasons = []*dislike.DisklikeReason{
- &dislike.DisklikeReason{ReasonID: _seasonUpper, ReasonName: "UP主:" + i.Name},
- &dislike.DisklikeReason{ReasonID: _seasonRegion, ReasonName: "分区:" + i.TName},
- &dislike.DisklikeReason{ReasonID: _seasonNoSeason, ReasonName: "不感兴趣"},
- }
- }
- }
- func (i *Item) fillArcStat(a *archive.Archive3) {
- if a == nil {
- return
- }
- if a.Access == 0 {
- i.Play = int(a.Stat.View)
- }
- i.Danmaku = int(a.Stat.Danmaku)
- i.Reply = int(a.Stat.Reply)
- i.Fav = int(a.Stat.Fav)
- i.Coin = int(a.Stat.Coin)
- i.Share = int(a.Stat.Share)
- i.Like = int(a.Stat.Like)
- i.Dislike = int(a.Stat.DisLike)
- }
- func (i *Item) fillArtStat(m *article.Meta) {
- if m == nil {
- return
- }
- i.Play = int(m.Stats.View)
- i.Reply = int(m.Stats.Reply)
- }
- func (i *Item) FromTabCards(r *operate.Active, am map[int64]*archive.ArchiveWithPlayer, downm map[int64]*operate.Download, sm map[int64]*bangumi.Season, rm map[int64]*live.Room, metam map[int64]*article.Meta, spm map[int64]*operate.Special) {
- items := make([]*Item, 0, len(r.Items))
- for _, r := range r.Items {
- item := &Item{}
- switch r.Goto {
- case model.GotoWeb:
- item.FromWeb(r.Title, r.Cover, model.FillURI(model.GotoWeb, r.Param, 0, 0, nil))
- case model.GotoGame:
- if d, ok := downm[r.Pid]; ok {
- item.FromGameDownloadS(d, 0, 0)
- }
- case model.GotoAv:
- if a, ok := am[r.Pid]; ok {
- item.FromAv(a)
- }
- case model.GotoBangumi:
- if b, ok := sm[r.Pid]; ok {
- item.FromSeason(b)
- }
- case model.GotoLive:
- if r, ok := rm[r.Pid]; ok {
- item.FromLive(r)
- }
- case model.GotoArticle:
- if m, ok := metam[r.Pid]; ok {
- item.FromArticleS(m)
- }
- case model.GotoSpecial:
- if sc, ok := spm[r.Pid]; ok {
- item.FromSpecialS(sc.ID, sc.Title, sc.Cover, sc.SingleCover, sc.Desc, sc.ReValue, sc.ReType, sc.Badge)
- }
- }
- if item.Goto != "" {
- items = append(items, item)
- }
- }
- if len(items) == 0 {
- return
- }
- i.Item = items
- i.Title = r.Title
- i.URI = model.FillURI(model.GotoWeb, r.Param, 0, 0, nil)
- i.Subtitle = r.Subtitle
- i.Goto = r.Type
- }
- func (i *Item) FromTabTags(r *operate.Active, am map[int64]*archive.ArchiveWithPlayer, tagm map[int64]*tag.Tag) {
- items := make([]*Item, 0, len(r.Items))
- for _, r := range r.Items {
- if r == nil {
- continue
- }
- item := &Item{}
- switch r.Goto {
- case model.GotoAv:
- if a, ok := am[r.Pid]; ok {
- item.FromAv(a)
- }
- }
- if item.Goto != "" {
- items = append(items, item)
- }
- }
- if len(items) == 0 {
- return
- }
- i.Item = items
- i.Param = strconv.FormatInt(r.Pid, 10)
- if t, ok := tagm[r.Pid]; ok {
- i.Title = t.Name
- }
- i.Goto = r.Type
- }
- func (i *Item) FromTabBanner(r *operate.Active) {
- i.BannerItem = make([]*banner.Banner, 0, len(r.Items))
- for _, item := range r.Items {
- banner := &banner.Banner{ID: item.Pid, Title: item.Title, Image: item.Cover, URI: cdm.FillURI(item.Goto, item.Param, nil)}
- i.BannerItem = append(i.BannerItem, banner)
- }
- i.Goto = model.GotoBanner
- }
- func (i *Item) FromNews(r *operate.Active) {
- if r.Desc == "" {
- return
- }
- i.Title = r.Title
- i.Content = r.Desc
- i.Goto = model.GotoTabNews
- i.URI = model.FillURI(model.GotoWeb, r.Param, 0, 0, nil)
- }
- //最多配10张卡片 取3个未关注的 不足则不显示该卡片
- func (i *Item) FromSubscribe(r *operate.Follow, card map[int64]*account.Card, follow map[int64]bool, statm map[int64]*relation.Stat, tagm map[int64]*bustag.Tag) {
- if r == nil {
- return
- }
- is := make([]*Item, 0, 3)
- switch r.Type {
- case "upper":
- for _, r := range r.Items {
- item := &Item{}
- if card, ok := card[r.Pid]; ok {
- if follow[r.Pid] {
- continue
- }
- item.Name = card.Name
- item.Face = card.Face
- item.Mid = card.Mid
- if card.Official.Role != 0 {
- item.Official = &OfficialInfo{Role: card.Official.Role, Title: card.Official.Title, Desc: card.Official.Desc}
- }
- item.IsAtten = 0
- if stat, ok := statm[r.Pid]; ok {
- item.Fans = stat.Follower
- }
- is = append(is, item)
- }
- }
- i.Kind = "upper"
- case "channel_three":
- for _, r := range r.Items {
- item := &Item{}
- tg, ok := tagm[r.Pid]
- if !ok || tg.IsAtten == 1 {
- continue
- }
- item.Name = tg.Name
- item.Face = tg.Cover
- item.Fans = int64(tg.Count.Atten)
- item.IsAtten = tg.IsAtten
- item.Param = strconv.FormatInt(tg.ID, 10)
- if item.Face != "" {
- is = append(is, item)
- }
- }
- i.Kind = "channel"
- }
- if len(is) < 3 {
- return
- }
- i.Item = is[:3]
- i.Title = r.Title
- i.Param = strconv.FormatInt(r.ID, 10)
- i.Goto = model.GotoSubscribe
- }
- func (i *Item) FromChannelRcmd(r *operate.Follow, am map[int64]*archive.ArchiveWithPlayer, tagm map[int64]*bustag.Tag) {
- if r == nil {
- return
- }
- if a, ok := am[r.Pid]; ok {
- i.Goto = model.GotoChannelRcmd
- i.URI = model.FillURI(model.GotoAv, strconv.FormatInt(a.Aid, 10), 0, 0, model.AvPlayHandler(a.Archive3, a.PlayerInfo))
- i.Title = a.Title
- i.Cover = a.Pic
- if tag, ok := tagm[r.Tid]; ok {
- i.Tag = &Tag{ID: tag.ID, Name: tag.Name, Face: tag.Cover, Fans: tag.Count.Atten, IsAtten: tag.IsAtten}
- }
- i.Cid = a.FirstCid
- i.Autoplay = a.Rights.Autoplay
- i.fillArcStat(a.Archive3)
- i.Duration = a.Duration
- // TODO 等待开启
- // percent := i.Like / (i.Like + i.Dislike) * 100
- // if percent != 0 {
- // i.Desc = strconv.Itoa(percent) + "%的人推荐"
- // }
- i.Param = strconv.FormatInt(r.ID, 10)
- }
- }
|