123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 |
- package channel
- import (
- "context"
- "encoding/json"
- "fmt"
- "strconv"
- "sync"
- "time"
- cdm "go-common/app/interface/main/app-card/model"
- cardm "go-common/app/interface/main/app-card/model/card"
- "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/live"
- "go-common/app/interface/main/app-card/model/card/operate"
- shopping "go-common/app/interface/main/app-card/model/card/show"
- "go-common/app/interface/main/app-channel/model"
- "go-common/app/interface/main/app-channel/model/card"
- "go-common/app/interface/main/app-channel/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"
- relation "go-common/app/service/main/relation/model"
- episodegrpc "go-common/app/service/openplatform/pgc-season/api/grpc/episode/v1"
- seasongrpc "go-common/app/service/openplatform/pgc-season/api/grpc/season/v1"
- "go-common/library/log"
- "go-common/library/sync/errgroup"
- farm "github.com/dgryski/go-farm"
- )
- const (
- _fTypeOperation = "operation"
- _fTypeRecommend = "recommend"
- )
- // Index channel index
- func (s *Service) Index2(c context.Context, mid, channelID, idx int64, plat int8, mobiApp, device, buvid, channelName, ip string,
- build, loginEvent, displayID, qn, fnver, fnval int, pull bool, now time.Time) (res *feed.Show2, err error) {
- var (
- aiCards []*card.Card
- requestCnt = 10
- isIpad = plat == model.PlatIPad
- topic cardm.Handler
- item []cardm.Handler
- channelResource *tag.ChannelResource
- topChannel, isRec int
- infocs []*feed.Item
- )
- if isIpad {
- requestCnt = 20
- }
- if channelID > 0 {
- channelName = ""
- }
- g, ctx := errgroup.WithContext(c)
- g.Go(func() (err error) {
- if channelResource, err = s.tg.Resources(ctx, plat, channelID, mid, channelName, buvid, build, requestCnt, loginEvent, displayID); err != nil {
- log.Error("index s.tg.Resources error(%v)", err)
- return
- }
- if channelResource != nil {
- aids := channelResource.Oids
- for _, aid := range aids {
- t := &card.Card{
- Type: model.GotoAv,
- Value: aid,
- FromType: _fTypeRecommend,
- }
- aiCards = append(aiCards, t)
- }
- if channelResource.Failover {
- isRec = 0
- } else {
- isRec = 1
- }
- if channelResource.IsChannel {
- topChannel = 1
- } else {
- topChannel = 0
- }
- }
- return
- })
- g.Go(func() (err error) {
- var t *tag.ChannelDetail
- if t, err = s.tg.ChannelDetail(c, mid, channelID, channelName, s.isOverseas(plat)); err != nil {
- log.Error("s.tag.ChannelDetail(%d, %d, %s) error(%v)", mid, channelID, channelName, err)
- return
- }
- channelID = t.Tag.ID
- channelName = t.Tag.Name
- return
- })
- err = g.Wait()
- //infoc
- infoc := &feedInfoc{
- mobiApp: mobiApp,
- device: device,
- build: strconv.Itoa(build),
- now: now.Format("2006-01-02 15:04:05"),
- pull: strconv.FormatBool(pull),
- loginEvent: strconv.Itoa(loginEvent),
- channelID: strconv.FormatInt(channelID, 10),
- channelName: channelName,
- mid: strconv.FormatInt(mid, 10),
- buvid: buvid,
- displayID: strconv.Itoa(displayID),
- isRec: strconv.Itoa(isRec),
- topChannel: strconv.Itoa(topChannel),
- ServerCode: "0",
- }
- //infoc
- if err != nil {
- log.Error("RankUser errgroup.WithContext error(%v)", err)
- res = &feed.Show2{
- Feed: []cardm.Handler{},
- }
- infoc.Items = []*feed.Item{}
- infoc.ServerCode = err.Error()
- s.infoc(infoc)
- return
- }
- var (
- tmps = []*card.Card{}
- )
- if loginEvent == 1 || loginEvent == 2 {
- if cards, ok := s.cardCache[channelID]; ok {
- isShowCard := s.isShowOperationCards(c, buvid, channelID, cards, now)
- for _, c := range cards {
- if !isShowCard && c.Type != model.GotoTopstick {
- continue
- }
- t := &card.Card{}
- *t = *c
- t.FromType = _fTypeOperation
- tmps = append(tmps, t)
- }
- tmps = append(tmps, aiCards...)
- } else {
- tmps = aiCards
- }
- } else {
- tmps = aiCards
- }
- topic, item, infocs, err = s.dealItem2(c, mid, idx, channelID, plat, build, buvid, ip, mobiApp, pull, qn, fnver, fnval, now, tmps)
- res = &feed.Show2{
- Topic: topic,
- Feed: item,
- }
- infoc.Items = infocs
- s.infoc(infoc)
- return
- }
- // dealItem
- func (s *Service) dealItem2(c context.Context, mid, idx, channelID int64, plat int8, build int, buvid, ip, mobiApp string, pull bool,
- qn, fnver, fnval int, now time.Time, cards []*card.Card) (top cardm.Handler, is []cardm.Handler, infocs []*feed.Item, err error) {
- if len(cards) == 0 {
- is = []cardm.Handler{}
- return
- }
- var (
- aids, shopIDs, audioIDs, sids, roomIDs, metaIDs []int64
- upIDs, tids, rmUpIDs, mtUpIDs, avUpIDs, avUpCountIDs []int64
- seasonIDs, epIDs []int32
- am map[int64]*archive.ArchiveWithPlayer
- tagm map[int64]*tag.Tag
- rm map[int64]*live.Room
- sm map[int64]*bangumi.Season
- metam map[int64]*article.Meta
- shopm map[int64]*shopping.Shopping
- audiom map[int64]*audio.Audio
- cardAids = map[int64]struct{}{}
- ac map[int64]*account.Card
- statm map[int64]*relation.Stat
- isAtten map[int64]int8
- upAvCount = map[int64]int{}
- channelCards []*card.Card
- seasonm map[int32]*seasongrpc.CardInfoProto
- epidsCards map[int32]*episodegrpc.EpisodeCardsProto
- // key
- _initCardPlatKey = "card_platkey_%d_%d"
- )
- specialm := map[int64]*operate.Card{}
- convergem := map[int64]*operate.Card{}
- downloadm := map[int64]*operate.Card{}
- followm := map[int64]*operate.Card{}
- liveUpm := map[int64][]*live.Card{}
- cardSet := map[int64]*operate.Card{}
- LOOP:
- for _, card := range cards {
- key := fmt.Sprintf(_initCardPlatKey, plat, card.ID)
- if cardPlat, ok := s.cardPlatCache[key]; ok {
- for _, l := range cardPlat {
- if model.InvalidBuild(build, l.Build, l.Condition) {
- continue LOOP
- }
- }
- } else if card.FromType == _fTypeOperation {
- continue LOOP
- }
- channelCards = append(channelCards, card)
- switch card.Type {
- case model.GotoAv, model.GotoPlayer, model.GotoUpRcmdAv:
- if card.Value != 0 {
- aids = append(aids, card.Value)
- cardAids[card.Value] = struct{}{}
- }
- case model.GotoLive, model.GotoPlayerLive:
- if card.Value != 0 {
- roomIDs = append(roomIDs, card.Value)
- }
- case model.GotoBangumi:
- if card.Value != 0 {
- sids = append(sids, card.Value)
- }
- case model.GotoPGC:
- if card.Value != 0 {
- epIDs = append(epIDs, int32(card.Value))
- }
- case model.GotoConverge:
- if card.Value != 0 {
- cardm, aid, roomID, metaID := s.convergeCard2(c, 3, card.Value)
- for id, card := range cardm {
- convergem[id] = card
- }
- aids = append(aids, aid...)
- roomIDs = append(roomIDs, roomID...)
- metaIDs = append(metaIDs, metaID...)
- }
- case model.GotoGameDownload, model.GotoGameDownloadS:
- if card.Value != 0 {
- cardm := s.downloadCard(c, card.Value)
- for id, card := range cardm {
- downloadm[id] = card
- }
- }
- case model.GotoArticle, model.GotoArticleS:
- if card.Value != 0 {
- metaIDs = append(metaIDs, card.Value)
- }
- case model.GotoShoppingS:
- if card.Value != 0 {
- shopIDs = append(shopIDs, card.Value)
- }
- case model.GotoAudio:
- if card.Value != 0 {
- audioIDs = append(audioIDs, card.Value)
- }
- case model.GotoChannelRcmd:
- cardm, aid, tid := s.channelRcmdCard(c, card.Value)
- for id, card := range cardm {
- followm[id] = card
- }
- aids = append(aids, aid...)
- tids = append(tids, tid...)
- case model.GotoLiveUpRcmd:
- if card.Value != 0 {
- cardm, upID := s.liveUpRcmdCard(c, card.Value)
- for id, card := range cardm {
- liveUpm[id] = card
- }
- upIDs = append(upIDs, upID...)
- }
- case model.GotoSubscribe:
- if card.Value != 0 {
- cardm, upID, tid := s.subscribeCard(c, card.Value)
- for id, card := range cardm {
- followm[id] = card
- }
- upIDs = append(upIDs, upID...)
- tids = append(tids, tid...)
- }
- case model.GotoSpecial, model.GotoSpecialS:
- cardm := s.specialCard(c, card.Value)
- for id, card := range cardm {
- specialm[id] = card
- }
- case model.GotoTopstick:
- cardm := s.topstickCard(c, card.Value)
- for id, card := range cardm {
- specialm[id] = card
- }
- case model.GotoPgcsRcmd:
- cardm, ssid := s.cardSetChange(c, card.Value)
- seasonIDs = append(seasonIDs, ssid...)
- for id, card := range cardm {
- cardSet[id] = card
- }
- case model.GotoUpRcmdS:
- if card.Value != 0 {
- avUpCountIDs = append(avUpCountIDs, card.Value)
- }
- }
- }
- 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, build); err != nil {
- return
- }
- 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 len(epIDs) != 0 {
- g.Go(func() (err error) {
- if epidsCards, err = s.bgm.EpidsCardsInfoReply(ctx, epIDs); 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.sp.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(avUpCountIDs) != 0 {
- var mutex sync.Mutex
- for _, upid := range avUpCountIDs {
- var (
- tmpupid = upid
- )
- g.Go(func() (err error) {
- var cnt int
- if cnt, err = s.arc.UpCount2(ctx, tmpupid); err != nil {
- log.Error("%+v", err)
- err = nil
- }
- mutex.Lock()
- upAvCount[tmpupid] = cnt
- mutex.Unlock()
- return
- })
- }
- }
- if err = g.Wait(); err != nil {
- log.Error("%+v", err)
- return
- }
- upIDs = append(upIDs, avUpIDs...)
- upIDs = append(upIDs, rmUpIDs...)
- upIDs = append(upIDs, mtUpIDs...)
- upIDs = append(upIDs, avUpCountIDs...)
- g, ctx = errgroup.WithContext(c)
- if len(upIDs) != 0 {
- g.Go(func() (err error) {
- if ac, 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 {
- g.Go(func() error {
- isAtten = s.acc.IsAttention(ctx, upIDs, mid)
- return nil
- })
- }
- }
- if err = g.Wait(); err != nil {
- log.Error("%+v", err)
- return
- }
- for _, card := range channelCards {
- var (
- r = card.CardToAiChange()
- main interface{}
- )
- switch r.Goto {
- case model.GotoAv, model.GotoUpRcmdAv, model.GotoPlayer:
- r.HideButton = true
- }
- h := cardm.Handle(plat, cdm.CardGt(r.Goto), "", cdm.ColumnSvrSingle, r, tagm, isAtten, statm, ac)
- if h == nil {
- continue
- }
- op := &operate.Card{}
- op.From(cdm.CardGt(r.Goto), r.ID, 0, plat, build)
- switch r.Goto {
- case model.GotoAv, model.GotoUpRcmdAv, model.GotoPlayer:
- op.ShowUGCPay = true
- if a, ok := am[r.ID]; ok && (a.AttrVal(archive.AttrBitOverseaLock) == 0 || !model.IsOverseas(plat)) {
- main = am
- }
- op.Switch = cdm.SwitchCooperationHide
- case model.GotoLive, model.GotoPlayerLive:
- main = rm
- case model.GotoBangumi:
- main = sm
- case model.GotoPGC:
- main = epidsCards
- case model.GotoSpecial, model.GotoSpecialS, model.GotoTopstick:
- op = specialm[r.ID]
- case model.GotoGameDownload, model.GotoGameDownloadS:
- op = downloadm[r.ID]
- case model.GotoArticle, 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:
- op = followm[r.ID]
- case model.GotoLiveUpRcmd:
- main = liveUpm
- case model.GotoConverge:
- main = map[cdm.Gt]interface{}{cdm.GotoAv: am, cdm.GotoLive: rm, cdm.GotoArticle: metam}
- op = convergem[r.ID]
- case model.GotoPgcsRcmd:
- main = seasonm
- op = cardSet[r.ID]
- case model.GotoUpRcmdS:
- op.Limit = upAvCount[r.ID]
- }
- h.From(main, op)
- if h.Get() == nil {
- continue
- }
- h.Get().FromType = card.FromType
- if h.Get().Right {
- switch card.FromType {
- case _fTypeOperation:
- h.Get().ThreePointWatchLater()
- case _fTypeRecommend:
- h.Get().ThreePointChannel()
- }
- switch r.Goto {
- case model.GotoTopstick:
- top = h
- default:
- is = append(is, h)
- }
- }
- // infoc
- tinfo := &feed.Item{
- Goto: card.Type,
- Param: strconv.FormatInt(card.Value, 10),
- URI: h.Get().URI,
- FromType: card.FromType,
- }
- infocs = append(infocs, tinfo)
- }
- rl := len(is)
- if rl == 0 {
- is = []cardm.Handler{}
- return
- }
- if idx == 0 {
- idx = now.Unix()
- }
- for i, h := range is {
- if pull {
- h.Get().Idx = idx + int64(rl-i)
- } else {
- h.Get().Idx = idx - int64(i+1)
- }
- }
- return
- }
- // ArchivesWithPlayer archives witch player
- func (s *Service) ArchivesWithPlayer(c context.Context, aids []int64, qn int, platform string, fnver, fnval, build int) (res map[int64]*archive.ArchiveWithPlayer, err error) {
- if res, err = s.arc.ArchivesWithPlayer(c, aids, qn, platform, fnver, fnval, build); err != nil {
- log.Error("%+v", err)
- }
- if len(res) != 0 {
- return
- }
- am, err := s.arc.Archives(c, aids)
- if err != nil {
- return
- }
- if len(am) == 0 {
- return
- }
- res = make(map[int64]*archive.ArchiveWithPlayer, len(am))
- for aid, a := range am {
- res[aid] = &archive.ArchiveWithPlayer{Archive3: archive.BuildArchive3(a)}
- }
- return
- }
- // isShowOperationCards is show operation cards by buvid
- func (s *Service) isShowOperationCards(c context.Context, buvid string, channelID int64, cards []*card.Card, now time.Time) (isShow bool) {
- var (
- md5, mcmd5 string
- )
- g, ctx := errgroup.WithContext(c)
- g.Go(func() (err error) {
- if mcmd5, err = s.cd.ChannelCardCache(ctx, buvid, channelID); err != nil {
- isShow = true
- return
- }
- return nil
- })
- g.Go(func() (err error) {
- md5 = s.hashCards(cards)
- return nil
- })
- g.Wait()
- if md5 != mcmd5 {
- isShow = true
- s.cd.AddChannelCardCache(c, buvid, md5, channelID, now)
- }
- return
- }
- func (s *Service) hashCards(v []*card.Card) string {
- bs, err := json.Marshal(v)
- if err != nil {
- log.Error("json.Marshal error(%v)", err)
- return ""
- }
- return strconv.FormatUint(farm.Hash64(bs), 10)
- }
|