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 = [
"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
}