12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088 |
- 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/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/feed"
- bustag "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 (
- _cardAdAv = 1
- _cardAdWeb = 2
- _cardAdWebS = 3
- _cardAdLarge = 7
- _feedgroups = "tianma2.0_autoplay_card"
- )
- // Index is
- func (s *Service) Index(c context.Context, mid int64, plat int8, build int, buvid, network, mobiApp, device, platform, openEvent string, loginEvent int, idx int64, pull bool, now time.Time, bannerHash, adExtra string, qn int, interest string, style, flush, fnver, fnval, autoplayCard int) (is []*feed.Item, userFeature json.RawMessage, isRcmd, newUser bool, code, clean int, autoPlayInfoc string, err error) {
- var (
- ris []*ai.Item
- adm map[int]*cm.AdInfo
- adAidm map[int64]struct{}
- hasBanner bool
- bs []*banner.Banner
- version string
- blackAidm map[int64]struct{}
- adInfom map[int]*cm.AdInfo
- follow *operate.Follow
- autoPlay int
- ip = metadata.String(c, metadata.RemoteIP)
- info *locmdl.Info
- )
- //abtest================
- // if mid > 0 && mid%20 == 19 {
- // clean = 1
- // } else {
- // clean = 0
- // }
- clean = 0
- if ab, ok := s.abtestCache[_feedgroups]; ok {
- if ab.AbTestIn(buvid + _feedgroups) {
- switch autoplayCard {
- case 0, 1, 2, 3:
- autoPlay = 1
- default:
- autoPlay = 2
- }
- } else {
- autoPlay = 2
- }
- } else {
- switch autoplayCard {
- case 1, 3:
- autoPlay = 1
- default:
- autoPlay = 2
- }
- }
- autoPlayInfoc = fmt.Sprintf("%d|%d", autoPlay, autoplayCard)
- if info, err = s.loc.Info(c, ip); err != nil {
- log.Warn("s.loc.Info(%v) error(%v)", ip, err)
- err = nil
- }
- //abtest================
- group := s.group(mid, buvid)
- g, ctx := errgroup.WithContext(c)
- g.Go(func() error {
- ris, userFeature, isRcmd, newUser, code = s.indexRcmd(ctx, plat, build, buvid, mid, group, loginEvent, 0, info, interest, network, style, -1, flush, autoPlayInfoc, now)
- return nil
- })
- // 暂停实验
- // if !((group == 18 || group == 19) && style == 3) {
- g.Go(func() (err error) {
- if adm, adAidm, err = s.indexAd(ctx, plat, build, buvid, mid, network, mobiApp, device, openEvent, info, now, adExtra, style); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- // }
- g.Go(func() (err error) {
- if hasBanner, bs, version, err = s.indexBanner(ctx, plat, build, buvid, mid, loginEvent, bannerHash, network, mobiApp, device, "", adExtra); 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.SearchFollow(ctx, platform, mobiApp, device, buvid, build, mid); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- if err = g.Wait(); err != nil {
- return
- }
- ris, adInfom = s.mergeItem(c, mid, ris, adm, adAidm, hasBanner, blackAidm, plat, follow)
- is, isRcmd, err = s.dealItem(c, mid, plat, build, buvid, ris, bs, version, isRcmd, network, mobiApp, device, openEvent, idx, pull, qn, now, adExtra, adInfom, fnver, fnval, autoPlay, follow)
- return
- }
- // Dislike is.
- func (s *Service) Dislike(c context.Context, mid, id int64, buvid, gt string, reasonID, cmreasonID, feedbackID, upperID, rid, tagID int64, adcb string, now time.Time) (err error) {
- if gt == model.GotoAv {
- s.blk.AddBlacklist(mid, id)
- }
- return s.rcmd.PubDislike(c, buvid, gt, id, mid, reasonID, cmreasonID, feedbackID, upperID, rid, tagID, adcb, now)
- }
- // DislikeCancel is.
- func (s *Service) DislikeCancel(c context.Context, mid, id int64, buvid, gt string, reasonID, cmreasonID, feedbackID, upperID, rid, tagID int64, adcb string, now time.Time) (err error) {
- if gt == model.GotoAv {
- s.blk.DelBlacklist(mid, id)
- }
- return s.rcmd.PubDislikeCancel(c, buvid, gt, id, mid, reasonID, cmreasonID, feedbackID, upperID, rid, tagID, adcb, now)
- }
- func (s *Service) indexRcmd(c context.Context, plat int8, build int, buvid string, mid int64, group int, loginEvent, parentMode int, zone *locmdl.Info, interest, network string, style int, column cdm.ColumnStatus, flush int, autoPlay string, 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, build, loginEvent, parentMode, 0, zoneID, group, interest, network, style, column, flush, autoPlay, now); err != nil {
- log.Error("%+v", err)
- } else 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) indexAd(c context.Context, plat int8, build int, buvid string, mid int64, network, mobiApp, device, openEvent string, zone *locmdl.Info, now time.Time, adExtra string, style int) (adm map[int]*cm.AdInfo, adAidm map[int64]struct{}, err error) {
- var advert *cm.Ad
- resource := s.adResource(plat, 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, build, buvid, []int64{resource}, country, province, city, network, mobiApp, device, openEvent, 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) indexBanner(c context.Context, plat int8, build int, buvid string, mid int64, loginEvent int, hash, network, mobiApp, device, openEvent, adExtra string) (has bool, bs []*banner.Banner, version string, err error) {
- const (
- _androidBanBannerHash = 515009
- _iphoneBanBannerHash = 6120
- _ipadBanBannerHash = 6160
- )
- if (plat == model.PlatAndroid && build > _androidBanBannerHash) || (plat == model.PlatIPhone && build > _iphoneBanBannerHash) || (plat == model.PlatIPad && build > _ipadBanBannerHash) || loginEvent != 0 {
- if bs, version, err = s.banners(c, plat, build, mid, buvid, network, mobiApp, device, openEvent, adExtra, ""); err != nil {
- return
- } else if loginEvent != 0 {
- has = true
- } else if version != "" {
- has = hash != version
- }
- }
- return
- }
- func (s *Service) mergeItem(c context.Context, mid int64, rs []*ai.Item, adm map[int]*cm.AdInfo, adAidm map[int64]struct{}, hasBanner bool, blackAids map[int64]struct{}, plat int8, follow *operate.Follow) (is []*ai.Item, adInfom map[int]*cm.AdInfo) {
- if len(rs) == 0 {
- return
- }
- const (
- cardIndex = 7
- cardIndexIPad = 17
- cardOffset = 2
- )
- if hasBanner {
- rs = append([]*ai.Item{&ai.Item{Goto: model.GotoBanner}}, rs...)
- for index, ad := range adm {
- if ((model.IsIPad(plat) && index <= cardIndexIPad) || index <= cardIndex) && (ad.CardType == _cardAdWeb || ad.CardType == _cardAdLarge) {
- 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 existsBanner, existsAdWeb bool
- for _, r := range rs {
- for {
- if ad, ok := adm[len(is)]; ok {
- if ad.CreativeID != 0 {
- var item *ai.Item
- if ad.CardType == _cardAdAv {
- item = &ai.Item{ID: ad.CreativeContent.VideoID, Goto: model.GotoAdAv, Ad: ad}
- } else if ad.CardType == _cardAdWeb {
- item = &ai.Item{Goto: model.GotoAdWeb, Ad: ad}
- existsAdWeb = true
- } else if ad.CardType == _cardAdWebS {
- item = &ai.Item{Goto: model.GotoAdWebS, Ad: ad}
- } else if ad.CardType == _cardAdLarge {
- item = &ai.Item{Goto: model.GotoAdLarge, Ad: ad}
- } else {
- b, _ := json.Marshal(ad)
- log.Error("ad---%s", b)
- break
- }
- is = append(is, item)
- continue
- } else {
- adInfom[len(is)] = 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 {
- if existsBanner {
- continue
- } else {
- existsBanner = true
- }
- } else if r.Goto == model.GotoRank && existsAdWeb {
- continue
- } else if r.Goto == model.GotoLogin && mid != 0 {
- continue
- }
- is = append(is, r)
- }
- return
- }
- func (s *Service) dealItem(c context.Context, mid int64, plat int8, build int, buvid string, rs []*ai.Item, bs []*banner.Banner, version string, isRcmd bool, network, mobiApp, device, openEvent string, idx int64, pull bool, qn int, now time.Time, adExtra string, adInfom map[int]*cm.AdInfo, fnver, fnval, autoPlay int, follow *operate.Follow) (is []*feed.Item, isAI bool, err error) {
- if len(rs) == 0 {
- is = _emptyItem
- return
- }
- var (
- aids, tids, roomIDs, sids, metaIDs, shopIDs, audioIDs []int64
- upIDs, avUpIDs, rmUpIDs, mtUpIDs []int64
- seasonIDs []int32
- ranks []*rank.Rank
- am map[int64]*archive.ArchiveWithPlayer
- tagm map[int64]*bustag.Tag
- follows map[int64]bool
- rm map[int64]*live.Room
- sm map[int64]*bangumi.Season
- hasBangumiRcmd bool
- update *bangumi.Update
- atm map[int64]*article.Meta
- scm map[int64]*show.Shopping
- aum map[int64]*audio.Audio
- hasBanner bool
- card map[int64]*account.Card
- upStatm map[int64]*relation.Stat
- arcOK bool
- seasonCards map[int32]*episodegrpc.EpisodeCardsProto
- )
- isAI = isRcmd
- convergem := map[int64]*operate.Converge{}
- downloadm := map[int64]*operate.Download{}
- liveUpm := map[int64][]*live.Card{}
- followm := map[int64]*operate.Follow{}
- for _, r := range rs {
- switch r.Goto {
- 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:
- card, aid := s.RankCard(model.PlatIPhone)
- ranks = card
- aids = append(aids, aid...)
- case model.GotoBangumiRcmd:
- hasBangumiRcmd = true
- case model.GotoBanner:
- hasBanner = true
- case model.GotoConverge:
- if card, ok := s.convergeCache[r.ID]; ok {
- for _, item := range card.Items {
- switch item.Goto {
- case model.GotoAv:
- if item.Pid != 0 {
- aids = append(aids, item.Pid)
- }
- case model.GotoLive:
- if item.Pid != 0 {
- roomIDs = append(roomIDs, item.Pid)
- }
- case model.GotoArticle:
- if item.Pid != 0 {
- metaIDs = append(metaIDs, item.Pid)
- }
- }
- }
- convergem[r.ID] = card
- }
- case model.GotoGameDownloadS:
- if card, ok := s.downloadCache[r.ID]; ok {
- downloadm[r.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:
- if r.ID != 0 {
- if cs, ok := s.liveCardCache[r.ID]; ok {
- for _, c := range cs {
- upIDs = append(upIDs, c.UID)
- }
- }
- }
- case model.GotoSubscribe:
- if r.ID != 0 {
- if card, ok := s.followCache[r.ID]; ok {
- for _, item := range card.Items {
- switch item.Goto {
- case cdm.GotoMid:
- if item.Pid != 0 {
- upIDs = append(upIDs, item.Pid)
- }
- case cdm.GotoTag:
- if item.Pid != 0 {
- tids = append(tids, item.Pid)
- }
- }
- }
- followm[r.ID] = card
- }
- }
- case model.GotoChannelRcmd:
- if r.ID != 0 {
- if card, ok := s.followCache[r.ID]; ok {
- if card.Pid != 0 {
- aids = append(aids, card.Pid)
- }
- if card.Tid != 0 {
- tids = append(tids, card.Tid)
- }
- followm[r.ID] = card
- }
- }
- case model.GotoSearchSubscribe:
- if follow != nil {
- followm[follow.ID] = follow
- for _, item := range follow.Items {
- upIDs = append(upIDs, item.Pid)
- }
- }
- }
- }
- g, ctx := errgroup.WithContext(c)
- if len(aids) != 0 {
- g.Go(func() (err error) {
- if am, err = s.ArchivesWithPlayer(ctx, aids, qn, mobiApp, fnver, fnval, 0, 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 seasonCards, err = s.bgm.CardsInfoReply(ctx, seasonIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- // TODO DEL
- // if hasBangumiRcmd && mid != 0 {
- if hasBangumiRcmd {
- g.Go(func() (err error) {
- if update, err = s.bgm.Updates(ctx, mid, now); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if hasBanner && version == "" {
- g.Go(func() (err error) {
- if bs, version, err = s.banners(ctx, plat, build, mid, buvid, network, mobiApp, device, openEvent, adExtra, ""); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if len(metaIDs) != 0 {
- g.Go(func() (err error) {
- if atm, err = s.art.Articles(ctx, metaIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- for _, at := range atm {
- if at.Author != nil {
- mtUpIDs = append(mtUpIDs, at.Author.Mid)
- }
- }
- return
- })
- }
- if len(shopIDs) != 0 {
- g.Go(func() (err error) {
- if scm, 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 aum, err = s.audio.Audios(ctx, audioIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- }
- if err = g.Wait(); err != nil {
- log.Error("%+v", err)
- 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 card, err = s.acc.Cards3(ctx, upIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- g.Go(func() (err error) {
- if upStatm, err = s.rel.Stats(ctx, upIDs); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- return
- })
- if mid != 0 {
- g.Go(func() error {
- follows = s.acc.Relations3(ctx, upIDs, mid)
- return nil
- })
- }
- }
- g.Wait()
- }
- isAI = isAI && arcOK
- // init feed items
- is = make([]*feed.Item, 0, len(rs))
- var (
- smallCardCnt int
- middleCardCnt int
- )
- ip := metadata.String(c, metadata.RemoteIP)
- adm := map[int]*feed.Item{}
- isIpad := plat == model.PlatIPad
- for _, r := range rs {
- il := len(is)
- i := &feed.Item{AI: r}
- i.FromRcmd(r)
- switch r.Goto {
- case model.GotoAv, model.GotoUpRcmdAv:
- a, ok := am[r.ID]
- if !ok && !arcOK {
- a = &archive.ArchiveWithPlayer{Archive3: r.Archive}
- }
- isOsea := model.IsOverseas(plat)
- if a != nil && a.Archive3 != nil && a.IsNormal() && (!isOsea || (isOsea && a.AttrVal(archive.AttrBitOverseaLock) == 0)) {
- i.FromPlayerAv(a)
- if arcOK {
- if info, ok := tagm[r.Tid]; ok {
- i.Tag = &feed.Tag{TagID: info.ID, TagName: info.Name, IsAtten: info.IsAtten, Count: &feed.TagCount{Atten: info.Count.Atten}}
- }
- } else if r.Tag != nil {
- i.Tag = &feed.Tag{TagID: r.Tag.ID, TagName: r.Tag.Name}
- }
- i.FromDislikeReason(plat, build)
- i.FromRcmdReason(r.RcmdReason)
- if follows[i.Mid] {
- i.IsAtten = 1
- }
- if card, ok := card[i.Mid]; ok {
- if card.Official.Role != 0 {
- i.Official = &feed.OfficialInfo{Role: card.Official.Role, Title: card.Official.Title, Desc: card.Official.Desc}
- }
- }
- // for GotoUpRcmdAv
- i.Goto = r.Goto
- if i.Goto == model.GotoUpRcmdAv {
- // TODO 等待开启
- // percent := i.Like / (i.Like + i.Dislike) * 100
- // if percent != 0 {
- // i.Desc = strconv.Itoa(percent) + "%的人推荐"
- // }
- i.Desc = ""
- }
- is = append(is, i)
- smallCardCnt++
- }
- case model.GotoLive:
- if r, ok := rm[r.ID]; ok {
- i.FromLive(r)
- if card, ok := card[i.Mid]; ok {
- if card.Official.Role != 0 {
- i.Official = &feed.OfficialInfo{Role: card.Official.Role, Title: card.Official.Title, Desc: card.Official.Desc}
- }
- }
- if stat, ok := upStatm[i.Mid]; ok {
- i.Fans = stat.Follower
- }
- if follows[i.Mid] {
- i.IsAtten = 1
- }
- if i.Goto != "" {
- is = append(is, i)
- smallCardCnt++
- }
- }
- case model.GotoBangumi:
- if s, ok := sm[r.ID]; ok {
- i.FromSeason(s)
- is = append(is, i)
- smallCardCnt++
- }
- case model.GotoPGC:
- if s, ok := seasonCards[int32(r.ID)]; ok {
- i.FromPGCSeason(s)
- is = append(is, i)
- smallCardCnt++
- }
- case model.GotoLogin:
- i.FromLogin()
- is = append(is, i)
- smallCardCnt++
- case model.GotoAdAv:
- if r.Ad != nil {
- if a, ok := am[r.ID]; ok && model.AdAvIsNormal(a) {
- i.FromAdAv(r.Ad, a)
- if follows[i.Mid] {
- i.IsAtten = 1
- }
- if card, ok := card[i.Mid]; ok {
- if card.Official.Role != 0 {
- i.Official = &feed.OfficialInfo{Role: card.Official.Role, Title: card.Official.Title, Desc: card.Official.Desc}
- }
- }
- i.ClientIP = ip
- adm[i.CardIndex-1] = i
- }
- }
- case model.GotoAdWebS:
- if r.Ad != nil {
- i.FromAdWebS(r.Ad)
- i.ClientIP = ip
- adm[i.CardIndex-1] = i
- }
- case model.GotoAdWeb:
- if r.Ad != nil {
- i.FromAdWeb(r.Ad)
- i.ClientIP = ip
- adm[i.CardIndex-1] = i
- }
- case model.GotoAdLarge:
- if r.Ad != nil {
- i.FromAdLarge(r.Ad)
- i.ClientIP = ip
- adm[i.CardIndex-1] = i
- }
- case model.GotoSpecial:
- if sc, ok := s.specialCache[r.ID]; ok {
- i.FromSpecial(sc.ID, sc.Title, sc.Cover, sc.Desc, sc.ReValue, sc.ReType, sc.Badge, sc.Size)
- }
- if i.Goto != "" {
- if !isIpad {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- } else {
- if (smallCardCnt+middleCardCnt*2)%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- middleCardCnt++
- }
- }
- case model.GotoSpecialS:
- if sc, ok := s.specialCache[r.ID]; ok {
- i.FromSpecialS(sc.ID, sc.Title, sc.Cover, sc.SingleCover, sc.Desc, sc.ReValue, sc.ReType, sc.Badge)
- }
- if i.Goto != "" {
- if !isIpad {
- is = append(is, i)
- smallCardCnt++
- }
- }
- case model.GotoRank:
- i.FromRank(ranks, am)
- if i.Goto != "" {
- if !isIpad {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- } else {
- if (smallCardCnt+middleCardCnt*2)%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- middleCardCnt++
- }
- }
- case model.GotoBangumiRcmd:
- if mid != 0 && update != nil && update.Updates != 0 {
- i.FromBangumiRcmd(update)
- if !isIpad {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- } else {
- is = append(is, i)
- smallCardCnt++
- }
- }
- case model.GotoBanner:
- if len(bs) != 0 {
- i.FromBanner(bs, version)
- if !isIpad {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- } else {
- switch (smallCardCnt + middleCardCnt*2) % 4 {
- case 0:
- is = append(is, i)
- case 1:
- is = swapTwoItem(is, i)
- case 2:
- switch is[len(is)-1].Goto {
- case model.GotoRank, model.GotoAdWeb, model.GotoAdLarge:
- is = swapTwoItem(is, i)
- default:
- is = swapThreeItem(is, i)
- }
- case 3:
- is = swapThreeItem(is, i)
- }
- }
- }
- case model.GotoConverge:
- if cc, ok := convergem[r.ID]; ok {
- i.FromConverge(cc, am, rm, atm)
- if i.Goto != "" {
- if !isIpad {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- }
- }
- }
- case model.GotoGameDownloadS:
- if gd, ok := downloadm[r.ID]; ok {
- i.FromGameDownloadS(gd, plat, build)
- if i.Goto != "" {
- if !isIpad {
- is = append(is, i)
- smallCardCnt++
- }
- }
- }
- case model.GotoArticleS:
- if m, ok := atm[r.ID]; ok {
- i.FromArticleS(m)
- if card, ok := card[i.Mid]; ok {
- if card.Official.Role != 0 {
- i.Official = &feed.OfficialInfo{Role: card.Official.Role, Title: card.Official.Title, Desc: card.Official.Desc}
- }
- }
- if i.Goto != "" {
- if !isIpad {
- is = append(is, i)
- smallCardCnt++
- }
- }
- }
- case model.GotoShoppingS:
- if c, ok := scm[r.ID]; ok {
- i.FromShoppingS(c)
- if i.Goto != "" {
- if !isIpad {
- is = append(is, i)
- smallCardCnt++
- }
- }
- }
- case model.GotoAudio:
- if au, ok := aum[r.ID]; ok {
- i.FromAudio(au)
- is = append(is, i)
- smallCardCnt++
- }
- case model.GotoPlayer:
- if a, ok := am[r.ID]; ok {
- i.FromPlayer(a)
- if i.Goto != "" {
- if info, ok := tagm[r.Tid]; ok {
- i.Tag = &feed.Tag{TagID: info.ID, TagName: info.Name, IsAtten: info.IsAtten, Count: &feed.TagCount{Atten: info.Count.Atten}}
- }
- if follows[i.Mid] {
- i.IsAtten = 1
- }
- if card, ok := card[i.Mid]; ok {
- if card.Official.Role != 0 {
- i.Official = &feed.OfficialInfo{Role: card.Official.Role, Title: card.Official.Title, Desc: card.Official.Desc}
- }
- }
- i.FromDislikeReason(plat, build)
- if !isIpad {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- }
- }
- }
- case model.GotoPlayerLive:
- if r, ok := rm[r.ID]; ok {
- i.FromPlayerLive(r)
- if i.Goto != "" {
- if follows[i.Mid] {
- i.IsAtten = 1
- }
- if card, ok := card[i.Mid]; ok {
- if card.Official.Role != 0 {
- i.Official = &feed.OfficialInfo{Role: card.Official.Role, Title: card.Official.Title, Desc: card.Official.Desc}
- }
- }
- if stat, ok := upStatm[i.Mid]; ok {
- i.Fans = stat.Follower
- }
- if !isIpad {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- }
- }
- }
- case model.GotoSubscribe, model.GotoSearchSubscribe:
- if c, ok := followm[r.ID]; ok {
- if !isIpad {
- i.FromSubscribe(c, card, follows, upStatm, tagm)
- if i.Goto != "" {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- }
- }
- }
- case model.GotoChannelRcmd:
- if c, ok := followm[r.ID]; ok {
- if !isIpad {
- i.FromChannelRcmd(c, am, tagm)
- if i.Goto != "" {
- if !isIpad {
- is = append(is, i)
- smallCardCnt++
- }
- }
- }
- }
- case model.GotoLiveUpRcmd:
- if c, ok := liveUpm[r.ID]; ok {
- if !isIpad {
- i.FromLiveUpRcmd(r.ID, c, card)
- if i.Goto != "" {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, i)
- } else {
- is = append(is, i)
- }
- }
- }
- }
- default:
- log.Warn("unexpected goto(%s) %+v", r.Goto, r)
- continue
- }
- if ad, ok := adm[il]; ok {
- switch ad.Goto {
- case model.GotoAdAv, model.GotoAdWebS:
- is = append(is, ad)
- smallCardCnt++
- case model.GotoAdWeb, model.GotoAdLarge:
- if !isIpad {
- if smallCardCnt%2 != 0 {
- is = swapTwoItem(is, ad)
- } else {
- is = append(is, ad)
- }
- } else {
- if (smallCardCnt+middleCardCnt*2)%2 != 0 {
- is = swapTwoItem(is, ad)
- } else {
- is = append(is, ad)
- }
- middleCardCnt++
- }
- }
- }
- }
- if !isIpad {
- is = is[:len(is)-smallCardCnt%2]
- } else {
- switch (smallCardCnt + middleCardCnt*2) % 4 {
- case 1:
- is = is[:len(is)-1]
- case 2:
- if isMiddleCard(is[len(is)-1].Goto) {
- is = is[:len(is)-1]
- } else {
- is = is[:len(is)-2]
- }
- case 3:
- if isMiddleCard(is[len(is)-1].Goto) {
- is = is[:len(is)-2]
- } else {
- is = is[:len(is)-3]
- }
- }
- }
- rl := len(is)
- if rl == 0 {
- is = _emptyItem
- return
- }
- if idx == 0 {
- idx = now.Unix()
- }
- for i, r := range is {
- if pull {
- r.Idx = idx + int64(rl-i)
- } else {
- r.Idx = idx - int64(i+1)
- }
- if ad, ok := adInfom[i]; ok {
- r.SrcID = ad.Source
- r.RequestID = ad.RequestID
- r.IsAdLoc = ad.IsAdLoc
- r.IsAd = ad.IsAd
- r.CmMark = ad.CmMark
- r.AdIndex = ad.Index
- r.ClientIP = ip
- r.CardIndex = i + 1
- } else if r.IsAd {
- r.CardIndex = i + 1
- }
- if i == 0 {
- r.AutoplayCard = autoPlay
- }
- }
- return
- }
- func (s *Service) adResource(plat int8, build int) (resource int64) {
- const (
- _androidBanAd = 500001
- )
- if plat == model.PlatIPhone || plat == model.PlatIPhoneB || (plat == model.PlatAndroid && build >= _androidBanAd) || plat == model.PlatIPad {
- resource = s.cmResourceMap[plat]
- }
- return
- }
- func swapTwoItem(rs []*feed.Item, i *feed.Item) (is []*feed.Item) {
- rs[len(rs)-1].Idx, i.Idx = i.Idx, rs[len(rs)-1].Idx
- is = append(rs, rs[len(rs)-1])
- is[len(is)-2] = i
- return
- }
- func swapThreeItem(rs []*feed.Item, i *feed.Item) (is []*feed.Item) {
- rs[len(rs)-1].Idx, i.Idx = i.Idx, rs[len(rs)-1].Idx
- rs[len(rs)-2].Idx, rs[len(is)-1].Idx = rs[len(rs)-1].Idx, rs[len(rs)-2].Idx
- is = append(rs, rs[len(rs)-1])
- is[len(is)-2] = i
- is[len(is)-3], is[len(is)-2] = is[len(is)-2], is[len(is)-3]
- return
- }
- func isMiddleCard(gt string) bool {
- return gt == model.GotoRank || gt == model.GotoAdWeb || gt == model.GotoPlayer ||
- gt == model.GotoPlayerLive || gt == model.GotoConverge || gt == model.GotoSpecial || gt == model.GotoAdLarge || gt == model.GotoLiveUpRcmd
- }
- func (s *Service) indexCount(plat int8) (count int) {
- if plat == model.PlatIPad {
- count = s.c.Feed.Index.IPadCount
- } else {
- count = s.c.Feed.Index.Count
- }
- return
- }
|