Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"black.go",
"cache.go",
"index.go",
"infoc.go",
"operate.go",
"player.go",
"rank.go",
"service.go",
],
importpath = "go-common/app/interface/main/app-intl/service/feed",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-card/model:go_default_library",
"//app/interface/main/app-card/model/card:go_default_library",
"//app/interface/main/app-card/model/card/ai:go_default_library",
"//app/interface/main/app-card/model/card/banner:go_default_library",
"//app/interface/main/app-card/model/card/cm:go_default_library",
"//app/interface/main/app-card/model/card/operate:go_default_library",
"//app/interface/main/app-card/model/card/rank:go_default_library",
"//app/interface/main/app-intl/conf:go_default_library",
"//app/interface/main/app-intl/dao/account:go_default_library",
"//app/interface/main/app-intl/dao/archive:go_default_library",
"//app/interface/main/app-intl/dao/black:go_default_library",
"//app/interface/main/app-intl/dao/card:go_default_library",
"//app/interface/main/app-intl/dao/location:go_default_library",
"//app/interface/main/app-intl/dao/rank:go_default_library",
"//app/interface/main/app-intl/dao/recommend:go_default_library",
"//app/interface/main/app-intl/dao/relation:go_default_library",
"//app/interface/main/app-intl/dao/tag:go_default_library",
"//app/interface/main/app-intl/model:go_default_library",
"//app/interface/main/app-intl/model/feed:go_default_library",
"//app/interface/main/tag/model:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/model/archive:go_default_library",
"//app/service/main/location/model:go_default_library",
"//app/service/main/relation/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/text/translate/chinese:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,35 @@
package feed
import (
"context"
"time"
"go-common/library/log"
)
// loadBlackCache is.
func (s *Service) loadBlackCache() {
bs, err := s.blk.Black(context.Background())
if err != nil {
log.Error("s.blk.Black error(%v)", err)
return
}
s.blackCache = bs
log.Info("reBlackList success")
}
// blackproc load blacklist cache.
func (s *Service) blackproc() {
for {
time.Sleep(s.tick)
s.loadBlackCache()
}
}
// BlackList is.
func (s *Service) BlackList(c context.Context, mid int64) (aidm map[int64]struct{}, err error) {
if mid == 0 {
return
}
return s.blk.BlackList(c, mid)
}

View File

@@ -0,0 +1,180 @@
package feed
import (
"context"
"hash/crc32"
"math/rand"
"time"
"go-common/app/interface/main/app-card/model/card/ai"
"go-common/app/interface/main/app-intl/model"
"go-common/library/log"
)
// indexCache is.
func (s *Service) indexCache(c context.Context, mid int64, count int) (rs []*ai.Item, err error) {
var (
pos, nextPos int
)
cache := s.rcmdCache
if len(cache) < count {
return
}
if pos, err = s.rcmd.PositionCache(c, mid); err != nil {
return
}
rs = make([]*ai.Item, 0, count)
if pos < len(cache)-count-1 {
nextPos = pos + count
rs = append(rs, cache[pos:nextPos]...)
} else if pos < len(cache)-1 {
nextPos = count - (len(cache) - pos)
rs = append(rs, cache[pos:]...)
rs = append(rs, cache[:nextPos]...)
} else {
nextPos = count - 1
rs = append(rs, cache[:nextPos]...)
}
s.addCache(func() {
s.rcmd.AddPositionCache(context.Background(), mid, nextPos)
})
return
}
// recommendCache is.
func (s *Service) recommendCache(count int) (rs []*ai.Item) {
cache := s.rcmdCache
index := len(cache)
if count > 0 && count < index {
index = count
}
rs = make([]*ai.Item, 0, index)
for _, idx := range rand.Perm(len(cache))[:index] {
rs = append(rs, cache[idx])
}
return
}
// group is.
func (s *Service) group(mid int64, buvid string) (group int) {
if mid == 0 && buvid == "" {
group = -1
return
}
if mid != 0 {
if v, ok := s.groupCache[mid]; ok {
group = v
return
}
group = int(mid % 20)
return
}
group = int(crc32.ChecksumIEEE([]byte(buvid)) % 20)
return
}
// loadRcmdCache is.
func (s *Service) loadRcmdCache() {
is, err := s.rcmd.RcmdCache(context.Background())
if err != nil {
log.Error("%+v", err)
}
if len(is) >= 50 {
for _, i := range is {
i.Goto = model.GotoAv
}
s.rcmdCache = is
return
}
aids, err := s.rcmd.Hots(context.Background())
if err != nil {
log.Error("%+v", err)
}
if len(aids) == 0 {
if aids, err = s.rcmd.RcmdAidsCache(context.Background()); err != nil {
return
}
}
if len(aids) < 50 && len(s.rcmdCache) != 0 {
return
}
s.rcmdCache = s.fromAids(aids)
s.addCache(func() {
s.rcmd.AddRcmdAidsCache(context.Background(), aids)
})
}
// fromAids is.
func (s *Service) fromAids(aids []int64) (is []*ai.Item) {
is = make([]*ai.Item, 0, len(aids))
for _, aid := range aids {
i := &ai.Item{
ID: aid,
Goto: model.GotoAv,
}
is = append(is, i)
}
return
}
// rcmdproc is.
func (s *Service) rcmdproc() {
for {
time.Sleep(s.tick)
s.loadRcmdCache()
}
}
// loadRankCache is.
func (s *Service) loadRankCache() {
rank, err := s.rank.AllRank(context.Background())
if err != nil {
log.Error("%+v", err)
return
}
s.rankCache = rank
}
// rankproc is.
func (s *Service) rankproc() {
for {
time.Sleep(s.tick)
s.loadRankCache()
}
}
// loadUpCardCache is.
func (s *Service) loadUpCardCache() {
follow, err := s.card.Follow(context.Background())
if err != nil {
log.Error("%+v", err)
return
}
s.followCache = follow
}
// upCardproc is.
func (s *Service) upCardproc() {
for {
time.Sleep(s.tick)
s.loadUpCardCache()
}
}
// loadGroupCache is.
func (s *Service) loadGroupCache() {
group, err := s.rcmd.Group(context.Background())
if err != nil {
log.Error("%+v", err)
return
}
s.groupCache = group
}
// groupproc is.
func (s *Service) groupproc() {
for {
time.Sleep(s.tick)
s.loadGroupCache()
}
}

View File

@@ -0,0 +1,438 @@
package feed
import (
"context"
"encoding/json"
"time"
cdm "go-common/app/interface/main/app-card/model"
"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/banner"
"go-common/app/interface/main/app-card/model/card/cm"
"go-common/app/interface/main/app-card/model/card/operate"
"go-common/app/interface/main/app-intl/model"
"go-common/app/interface/main/app-intl/model/feed"
tag "go-common/app/interface/main/tag/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"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
"go-common/library/text/translate/chinese"
)
// Index is.
func (s *Service) Index(c context.Context, buvid string, mid int64, plat int8, param *feed.IndexParam, now time.Time, style int) (is []card.Handler, userFeature json.RawMessage, isRcmd, newUser bool, code int, autoPlay, clean int8, autoPlayInfoc string, 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
ip = metadata.String(c, metadata.RemoteIP)
info *locmdl.Info
isTW = model.TWLocale(param.Locale)
)
// 国际版不做abtest
clean = 0
autoPlay = 2
group := s.group(mid, buvid)
if info, err = s.loc.Info(c, ip); err != nil {
log.Warn("s.loc.Info(%v) error(%v)", ip, err)
err = nil
}
if !s.c.Feed.Index.Abnormal {
g, ctx := errgroup.WithContext(c)
g.Go(func() error {
rs, userFeature, isRcmd, newUser, code = s.indexRcmd(ctx, plat, param.Build, buvid, mid, group, param.LoginEvent, info, param.Interest, param.Network, style, param.Column, param.Flush, autoPlayInfoc, now)
if isTW {
for _, r := range rs {
if r.RcmdReason != nil {
r.RcmdReason.Content = chinese.Convert(ctx, r.RcmdReason.Content)
}
}
}
return nil
})
g.Go(func() (err error) {
if blackAidm, err = s.BlackList(ctx, mid); err != nil {
log.Error("%+v", err)
err = nil
}
return
})
if err = g.Wait(); err != nil {
return
}
rs, adInfom = s.mergeItem(c, mid, rs, adm, adAidm, banners, version, blackAidm, plat, follow)
} else {
count := s.indexCount(plat)
rs = s.recommendCache(count)
log.Warn("feed index show disaster recovery data len(%d)", len(is))
}
is, isRcmd, err = s.dealItem(c, param.Column, mid, buvid, plat, param.Build, rs, isRcmd, param.MobiApp, param.Device, param.Network, param.OpenEvent, param.AdExtra, param.Qn, param.Fnver, param.Fnval, follow, isTW, now)
s.dealAdLoc(is, param, adInfom, now)
return
}
// indexRcmd is.
func (s *Service) indexRcmd(c context.Context, plat int8, build int, buvid string, mid int64, group int, loginEvent int, info *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 info != nil {
zoneID = info.ZoneID
}
if is, userFeature, code, newUser, err = s.rcmd.Recommend(c, plat, buvid, mid, build, loginEvent, 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
}
// mergeItem is.
func (s *Service) mergeItem(c context.Context, mid int64, rs []*ai.Item, adm map[int]*cm.AdInfo, adAidm map[int64]struct{}, banners []*banner.Banner, version string, blackAids map[int64]struct{}, plat int8, follow *operate.Card) (is []*ai.Item, adInfom map[int]*cm.AdInfo) {
if len(rs) == 0 {
return
}
if len(banners) != 0 {
rs = append([]*ai.Item{{Goto: model.GotoBanner, Banners: banners, Version: version}}, rs...)
}
is = make([]*ai.Item, 0, len(rs)+len(adm))
adInfom = make(map[int]*cm.AdInfo, len(adm))
for _, r := range rs {
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.GotoLogin && mid != 0 {
continue
}
is = append(is, r)
}
return
}
// dealAdLoc is.
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
}
}
}
// dealItem is.
func (s *Service) dealItem(c context.Context, column cdm.ColumnStatus, mid int64, buvid string, plat int8, build int, rs []*ai.Item, isRcmd bool, mobiApp, device, network, openEvent, adExtra string, qn, fnver, fnval int, follow *operate.Card, isTW bool, now time.Time) (is []card.Handler, isAI bool, err error) {
if len(rs) == 0 {
is = []card.Handler{}
return
}
var (
aids, tids []int64
upIDs, avUpIDs, rmUpIDs, mtUpIDs []int64
am map[int64]*archive.ArchiveWithPlayer
tagm map[int64]*tag.Tag
rank *operate.Card
cardm map[int64]*account.Card
statm map[int64]*relation.Stat
isAtten map[int64]int8
arcOK bool
)
followm := map[int64]*operate.Card{}
isAI = isRcmd
for _, r := range rs {
if r == nil {
continue
}
if isTW && r.RcmdReason != nil {
r.RcmdReason.Content = chinese.Convert(c, r.RcmdReason.Content)
}
switch r.Goto {
case model.GotoAv, model.GotoPlayer, model.GotoUpRcmdAv:
if r.ID != 0 {
aids = append(aids, r.ID)
}
if r.Tid != 0 {
tids = append(tids, r.Tid)
}
case model.GotoRank:
os, aid := s.RankCard(plat)
rank = &operate.Card{}
rank.FromRank(os)
aids = append(aids, aid...)
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...)
}
}
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); err != nil {
return
}
arcOK = true
for _, a := range am {
avUpIDs = append(avUpIDs, a.Author.Mid)
if isTW {
out := chinese.Converts(ctx, a.Title, a.Desc, a.TypeName)
a.Title = out[a.Title]
a.Desc = out[a.Desc]
a.TypeName = out[a.TypeName]
}
}
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 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 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 {
g.Go(func() error {
isAtten = s.acc.IsAttention(ctx, upIDs, mid)
return nil
})
}
}
g.Wait()
}
isAI = isAI && arcOK
var cardTotal int
is = make([]card.Handler, 0, len(rs))
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, build)
h := card.Handle(plat, cdm.CardGt(r.Goto), cardType, column, r, tagm, isAtten, statm, cardm)
if h == nil {
continue
}
switch r.Goto {
case model.GotoAv, model.GotoPlayer, model.GotoUpRcmdAv:
if !arcOK {
if r.Archive != nil {
if isTW {
out := chinese.Converts(c, r.Archive.Title, r.Archive.Desc, r.Archive.TypeName, r.Archive.Author.Name)
r.Archive.Title = out[r.Archive.Title]
r.Archive.Desc = out[r.Archive.Desc]
r.Archive.TypeName = out[r.Archive.TypeName]
}
am = map[int64]*archive.ArchiveWithPlayer{r.Archive.Aid: {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
}
case model.GotoRank:
main = map[cdm.Gt]interface{}{cdm.GotoAv: am}
op = rank
case model.GotoChannelRcmd:
main = am
case model.GotoLogin:
op.FromLogin(r.ID)
default:
log.Warn("unexpected goto(%s) %+v", r.Goto, r)
continue
}
h.From(main, op)
// 卡片不正常要continue
if !h.Get().Right {
continue
}
is, cardTotal = s.appendItem(plat, is, h, column, cardTotal)
}
// 双列末尾卡片去空窗
if !model.IsIPad(plat) {
if cdm.Columnm[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
}
// appendItem is.
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 h.Get().ThreePoint != nil {
h.Get().ThreePoint.Feedbacks = nil
}
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
}
// indexCount is.
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
}

View File

@@ -0,0 +1,234 @@
package feed
import (
"bytes"
"context"
"encoding/json"
"strconv"
"time"
"go-common/app/interface/main/app-card/model/card/ai"
"go-common/app/interface/main/app-intl/model"
"go-common/library/log"
binfoc "go-common/library/log/infoc"
"go-common/library/net/metadata"
)
// infoc struct
type infoc struct {
typ string
mid string
client string
build string
buvid string
disid string
ip string
style string
api string
now string
isRcmd string
pull string
userFeature json.RawMessage
code string
items []*ai.Item
lp bool
zoneID string
adResponse string
deviceID string
network string
newUser string
flush string
autoPlay string
deviceType string
}
// IndexInfoc is.
func (s *Service) IndexInfoc(c context.Context, mid int64, plat int8, build int, buvid, disid, api string, userFeature json.RawMessage, style, code int, items []*ai.Item, isRcmd, pull, newUser bool, now time.Time, adResponse, deviceID, network string, flush int, autoPlay string, deviceType int) {
if items == nil {
return
}
var (
isRc = "0"
isPull = "0"
isNewUser = "0"
zoneID int64
)
if isRcmd {
isRc = "1"
}
if pull {
isPull = "1"
}
if newUser {
isNewUser = "1"
}
ip := metadata.String(c, metadata.RemoteIP)
info, err := s.loc.Info(c, ip)
if err != nil {
log.Warn(" s.loc.Info(%v) error(%v)", ip, err)
err = nil
}
if info != nil {
zoneID = info.ZoneID
}
s.infoc(infoc{"综合推荐", strconv.FormatInt(mid, 10), strconv.Itoa(int(plat)), strconv.Itoa(build), buvid, disid, ip, strconv.Itoa(style), api, strconv.FormatInt(now.Unix(), 10), isRc, isPull, userFeature, strconv.Itoa(code), items, false, strconv.FormatInt(zoneID, 10), adResponse, deviceID, network, isNewUser, strconv.Itoa(flush), autoPlay, strconv.Itoa(deviceType)})
}
// infoc is.
func (s *Service) infoc(i interface{}) {
select {
case s.logCh <- i:
default:
log.Warn("infocproc chan full")
}
}
// infocproc is.
func (s *Service) infocproc() {
const (
// infoc format {"section":{"id":"%s推荐","pos":1,"style":%d,"items":[{"id":%s,"pos":%d,"type":1,"url":""}]}}
noItem1 = `{"section":{"id":"`
noItem2 = `{","pos":1,"style":`
noItem3 = `,"items":[]}}`
)
var (
msg1 = []byte(`{"section":{"id":"`)
msg2 = []byte(`","pos":1,"style":`)
msg3 = []byte(`,"items":[`)
msg4 = []byte(`{"id":`)
msg5 = []byte(`,"pos":`)
msg6 = []byte(`,"type":`)
msg7 = []byte(`,"source":"`)
msg8 = []byte(`","tid":`)
msg9 = []byte(`,"av_feature":`)
msg10 = []byte(`,"url":"`)
msg11 = []byte(`","rcmd_reason":"`)
msg12 = []byte(`"},`)
msg13 = []byte(`]}}`)
showInf = binfoc.New(s.c.ShowInfoc)
buf bytes.Buffer
list string
trackID string
)
for {
i, ok := <-s.logCh
if !ok {
log.Warn("infoc proc exit")
return
}
switch l := i.(type) {
case infoc:
if len(l.items) > 0 {
buf.Write(msg1)
buf.WriteString(l.typ)
buf.Write(msg2)
buf.WriteString(l.style)
buf.Write(msg3)
for i, v := range l.items {
if v == nil {
continue
}
if v.TrackID != "" {
trackID = v.TrackID
}
buf.Write(msg4)
buf.WriteString(strconv.FormatInt(v.ID, 10))
buf.Write(msg5)
buf.WriteString(strconv.Itoa(i + 1))
buf.Write(msg6)
buf.WriteString(gotoMapID(v.Goto))
buf.Write(msg7)
buf.WriteString(v.Source)
buf.Write(msg8)
buf.WriteString(strconv.FormatInt(v.Tid, 10))
buf.Write(msg9)
if v.AvFeature != nil {
buf.Write(v.AvFeature)
} else {
buf.Write([]byte(`""`))
}
buf.Write(msg10)
buf.WriteString("")
buf.Write(msg11)
if v.RcmdReason != nil {
buf.WriteString(v.RcmdReason.Content)
}
buf.Write(msg12)
}
buf.Truncate(buf.Len() - 1)
buf.Write(msg13)
list = buf.String()
buf.Reset()
} else {
list = noItem1 + l.typ + noItem2 + l.style + noItem3
}
showInf.Info(l.ip, l.now, l.api, l.buvid, l.mid, l.client, l.pull, list, l.disid, l.isRcmd, l.build, l.code, string(l.userFeature), l.zoneID, l.adResponse, l.deviceID, l.network, l.newUser, l.flush, l.autoPlay, trackID, l.deviceType)
log.Info("infocproc %s param(mid:%s,buvid:%s,plat:%s,build:%s,isRcmd:%s,code:%s,zone_id:%s,user_feature:%s,ad_response:%s,device_id:%s,network:%s,new_user:%s,flush:%s,autoplay_card:%s,trackid:%s,device_type:%s) response(%s)", l.api, l.mid, l.buvid, l.client, l.build, l.isRcmd, l.code, l.zoneID, l.userFeature, l.adResponse, l.deviceID, l.network, l.newUser, l.flush, l.autoPlay, trackID, l.deviceType, list)
}
}
}
// gotoMapID is.
func gotoMapID(gt string) (id string) {
if gt == model.GotoAv {
id = "1"
} else if gt == model.GotoBangumi {
id = "2"
} else if gt == model.GotoLive {
id = "3"
} else if gt == model.GotoRank {
id = "6"
} else if gt == model.GotoAdAv {
id = "8"
} else if gt == model.GotoAdWeb {
id = "9"
} else if gt == model.GotoBangumiRcmd {
id = "10"
} else if gt == model.GotoLogin {
id = "11"
} else if gt == model.GotoBanner {
id = "13"
} else if gt == model.GotoAdWebS {
id = "14"
} else if gt == model.GotoConverge {
id = "17"
} else if gt == model.GotoSpecial {
id = "18"
} else if gt == model.GotoArticleS {
id = "20"
} else if gt == model.GotoGameDownloadS {
id = "21"
} else if gt == model.GotoShoppingS {
id = "22"
} else if gt == model.GotoAudio {
id = "23"
} else if gt == model.GotoPlayer {
id = "24"
} else if gt == model.GotoSpecialS {
id = "25"
} else if gt == model.GotoAdLarge {
id = "26"
} else if gt == model.GotoPlayerLive {
id = "27"
} else if gt == model.GotoSong {
id = "28"
} else if gt == model.GotoLiveUpRcmd {
id = "29"
} else if gt == model.GotoUpRcmdAv {
id = "30"
} else if gt == model.GotoSubscribe {
id = "31"
} else if gt == model.GotoChannelRcmd {
id = "32"
} else if gt == model.GotoMoe {
id = "33"
} else if gt == model.GotoPGC {
id = "34"
} else if gt == model.GotoSearchSubscribe {
id = "35"
} else {
id = "-1"
}
return
}

View File

@@ -0,0 +1,32 @@
package feed
import (
"context"
"go-common/app/interface/main/app-card/model"
"go-common/app/interface/main/app-card/model/card/operate"
)
// channelRcmdCard is.
func (s *Service) channelRcmdCard(c context.Context, ids ...int64) (cardm map[int64]*operate.Card, aids, tids []int64) {
if len(ids) == 0 {
return
}
cardm = make(map[int64]*operate.Card, len(ids))
for _, id := range ids {
if o, ok := s.followCache[id]; ok {
card := &operate.Card{}
card.FromFollow(o)
cardm[id] = card
switch card.Goto {
case model.GotoAv:
if card.ID != 0 {
aids = append(aids, card.ID)
}
if card.Tid != 0 {
tids = append(tids, card.Tid)
}
}
}
}
return
}

View File

@@ -0,0 +1,30 @@
package feed
import (
"context"
"go-common/app/service/main/archive/model/archive"
"go-common/library/log"
)
// ArchivesWithPlayer archives witch player
func (s *Service) ArchivesWithPlayer(c context.Context, aids []int64, qn int, platform string, fnver, fnval int) (res map[int64]*archive.ArchiveWithPlayer, err error) {
if res, err = s.arc.ArchivesWithPlayer(c, aids, qn, platform, fnver, fnval); 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
}

View File

@@ -0,0 +1,26 @@
package feed
import (
"go-common/app/interface/main/app-card/model/card/rank"
"go-common/app/interface/main/app-intl/model"
)
// RankCard is.
func (s *Service) RankCard(plat int8) (ranks []*rank.Rank, aids []int64) {
var limit int
if !model.IsIPad(plat) {
limit = 3
} else {
limit = 4
}
ranks = make([]*rank.Rank, 0, limit)
aids = make([]int64, 0, limit)
for _, rank := range s.rankCache {
ranks = append(ranks, rank)
aids = append(aids, rank.Aid)
if len(ranks) == limit {
break
}
}
return
}

View File

@@ -0,0 +1,117 @@
package feed
import (
"time"
"go-common/app/interface/main/app-card/model/card/ai"
"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-intl/conf"
accdao "go-common/app/interface/main/app-intl/dao/account"
arcdao "go-common/app/interface/main/app-intl/dao/archive"
blkdao "go-common/app/interface/main/app-intl/dao/black"
carddao "go-common/app/interface/main/app-intl/dao/card"
locdao "go-common/app/interface/main/app-intl/dao/location"
rankdao "go-common/app/interface/main/app-intl/dao/rank"
rcmdao "go-common/app/interface/main/app-intl/dao/recommend"
reldao "go-common/app/interface/main/app-intl/dao/relation"
tagdao "go-common/app/interface/main/app-intl/dao/tag"
"go-common/library/log"
"go-common/library/stat/prom"
)
// Service is show service.
type Service struct {
c *conf.Config
pHit *prom.Prom
pMiss *prom.Prom
// dao
rcmd *rcmdao.Dao
tg *tagdao.Dao
blk *blkdao.Dao
rank *rankdao.Dao
card *carddao.Dao
// rpc
arc *arcdao.Dao
acc *accdao.Dao
rel *reldao.Dao
loc *locdao.Dao
// tick
tick time.Duration
// black cache
blackCache map[int64]struct{} // black aids
// ai cache
rcmdCache []*ai.Item
// rank cache
rankCache []*rank.Rank
// follow cache
followCache map[int64]*operate.Follow
// group cache
groupCache map[int64]int
// cache
cacheCh chan func()
// infoc
logCh chan interface{}
}
// New new a show service.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
pHit: prom.CacheHit,
pMiss: prom.CacheMiss,
// dao
rcmd: rcmdao.New(c),
blk: blkdao.New(c),
rank: rankdao.New(c),
tg: tagdao.New(c),
card: carddao.New(c),
// rpc
arc: arcdao.New(c),
rel: reldao.New(c),
acc: accdao.New(c),
loc: locdao.New(c),
// tick
tick: time.Duration(c.Tick),
// group cache
groupCache: map[int64]int{},
// cache
cacheCh: make(chan func(), 1024),
// infoc
logCh: make(chan interface{}, 1024),
}
s.loadBlackCache()
s.loadRcmdCache()
s.loadRankCache()
s.loadUpCardCache()
s.loadGroupCache()
go s.cacheproc()
go s.blackproc()
go s.rcmdproc()
go s.rankproc()
go s.upCardproc()
go s.groupproc()
go s.infocproc()
return
}
// addCache is.
func (s *Service) addCache(f func()) {
select {
case s.cacheCh <- f:
default:
log.Warn("cacheproc chan full")
}
}
// cacheproc is.
func (s *Service) cacheproc() {
for {
f, ok := <-s.cacheCh
if !ok {
log.Warn("cache proc exit")
return
}
f()
}
}

View File

@@ -0,0 +1,43 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/interface/main/app-intl/service/player",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-intl/conf:go_default_library",
"//app/interface/main/app-intl/dao/account:go_default_library",
"//app/interface/main/app-intl/dao/archive:go_default_library",
"//app/interface/main/app-intl/dao/player:go_default_library",
"//app/interface/main/app-intl/dao/resource:go_default_library",
"//app/interface/main/app-intl/dao/ugcpay:go_default_library",
"//app/interface/main/app-intl/model:go_default_library",
"//app/interface/main/app-intl/model/player:go_default_library",
"//app/interface/main/app-intl/model/player/archive:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/ugcpay/api/grpc/v1:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,194 @@
package player
import (
"context"
"strings"
"time"
"go-common/app/interface/main/app-intl/conf"
accdao "go-common/app/interface/main/app-intl/dao/account"
arcdao "go-common/app/interface/main/app-intl/dao/archive"
playerdao "go-common/app/interface/main/app-intl/dao/player"
resdao "go-common/app/interface/main/app-intl/dao/resource"
ugcpaydao "go-common/app/interface/main/app-intl/dao/ugcpay"
"go-common/app/interface/main/app-intl/model"
"go-common/app/interface/main/app-intl/model/player"
"go-common/app/interface/main/app-intl/model/player/archive"
accmdl "go-common/app/service/main/account/model"
ugcpaymdl "go-common/app/service/main/ugcpay/api/grpc/v1"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_qn1080 = 80
_qn480 = 32
_relationPaid = "paid"
_playURLV2 = "/v2/playurl"
_playURLV3 = "/v3/playurl"
)
var (
vipQn = []int64{116, 112, 74}
)
// Service is space service
type Service struct {
c *conf.Config
playerDao *playerdao.Dao
arcDao *arcdao.Dao
accDao *accdao.Dao
ugcpayDao *ugcpaydao.Dao
resDao *resdao.Dao
//vip qn
vipQnMap map[int64]struct{}
// paster
pasterCache map[int64]int64
}
// New new space
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
playerDao: playerdao.New(c),
arcDao: arcdao.New(c),
accDao: accdao.New(c),
ugcpayDao: ugcpaydao.New(c),
resDao: resdao.New(c),
vipQnMap: make(map[int64]struct{}),
pasterCache: make(map[int64]int64),
}
// type cache
for _, pn := range vipQn {
s.vipQnMap[pn] = struct{}{}
}
s.loadPasterCID()
go s.reloadproc()
return
}
func (s *Service) loadPasterCID() (err error) {
var tmpPaster map[int64]int64
if tmpPaster, err = s.resDao.PasterCID(context.Background()); err != nil {
log.Error("%v", err)
return
}
s.pasterCache = tmpPaster
return
}
// reloadproc reload data.
func (s *Service) reloadproc() {
for {
time.Sleep(time.Minute * 10)
s.loadPasterCID()
}
}
// Playurl is
func (s *Service) Playurl(c context.Context, mid int64, params *player.Param, plat int8, buvid, fp string) (playurl *player.Playurl, err error) {
var (
code int
reqPath = _playURLV2
aid = params.AID
cid = params.CID
qn = params.Qn
)
_, ok := s.pasterCache[cid]
if aid > 0 && !ok {
reqPath = _playURLV3
var (
arc *archive.Info
relation *ugcpaymdl.AssetRelationResp
)
if arc, err = s.arcDao.ArchiveCache(c, aid); err != nil {
log.Error("verifyArchive %+v", err)
return
}
if !arc.IsNormal() || !arc.HasCid(cid) {
err = ecode.NothingFound
log.Warn("verifyArchive aid(%d) can not play or no cid(%d)", aid, cid)
return
}
// TODO 历史老坑 纪录片之类的会请求UGC的playurl先打日志记一记
if arc.IsPGC() && arc.AttrVal(archive.AttrBitBadgepay) == archive.AttrYes {
log.Warn("verifyArchive aid(%d) pay(%d) cid(%d) is pgc!!!!", aid, arc.AttrVal(archive.AttrBitBadgepay), cid)
err = ecode.NothingFound
return
}
if arc.AttrVal(archive.AttrBitUGCPay) == 1 {
if mid <= 0 {
err = ecode.PlayURLNotLogin
return
} else if arc.Mid != mid {
if relation, err = s.ugcpayDao.AssetRelation(c, aid, mid); err != nil {
log.Error("verifyArchive %+v", err)
err = ecode.PlayURLNotPay
return
} else if relation.State != _relationPaid {
log.Warn("verifyArchive not pay aid(%d) mid(%d) state(%s)", aid, mid, relation.State)
err = ecode.PlayURLNotPay
return
}
}
}
if mid <= 0 && qn > _qn480 {
qn = _qn480
}
_, isVipQn := s.vipQnMap[qn]
if isVipQn && arc.Mid != mid {
var card *accmdl.Card
if card, err = s.accDao.Card3(c, mid); err != nil {
log.Error("verifyArchive %+v", err)
err = nil
qn = _qn1080
} else if card.Vip.Status != 1 || card.Vip.Type <= 0 {
qn = _qn1080
}
}
}
reqURL := s.c.Host.Playurl + reqPath
playurl, code, err = s.playerDao.Playurl(c, mid, aid, cid, qn, params.Npcybs, params.Fnver, params.Fnval, params.ForceHost, params.Otype, params.MobiApp, buvid, fp, params.Session, reqURL)
if err != nil {
log.Error("%+v", err)
reqURL = s.c.Host.PlayurlBk + _playURLV2
playurl, code, err = s.playerDao.Playurl(c, mid, aid, cid, qn, params.Npcybs, params.Fnver, params.Fnval, params.ForceHost, params.Otype, params.MobiApp, buvid, fp, params.Session, reqURL)
if err != nil {
log.Error("%+v", err)
return
}
}
if code != ecode.OK.Code() {
log.Error("playurl aid(%d) cid(%d) code(%d)", aid, cid, code)
err = ecode.NothingFound
playurl = nil
return
}
if playurl == nil {
err = ecode.NothingFound
return
}
// 版本过滤
if plat == model.PlatAndroidI && params.Build < 2002000 {
qualitys := make([]int64, 0, len(playurl.AcceptQuality))
descs := make([]string, 0, len(playurl.AcceptDescription))
formats := make([]string, 0, len(playurl.AcceptQuality))
acceptFormats := strings.Split(playurl.AcceptFormat, ",")
for index, quality := range playurl.AcceptQuality {
if _, ok := s.vipQnMap[quality]; !ok {
qualitys = append(qualitys, quality)
if index < len(playurl.AcceptDescription) {
descs = append(descs, playurl.AcceptDescription[index])
}
if index < len(acceptFormats) {
formats = append(formats, acceptFormats[index])
}
}
}
playurl.AcceptQuality = qualitys
playurl.AcceptDescription = descs
playurl.AcceptFormat = strings.Join(formats, ",")
}
return
}

View File

@@ -0,0 +1,60 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["search_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-intl/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["search.go"],
importpath = "go-common/app/interface/main/app-intl/service/search",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-interface/model/tag:go_default_library",
"//app/interface/main/app-intl/conf:go_default_library",
"//app/interface/main/app-intl/dao/account:go_default_library",
"//app/interface/main/app-intl/dao/archive:go_default_library",
"//app/interface/main/app-intl/dao/article:go_default_library",
"//app/interface/main/app-intl/dao/bangumi:go_default_library",
"//app/interface/main/app-intl/dao/resource:go_default_library",
"//app/interface/main/app-intl/dao/search:go_default_library",
"//app/interface/main/app-intl/dao/tag:go_default_library",
"//app/interface/main/app-intl/model:go_default_library",
"//app/interface/main/app-intl/model/bangumi:go_default_library",
"//app/interface/main/app-intl/model/search:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/log:go_default_library",
"//library/sync/errgroup:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,544 @@
package search
import (
"context"
"time"
tag "go-common/app/interface/main/app-interface/model/tag"
"go-common/app/interface/main/app-intl/conf"
accdao "go-common/app/interface/main/app-intl/dao/account"
arcdao "go-common/app/interface/main/app-intl/dao/archive"
artdao "go-common/app/interface/main/app-intl/dao/article"
bgmdao "go-common/app/interface/main/app-intl/dao/bangumi"
resdao "go-common/app/interface/main/app-intl/dao/resource"
srchdao "go-common/app/interface/main/app-intl/dao/search"
tagdao "go-common/app/interface/main/app-intl/dao/tag"
"go-common/app/interface/main/app-intl/model"
"go-common/app/interface/main/app-intl/model/bangumi"
"go-common/app/interface/main/app-intl/model/search"
article "go-common/app/interface/openplatform/article/model"
account "go-common/app/service/main/account/model"
"go-common/app/service/main/archive/api"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
var (
_emptyResult = &search.Result{
NavInfo: []*search.NavInfo{},
Page: 0,
}
)
// Service is search service
type Service struct {
c *conf.Config
srchDao *srchdao.Dao
accDao *accdao.Dao
arcDao *arcdao.Dao
artDao *artdao.Dao
// artDao *artdao.Dao
resDao *resdao.Dao
tagDao *tagdao.Dao
bgmDao *bgmdao.Dao
// config
seasonNum int
movieNum int
seasonShowMore int
movieShowMore int
upUserNum int
uvLimit int
userNum int
userVideoLimit int
biliUserNum int
biliUserVideoLimit int
iPadSearchBangumi int
iPadSearchFt int
}
// New is search service initial func
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
srchDao: srchdao.New(c),
accDao: accdao.New(c),
arcDao: arcdao.New(c),
artDao: artdao.New(c),
// artDao: artdao.New(c),
resDao: resdao.New(c),
tagDao: tagdao.New(c),
bgmDao: bgmdao.New(c),
seasonNum: c.Search.SeasonNum,
movieNum: c.Search.MovieNum,
seasonShowMore: c.Search.SeasonMore,
movieShowMore: c.Search.MovieMore,
upUserNum: c.Search.UpUserNum,
uvLimit: c.Search.UVLimit,
userNum: c.Search.UpUserNum,
userVideoLimit: c.Search.UVLimit,
biliUserNum: c.Search.BiliUserNum,
biliUserVideoLimit: c.Search.BiliUserVideoLimit,
iPadSearchBangumi: c.Search.IPadSearchBangumi,
iPadSearchFt: c.Search.IPadSearchFt,
}
return
}
// Search get all type search data.
func (s *Service) Search(c context.Context, mid, zoneid int64, mobiApp, device, platform, buvid, keyword, duration, order, filtered, lang, fromSource, recommend string, plat int8, rid, highlight, build, pn, ps int, now time.Time) (res *search.Result, err error) {
var (
aids []int64
am map[int64]*api.Arc
owners []int64
follows map[int64]bool
seasonIDs []int64
bangumis map[string]*bangumi.Card
)
var (
seasonNum int
movieNum int
)
seasonNum = s.seasonNum
movieNum = s.movieNum
all, code, err := s.srchDao.Search(c, mid, zoneid, mobiApp, device, platform, buvid, keyword, duration, order, filtered, fromSource, recommend, plat, seasonNum, movieNum, s.upUserNum, s.uvLimit, s.userNum, s.userVideoLimit, s.biliUserNum, s.biliUserVideoLimit, rid, highlight, build, pn, ps, now)
if err != nil {
log.Error("%+v", err)
return
}
if code == model.ForbidCode || code == model.NoResultCode {
res = _emptyResult
return
}
res = &search.Result{}
res.Trackid = all.Trackid
res.Page = all.Page
res.Array = all.FlowPlaceholder
res.Attribute = all.Attribute
res.NavInfo = s.convertNav(all, plat, build, lang)
if len(all.FlowResult) != 0 {
var item []*search.Item
for _, v := range all.FlowResult {
switch v.Type {
case search.TypeUser, search.TypeBiliUser:
owners = append(owners, v.User.Mid)
for _, vr := range v.User.Res {
aids = append(aids, vr.Aid)
}
case search.TypeVideo:
aids = append(aids, v.Video.ID)
case search.TypeMediaBangumi, search.TypeMediaFt:
seasonIDs = append(seasonIDs, v.Media.SeasonID)
}
}
g, ctx := errgroup.WithContext(c)
if len(owners) != 0 {
if mid > 0 {
g.Go(func() error {
follows = s.accDao.Relations3(ctx, owners, mid)
return nil
})
}
}
if len(aids) != 0 {
g.Go(func() (err error) {
if am, err = s.arcDao.Archives(ctx, aids); err != nil {
log.Error("%+v", err)
err = nil
}
return
})
}
if len(seasonIDs) != 0 {
g.Go(func() (err error) {
if bangumis, err = s.bgmDao.Card(ctx, mid, seasonIDs); err != nil {
log.Error("%+v", err)
err = nil
}
return
})
}
if err = g.Wait(); err != nil {
log.Error("%+v", err)
return
}
if all.SuggestKeyword != "" && pn == 1 {
i := &search.Item{Title: all.SuggestKeyword, Goto: model.GotoSuggestKeyWord}
item = append(item, i)
}
for _, v := range all.FlowResult {
i := &search.Item{TrackID: v.TrackID, LinkType: v.LinkType, Position: v.Position}
switch v.Type {
case search.TypeVideo:
i.FromVideo(v.Video, am[v.Video.ID])
case search.TypeMediaBangumi:
i.FromMedia(v.Media, "", model.GotoBangumi, bangumis)
case search.TypeMediaFt:
i.FromMedia(v.Media, "", model.GotoMovie, bangumis)
case search.TypeSpecial:
i.FromOperate(v.Operate, model.GotoSpecial)
case search.TypeBanner:
i.FromOperate(v.Operate, model.GotoBanner)
case search.TypeUser:
if follows[v.User.Mid] {
i.Attentions = 1
}
i.FromUser(v.User, am)
case search.TypeBiliUser:
if follows[v.User.Mid] {
i.Attentions = 1
}
i.FromUpUser(v.User, am)
case search.TypeSpecialS:
i.FromOperate(v.Operate, model.GotoSpecialS)
case search.TypeQuery:
i.Title = v.TypeName
i.FromQuery(v.Query)
case search.TypeConverge:
var (
avids, artids []int64
avm map[int64]*api.Arc
artm map[int64]*article.Meta
)
for _, c := range v.Operate.ContentList {
switch c.Type {
case 0:
avids = append(avids, c.ID)
case 2:
artids = append(artids, c.ID)
}
}
g, ctx := errgroup.WithContext(c)
if len(aids) != 0 {
g.Go(func() (err error) {
if avm, err = s.arcDao.Archives(ctx, avids); err != nil {
log.Error("%+v", err)
err = nil
}
return
})
}
if len(artids) != 0 {
g.Go(func() (err error) {
if artm, err = s.artDao.Articles(ctx, artids); err != nil {
log.Error("%+v", err)
err = nil
}
return
})
}
if err = g.Wait(); err != nil {
log.Error("%+v", err)
continue
}
i.FromConverge(v.Operate, avm, artm)
case search.TypeTwitter:
i.FromTwitter(v.Twitter)
}
if i.Goto != "" {
item = append(item, i)
}
}
res.Item = item
if all.EggInfo != nil {
res.EasterEgg = &search.EasterEgg{ID: all.EggInfo.Source, ShowCount: all.EggInfo.ShowCount}
}
return
}
// archive
for _, v := range all.Result.Video {
aids = append(aids, v.ID)
}
if duration == "0" && order == "totalrank" && rid == 0 {
for _, v := range all.Result.Movie {
if v.Type == "movie" {
aids = append(aids, v.Aid)
}
}
}
if pn == 1 {
for _, v := range all.Result.User {
for _, vr := range v.Res {
aids = append(aids, vr.Aid)
}
}
for _, v := range all.Result.BiliUser {
for _, vr := range v.Res {
aids = append(aids, vr.Aid)
}
owners = append(owners, v.Mid)
}
}
g, ctx := errgroup.WithContext(c)
if len(owners) != 0 {
if mid > 0 {
g.Go(func() error {
follows = s.accDao.Relations3(ctx, owners, mid)
return nil
})
}
}
if len(aids) != 0 {
g.Go(func() (err error) {
if am, err = s.arcDao.Archives(ctx, aids); err != nil {
log.Error("%+v", err)
err = nil
}
return
})
}
if err = g.Wait(); err != nil {
log.Error("%+v", err)
return
}
return
}
// SearchByType is tag bangumi movie upuser video search
func (s *Service) SearchByType(c context.Context, mid, zoneid int64, mobiApp, device, platform, buvid, sType, keyword, filtered, order string, plat int8, build, highlight, categoryID, userType, orderSort, pn, ps int, now time.Time) (res *search.TypeSearch, err error) {
switch sType {
case "upper":
if res, err = s.upper(c, mid, keyword, mobiApp, device, platform, buvid, filtered, order, s.biliUserVideoLimit, highlight, build, userType, orderSort, pn, ps, now); err != nil {
return
}
case "article":
if res, err = s.article(c, mid, zoneid, highlight, keyword, mobiApp, device, platform, buvid, filtered, order, sType, plat, categoryID, build, pn, ps, now); err != nil {
return
}
case "season2":
if res, err = s.srchDao.Season2(c, mid, keyword, mobiApp, device, platform, buvid, highlight, build, pn, ps); err != nil {
return
}
case "movie2":
if res, err = s.srchDao.MovieByType2(c, mid, keyword, mobiApp, device, platform, buvid, highlight, build, pn, ps); err != nil {
return
}
case "tag":
if res, err = s.channel(c, mid, keyword, mobiApp, platform, buvid, device, order, sType, build, pn, ps, highlight); err != nil {
return
}
}
if res == nil {
res = &search.TypeSearch{Items: []*search.Item{}}
}
return
}
// Suggest3 for search suggest
func (s *Service) Suggest3(c context.Context, mid int64, platform, buvid, keyword string, build, highlight int, mobiApp string, now time.Time) (res *search.SuggestionResult3) {
var (
suggest *search.Suggest3
err error
aids []int64
am map[int64]*api.Arc
)
res = &search.SuggestionResult3{}
if suggest, err = s.srchDao.Suggest3(c, mid, platform, buvid, keyword, build, highlight, mobiApp, now); err != nil {
log.Error("%+v", err)
return
}
for _, v := range suggest.Result {
if v.TermType == search.SuggestionJump {
if v.SubType == search.SuggestionAV {
aids = append(aids, v.Ref)
}
}
}
g, ctx := errgroup.WithContext(c)
if len(aids) != 0 {
g.Go(func() (err error) {
if am, err = s.arcDao.Archives(ctx, aids); err != nil {
log.Error("%+v", err)
err = nil
}
return
})
}
if err = g.Wait(); err != nil {
log.Error("%+v", err)
return
}
for _, v := range suggest.Result {
si := &search.Item{}
si.FromSuggest3(v, am)
res.List = append(res.List, si)
}
res.TrackID = suggest.TrackID
return
}
// convertNav deal with old search pageinfo to new.
func (s *Service) convertNav(all *search.Search, plat int8, build int, lang string) (nis []*search.NavInfo) {
const (
_showHide = 0
)
var (
season = "番剧"
upper = "用户"
movie = "影视"
article = "专栏"
)
if lang == model.Hant {
season = "番劇"
upper = "UP主"
movie = "影視"
article = "專欄"
}
nis = make([]*search.NavInfo, 0, 4)
// season
// media season
if all.PageInfo.MediaBangumi != nil {
var nav = &search.NavInfo{
Name: season,
Total: all.PageInfo.MediaBangumi.NumResults,
Pages: all.PageInfo.MediaBangumi.Pages,
Type: 7,
}
if all.PageInfo.MediaBangumi.NumResults > s.seasonNum {
nav.Show = s.seasonShowMore
} else {
nav.Show = _showHide
}
nis = append(nis, nav)
}
// upper
if all.PageInfo.BiliUser != nil {
var nav = &search.NavInfo{
Name: upper,
Total: all.PageInfo.BiliUser.NumResults,
Pages: all.PageInfo.BiliUser.Pages,
Type: 2,
}
nis = append(nis, nav)
}
// media movie
if all.PageInfo.MediaFt != nil {
var nav = &search.NavInfo{
Name: movie,
Total: all.PageInfo.MediaFt.NumResults,
Pages: all.PageInfo.MediaFt.Pages,
Type: 8,
}
if all.PageInfo.MediaFt.NumResults > s.movieNum {
nav.Show = s.movieShowMore
} else {
nav.Show = _showHide
}
nis = append(nis, nav)
}
if all.PageInfo.Article != nil {
var nav = &search.NavInfo{
Name: article,
Total: all.PageInfo.Article.NumResults,
Pages: all.PageInfo.Article.Pages,
Type: 6,
}
nis = append(nis, nav)
}
return
}
// upper search for upper
func (s *Service) upper(c context.Context, mid int64, keyword, mobiApp, device, platform, buvid, filtered, order string, biliUserVL, highlight, build, userType, orderSort, pn, ps int, now time.Time) (res *search.TypeSearch, err error) {
var (
owners []int64
follows map[int64]bool
)
if res, err = s.srchDao.Upper(c, mid, keyword, mobiApp, device, platform, buvid, filtered, order, biliUserVL, highlight, build, userType, orderSort, pn, ps, now); err != nil {
return
}
if res == nil || len(res.Items) == 0 {
return
}
owners = make([]int64, 0, len(res.Items))
for _, item := range res.Items {
owners = append(owners, item.Mid)
}
if len(owners) != 0 {
g, ctx := errgroup.WithContext(c)
if mid > 0 {
g.Go(func() error {
follows = s.accDao.Relations3(ctx, owners, mid)
return nil
})
}
if err = g.Wait(); err != nil {
log.Error("%+v", err)
return
}
for _, item := range res.Items {
if follows[item.Mid] {
item.Attentions = 1
}
}
}
return
}
// article search for article
func (s *Service) article(c context.Context, mid, zoneid int64, highlight int, keyword, mobiApp, device, platform, buvid, filtered, order, sType string, plat int8, categoryID, build, pn, ps int, now time.Time) (res *search.TypeSearch, err error) {
if res, err = s.srchDao.ArticleByType(c, mid, zoneid, keyword, mobiApp, device, platform, buvid, filtered, order, sType, plat, categoryID, build, highlight, pn, ps, now); err != nil {
log.Error("%+v", err)
return
}
if res != nil && len(res.Items) != 0 {
return
}
var mids []int64
for _, v := range res.Items {
mids = append(mids, v.Mid)
}
var infom map[int64]*account.Info
if infom, err = s.accDao.Infos3(c, mids); err != nil {
log.Error("%+v", err)
err = nil
return
}
for _, item := range res.Items {
if info, ok := infom[item.Mid]; ok {
item.Name = info.Name
}
}
return
}
// channel search for channel
func (s *Service) channel(c context.Context, mid int64, keyword, mobiApp, platform, buvid, device, order, sType string, build, pn, ps, highlight int) (res *search.TypeSearch, err error) {
var (
g *errgroup.Group
ctx context.Context
tags []int64
tagMyInfos []*tag.Tag
)
if res, err = s.srchDao.Channel(c, mid, keyword, mobiApp, platform, buvid, device, order, sType, build, pn, ps, highlight); err != nil {
return
}
if res == nil || len(res.Items) == 0 {
return
}
tags = make([]int64, 0, len(res.Items))
for _, item := range res.Items {
tags = append(tags, item.ID)
}
if len(tags) != 0 {
g, ctx = errgroup.WithContext(c)
if mid > 0 {
g.Go(func() error {
tagMyInfos, _ = s.tagDao.TagInfos(ctx, tags, mid)
return nil
})
}
if err = g.Wait(); err != nil {
log.Error("%+v", err)
return
}
for _, item := range res.Items {
for _, myInfo := range tagMyInfos {
if myInfo != nil && myInfo.TagID == item.ID {
item.IsAttention = myInfo.IsAtten
break
}
}
}
}
return
}

View File

@@ -0,0 +1,45 @@
package search
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-intl/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../cmd/app-intl-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func Test_Search(t *testing.T) {
Convey("get app banner", t, WithService(func(s *Service) {
_, err := s.Search(context.Background(), 1, 2, "", "", "", "", "", "", "", "", "", "", "", 3, 4, 5, 6, 7, 8, time.Now())
So(err, ShouldBeNil)
}))
}
func Test_SearchByType(t *testing.T) {
Convey("get app banner", t, WithService(func(s *Service) {
_, err := s.SearchByType(context.Background(), 1, 2, "", "", "", "", "", "", "", "", 3, 4, 5, 6, 7, 8, 8, 8, time.Now())
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,70 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"access.go",
"contain.go",
"infoc.go",
"service.go",
"view.go",
],
importpath = "go-common/app/interface/main/app-intl/service/view",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-intl/conf:go_default_library",
"//app/interface/main/app-intl/dao/account:go_default_library",
"//app/interface/main/app-intl/dao/archive:go_default_library",
"//app/interface/main/app-intl/dao/assist:go_default_library",
"//app/interface/main/app-intl/dao/audio:go_default_library",
"//app/interface/main/app-intl/dao/bangumi:go_default_library",
"//app/interface/main/app-intl/dao/coin:go_default_library",
"//app/interface/main/app-intl/dao/dm:go_default_library",
"//app/interface/main/app-intl/dao/favorite:go_default_library",
"//app/interface/main/app-intl/dao/location:go_default_library",
"//app/interface/main/app-intl/dao/manager:go_default_library",
"//app/interface/main/app-intl/dao/region:go_default_library",
"//app/interface/main/app-intl/dao/relation:go_default_library",
"//app/interface/main/app-intl/dao/resource:go_default_library",
"//app/interface/main/app-intl/dao/tag:go_default_library",
"//app/interface/main/app-intl/dao/thumbup:go_default_library",
"//app/interface/main/app-intl/dao/vip:go_default_library",
"//app/interface/main/app-intl/model:go_default_library",
"//app/interface/main/app-intl/model/bangumi:go_default_library",
"//app/interface/main/app-intl/model/manager:go_default_library",
"//app/interface/main/app-intl/model/region:go_default_library",
"//app/interface/main/app-intl/model/view:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/archive/model/archive:go_default_library",
"//app/service/main/location/model:go_default_library",
"//app/service/main/thumbup/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/text/translate/chinese:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,117 @@
package view
import (
"context"
"go-common/app/interface/main/app-intl/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"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
// ipLimit ip limit
func (s *Service) ipLimit(c context.Context, mid, aid int64, cdnIP string) (down int64, err error) {
var auth *locmdl.Auth
ip := metadata.String(c, metadata.RemoteIP)
if auth, err = s.locDao.Archive(c, aid, mid, ip, cdnIP); err != nil {
log.Error("%v", err)
err = nil // NOTE: return or ignore err???
}
if auth != nil {
down = auth.Down
switch auth.Play {
case locmdl.Forbidden:
err = ecode.AccessDenied
s.prom.Incr("ip_limit_access")
}
}
return
}
// areaLimit area limit
func (s *Service) areaLimit(c context.Context, plat int8, rid int16) (err error) {
ip := metadata.String(c, metadata.RemoteIP)
if rm, ok := s.region[plat]; !ok {
return
} else if r, ok := rm[rid]; ok && r != nil && r.Area != "" {
var auths map[string]*locmdl.Auth
if auths, err = s.locDao.AuthPIDs(c, r.Area, ip); err != nil {
log.Error("error(%v) area(%v) ip(%v)", err, r.Area, ip)
err = nil
return
}
if auth, ok := auths[r.Area]; ok && auth.Play == locmdl.Forbidden {
log.Error("zlimit region area(%s) ip(%v) forbid", r.Area, ip)
err = ecode.NothingFound
s.prom.Incr("region_limit_access")
}
}
return
}
// checkAceess check user Aceess
func (s *Service) checkAceess(c context.Context, mid, aid int64, state, access int, ak string) (err error) {
if state >= 0 && access == 0 {
return
}
if state < 0 {
if state == archive.StateForbidFixed {
log.Warn("archive(%d) is fixed", aid)
} else if state == archive.StateForbidUpDelete {
log.Warn("archive(%d) is deleted", aid)
} else {
log.Warn("mid(%d) have not access view not pass archive(%d) ", mid, aid)
}
err = ecode.NothingFound
return
}
if mid == 0 {
log.Warn("not login can not view(%d) state(%d) access(%d)", aid, state, access)
err = ecode.AccessDenied
s.prom.Incr("no_login_access")
return
}
card, err := s.accDao.Card3(c, mid)
if err != nil || card == nil {
if err != nil {
log.Error("s.accDao.Info(%d) error(%v)", mid, err)
}
err = ecode.AccessDenied
log.Warn("s.accDao.Info failed can not view(%d) state(%d) access(%d)", aid, state, access)
s.prom.Incr("err_login_access")
return
}
if access > 0 && int(card.Rank) < access && (card.Vip.Type == 0 || card.Vip.Status == 0 || card.Vip.Status == 2 || card.Vip.Status == 3) {
err = ecode.AccessDenied
log.Warn("mid(%d) rank(%d) vip(tp:%d,status:%d) have not access(%d) view archive(%d) ", mid, card.Rank, card.Vip.Type, card.Vip.Status, access, aid)
s.prom.Incr("login_access")
}
return
}
// checkVIP check user is vip or no .
func (s *Service) checkVIP(c context.Context, mid int64) (vip bool) {
var (
card *account.Card
err error
)
if mid > 0 {
if card, err = s.accDao.Card3(c, mid); err != nil || card == nil {
log.Warn("s.acc.Info(%d) error(%v)", mid, err)
return
}
vip = card.Vip.Type > 0 && card.Vip.Status == 1
}
return
}
func (s *Service) overseaCheck(a *archive.Archive3, plat int8) bool {
if a.AttrVal(archive.AttrBitOverseaLock) == archive.AttrYes && model.IsOverseas(plat) {
s.prom.Incr("oversea_access")
return true
}
return false
}

View File

@@ -0,0 +1,581 @@
package view
import (
"context"
"fmt"
"time"
"go-common/app/interface/main/app-intl/model"
"go-common/app/interface/main/app-intl/model/bangumi"
"go-common/app/interface/main/app-intl/model/manager"
"go-common/app/interface/main/app-intl/model/view"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
location "go-common/app/service/main/location/model"
thumbup "go-common/app/service/main/thumbup/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
"go-common/library/text/translate/chinese"
)
var (
_rate = map[int]int64{15: 464, 16: 464, 32: 1028, 48: 1328, 64: 2192, 74: 3192, 80: 3192, 112: 6192, 116: 6192, 66: 1820}
)
const (
_dmformat = "http://comment.bilibili.com/%d.xml"
_qn480 = 32
_qnAndroidBuild = 5325000
_qnIosBuild = 8170
)
// initReqUser init Req User
func (s *Service) initReqUser(c context.Context, v *view.View, mid int64, plat int8, build int) {
// owner ext
g, ctx := errgroup.WithContext(c)
if v.Author.Mid > 0 {
g.Go(func() (err error) {
v.OwnerExt.OfficialVerify.Type = -1
card, err := s.accDao.Card3(ctx, v.Author.Mid)
if err != nil {
log.Error("%+v", err)
err = nil
return
}
if card != nil {
otp := -1
odesc := ""
if card.Official.Role != 0 {
if card.Official.Role <= 2 {
otp = 0
} else {
otp = 1
}
odesc = card.Official.Title
}
v.OwnerExt.OfficialVerify.Type = otp
v.OwnerExt.OfficialVerify.Desc = odesc
v.OwnerExt.Vip.Type = int(card.Vip.Type)
v.OwnerExt.Vip.VipStatus = int(card.Vip.Status)
v.OwnerExt.Vip.DueDate = card.Vip.DueDate
v.Author.Name = card.Name
v.Author.Face = card.Face
}
return
})
g.Go(func() (err error) {
stat, err := s.relDao.Stat(c, v.Author.Mid)
if err != nil {
log.Error("%+v", err)
err = nil
return
}
if stat != nil {
v.OwnerExt.Fans = int(stat.Follower)
}
return
})
g.Go(func() error {
if ass, err := s.assDao.Assist(ctx, v.Author.Mid); err != nil {
log.Error("%+v", err)
} else {
v.OwnerExt.Assists = ass
}
return nil
})
}
// req user
v.ReqUser = &view.ReqUser{Favorite: 0, Attention: -999, Like: 0, Dislike: 0}
// check req user
if mid > 0 {
g.Go(func() error {
if is, _ := s.favDao.IsFav(ctx, mid, v.Aid); is {
v.ReqUser.Favorite = 1
}
return nil
})
g.Go(func() error {
res, err := s.thumbupDao.HasLike(ctx, mid, _businessLike, []int64{v.Aid})
if err != nil {
log.Error("%+v", err)
return nil
}
if typ, ok := res[v.Aid]; ok {
if typ == thumbup.StateLike {
v.ReqUser.Like = 1
} else if typ == thumbup.StateDislike {
v.ReqUser.Dislike = 1
}
}
return nil
})
g.Go(func() (err error) {
res, err := s.coinDao.ArchiveUserCoins(ctx, v.Aid, mid, _avTypeAv)
if err != nil {
log.Error("%+v", err)
err = nil
}
if res != nil && res.Multiply > 0 {
v.ReqUser.Coin = 1
}
return
})
if v.Author.Mid > 0 {
g.Go(func() error {
fl, err := s.accDao.Following3(ctx, mid, v.Author.Mid)
if err != nil {
log.Error("%+v", err)
return nil
}
if fl {
v.ReqUser.Attention = 1
}
return nil
})
}
}
if err := g.Wait(); err != nil {
log.Error("%+v", err)
}
}
// initRelateCMTag is.
func (s *Service) initRelateCMTag(c context.Context, v *view.View, plat int8, build int, mid int64, buvid, mobiApp, device, network, adExtra, from string, now time.Time, isTW bool) {
var (
rls []*view.Relate
mr *manager.Relate
err error
)
tids := s.initTag(c, v, mid)
g, ctx := errgroup.WithContext(c)
g.Go(func() (err error) {
if mid > 0 || buvid != "" {
if rls, v.UserFeature, v.ReturnCode, err = s.newRcmdRelate(ctx, plat, v.Aid, mid, buvid, mobiApp, from, build); err != nil {
log.Error("s.newRcmdRelate(%d) error(%+v)", v.Aid, err)
}
}
if len(rls) == 0 {
rls, err = s.dealRcmdRelate(ctx, plat, v.Aid)
log.Warn("s.dealRcmdRelate aid(%d) mid(%d) buvid(%s)", v.Aid, mid, buvid)
return
}
v.IsRec = 1
log.Warn("s.newRcmdRelate returncode(%s) aid(%d) mid(%d) buvid(%s)", v.ReturnCode, v.Aid, mid, buvid)
return
})
g.Go(func() (err error) {
mr = s.relateCache(ctx, plat, build, now, v.Aid, tids, v.TypeID)
return
})
if err = g.Wait(); err != nil {
log.Error("%+v", err)
return
}
if len(rls) == 0 {
s.prom.Incr("zero_relates")
return
}
var (
r *view.Relate
rm map[int]*view.Relate
)
aidm := map[int64]struct{}{}
if r, err = s.dealManagerRelate(c, plat, mr); err != nil {
log.Error("%+v", err)
}
if r != nil {
// 相关推荐的第一位是运营插入位
rm = map[int]*view.Relate{0: r}
aidm[r.Aid] = struct{}{}
}
// 权重:详情页稿件>相关推荐运营位稿件>AI相关推荐稿件
for _, rl := range rls {
// AI相关推荐稿件不能和详情页稿件重复
if rl.Aid == v.Aid {
continue
}
if len(rm) != 0 {
for {
// 相关推荐运营位稿件不能和详情页稿件重复
if r, ok := rm[len(v.Relates)]; ok && r.Aid != v.Aid {
v.Relates = append(v.Relates, r)
continue
}
// AI相关推荐稿件不能和相关推荐运营位稿件重复
if _, ok := aidm[rl.Aid]; !ok {
v.Relates = append(v.Relates, rl)
}
break
}
} else {
v.Relates = append(v.Relates, rl)
}
}
if isTW {
for _, rl := range v.Relates {
rl.Title = chinese.Convert(c, rl.Title)
}
}
}
// initMovie is.
func (s *Service) initMovie(c context.Context, v *view.View, mid int64, build int, mobiApp, device string, nMovie bool) (err error) {
s.pHit.Incr("is_movie")
var m *bangumi.Movie
if m, err = s.banDao.Movie(c, v.Aid, mid, build, mobiApp, device); err != nil || m == nil {
log.Error("%+v", err)
err = ecode.NothingFound
s.pMiss.Incr("err_is_PGC")
return
}
if v.Rights.HD5 == 1 && m.PayUser.Status == 0 && !s.checkVIP(c, mid) {
v.Rights.HD5 = 0
}
if len(m.List) == 0 {
err = ecode.NothingFound
return
}
vps := make([]*view.Page, 0, len(m.List))
for _, l := range m.List {
vp := &view.Page{
Page3: &archive.Page3{Cid: l.Cid, Page: int32(l.Page), From: l.Type, Part: l.Part, Vid: l.Vid},
}
vps = append(vps, vp)
}
m.List = nil
// view
v.Pages = vps
v.Rights.Download = int32(m.AllowDownload)
m.AllowDownload = 0
v.Rights.Bp = 0
if nMovie {
v.Movie = m
v.Desc = m.Season.Evaluate
}
return
}
// initPGC is.
func (s *Service) initPGC(c context.Context, v *view.View, mid int64, build int, mobiApp, device string) (err error) {
s.pHit.Incr("is_PGC")
var season *bangumi.Season
if season, err = s.banDao.PGC(c, v.Aid, mid, build, mobiApp, device); err != nil {
log.Error("%+v", err)
err = ecode.NothingFound
s.pMiss.Incr("err_is_PGC")
return
}
if season != nil {
if season.Player != nil {
if len(v.Pages) != 0 {
if season.Player.Cid != 0 {
v.Pages[0].Cid = season.Player.Cid
}
if season.Player.From != "" {
v.Pages[0].From = season.Player.From
}
if season.Player.Vid != "" {
v.Pages[0].Vid = season.Player.Vid
}
}
season.Player = nil
}
if season.AllowDownload == "1" {
v.Rights.Download = 1
} else {
v.Rights.Download = 0
}
if season.SeasonID != "" {
season.AllowDownload = ""
v.Season = season
}
}
if v.Rights.HD5 == 1 && !s.checkVIP(c, mid) {
v.Rights.HD5 = 0
}
v.Rights.Bp = 0
return
}
// initPages is.
func (s *Service) initPages(c context.Context, vs *view.ViewStatic, ap []*archive.Page3) {
pages := make([]*view.Page, 0, len(ap))
for _, v := range ap {
page := &view.Page{}
metas := make([]*view.Meta, 0, 4)
for q, r := range _rate {
meta := &view.Meta{
Quality: q,
Size: int64(float64(r*v.Duration) * 1.1 / 8.0),
}
metas = append(metas, meta)
}
if vs.AttrVal(archive.AttrBitIsBangumi) == archive.AttrYes {
v.From = "bangumi"
}
page.Page3 = v
page.Metas = metas
page.DMLink = fmt.Sprintf(_dmformat, v.Cid)
pages = append(pages, page)
}
vs.Pages = pages
}
// initDownload is.
func (s *Service) initDownload(c context.Context, v *view.View, mid int64, cdnIP string) (err error) {
var download int64
if v.AttrVal(archive.AttrBitLimitArea) == archive.AttrYes {
if download, err = s.ipLimit(c, mid, v.Aid, cdnIP); err != nil {
return
}
} else {
download = location.AllowDown
}
if download == location.ForbiddenDown {
v.Rights.Download = int32(download)
return
}
for _, p := range v.Pages {
if p.From == "qq" {
download = location.ForbiddenDown
break
}
}
v.Rights.Download = int32(download)
return
}
// initContributions is.
func (s *Service) initContributions(c context.Context, v *view.View, isTW bool) {
const _count = 5
if v.ReqUser != nil && v.ReqUser.Attention == 1 {
return
}
var hasAudio bool
for _, page := range v.Pages {
if page.Audio != nil {
hasAudio = true
break
}
}
if hasAudio || v.OwnerExt.Archives < 20 {
return
}
aids, err := s.arcDao.ViewContributeCache(c, v.Author.Mid)
if err != nil {
log.Error("%+v", err)
return
}
if len(aids) < _count+1 {
return
}
as, err := s.arcDao.Archives(c, aids)
if err != nil {
log.Error("%+v", err)
return
}
if len(as) == 0 {
return
}
ctbt := make([]*view.Contribution, 0, len(as))
for _, aid := range aids {
if a, ok := as[aid]; ok && a.IsNormal() {
if a.Aid != v.Aid {
if isTW {
a.Title = chinese.Convert(c, a.Title)
}
vc := &view.Contribution{Aid: a.Aid, Title: a.Title, Pic: a.Pic, Author: a.Author, Stat: a.Stat, CTime: a.PubDate}
ctbt = append(ctbt, vc)
}
}
}
if len(ctbt) > _count {
ctbt = ctbt[:_count]
}
if len(ctbt) == _count {
v.Contributions = ctbt
}
}
// initAudios is.
func (s *Service) initAudios(c context.Context, v *view.View) {
pLen := len(v.Pages)
if pLen == 0 || pLen > 100 {
return
}
if pLen > 50 {
pLen = 50
}
cids := make([]int64, 0, len(v.Pages[:pLen]))
for _, p := range v.Pages[:pLen] {
cids = append(cids, p.Cid)
}
vam, err := s.audioDao.AudioByCids(c, cids)
if err != nil {
log.Error("%+v", err)
return
}
if len(vam) != 0 {
for _, p := range v.Pages[:pLen] {
if va, ok := vam[p.Cid]; ok {
p.Audio = va
}
}
if len(v.Pages) == 1 {
if va, ok := vam[v.Pages[0].Cid]; ok {
v.Audio = va
}
}
}
}
// initTag is.
func (s *Service) initTag(c context.Context, v *view.View, mid int64) (tids []int64) {
tags, err := s.tagDao.ArcTags(c, v.Aid, mid)
if err != nil {
log.Error("%+v", err)
return
}
tids = make([]int64, 0, len(tags))
for _, tag := range tags {
tids = append(tids, tag.ID)
}
v.Tag = tags
return
}
// initDM is.
func (s *Service) initDM(c context.Context, v *view.View) {
const (
_dmTypeAv = 1
_dmPlatMobie = 1
)
pLen := len(v.Pages)
if pLen == 0 || pLen > 100 {
return
}
if pLen > 50 {
pLen = 50
}
cids := make([]int64, 0, len(v.Pages[:pLen]))
for _, p := range v.Pages[:pLen] {
cids = append(cids, p.Cid)
}
res, err := s.dmDao.SubjectInfos(c, _dmTypeAv, _dmPlatMobie, cids...)
if err != nil {
log.Error("%+v", err)
return
}
if len(res) == 0 {
return
}
for _, p := range v.Pages[:pLen] {
if r, ok := res[p.Cid]; ok {
p.DM = r
}
}
}
// dealRcmdRelate is.
func (s *Service) dealRcmdRelate(c context.Context, plat int8, aid int64) (rls []*view.Relate, err error) {
if rls, err = s.arcDao.RelatesCache(c, aid); err != nil {
return
}
if len(rls) != 0 {
return
}
s.prom.Incr("need_relates")
var aids []int64
if aids, err = s.arcDao.RelateAids(c, aid); err != nil {
return
}
if len(aids) == 0 {
return
}
var as map[int64]*api.Arc
if as, err = s.arcDao.Archives(c, aids); err != nil {
return
}
for _, aid := range aids {
if a, ok := as[aid]; ok {
if s.overseaCheck(archive.BuildArchive3(a), plat) || !a.IsNormal() {
continue
}
r := &view.Relate{}
r.FromAv(a, "", "", nil)
rls = append(rls, r)
}
}
if len(rls) != 0 {
// 如果是繁体区会修改relate的titleaddcache是异步操作需要深度拷贝避免并发读写的panci
rels := make([]*view.Relate, 0, len(rls))
for _, rl := range rls {
r := &view.Relate{}
*r = *rl
rels = append(rels, r)
}
s.arcDao.AddRelatesCache(aid, rels)
}
return
}
// dealManagerRelate is.
func (s *Service) dealManagerRelate(c context.Context, plat int8, mr *manager.Relate) (r *view.Relate, err error) {
if mr == nil || mr.Param < 1 {
return
}
switch mr.Goto {
case model.GotoAv:
var a *api.Arc
if a, err = s.arcDao.Archive(c, mr.Param); err != nil {
return
}
if a != nil {
r = &view.Relate{}
r.FromOperate(mr, a, model.FromOperation)
}
}
return
}
// newRcmdRelate is.
func (s *Service) newRcmdRelate(c context.Context, plat int8, aid, mid int64, buvid, mobiApp, from string, build int) (rls []*view.Relate, userFeature, returnCode string, err error) {
recData, userFeature, returnCode, err := s.arcDao.NewRelateAids(c, aid, mid, build, buvid, from, plat)
if err != nil || len(recData) == 0 {
return
}
var (
aids []int64
arcm map[int64]*api.Arc
)
for _, rec := range recData {
switch rec.Goto {
case model.GotoAv:
aids = append(aids, rec.Oid)
}
}
if len(aids) == 0 {
return
}
if arcm, err = s.arcDao.Archives(c, aids); err != nil {
log.Error("%+v", err)
return
}
if len(arcm) == 0 {
return
}
for _, rec := range recData {
switch rec.Goto {
case model.GotoAv:
arc, ok := arcm[rec.Oid]
if !ok || s.overseaCheck(archive.BuildArchive3(arc), plat) || !arc.IsNormal() {
continue
}
r := &view.Relate{AvFeature: rec.AvFeature, Source: rec.Source}
r.FromAv(arc, "", rec.TrackID, nil)
rls = append(rls, r)
}
}
return
}

View File

@@ -0,0 +1,132 @@
package view
import (
"bytes"
"fmt"
"strconv"
"time"
"go-common/app/interface/main/app-intl/conf"
"go-common/app/interface/main/app-intl/model/view"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/log/infoc"
)
// viewInfoc struct
type viewInfoc struct {
mid string
client string
build string
buvid string
disid string
ip string
api string
now string
aid string
err string
from string
trackid string
autoplay string
}
// relateInfoc struct
type relateInfoc struct {
mid string
aid string
client string
buvid string
disid string
ip string
api string
now string
isRcmmnd int8
rls []*view.Relate
trackid string
build string
returnCode string
userFeature string
from string
}
//ViewInfoc view infoc
func (s *Service) ViewInfoc(mid int64, plat int, trackid, aid, ip, api, build, buvid, disid, from string, now time.Time, err error, autoplay int) {
s.infoc(viewInfoc{strconv.FormatInt(mid, 10), strconv.Itoa(plat), build, buvid, disid, ip, api, strconv.FormatInt(now.Unix(), 10), aid, strconv.Itoa(ecode.Cause(err).Code()), from, trackid, strconv.Itoa(autoplay)})
}
// RelateInfoc Relate Infoc
func (s *Service) RelateInfoc(mid, aid int64, plat int, trackid, build, buvid, disid, ip, api, returnCode, userFeature, from string, rls []*view.Relate, now time.Time, isRec int8) {
s.infoc(relateInfoc{strconv.FormatInt(mid, 10), strconv.FormatInt(aid, 10), strconv.Itoa(plat), buvid, disid, ip, api, strconv.FormatInt(now.Unix(), 10), isRec, rls, trackid, build, returnCode, userFeature, from})
}
// infoc is.
func (s *Service) infoc(i interface{}) {
select {
case s.inCh <- i:
default:
log.Warn("cacheproc chan full")
}
}
// WriteViewInfoc Write View Infoc
func (s *Service) infocproc() {
const (
noItem = `{"section":{"id":"相关视频","pos":1,"from_item":"%s","items":[]}}`
)
var (
msg1 = []byte(`{"section":{"id":"相关视频","pos":1,"from_item":"`)
msg2 = []byte(`","items":[`)
msg3 = []byte(`{"id":`)
msg4 = []byte(`,"pos":`)
msg5 = []byte(`,"goto":"`)
msg6 = []byte(`","from":"`)
msg7 = []byte(`","source":"`)
msg8 = []byte(`","av_feature":`)
msg9 = []byte(`,"type":1,"url":""},`)
infView = infoc.New(conf.Conf.ViewInfoc)
infRelate = infoc.New(conf.Conf.RelateInfoc)
buf bytes.Buffer
list string
)
for {
i := <-s.inCh
switch v := i.(type) {
case viewInfoc:
infView.Info(v.ip, v.now, v.api, v.buvid, v.mid, v.client, v.aid, v.disid, v.err, v.from, v.build, v.trackid, v.autoplay)
case relateInfoc:
if len(v.rls) > 0 {
buf.Write(msg1)
buf.WriteString(v.aid)
buf.Write(msg2)
for key, value := range v.rls {
buf.Write(msg3)
buf.WriteString(strconv.Itoa(int(value.Aid)))
buf.Write(msg4)
buf.WriteString(strconv.Itoa(key + 1))
buf.Write(msg5)
buf.WriteString(value.Goto)
buf.Write(msg6)
buf.WriteString(value.From)
buf.Write(msg7)
buf.WriteString(value.Source)
buf.Write(msg8)
if value.AvFeature != nil {
buf.Write(value.AvFeature)
} else {
buf.Write([]byte(`""`))
}
buf.Write(msg9)
}
buf.Truncate(buf.Len() - 1)
buf.WriteString(`]}}`)
list = buf.String()
buf.Reset()
} else {
list = fmt.Sprintf(noItem, v.aid)
}
infRelate.Info(v.ip, v.now, v.api, v.buvid, v.mid, v.client, "2", list, v.disid, v.isRcmmnd, v.trackid, v.build, v.returnCode, v.userFeature, v.from)
default:
log.Warn("infocproc can't process the type")
}
}
}

View File

@@ -0,0 +1,237 @@
package view
import (
"context"
"time"
"go-common/app/interface/main/app-intl/conf"
"go-common/app/interface/main/app-intl/model/region"
accdao "go-common/app/interface/main/app-intl/dao/account"
arcdao "go-common/app/interface/main/app-intl/dao/archive"
assdao "go-common/app/interface/main/app-intl/dao/assist"
audiodao "go-common/app/interface/main/app-intl/dao/audio"
bandao "go-common/app/interface/main/app-intl/dao/bangumi"
coindao "go-common/app/interface/main/app-intl/dao/coin"
// creativedao "go-common/app/interface/main/app-intl/dao/creative"
dmdao "go-common/app/interface/main/app-intl/dao/dm"
favdao "go-common/app/interface/main/app-intl/dao/favorite"
managerdao "go-common/app/interface/main/app-intl/dao/manager"
rgndao "go-common/app/interface/main/app-intl/dao/region"
reldao "go-common/app/interface/main/app-intl/dao/relation"
rscdao "go-common/app/interface/main/app-intl/dao/resource"
tagdao "go-common/app/interface/main/app-intl/dao/tag"
thumbupdao "go-common/app/interface/main/app-intl/dao/thumbup"
locdao "go-common/app/interface/main/app-intl/dao/location"
vipdao "go-common/app/interface/main/app-intl/dao/vip"
"go-common/app/interface/main/app-intl/model"
"go-common/app/interface/main/app-intl/model/manager"
"go-common/app/interface/main/app-intl/model/view"
"go-common/library/log"
"go-common/library/stat/prom"
)
// Service is view service
type Service struct {
c *conf.Config
pHit *prom.Prom
pMiss *prom.Prom
prom *prom.Prom
// dao
accDao *accdao.Dao
arcDao *arcdao.Dao
tagDao *tagdao.Dao
favDao *favdao.Dao
banDao *bandao.Dao
rgnDao *rgndao.Dao
assDao *assdao.Dao
audioDao *audiodao.Dao
thumbupDao *thumbupdao.Dao
rscDao *rscdao.Dao
relDao *reldao.Dao
coinDao *coindao.Dao
vipDao *vipdao.Dao
mngDao *managerdao.Dao
dmDao *dmdao.Dao
locDao *locdao.Dao
// creativeDao *creativedao.Dao
// tick
tick time.Duration
// region
region map[int8]map[int16]*region.Region
// chan
inCh chan interface{}
// vip active cache
vipActiveCache map[int]string
vipTick time.Duration
// mamager cache
RelateCache []*manager.Relate
// player icon
playerIcon *view.PlayerIcon
// view relate game from AI
RelateGameCache map[int64]int64
}
// New new archive
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
pHit: prom.CacheHit,
pMiss: prom.CacheMiss,
prom: prom.BusinessInfoCount,
// dao
accDao: accdao.New(c),
arcDao: arcdao.New(c),
tagDao: tagdao.New(c),
favDao: favdao.New(c),
banDao: bandao.New(c),
rgnDao: rgndao.New(c),
assDao: assdao.New(c),
relDao: reldao.New(c),
coinDao: coindao.New(c),
audioDao: audiodao.New(c),
thumbupDao: thumbupdao.New(c),
rscDao: rscdao.New(c),
vipDao: vipdao.New(c),
mngDao: managerdao.New(c),
dmDao: dmdao.New(c),
locDao: locdao.New(c),
// tick
tick: time.Duration(c.Tick),
// region
region: map[int8]map[int16]*region.Region{},
// chan
inCh: make(chan interface{}, 1024),
// vip
vipActiveCache: make(map[int]string),
vipTick: time.Duration(c.View.VipTick),
// manager
RelateCache: []*manager.Relate{},
// player icon
playerIcon: &view.PlayerIcon{},
}
// load data
s.loadRegion()
s.loadPlayerIcon()
s.loadVIPActive()
s.loadManager()
go s.infocproc()
go s.tickproc()
go s.vipproc()
return
}
// Ping is dao ping.
func (s *Service) Ping(c context.Context) (err error) {
return s.arcDao.Ping(c)
}
// tickproc tick load cache.
func (s *Service) tickproc() {
for {
time.Sleep(s.tick)
s.loadPlayerIcon()
s.loadManager()
}
}
// vipproc tick load vip cache.
func (s *Service) vipproc() {
for {
time.Sleep(s.vipTick)
s.loadVIPActive()
}
}
// loadVIPActive tick load vip active cache.
func (s *Service) loadVIPActive() {
var (
va map[int]string
err error
)
va = make(map[int]string)
if va[view.VIPActiveView], err = s.vipDao.VIPActive(context.TODO(), view.VIPActiveView); err != nil {
log.Error("s.vipDao.VIPActinve(%d) error(%v)", view.VIPActiveView, err)
return
}
s.vipActiveCache = va
log.Info("load vip active success")
}
// loadRegion is.
func (s *Service) loadRegion() {
res, err := s.rgnDao.Seconds(context.TODO())
if err != nil {
log.Error("%+v", err)
return
}
s.region = res
}
// loadManager is.
func (s *Service) loadManager() {
r, err := s.mngDao.Relate(context.TODO())
if err != nil {
log.Error("%+v", err)
return
}
s.RelateCache = r
}
// loadPlayerIcon is.
func (s *Service) loadPlayerIcon() {
res, err := s.rscDao.PlayerIcon(context.TODO())
if err != nil {
log.Error("%+v", err)
return
}
if res != nil {
s.playerIcon = &view.PlayerIcon{URL1: res.URL1, Hash1: res.Hash1, URL2: res.URL2, Hash2: res.Hash2, CTime: res.CTime}
} else {
s.playerIcon = nil
}
}
// relateCache is.
func (s *Service) relateCache(c context.Context, plat int8, build int, now time.Time, aid int64, tids []int64, rid int32) (relate *manager.Relate) {
rs := s.RelateCache
rls := make([]*manager.Relate, 0, len(rs))
if len(rs) != 0 {
LOOP:
for _, r := range rs {
if vs, ok := r.Versions[plat]; ok {
for _, v := range vs {
if model.InvalidBuild(build, v.Build, v.Condition) {
continue LOOP
}
}
if (r.STime == 0 || now.After(r.STime.Time())) && (r.ETime == 0 || now.Before(r.ETime.Time())) {
rls = append(rls, r)
}
}
}
}
for _, r := range rls {
if _, ok := r.Aids[aid]; ok {
relate = r
break
}
if len(tids) != 0 {
for _, tid := range tids {
if _, ok := r.Tids[tid]; ok {
relate = r
break
}
}
}
if _, ok := r.Rids[int64(rid)]; ok {
relate = r
break
}
}
return
}

View File

@@ -0,0 +1,192 @@
package view
import (
"context"
"time"
"go-common/app/interface/main/app-intl/model"
"go-common/app/interface/main/app-intl/model/view"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
"go-common/library/text/translate/chinese"
)
const (
// _descLen is.
_descLen = 250
// _avTypeAv is.
_avTypeAv = 1
// _businessLike is.
_businessLike = "archive"
)
// View all view data.
func (s *Service) View(c context.Context, mid, aid, movieID int64, plat int8, build int, ak, mobiApp, device, buvid, cdnIP, network, adExtra, from string, now time.Time, locale string) (v *view.View, err error) {
if v, err = s.ViewPage(c, mid, aid, movieID, plat, build, ak, mobiApp, device, cdnIP, true, now, locale); err != nil {
ip := metadata.String(c, metadata.RemoteIP)
if err == ecode.AccessDenied || err == ecode.NothingFound {
log.Warn("s.ViewPage() mid(%d) aid(%d) movieID(%d) plat(%d) ak(%s) ip(%s) cdn_ip(%s) error(%v)", mid, aid, movieID, plat, ak, ip, cdnIP, err)
} else {
log.Error("s.ViewPage() mid(%d) aid(%d) movieID(%d) plat(%d) ak(%s) ip(%s) cdn_ip(%s) error(%v)", mid, aid, movieID, plat, ak, ip, cdnIP, err)
}
return
}
isTW := model.TWLocale(locale)
g, ctx := errgroup.WithContext(c)
g.Go(func() (err error) {
v.VIPActive = s.vipActiveCache[view.VIPActiveView]
return
})
g.Go(func() (err error) {
s.initReqUser(ctx, v, mid, plat, build)
if v.AttrVal(archive.AttrBitIsPGC) != archive.AttrYes {
s.initContributions(ctx, v, isTW)
}
return
})
g.Go(func() (err error) {
s.initRelateCMTag(ctx, v, plat, build, mid, buvid, mobiApp, device, network, adExtra, from, now, isTW)
return
})
if v.AttrVal(archive.AttrBitIsPGC) != archive.AttrYes {
g.Go(func() (err error) {
s.initDM(ctx, v)
return
})
g.Go(func() (err error) {
s.initAudios(ctx, v)
return
})
if len([]rune(v.Desc)) > _descLen {
g.Go(func() (err error) {
if desc, _ := s.arcDao.Description(ctx, v.Aid); desc != "" {
v.Desc = desc
}
return
})
}
}
if err = g.Wait(); err != nil {
log.Error("%+v", err)
}
return
}
// ViewPage view page data.
func (s *Service) ViewPage(c context.Context, mid, aid, movieID int64, plat int8, build int, ak, mobiApp, device, cdnIP string, nMovie bool, now time.Time, locale string) (v *view.View, err error) {
if aid == 0 && movieID == 0 {
err = ecode.NothingFound
return
}
var (
vs *view.ViewStatic
vp *archive.View3
seasoninfo map[int64]int64
ok bool
)
if movieID != 0 {
if seasoninfo, err = s.banDao.SeasonidAid(c, movieID, now); err != nil {
log.Error("%+v", err)
err = ecode.NothingFound
return
}
if aid, ok = seasoninfo[movieID]; !ok || aid == 0 {
err = ecode.NothingFound
return
}
var a *api.Arc
if a, err = s.arcDao.Archive3(c, aid); err != nil {
log.Error("%+v", err)
err = ecode.NothingFound
return
}
if a == nil {
err = ecode.NothingFound
return
}
vs = &view.ViewStatic{Archive3: archive.BuildArchive3(a)}
s.prom.Incr("from_movieID")
} else {
if vp, err = s.arcDao.ViewCache(c, aid); err != nil {
log.Error("%+v", err)
}
if vp == nil || vp.Archive3 == nil || len(vp.Pages) == 0 || vp.AttrVal(archive.AttrBitIsMovie) == archive.AttrYes {
if vp, err = s.arcDao.View3(c, aid); err != nil {
log.Error("%+v", err)
err = ecode.NothingFound
return
}
}
if vp == nil || vp.Archive3 == nil || len(vp.Pages) == 0 {
err = ecode.NothingFound
return
}
vs = &view.ViewStatic{Archive3: vp.Archive3}
s.initPages(c, vs, vp.Pages)
s.prom.Incr("from_aid")
}
isTW := model.TWLocale(locale)
if isTW {
out := chinese.Converts(c, vs.Title, vs.Desc)
vs.Title = out[vs.Title]
vs.Desc = out[vs.Desc]
}
// TODO fuck chanpin
vs.Stat.DisLike = 0
if s.overseaCheck(vs.Archive3, plat) {
err = ecode.AreaLimit
return
}
// check region area limit
if err = s.areaLimit(c, plat, int16(vs.TypeID)); err != nil {
return
}
v = &view.View{ViewStatic: vs, DMSeg: 1, PlayerIcon: s.playerIcon}
if v.AttrVal(archive.AttrBitIsPGC) != archive.AttrYes {
// check access
if err = s.checkAceess(c, mid, v.Aid, int(v.State), int(v.Access), ak); err != nil {
// archive is ForbitFixed and Transcoding and StateForbitDistributing need analysis history body .
if v.State != archive.StateForbidFixed {
return
}
err = nil
}
if v.Access > 0 {
v.Stat.View = 0
}
}
g, ctx := errgroup.WithContext(c)
if mid != 0 {
g.Go(func() (err error) {
v.History, _ = s.arcDao.Progress(ctx, v.Aid, mid)
return
})
}
if v.AttrVal(archive.AttrBitIsPGC) == archive.AttrYes {
if v.AttrVal(archive.AttrBitIsMovie) != archive.AttrYes {
g.Go(func() error {
return s.initPGC(ctx, v, mid, build, mobiApp, device)
})
} else {
g.Go(func() error {
return s.initMovie(ctx, v, mid, build, mobiApp, device, nMovie)
})
}
} else {
g.Go(func() (err error) {
if err = s.initDownload(ctx, v, mid, cdnIP); err != nil {
ip := metadata.String(ctx, metadata.RemoteIP)
log.Error("aid(%d) mid(%d) ip(%s) cdn_ip(%s) error(%+v)", v.Aid, mid, ip, cdnIP, err)
}
return
})
}
if err = g.Wait(); err != nil {
log.Error("%+v", err)
}
return
}