12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004 |
- package feed
- import (
- "context"
- "encoding/json"
- "fmt"
- "time"
- cdm "go-common/app/interface/main/app-card/model"
- "go-common/app/interface/main/app-card/model/bplus"
- "go-common/app/interface/main/app-card/model/card"
- "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/show"
- "go-common/app/interface/main/app-feed/model"
- "go-common/app/interface/main/app-feed/model/feed"
- 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"
- locmdl "go-common/app/service/main/location/model"
- relation "go-common/app/service/main/relation/model"
- episodegrpc "go-common/app/service/openplatform/pgc-season/api/grpc/episode/v1"
- "go-common/library/ecode"
- "go-common/library/log"
- "go-common/library/net/metadata"
- "go-common/library/sync/errgroup"
- )
- const _qn480 = 32
- var (
- _cardAdAvm = map[int]struct{}{
- 1: struct{}{},
- }
- _cardAdWebm = map[int]struct{}{
- 2: struct{}{},
- 7: struct{}{},
- 20: struct{}{},
- }
- _cardAdWebSm = map[int]struct{}{
- 3: struct{}{},
- 26: struct{}{},
- }
- _followMode = &feed.FollowMode{
- Title: "当前为首页推荐 - 关注模式(内测版)",
- Option: []*feed.Option{
- {Title: "通用模式", Desc: "开启后,推荐你可能感兴趣的内容", Value: 0},
- {Title: "关注模式(内测版)", Desc: "开启后,仅显示关注UP主更新的视频", Value: 1},
- },
- ToastMessage: "关注UP主的内容已经看完啦,请稍后再试",
- }
- )
- func (s *Service) Index2(c context.Context, buvid string, mid int64, plat int8, param *feed.IndexParam, style int, now time.Time) (is []card.Handler, config *feed.Config, infoc *feed.Infoc, err error) {
- var (
- rs []*ai.Item
- adm map[int]*cm.AdInfo
- adAidm map[int64]struct{}
- banners []*banner.Banner
- version string
- blackAidm map[int64]struct{}
- adInfom map[int]*cm.AdInfo
- follow *operate.Card
- info *locmdl.Info
- )
- ip := metadata.String(c, metadata.RemoteIP)
- config = s.indexConfig(c, plat, buvid, mid, param)
- if config.FollowMode == nil {
- param.RecsysMode = 0
- }
- noCache := param.RecsysMode == 1
- followMode := config.FollowMode != nil
- infoc = &feed.Infoc{}
- infoc.AutoPlayInfoc = fmt.Sprintf("%d|%d", config.AutoplayCard, param.AutoPlayCard)
- if info, err = s.loc.Info(c, ip); err != nil {
- log.Warn("s.loc.Info(%v) error(%v)", ip, err)
- err = nil
- }
- group := s.group(mid, buvid)
- if !s.c.Feed.Index.Abnormal || followMode {
- g, ctx := errgroup.WithContext(c)
- g.Go(func() error {
- rs, infoc.UserFeature, infoc.IsRcmd, infoc.NewUser, infoc.Code = s.indexRcmd2(ctx, plat, buvid, mid, param, group, info, style, infoc.AutoPlayInfoc, noCache, now)
- return nil
- })
- g.Go(func() (err error) {
- if banners, version, err = s.indexBanner2(ctx, plat, buvid, mid, param); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- if param.RecsysMode == 0 {
- g.Go(func() (err error) {
- if adm, adAidm, err = s.indexAd2(ctx, plat, buvid, mid, param, info, style, now); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- g.Go(func() (err error) {
- if blackAidm, err = s.BlackList(ctx, mid); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- g.Go(func() (err error) {
- if follow, err = s.SearchFollow2(ctx, param.Platform, param.MobiApp, param.Device, buvid, param.Build, mid); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if err = g.Wait(); err != nil {
- log.Error("%+v", err)
- return
- }
- if param.RecsysMode == 1 {
- var tmp []*ai.Item
- for _, r := range rs {
- if r.Goto == model.GotoBanner {
- continue
- }
- tmp = append(tmp, r)
- }
- if len(tmp) == 0 {
- is = []card.Handler{}
- return
- }
- }
- rs, adInfom = s.mergeItem2(c, plat, mid, rs, adm, adAidm, banners, version, blackAidm, follow, followMode)
- } else {
- count := s.indexCount(plat)
- rs = s.recommendCache(count)
- log.Warn("feed index show disaster recovery data len(%d)", len(is))
- }
- if config.AutoplayCard == 1 && cdm.Columnm[param.Column] == cdm.ColumnSvrSingle {
- param.Qn = _qn480
- }
- is, infoc.IsRcmd = s.dealItem2(c, mid, buvid, plat, rs, param, infoc.IsRcmd, noCache, followMode, follow, now)
- s.dealAdLoc(is, param, adInfom, now)
- return
- }
- func (s *Service) indexConfig(c context.Context, plat int8, buvid string, mid int64, param *feed.IndexParam) (config *feed.Config) {
- config = &feed.Config{}
- config.Column = cdm.Columnm[param.Column]
- // if mid > 0 && mid%20 == 19 {
- // config.FeedCleanAbtest = 1
- // } else {
- // config.FeedCleanAbtest = 0
- // }
- config.FeedCleanAbtest = 0
- if !model.IsIPad(plat) {
- if ab, ok := s.abtestCache[_feedgroups]; ok {
- if ab.AbTestIn(buvid + _feedgroups) {
- switch param.AutoPlayCard {
- case 0, 1, 2, 3:
- config.AutoplayCard = 1
- default:
- config.AutoplayCard = 2
- }
- } else {
- config.AutoplayCard = 2
- }
- } else {
- switch param.AutoPlayCard {
- case 1, 3:
- config.AutoplayCard = 1
- default:
- config.AutoplayCard = 2
- }
- }
- } else {
- // ipad 不允许自动播放
- config.AutoplayCard = 2
- }
- if mid < 1 {
- return
- }
- if _, ok := s.autoplayMidsCache[mid]; ok && param.AutoPlayCard != 4 {
- config.AutoplayCard = 1
- }
- if _, ok := s.followModeList[mid]; ok {
- tmpConfig := &feed.FollowMode{}
- if s.c.Feed.Index.FollowMode == nil {
- *tmpConfig = *_followMode
- } else {
- *tmpConfig = *s.c.Feed.Index.FollowMode
- }
- if param.RecsysMode != 1 {
- tmpConfig.ToastMessage = ""
- }
- config.FollowMode = tmpConfig
- }
- return
- }
- func (s *Service) indexRcmd2(c context.Context, plat int8, buvid string, mid int64, param *feed.IndexParam, group int, zone *locmdl.Info, style int, autoPlay string, noCache bool, now time.Time) (is []*ai.Item, userFeature json.RawMessage, isRcmd, newUser bool, code int) {
- count := s.indexCount(plat)
- if buvid != "" || mid > 0 {
- var (
- err error
- zoneID int64
- )
- if zone != nil {
- zoneID = zone.ZoneID
- }
- if is, userFeature, code, newUser, err = s.rcmd.Recommend(c, plat, buvid, mid, param.Build, param.LoginEvent, param.ParentMode, param.RecsysMode, zoneID, group, param.Interest, param.Network, style, param.Column, param.Flush, autoPlay, now); err != nil {
- log.Error("%+v", err)
- }
- if noCache {
- isRcmd = true
- return
- }
- if len(is) != 0 {
- isRcmd = true
- }
- var fromCache bool
- if len(is) == 0 && mid > 0 && !ecode.ServiceUnavailable.Equal(err) {
- if is, err = s.indexCache(c, mid, count); err != nil {
- log.Error("%+v", err)
- }
- if len(is) != 0 {
- s.pHit.Incr("index_cache")
- } else {
- s.pMiss.Incr("index_cache")
- }
- fromCache = true
- }
- if len(is) == 0 || (fromCache && len(is) < count) {
- is = s.recommendCache(count)
- }
- } else {
- is = s.recommendCache(count)
- }
- return
- }
- func (s *Service) indexAd2(c context.Context, plat int8, buvid string, mid int64, param *feed.IndexParam, zone *locmdl.Info, style int, now time.Time) (adm map[int]*cm.AdInfo, adAidm map[int64]struct{}, err error) {
- var advert *cm.Ad
- resource := s.adResource(plat, param.Build)
- if resource == 0 {
- return
- }
- // 兼容老的style逻辑,3为新单列,上报给商业产品的参数定义为:1 单列 2双列
- if style == 3 {
- style = 1
- }
- var country, province, city string
- if zone != nil {
- country = zone.Country
- province = zone.Province
- city = zone.City
- }
- if advert, err = s.ad.Ad(c, mid, param.Build, buvid, []int64{resource}, country, province, city, param.Network, param.MobiApp, param.Device, param.OpenEvent, param.AdExtra, style, now); err != nil {
- return
- }
- if advert == nil || len(advert.AdsInfo) == 0 {
- return
- }
- if adsInfo, ok := advert.AdsInfo[resource]; ok {
- adm = make(map[int]*cm.AdInfo, len(adsInfo))
- adAidm = make(map[int64]struct{}, len(adsInfo))
- for source, info := range adsInfo {
- if info == nil {
- continue
- }
- var adInfo *cm.AdInfo
- if info.AdInfo != nil {
- adInfo = info.AdInfo
- adInfo.RequestID = advert.RequestID
- adInfo.Resource = resource
- adInfo.Source = source
- adInfo.IsAd = info.IsAd
- adInfo.IsAdLoc = true
- adInfo.CmMark = info.CmMark
- adInfo.Index = info.Index
- adInfo.CardIndex = info.CardIndex
- adInfo.ClientIP = advert.ClientIP
- if adInfo.CreativeID != 0 && adInfo.CardType == _cardAdAv {
- adAidm[adInfo.CreativeContent.VideoID] = struct{}{}
- }
- } else {
- adInfo = &cm.AdInfo{RequestID: advert.RequestID, Resource: resource, Source: source, IsAdLoc: true, IsAd: info.IsAd, CmMark: info.CmMark, Index: info.Index, CardIndex: info.CardIndex, ClientIP: advert.ClientIP}
- }
- adm[adInfo.CardIndex-1] = adInfo
- }
- }
- return
- }
- func (s *Service) indexBanner2(c context.Context, plat int8, buvid string, mid int64, param *feed.IndexParam) (banners []*banner.Banner, version string, err error) {
- hash := param.BannerHash
- if param.LoginEvent != 0 {
- hash = ""
- }
- banners, version, err = s.banners(c, plat, param.Build, mid, buvid, param.Network, param.MobiApp, param.Device, param.OpenEvent, param.AdExtra, hash)
- return
- }
- func (s *Service) mergeItem2(c context.Context, plat int8, mid int64, rs []*ai.Item, adm map[int]*cm.AdInfo, adAidm map[int64]struct{}, banners []*banner.Banner, version string, blackAids map[int64]struct{}, follow *operate.Card, followMode bool) (is []*ai.Item, adInfom map[int]*cm.AdInfo) {
- if len(rs) == 0 {
- return
- }
- const (
- cardIndex = 7
- cardIndexIPad = 17
- cardOffset = 2
- )
- if len(banners) != 0 {
- rs = append([]*ai.Item{&ai.Item{Goto: model.GotoBanner, Banners: banners, Version: version}}, rs...)
- for index, ad := range adm {
- if _, ok := _cardAdWebm[ad.CardType]; ok && ((model.IsIPad(plat) && index <= cardIndexIPad) || index <= cardIndex) {
- ad.CardIndex = ad.CardIndex + cardOffset
- }
- }
- }
- if follow != nil {
- followPos := s.c.Feed.Index.FollowPosition
- if followPos-1 >= 0 && followPos-1 <= len(rs) {
- rs = append(rs[:followPos-1], append([]*ai.Item{&ai.Item{ID: follow.ID, Goto: model.GotoSearchSubscribe}}, rs[followPos-1:]...)...)
- }
- }
- is = make([]*ai.Item, 0, len(rs)+len(adm))
- adInfom = make(map[int]*cm.AdInfo, len(adm))
- var existsAdWeb bool
- for _, r := range rs {
- for {
- if ad, ok := adm[len(is)]; ok {
- if ad.CreativeID != 0 {
- var item *ai.Item
- if _, ok := _cardAdAvm[ad.CardType]; ok {
- item = &ai.Item{ID: ad.CreativeContent.VideoID, Goto: model.GotoAdAv, Ad: ad}
- } else if _, ok := _cardAdWebm[ad.CardType]; ok {
- item = &ai.Item{Goto: model.GotoAdWeb, Ad: ad}
- existsAdWeb = true
- } else if _, ok := _cardAdWebSm[ad.CardType]; ok {
- item = &ai.Item{Goto: model.GotoAdWebS, Ad: ad}
- } else {
- b, _ := json.Marshal(ad)
- log.Error("ad---%s", b)
- break
- }
- is = append(is, item)
- continue
- } else {
- adInfom[ad.CardIndex-1] = ad
- }
- }
- break
- }
- if r.Goto == model.GotoAv {
- if _, ok := blackAids[r.ID]; ok {
- continue
- } else if _, ok := s.blackCache[r.ID]; ok {
- continue
- }
- if _, ok := adAidm[r.ID]; ok {
- continue
- }
- } else if r.Goto == model.GotoBanner && len(is) != 0 {
- // banner 必须在第一位
- continue
- } else if r.Goto == model.GotoRank && existsAdWeb {
- continue
- } else if r.Goto == model.GotoLogin && mid > 0 {
- continue
- } else if r.Goto == model.GotoFollowMode && !followMode {
- continue
- }
- is = append(is, r)
- }
- return
- }
- func (*Service) dealAdLoc(is []card.Handler, param *feed.IndexParam, adInfom map[int]*cm.AdInfo, now time.Time) {
- il := len(is)
- if il == 0 {
- return
- }
- if param.Idx < 1 {
- param.Idx = now.Unix()
- }
- for i, h := range is {
- if param.Pull {
- h.Get().Idx = param.Idx + int64(il-i)
- } else {
- h.Get().Idx = param.Idx - int64(i+1)
- }
- if ad, ok := adInfom[i]; ok {
- h.Get().AdInfo = ad
- } else if h.Get().AdInfo != nil {
- h.Get().AdInfo.CardIndex = i + 1
- }
- }
- }
- func (s *Service) dealItem2(c context.Context, mid int64, buvid string, plat int8, rs []*ai.Item, param *feed.IndexParam, isRcmd, noCache, followMode bool, follow *operate.Card, now time.Time) (is []card.Handler, isAI bool) {
- if len(rs) == 0 {
- is = []card.Handler{}
- return
- }
- var (
- aids, tids, roomIDs, sids, metaIDs, shopIDs, audioIDs, picIDs []int64
- seasonIDs []int32
- upIDs, avUpIDs, rmUpIDs, mtUpIDs []int64
- am map[int64]*archive.ArchiveWithPlayer
- tagm map[int64]*tag.Tag
- rm map[int64]*live.Room
- sm map[int64]*bangumi.Season
- hasUpdate, getBanner bool
- update *bangumi.Update
- metam map[int64]*article.Meta
- shopm map[int64]*show.Shopping
- audiom map[int64]*audio.Audio
- cardm map[int64]*account.Card
- statm map[int64]*relation.Stat
- moe *bangumi.Moe
- isAtten map[int64]int8
- arcOK bool
- rank *operate.Card
- seasonm map[int32]*episodegrpc.EpisodeCardsProto
- banners []*banner.Banner
- version string
- picm map[int64]*bplus.Picture
- )
- convergem := map[int64]*operate.Card{}
- followm := map[int64]*operate.Card{}
- downloadm := map[int64]*operate.Card{}
- specialm := map[int64]*operate.Card{}
- liveUpm := map[int64][]*live.Card{}
- isAI = isRcmd
- for _, r := range rs {
- if r == nil {
- continue
- }
- switch r.Goto {
- case model.GotoBanner:
- if len(r.Banners) != 0 {
- banners = r.Banners
- version = r.Version
- } else {
- getBanner = true
- }
- case model.GotoAv, model.GotoAdAv, model.GotoPlayer, model.GotoUpRcmdAv:
- if r.ID != 0 {
- aids = append(aids, r.ID)
- }
- if r.Tid != 0 {
- tids = append(tids, r.Tid)
- }
- case model.GotoLive, model.GotoPlayerLive:
- if r.ID != 0 {
- roomIDs = append(roomIDs, r.ID)
- }
- case model.GotoBangumi:
- if r.ID != 0 {
- sids = append(sids, r.ID)
- }
- case model.GotoPGC:
- if r.ID != 0 {
- seasonIDs = append(seasonIDs, int32(r.ID))
- }
- case model.GotoRank:
- os, aid := s.RankCard(plat)
- rank = &operate.Card{}
- rank.FromRank(os)
- aids = append(aids, aid...)
- case model.GotoBangumiRcmd:
- hasUpdate = true
- case model.GotoConverge:
- cardm, aid, roomID, metaID := s.convergeCard(c, 3, r.ID)
- for id, card := range cardm {
- convergem[id] = card
- }
- aids = append(aids, aid...)
- roomIDs = append(roomIDs, roomID...)
- metaIDs = append(metaIDs, metaID...)
- case model.GotoGameDownloadS:
- cardm := s.downloadCard(c, r.ID)
- for id, card := range cardm {
- downloadm[id] = card
- }
- case model.GotoArticleS:
- if r.ID != 0 {
- metaIDs = append(metaIDs, r.ID)
- }
- case model.GotoShoppingS:
- if r.ID != 0 {
- shopIDs = append(shopIDs, r.ID)
- }
- case model.GotoAudio:
- if r.ID != 0 {
- audioIDs = append(audioIDs, r.ID)
- }
- case model.GotoLiveUpRcmd:
- cardm, upID := s.liveUpRcmdCard(c, r.ID)
- for id, card := range cardm {
- liveUpm[id] = card
- }
- upIDs = append(upIDs, upID...)
- case model.GotoSubscribe:
- cardm, upID, tid := s.subscribeCard(c, r.ID)
- for id, card := range cardm {
- followm[id] = card
- }
- upIDs = append(upIDs, upID...)
- tids = append(tids, tid...)
- case model.GotoSearchSubscribe:
- if follow != nil {
- followm[follow.ID] = follow
- for _, item := range follow.Items {
- upIDs = append(upIDs, item.ID)
- }
- }
- case model.GotoChannelRcmd:
- cardm, aid, tid := s.channelRcmdCard(c, r.ID)
- for id, card := range cardm {
- followm[id] = card
- }
- aids = append(aids, aid...)
- tids = append(tids, tid...)
- case model.GotoSpecial, model.GotoSpecialS:
- cardm := s.specialCard(c, r.ID)
- for id, card := range cardm {
- specialm[id] = card
- }
- case model.GotoPicture:
- if r.ID != 0 {
- picIDs = append(picIDs, r.ID)
- }
- if r.RcmdReason != nil && r.RcmdReason.Style == 4 {
- upIDs = append(upIDs, r.RcmdReason.FollowedMid)
- }
- }
- }
- g, ctx := errgroup.WithContext(c)
- if getBanner {
- g.Go(func() (err error) {
- if banners, version, err = s.banners(ctx, plat, param.Build, mid, buvid, param.Network, param.MobiApp, param.Device, param.OpenEvent, param.AdExtra, ""); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if len(aids) != 0 {
- g.Go(func() (err error) {
- if am, err = s.ArchivesWithPlayer(ctx, aids, param.Qn, param.MobiApp, param.Fnver, param.Fnval, param.ForceHost, param.Build); err != nil {
- return
- }
- arcOK = true
- for _, a := range am {
- avUpIDs = append(avUpIDs, a.Author.Mid)
- }
- return
- })
- }
- if len(tids) != 0 {
- g.Go(func() (err error) {
- if tagm, err = s.tg.InfoByIDs(ctx, mid, tids); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if len(roomIDs) != 0 {
- g.Go(func() (err error) {
- if rm, err = s.lv.AppMRoom(ctx, roomIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- for _, r := range rm {
- rmUpIDs = append(rmUpIDs, r.UID)
- }
- return
- })
- }
- if len(sids) != 0 {
- g.Go(func() (err error) {
- if sm, err = s.bgm.Seasons(ctx, sids, now); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if len(seasonIDs) != 0 {
- g.Go(func() (err error) {
- if seasonm, err = s.bgm.CardsInfoReply(ctx, seasonIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if hasUpdate && mid > 0 {
- g.Go(func() (err error) {
- /*
- {
- "code": 0,
- "message": "success",
- "result": {
- "title": "小埋。。。",
- "square_cover": "http://i0.hdslb.com/bfs/bangumi/dd2281c9f1c44e07c835e488ce1e1bae36f533e3.jpg",
- "updates": 67
- }
- }
- */
- if update, err = s.bgm.Updates(ctx, mid, now); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if len(metaIDs) != 0 {
- g.Go(func() (err error) {
- if metam, err = s.art.Articles(ctx, metaIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- for _, meta := range metam {
- if meta.Author != nil {
- mtUpIDs = append(mtUpIDs, meta.Author.Mid)
- }
- }
- return
- })
- }
- if len(shopIDs) != 0 {
- g.Go(func() (err error) {
- if shopm, err = s.show.Card(ctx, shopIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if len(audioIDs) != 0 {
- g.Go(func() (err error) {
- if audiom, err = s.audio.Audios(ctx, audioIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if len(picIDs) != 0 {
- g.Go(func() (err error) {
- if picm, err = s.bplus.DynamicDetail(ctx, picIDs...); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- // 萌战下线
- // if mid > 0 {
- // g.Go(func() (err error) {
- // if moe, err = s.bgm.FollowPull(ctx, mid, mobiApp, device, now); err != nil {
- // log.Error("%+v", err)
- // err = nil
- // }
- // return
- // })
- // }
- if err := g.Wait(); err != nil {
- log.Error("%+v", err)
- if noCache {
- is = []card.Handler{}
- return
- }
- if isRcmd {
- count := s.indexCount(plat)
- rs = s.recommendCache(count)
- }
- } else {
- upIDs = append(upIDs, avUpIDs...)
- upIDs = append(upIDs, rmUpIDs...)
- upIDs = append(upIDs, mtUpIDs...)
- g, ctx = errgroup.WithContext(c)
- if len(upIDs) != 0 {
- g.Go(func() (err error) {
- if cardm, err = s.acc.Cards3(ctx, upIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- g.Go(func() (err error) {
- if statm, err = s.rel.Stats(ctx, upIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- if mid > 0 && param.RecsysMode == 0 {
- g.Go(func() error {
- isAtten = s.acc.IsAttention(ctx, upIDs, mid)
- return nil
- })
- }
- }
- g.Wait()
- }
- isAI = isAI && arcOK
- if moe != nil {
- moePos := s.c.Feed.Index.MoePosition
- if moePos-1 >= 0 && moePos-1 <= len(rs) {
- rs = append(rs[:moePos-1], append([]*ai.Item{&ai.Item{ID: moe.ID, Goto: model.GotoMoe}}, rs[moePos-1:]...)...)
- }
- }
- var cardTotal int
- is = make([]card.Handler, 0, len(rs))
- insert := map[int]card.Handler{}
- for _, r := range rs {
- if r == nil {
- continue
- }
- var (
- main interface{}
- cardType cdm.CardType
- )
- op := &operate.Card{}
- op.From(cdm.CardGt(r.Goto), r.ID, r.Tid, plat, param.Build)
- // 卡片展示点赞数实验
- // if mid%20 == 11 && ((plat == model.PlatIPhone && param.Build >= 8290) || (plat == model.PlatAndroid && param.Build >= 5360000)) {
- // op.FromSwitch(cdm.SwitchFeedIndexLike)
- // }
- // 变化卡片类型
- switch r.Goto {
- case model.GotoSpecialS, model.GotoGameDownloadS, model.GotoShoppingS:
- if r.Style == 2 {
- cardType = cdm.LargeCoverV1
- }
- case model.GotoPicture:
- if p, ok := picm[r.ID]; ok {
- switch cdm.Columnm[param.Column] {
- case cdm.ColumnSvrSingle:
- if len(p.Imgs) < 3 {
- cardType = cdm.OnePicV1
- } else {
- cardType = cdm.ThreePicV1
- }
- case cdm.ColumnSvrDouble:
- if len(p.Imgs) < 3 {
- // 版本过滤5.37为新卡片
- if (plat == model.PlatIPhone && param.Build > 8300) || (plat == model.PlatAndroid && param.Build > 5365000) {
- cardType = cdm.OnePicV2
- } else {
- cardType = cdm.SmallCoverV2
- }
- } else {
- cardType = cdm.ThreePicV2
- }
- default:
- continue
- }
- } else {
- continue
- }
- case model.GotoInterest:
- switch cdm.Columnm[param.Column] {
- case cdm.ColumnSvrSingle:
- cardType = cdm.OptionsV1
- case cdm.ColumnSvrDouble:
- cardType = cdm.OptionsV2
- default:
- continue
- }
- case model.GotoFollowMode:
- cardType = cdm.Select
- default:
- }
- h := card.Handle(plat, cdm.CardGt(r.Goto), cardType, param.Column, r, tagm, isAtten, statm, cardm)
- if h == nil {
- continue
- }
- switch r.Goto {
- case model.GotoAv, model.GotoUpRcmdAv, model.GotoPlayer:
- if !arcOK {
- if r.Archive != nil {
- am = map[int64]*archive.ArchiveWithPlayer{r.Archive.Aid: &archive.ArchiveWithPlayer{Archive3: r.Archive}}
- }
- if r.Tag != nil {
- tagm = map[int64]*tag.Tag{r.Tag.ID: r.Tag}
- op.Tid = r.Tag.ID
- }
- }
- if a, ok := am[r.ID]; ok && (a.AttrVal(archive.AttrBitOverseaLock) == 0 || !model.IsOverseas(plat)) {
- main = am
- op.TrackID = r.TrackID
- }
- if plat == model.PlatIPhone && param.Build > 8290 || plat == model.PlatAndroid && param.Build > 5365000 {
- op.Switch = cdm.SwitchCooperationShow
- } else {
- op.Switch = cdm.SwitchCooperationHide
- }
- case model.GotoLive, model.GotoPlayerLive:
- main = rm
- case model.GotoBangumi:
- main = sm
- case model.GotoPGC:
- main = seasonm
- case model.GotoLogin:
- op.FromLogin(r.ID)
- case model.GotoSpecial, model.GotoSpecialS:
- op = specialm[r.ID]
- case model.GotoRank:
- main = map[cdm.Gt]interface{}{cdm.GotoAv: am}
- op = rank
- case model.GotoBangumiRcmd:
- main = update
- case model.GotoBanner:
- op.FromBanner(banners, version)
- case model.GotoConverge:
- main = map[cdm.Gt]interface{}{cdm.GotoAv: am, cdm.GotoLive: rm, cdm.GotoArticle: metam}
- op = convergem[r.ID]
- case model.GotoGameDownloadS:
- op = downloadm[r.ID]
- case model.GotoArticleS:
- main = metam
- case model.GotoShoppingS:
- main = shopm
- case model.GotoAudio:
- main = audiom
- case model.GotoChannelRcmd:
- main = am
- op = followm[r.ID]
- case model.GotoSubscribe, model.GotoSearchSubscribe:
- op = followm[r.ID]
- case model.GotoLiveUpRcmd:
- main = liveUpm
- case model.GotoMoe:
- main = moe
- case model.GotoPicture:
- main = picm
- case model.GotoAdAv:
- main = am
- op.FromAdAv(r.Ad)
- case model.GotoAdWebS, model.GotoAdWeb:
- main = r.Ad
- case model.GotoInterest:
- main = s.c.Feed.Index.Interest
- case model.GotoFollowMode:
- var (
- title string
- desc string
- button []string
- )
- if s.c.Feed.Index.FollowMode != nil && s.c.Feed.Index.FollowMode.Card != nil {
- title = s.c.Feed.Index.FollowMode.Card.Title
- desc = s.c.Feed.Index.FollowMode.Card.Desc
- button = s.c.Feed.Index.FollowMode.Card.Button
- }
- op.FromFollowMode(title, desc, button)
- default:
- log.Warn("unexpected goto(%s) %+v", r.Goto, r)
- continue
- }
- if op != nil {
- op.Plat = plat
- op.Build = param.Build
- }
- h.From(main, op)
- // 卡片不正常要continue
- if !h.Get().Right {
- continue
- }
- switch r.Goto {
- case model.GotoAdAv, model.GotoAdWebS, model.GotoAdWeb:
- // 判断结果列表长度,如果列表的末尾不是广告位,则放到插入队列里
- if len(is) != r.Ad.CardIndex-1 {
- insert[r.Ad.CardIndex-1] = h
- // 插入队列后一定要continue,否则就直接加到队列末尾了
- continue
- }
- }
- is, cardTotal = s.appendItem(plat, is, h, param.Column, cardTotal)
- // 从插入队列里获取广告
- if h, ok := insert[len(is)]; ok {
- is, cardTotal = s.appendItem(plat, is, h, param.Column, cardTotal)
- }
- }
- // 双列末尾卡片去空窗
- if !model.IsIPad(plat) {
- if cdm.Columnm[param.Column] == cdm.ColumnSvrDouble {
- is = is[:len(is)-cardTotal%2]
- }
- } else {
- // 复杂的ipad去空窗逻辑
- if cardTotal%4 == 3 {
- if is[len(is)-2].Get().CardLen == 2 {
- is = is[:len(is)-2]
- } else {
- is = is[:len(is)-3]
- }
- } else if cardTotal%4 == 2 {
- if is[len(is)-1].Get().CardLen == 2 {
- is = is[:len(is)-1]
- } else {
- is = is[:len(is)-2]
- }
- } else if cardTotal%4 == 1 {
- is = is[:len(is)-1]
- }
- }
- if len(is) == 0 {
- is = []card.Handler{}
- return
- }
- return
- }
- func (s *Service) appendItem(plat int8, rs []card.Handler, h card.Handler, column cdm.ColumnStatus, cardTotal int) (is []card.Handler, total int) {
- h.Get().ThreePointFrom()
- if !model.IsIPad(plat) {
- // 双列大小卡换位去空窗
- if cdm.Columnm[column] == cdm.ColumnSvrDouble {
- // 通栏卡
- if h.Get().CardLen == 0 {
- if cardTotal%2 == 1 {
- is = card.SwapTwoItem(rs, h)
- } else {
- is = append(rs, h)
- }
- } else {
- is = append(rs, h)
- }
- } else {
- is = append(rs, h)
- }
- } else {
- // ipad卡片不展示标签
- h.Get().DescButton = nil
- // ipad大小卡换位去空窗
- if h.Get().CardLen == 0 {
- // 通栏卡
- if cardTotal%4 == 3 {
- is = card.SwapFourItem(rs, h)
- } else if cardTotal%4 == 2 {
- is = card.SwapThreeItem(rs, h)
- } else if cardTotal%4 == 1 {
- is = card.SwapTwoItem(rs, h)
- } else {
- is = append(rs, h)
- }
- } else if h.Get().CardLen == 2 {
- // 半栏卡
- if cardTotal%4 == 3 {
- is = card.SwapTwoItem(rs, h)
- } else if cardTotal%4 == 2 {
- is = append(rs, h)
- } else if cardTotal%4 == 1 {
- is = card.SwapTwoItem(rs, h)
- } else {
- is = append(rs, h)
- }
- } else {
- is = append(rs, h)
- }
- }
- total = cardTotal + h.Get().CardLen
- return
- }
- func (s *Service) Converge(c context.Context, mid int64, plat int8, param *feed.ConvergeParam, now time.Time) (is []card.Handler, converge *operate.Card, err error) {
- cardm, _, _, _ := s.convergeCard(c, 0, param.ID)
- converge, ok := cardm[param.ID]
- if !ok {
- is = []card.Handler{}
- return
- }
- rs := make([]*ai.Item, 0, len(converge.Items))
- for _, item := range converge.Items {
- rs = append(rs, &ai.Item{ID: item.ID, Goto: string(item.CardGoto)})
- }
- indexParam := &feed.IndexParam{
- MobiApp: param.MobiApp,
- Device: param.Device,
- Build: param.Build,
- Qn: param.Qn,
- Fnver: param.Fnver,
- Fnval: param.Fnval,
- ForceHost: param.ForceHost,
- }
- is, _ = s.dealItem2(c, mid, "", plat, rs, indexParam, false, true, false, nil, now)
- for _, item := range is {
- // 运营tab页没有不感兴趣
- item.Get().ThreePointWatchLater()
- }
- return
- }
|