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,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["banner_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//app/interface/main/app-show/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["banner.go"],
importpath = "go-common/app/interface/main/app-show/service/banner",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//app/interface/main/app-show/dao/resource:go_default_library",
"//app/interface/main/app-show/model:go_default_library",
"//app/interface/main/app-show/model/banner:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom: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,151 @@
package banner
import (
"context"
"strings"
"time"
"go-common/app/interface/main/app-show/conf"
resdao "go-common/app/interface/main/app-show/dao/resource"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/banner"
resource "go-common/app/service/main/resource/model"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/stat/prom"
)
var (
_banners = map[string]map[string]map[int8]int{
"discover": map[string]map[int8]int{
"bottom": map[int8]int{
model.PlatIPhone: 452,
model.PlatIPad: 800,
model.PlatIPhoneI: 1085,
model.PlatIPadI: 1255,
},
},
"mine": map[string]map[int8]int{
"top": map[int8]int{
model.PlatIPhone: 449,
model.PlatIPad: 801,
model.PlatIPhoneI: 1089,
model.PlatIPadI: 1259,
},
"center": map[int8]int{
model.PlatIPhone: 450,
model.PlatIPad: 802,
model.PlatIPhoneI: 1093,
model.PlatIPadI: 1263,
},
"bottom": map[int8]int{
model.PlatIPhone: 451,
model.PlatIPad: 803,
model.PlatIPhoneI: 1097,
model.PlatIPadI: 1267,
},
},
}
_bannersPlat = map[int8]string{
model.PlatIPhone: "452,499,450,451",
model.PlatIPad: "800,801,802,803",
model.PlatIPhoneI: "1085,1089,1093,1097",
model.PlatIPadI: "1255,1259,1263,1267",
}
)
// Service is banner service.
type Service struct {
// dao *bndao.Dao
res *resdao.Dao
tick time.Duration
bannerCache map[int8]map[int][]*resource.Banner
// prom
prmobi *prom.Prom
}
// New new a banner service.
func New(c *conf.Config) (s *Service) {
s = &Service{
// dao: bndao.New(c),
res: resdao.New(c),
tick: time.Duration(c.Tick),
bannerCache: map[int8]map[int][]*resource.Banner{},
// prom
prmobi: prom.BusinessInfoCount,
}
s.load()
go s.loadproc()
return
}
// Display get banner.
func (s *Service) Display(c context.Context, plat int8, build int, channel, module, position, mobiApp string) (res map[string][]*banner.Banner) {
ip := metadata.String(c, metadata.RemoteIP)
res = s.getCache(c, plat, build, channel, module, position, ip)
s.prmobi.Incr("banner_plat_" + mobiApp)
return
}
// getCahce get banner from cache.
func (s *Service) getCache(c context.Context, plat int8, build int, channel, module, position, ip string) (res map[string][]*banner.Banner) {
res = map[string][]*banner.Banner{}
var (
resIDs = _bannersPlat[plat]
err error
resbs map[int][]*resource.Banner
plm = s.bannerCache[plat]
resID int
)
if resbs, err = s.res.ResBanner(c, plat, build, 0, resIDs, channel, ip, "", "", "", "", "", false); err != nil || len(resbs) == 0 {
log.Error("s.res.ResBanner is null or err(%v)", err)
resbs = plm
}
mds := strings.Split(module, ",")
poss := strings.Split(position, ",")
for _, md := range mds {
for _, pos := range poss {
resID = _banners[md][pos][plat]
res[md+"_"+pos] = s.resBanners(resbs[resID])
}
}
return
}
// resBannersplat
func (s *Service) resBanners(rbs []*resource.Banner) (res []*banner.Banner) {
for _, rb := range rbs {
b := &banner.Banner{}
b.ResChangeBanner(rb)
res = append(res, b)
}
return
}
// load load all banner.
func (s *Service) load() {
var (
resbs = map[int8]map[int][]*resource.Banner{}
)
for plat, resIDStr := range _bannersPlat {
mobiApp := model.MobiApp(plat)
res, err := s.res.ResBanner(context.TODO(), plat, 515007, 0, resIDStr, "master", "", "", "", mobiApp, "", "", false)
if err != nil || len(res) == 0 {
log.Error("s.res.ResBanner is null or err(%v)", err)
return
}
resbs[plat] = res
}
if len(resbs) > 0 {
s.bannerCache = resbs
}
log.Info("banner cacheproc success")
}
// cacheproc load cache.
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
s.load()
}
}

View File

@@ -0,0 +1,39 @@
package banner
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-show/conf"
"go-common/app/interface/main/app-show/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-show-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestDisplay(t *testing.T) {
Convey("get Display data", t, WithService(func(s *Service) {
res := s.Display(context.TODO(), model.PlatIPhone, 0, "", "", "", "iphone")
So(res, ShouldNotBeEmpty)
}))
}

View File

@@ -0,0 +1,53 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["daily_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//app/interface/main/app-show/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["daily.go"],
importpath = "go-common/app/interface/main/app-show/service/daily",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//app/interface/main/app-show/dao/archive:go_default_library",
"//app/interface/main/app-show/dao/card:go_default_library",
"//app/interface/main/app-show/dao/tag:go_default_library",
"//app/interface/main/app-show/model:go_default_library",
"//app/interface/main/app-show/model/card:go_default_library",
"//app/interface/main/app-show/model/daily:go_default_library",
"//app/service/main/archive/api: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,406 @@
package daily
import (
"context"
"fmt"
"strconv"
"time"
"go-common/app/interface/main/app-show/conf"
arcdao "go-common/app/interface/main/app-show/dao/archive"
carddao "go-common/app/interface/main/app-show/dao/card"
tagdao "go-common/app/interface/main/app-show/dao/tag"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/card"
"go-common/app/interface/main/app-show/model/daily"
"go-common/app/service/main/archive/api"
"go-common/library/log"
)
const (
_initDailyKey = "daily_key_%d_%d"
_initColumnKey = "column_key_%d_%d"
_initColumnListKey = "columnlist_key_%d_%d"
)
var (
_emptyDaily = []*daily.Show{}
_emptyList = []*daily.Item{}
)
type Service struct {
c *conf.Config
cdao *carddao.Dao
arc *arcdao.Dao
tag *tagdao.Dao
// tick
tick time.Duration
// columnsCache
columnsCache map[string]*card.Column
// card
cardCache map[string][]*daily.Show
columnCache map[string]*daily.Show
columnListCache map[string][]*daily.Item
cardListCache map[string][]*card.ColumnList
}
// New new a daily service.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
cdao: carddao.New(c),
arc: arcdao.New(c),
tag: tagdao.New(c),
// tick
tick: time.Duration(c.Tick),
// columnsCache
columnsCache: map[string]*card.Column{},
// card
cardCache: map[string][]*daily.Show{},
columnCache: map[string]*daily.Show{},
columnListCache: map[string][]*daily.Item{},
cardListCache: map[string][]*card.ColumnList{},
}
now := time.Now()
s.loadColumnListCache(now)
s.loadColumnsCache()
s.loadNperCache(now)
go s.cacheproc()
return
}
// Daily
func (s *Service) Daily(c context.Context, plat int8, build, dailyID, pn, ps int) (res []*daily.Show) {
if pn > 0 {
pn = pn - 1
}
start := pn * ps
end := start + ps
key := fmt.Sprintf(_initColumnKey, plat, dailyID)
if column, ok := s.columnsCache[key]; ok {
if model.InvalidBuild(build, column.Build, column.Condition) {
res = _emptyDaily
return
}
cardKey := fmt.Sprintf(_initDailyKey, plat, dailyID)
if cards, ok := s.cardCache[cardKey]; ok {
for _, sw := range cards {
if model.InvalidBuild(build, sw.Build, sw.Condition) {
continue
}
res = append(res, sw)
}
resLen := len(res)
if resLen > end {
res = res[start:end]
} else if resLen > start {
res = res[start:]
} else {
res = _emptyDaily
}
}
}
if len(res) == 0 {
res = _emptyDaily
}
return
}
// ColumnList
func (s *Service) ColumnList(plat int8, build, columnID int) (res *daily.ColumnList) {
var (
column []*daily.ColumnList
)
key := fmt.Sprintf(_initColumnListKey, plat, columnID)
if columns, ok := s.cardListCache[key]; ok {
for _, c := range columns {
if model.InvalidBuild(build, c.Build, c.Condition) {
continue
}
tmp := &daily.ColumnList{
Cid: c.Cid,
Name: c.Name,
Ceid: c.Ceid,
Cname: c.Cname,
}
column = append(column, tmp)
}
if len(column) > 0 {
res = &daily.ColumnList{
Ceid: column[0].Ceid,
Name: column[0].Cname,
Children: column,
}
}
}
return
}
// Category
func (s *Service) Category(plat int8, build, categoryID, columnID, pn, ps int) (res *daily.Show) {
var (
key string
)
if pn > 0 {
pn = pn - 1
}
start := pn * ps
end := start + ps
if columnID > 0 {
key = fmt.Sprintf(_initDailyKey, plat, columnID)
} else {
listKey := fmt.Sprintf(_initColumnListKey, plat, categoryID)
if columns, ok := s.cardListCache[listKey]; ok {
for _, c := range columns {
if model.InvalidBuild(build, c.Build, c.Condition) {
continue
}
key = fmt.Sprintf(_initDailyKey, plat, c.Cid)
break
}
}
}
if columns, ok := s.columnCache[key]; ok {
res = columns
if pn*ps > 400 {
res.Body = _emptyList
return
}
if res.Body, ok = s.columnListCache[key]; ok {
resLen := len(res.Body)
if resLen > end {
res.Body = res.Body[start:end]
} else if resLen > start {
res.Body = res.Body[start:]
} else {
res.Body = _emptyList
}
}
if len(res.Body) == 0 {
res.Body = _emptyList
}
}
return
}
// loadColumnsCache load all columns cache
func (s *Service) loadColumnsCache() {
res, err := s.cdao.Columns(context.TODO())
if err != nil {
log.Error("s.cdao.Columns error(%v)", err)
return
}
tmp := map[string]*card.Column{}
for plat, columns := range res {
for _, column := range columns {
key := fmt.Sprintf(_initColumnKey, plat, column.ID)
tmp[key] = column
}
}
s.columnsCache = tmp
}
// loadColumnListCache
func (s *Service) loadColumnListCache(now time.Time) {
var (
tmp = map[string][]*card.ColumnList{}
)
platColumns, err := s.cdao.ColumnPlatList(context.TODO(), now)
if err != nil {
log.Error("s.cdao.ColumnPlatList error(%v)", err)
return
}
for plat, columns := range platColumns {
for _, column := range columns {
key := fmt.Sprintf(_initColumnListKey, plat, column.Ceid)
tmp[key] = append(tmp[key], column)
}
}
s.cardListCache = tmp
}
// loadNperCache
func (s *Service) loadNperCache(now time.Time) {
hdm, err := s.cdao.ColumnNpers(context.TODO(), now)
if err != nil {
log.Error("s.cdao.ColumnNpers error(%v)", err)
return
}
itm, aids, err := s.cdao.NperContents(context.TODO(), now)
if err != nil {
log.Error("s.cdao.NperContents error(%v)", err)
return
}
tmp, tmpColumns, tmpList := s.mergeCard(context.TODO(), hdm, itm, aids, now)
s.cardCache = tmp
s.columnCache = tmpColumns
s.columnListCache = tmpList
}
// cacheproc load all cache.
func (s *Service) cacheproc() {
for {
time.Sleep(s.tick)
now := time.Now()
s.loadColumnListCache(now)
s.loadColumnsCache()
s.loadNperCache(now)
}
}
// mergeCard
func (s *Service) mergeCard(c context.Context, hdm map[int8][]*card.ColumnNper, itm map[int][]*card.Content, itmaids map[int][]int64, now time.Time) (res map[string][]*daily.Show, columns map[string]*daily.Show, columnList map[string][]*daily.Item) {
var (
dailyMAX = 31
)
res = map[string][]*daily.Show{}
columnList = map[string][]*daily.Item{}
columns = map[string]*daily.Show{}
for plat, hds := range hdm {
for _, hd := range hds {
var (
ok bool
column *card.Column
)
columnskey := fmt.Sprintf(_initColumnKey, plat, hd.ColumnID)
if column, ok = s.columnsCache[columnskey]; !ok {
continue
}
switch column.Type {
case model.GotoDaily:
if dailykey := fmt.Sprintf(_initDailyKey, plat, hd.ColumnID); len(res[dailykey]) > dailyMAX {
continue
}
}
var (
sis []*daily.Item
)
its, ok := itm[hd.ID]
if !ok {
its = []*card.Content{}
}
switch column.Tpl {
case 1, 2:
var tmpItem = map[int64]*daily.Item{}
if aids, ok := itmaids[hd.ID]; ok {
tmpItem = s.fromCardAids(context.TODO(), aids)
}
for _, ci := range its {
si := s.fillCardItem(ci, tmpItem)
if si.Title == "" {
continue
}
if ci.TagID > 0 {
si.TagName, si.TagID = s.fromTagIDByName(c, ci.TagID, now)
}
sis = append(sis, si)
}
}
if len(sis) == 0 {
continue
}
sw := &daily.Show{}
sw.Head = &daily.Head{
ColumnID: hd.ID,
Build: hd.Build,
Condition: hd.Condition,
Plat: hd.Plat,
Desc: hd.Desc,
Type: column.Type,
}
if hd.Cover != "" {
sw.Cover = hd.Cover
}
var key string
switch sw.Head.Type {
case model.GotoDaily:
key = fmt.Sprintf(_initDailyKey, plat, hd.ColumnID)
sw.Head.Title = hd.Name
if len(res[key]) == 0 {
sw.Head.Date = now.Unix()
} else {
sw.Head.Date = int64(hd.NperTime)
}
sw.Body = sis
res[key] = append(res[key], sw)
case model.GotoColumn:
key = fmt.Sprintf(_initDailyKey, plat, hd.ID)
sw.Head.Title = hd.Name
sw.Head.Goto = hd.Goto
sw.Head.Param = hd.Param
sw.Head.URI = hd.URI
columnList[key] = sis
columns[key] = sw
}
}
}
return
}
// fillCardItem
func (s *Service) fillCardItem(csi *card.Content, tsi map[int64]*daily.Item) (si *daily.Item) {
si = &daily.Item{}
switch csi.Type {
case model.CardGotoAv:
si.Goto = model.GotoAv
si.Param = csi.Value
}
si.URI = model.FillURI(si.Goto, si.Param, nil)
if si.Goto == model.GotoAv {
aid, err := strconv.ParseInt(si.Param, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", si.Param, err)
} else {
if it, ok := tsi[aid]; ok {
si = it
if csi.Title != "" {
si.Title = csi.Title
}
} else {
si = &daily.Item{}
}
}
}
return
}
// fromCardAids get Aids.
func (s *Service) fromCardAids(ctx context.Context, aids []int64) (data map[int64]*daily.Item) {
var (
arc *api.Arc
ok bool
)
as, err := s.arc.ArchivesPB(ctx, aids)
if err != nil {
log.Error("s.arc.ArchivesPB(%v) error(%v)", aids, err)
return
}
if len(as) == 0 {
log.Warn("s.arc.ArchivesPB(%v) length is 0", aids)
return
}
data = map[int64]*daily.Item{}
for _, aid := range aids {
if arc, ok = as[aid]; ok {
if !arc.IsNormal() {
continue
}
i := &daily.Item{}
i.FromArchivePB(arc)
data[aid] = i
}
}
return
}
// fromTagIDByName from tag_id by tag_name
func (s *Service) fromTagIDByName(ctx context.Context, tagID int, now time.Time) (tagName string, tagIDInt int64) {
tag, err := s.tag.TagInfo(ctx, 0, tagID, now)
if err != nil {
log.Error("s.tag.TagInfo(%d) error(%v)", tagID, err)
return
}
tagName = tag.Name
tagIDInt = tag.Tid
return
}

View File

@@ -0,0 +1,53 @@
package daily
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-show/conf"
"go-common/app/interface/main/app-show/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-show-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestDaily(t *testing.T) {
Convey("get Daily data", t, WithService(func(s *Service) {
res := s.Daily(context.TODO(), model.PlatIPhone, 100000, 4, 1, 20)
So(res, ShouldNotBeEmpty)
}))
}
func TestColumnList(t *testing.T) {
Convey("get ColumnList data", t, WithService(func(s *Service) {
res := s.ColumnList(model.PlatIPhone, 100000, 4)
So(res, ShouldNotBeEmpty)
}))
}
func TestCategory(t *testing.T) {
Convey("get Category data", t, WithService(func(s *Service) {
res := s.Category(model.PlatIPhone, 100000, 4, 4, 1, 20)
So(res, ShouldNotBeEmpty)
}))
}

View File

@@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["ping_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["ping.go"],
importpath = "go-common/app/interface/main/app-show/service/ping",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//app/interface/main/app-show/dao/show: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,28 @@
package ping
import (
"context"
"go-common/app/interface/main/app-show/conf"
showdao "go-common/app/interface/main/app-show/dao/show"
)
type Service struct {
showDao *showdao.Dao
// bnDao *bndao.Dao
}
func New(c *conf.Config) (s *Service) {
s = &Service{
showDao: showdao.New(c),
}
return
}
// Ping is check server ping.
func (s *Service) Ping(c context.Context) (err error) {
if err = s.showDao.Ping(c); err != nil {
return
}
return
}

View File

@@ -0,0 +1,38 @@
package ping
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-show/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-show-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestPing(t *testing.T) {
Convey("get Ping data", t, WithService(func(s *Service) {
err := s.Ping(context.TODO())
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,61 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["rank_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"audit.go",
"rank.go",
],
importpath = "go-common/app/interface/main/app-show/service/rank",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//app/interface/main/app-show/dao/account:go_default_library",
"//app/interface/main/app-show/dao/archive:go_default_library",
"//app/interface/main/app-show/dao/audit:go_default_library",
"//app/interface/main/app-show/dao/recommend:go_default_library",
"//app/interface/main/app-show/dao/region:go_default_library",
"//app/interface/main/app-show/dao/relation:go_default_library",
"//app/interface/main/app-show/model:go_default_library",
"//app/interface/main/app-show/model/region: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/relation/model: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,85 @@
package rank
import (
"context"
"fmt"
"strconv"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/region"
"go-common/app/service/main/archive/api"
"go-common/library/log"
)
func (s *Service) loadAuditCache() {
as, err := s.adt.Audits(context.TODO())
if err != nil {
log.Error("s.adt.Audits error(%v)", err)
return
}
s.auditCache = as
}
// Audit check audit plat and ip, then return audit data.
func (s *Service) Audit(c context.Context, mobiApp, order string, plat int8, build, rid int) (res []*region.ShowItem, ok bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
res = s.auditData(c, plat, rid, _auditRankAids, order)
return res, true
}
}
return nil, false
}
// auditData some data for audit.
func (s *Service) auditData(c context.Context, p int8, rid int, auditAids map[string][]int64, order string) (res []*region.ShowItem) {
key := fmt.Sprintf(_initRank, order, rid)
aids := auditAids[key]
// archive
as, err := s.arc.ArchivesPB(c, aids)
if err != nil {
log.Error("s.arc.ArchivesPB() error(%v)", err)
as = map[int64]*api.Arc{}
}
for _, aid := range aids {
if aid == 0 {
continue
}
item := &region.ShowItem{}
item.Goto = model.GotoAv
item.Param = strconv.FormatInt(aid, 10)
item.URI = model.FillURI(item.Goto, item.Param, nil)
if a, ok := as[aid]; ok {
item.Title = a.Title
item.Cover = a.Pic
item.Name = a.Author.Name
item.Play = int(a.Stat.View)
item.Danmaku = int(a.Stat.Danmaku)
item.Reply = int(a.Stat.Reply)
item.Fav = int(a.Stat.Fav)
}
res = append(res, item)
}
return
}
var (
_auditRankAids = map[string][]int64{
// rid
"rank_key_all_13": []int64{2434272, 7408756, 2426501, 2425990, 2387429, 2425770, 2419790, 2425440, 2414401, 2414476, 2402042, 7411278, 7418371},
"rank_key_all_1": []int64{104614, 190257, 199852, 233649, 258271, 275039, 274410, 286678, 291630, 292757, 299622, 306718, 430248, 432195, 462832, 476328, 508255, 524615, 539880, 559050, 560190, 572499, 576101, 575891, 582598, 588108, 591021, 602868, 620545, 627451, 627197, 621797, 630172, 663583, 666971, 747286, 744310, 789570, 824454, 832270, 851414, 853831, 874099, 884419, 880538, 2460323, 2459108, 2469560, 2471090},
"rank_key_all_3": []int64{8363, 209887, 221107, 322800, 333069, 360940, 361637, 400161, 402851, 465230, 454882, 462766, 482844, 539600, 595218, 644461, 644935, 756287, 785484, 801851, 850424, 853895, 875374, 881693, 1964781, 1966586, 1966643, 1969527, 1968681, 1986904, 1986802, 1984971, 1984330, 2294239, 2473751, 2473083},
"rank_key_all_129": []int64{886841, 936016, 966192, 1406019, 1773160, 1935680, 1958897, 1960912, 1964367, 1976153, 1985297, 1984555},
"rank_key_all_4": []int64{846437, 862006, 861854, 861796, 861711, 861409, 861209, 861124, 860863, 860273, 860187, 859930, 859374, 859264, 859132, 866115, 866091, 865870, 865843, 865610, 865511, 865442, 865388, 865318, 865259, 865076, 864958, 864845, 864737, 864732, 864700, 864528, 864390, 864360, 864344, 864264, 864121, 863929, 864969, 864762},
"rank_key_all_36": []int64{403120, 580862, 834839, 844027, 862316, 876708, 875624, 872364, 873174, 880857, 1971484, 1969254, 1968901, 1986932, 1985610, 2312249, 2310494, 2313588, 2316089, 2317272},
"rank_key_all_5": []int64{2318219},
"rank_key_all_119": []int64{78287, 638240, 913421, 1625784, 1636345, 1727650, 1743126, 1911041, 1959692, 1975358, 1976535, 1979757, 1982533, 1986533, 1985956},
"rank_key_all_23": []int64{1974120, 2038896, 2006455, 1957548, 377264, 1983046, 1955773, 1933830},
"rank_key_all_155": []int64{4991648},
"rank_key_all_160": []int64{8141, 7790, 7698, 6608, 6510, 6336, 6234, 5876, 5464, 5309, 5242, 5230, 5222, 4914, 10040, 9649, 8996, 8993, 11239, 11472, 11787, 12243, 12182, 12727, 15347, 16900, 16762, 17907, 18888, 200595, 288592, 286616, 339727, 393459, 517475, 530016, 551985, 555395, 581574, 588820, 592772, 592586, 633358, 648300, 659978, 666026, 658894, 658644, 658110, 667016, 668533, 668054, 673692, 673220, 672850, 670544, 677766, 680535, 680029, 670137, 679027, 695862, 686220, 685223, 689694, 690522, 702762, 698339, 696603, 701297, 707328, 700111, 708986, 708474, 699555, 699508},
"rank_key_all_11": []int64{1916941, 2031210, 2034983, 2015734, 2016150, 1964927, 1961205, 2039658},
"rank_key_all_33": []int64{2434272},
"rank_key_all_0": []int64{104614, 190257, 199852, 233649, 258271, 275039, 274410, 286678, 291630, 292757, 299622, 306718, 430248, 432195, 462832, 476328, 508255, 524615, 539880, 559050, 560190, 572499, 576101, 575891, 582598, 588108, 591021, 602868, 620545, 627451, 627197, 621797, 630172, 663583, 666971, 747286, 744310, 789570, 824454, 832270, 851414, 853831, 874099, 884419, 880538, 2460323, 2459108, 2469560, 2471090, 209887, 221107, 322800, 333069, 360940, 361637, 400161, 402851, 465230, 454882, 462766, 482844, 539600, 595218, 644461, 644935, 756287, 785484, 801851, 850424, 853895, 875374, 881693, 1964781, 1966586, 1966643, 1969527, 1968681},
"rank_key_origin_0": []int64{291630, 299622, 364103, 430248, 432195, 462832, 508255, 539880, 559050, 560190, 576101, 582598, 588108, 620545, 627451, 627197, 630172, 824454, 832270, 851414, 874099, 884419, 880538, 2460323, 2459108, 2471090, 322800, 333069, 360940, 361637, 400161, 402851, 465230, 454882, 462766, 482844, 595218, 644461, 644935, 756287, 785484, 836018, 850424, 853895, 875374, 881693, 1966643, 1969527, 1968681, 1986904, 1986802, 1984330, 2473751, 2473083, 861854, 866115, 866091, 865843, 865610, 865511, 865442, 865388, 865318, 864958, 864845, 864737, 864700, 864528, 864390, 864360, 864344, 864264, 864121, 863929, 864705, 1977493, 1982920, 2312184, 2316655, 2314523},
}
)

View File

@@ -0,0 +1,298 @@
package rank
import (
"context"
"fmt"
"time"
"go-common/app/interface/main/app-show/conf"
accdao "go-common/app/interface/main/app-show/dao/account"
arcdao "go-common/app/interface/main/app-show/dao/archive"
adtdao "go-common/app/interface/main/app-show/dao/audit"
rcmmndao "go-common/app/interface/main/app-show/dao/recommend"
rgdao "go-common/app/interface/main/app-show/dao/region"
reldao "go-common/app/interface/main/app-show/dao/relation"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/region"
account "go-common/app/service/main/account/model"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
relation "go-common/app/service/main/relation/model"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const (
_initRank = "rank_key_%s_%d"
)
var (
// 番剧 动画,音乐,舞蹈,游戏,科技,娱乐,鬼畜,电影,时尚, 生活,连载番剧(二级分区),国漫,影视,纪录片,国创相关,数码
_tids = []int{13, 1, 3, 129, 4, 36, 5, 119, 23, 155, 160, 11, 33, 167, 181, 177, 168, 188}
// region.ShowItem
_emptyShowItems = []*region.ShowItem{}
// _pgctids = map[int]struct{}{
// 177: struct{}{},
// }
)
type Service struct {
c *conf.Config
// region
rdao *rgdao.Dao
// rcmmnd
rcmmnd *rcmmndao.Dao
// archive
arc *arcdao.Dao
// audit
adt *adtdao.Dao
// account
accd *accdao.Dao
// relation
reldao *reldao.Dao
// tick
tick time.Duration
// ranking
rankCache map[string][]*region.ShowItem
rankOseaCache map[string][]*region.ShowItem
// audit cache
auditCache map[string]map[int]struct{} // audit mobi_app builds
}
// New new a region service.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
rdao: rgdao.New(c),
rcmmnd: rcmmndao.New(c),
// archive
arc: arcdao.New(c),
// audit
adt: adtdao.New(c),
// account
accd: accdao.New(c),
// relation
reldao: reldao.New(c),
// tick
tick: time.Duration(c.Tick),
// ranking
rankCache: map[string][]*region.ShowItem{},
rankOseaCache: map[string][]*region.ShowItem{},
// audit cache
auditCache: map[string]map[int]struct{}{},
}
time.Sleep(time.Second * 2)
s.load()
s.loadAuditCache()
go s.loadproc()
return
}
// RankShow
func (s *Service) RankShow(c context.Context, plat int8, rid, pn, ps int, mid int64, order string) (res []*region.ShowItem) {
var (
key = fmt.Sprintf(_initRank, order, rid)
tmp []*region.ShowItem
authorMids []int64
authorMidExist = map[int64]struct{}{}
authorRelations map[int64]*account.Relation
authorStats map[int64]*relation.Stat
authorCards map[int64]*account.Card
err error
)
if model.IsOverseas(plat) {
tmp = s.rankOseaCache[key]
} else {
tmp = s.rankCache[key]
}
start := (pn - 1) * ps
end := start + ps
if len(tmp) == 0 || start > len(tmp) {
res = _emptyShowItems
return
}
if end < len(tmp) {
tmp = tmp[start:end]
} else {
tmp = tmp[start:]
}
for _, t := range tmp {
i := &region.ShowItem{}
*i = *t
res = append(res, i)
// up mid
if _, ok := authorMidExist[i.Mid]; !ok && i.Mid > 0 {
authorMids = append(authorMids, i.Mid)
authorMidExist[i.Mid] = struct{}{}
}
}
if len(authorMids) > 0 {
g, ctx := errgroup.WithContext(c)
g.Go(func() error {
if authorCards, err = s.accd.Cards3(ctx, authorMids); err != nil {
log.Error("s.accd.Cards3 error(%v)", err)
}
return nil
})
if mid > 0 {
g.Go(func() error {
if authorRelations, err = s.accd.Relations3(ctx, mid, authorMids); err != nil {
log.Error("s.accd.Relations2 error(%v)", err)
}
return nil
})
}
g.Go(func() error {
if authorStats, err = s.reldao.Stats(ctx, authorMids); err != nil {
log.Error("s.reldao.Stats error(%v)", err)
}
return nil
})
if err = g.Wait(); err != nil {
log.Error("RankUser errgroup.WithContext error(%v)", err)
}
}
for _, i := range res {
if len(authorRelations) > 0 {
if relations, ok := authorRelations[i.Mid]; ok {
if relations.Following {
i.Attribute = 1
}
}
}
if len(authorStats) > 0 {
if stats, ok := authorStats[i.Mid]; ok {
i.Follower = int(stats.Follower)
}
}
if len(authorCards) > 0 {
if info, ok := authorCards[i.Mid]; ok {
ov := &region.OfficialVerify{}
ov.FromOfficialVerify(info.Official)
i.OfficialVerify = ov
}
}
if !model.IsIPad(plat) {
if i.RedirectURL != "" {
i.URI = i.RedirectURL
i.Goto = model.GotoBangumi
}
}
}
return
}
// loadproc
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
s.load()
s.loadAuditCache()
}
}
// load load Rank all
func (s *Service) load() {
var (
tmp = map[string][]*region.ShowItem{}
tmpOsea = map[string][]*region.ShowItem{}
)
for _, rid := range _tids {
if rid == 33 {
aids, others, scores, err := s.rcmmnd.RankAppBangumi(context.TODO())
key := fmt.Sprintf(_initRank, "bangumi", 0)
if err != nil || len(aids) < 5 {
log.Error("s.rcmmnd.RankAppBangumi len lt 20 OR error(%v)", err)
tmp[key], tmpOsea[key] = s.rankCache[key], s.rankOseaCache[key]
continue
}
tmp[key], tmpOsea[key] = s.fromRankAids(context.TODO(), aids, others, scores)
log.Info("loadRankBangumi success")
} else {
aids, others, scores, err := s.rcmmnd.RankAppRegion(context.TODO(), rid)
key := fmt.Sprintf(_initRank, "all", rid)
if err != nil || len(aids) < 5 {
log.Error("s.rcmmnd.RankAppRegion rid (%v) len lt 20 OR error(%v)", rid, err)
tmp[key], tmpOsea[key] = s.rankCache[key], s.rankOseaCache[key]
continue
}
tmp[key], tmpOsea[key] = s.fromRankAids(context.TODO(), aids, others, scores)
log.Info("loadRankRegion(%s_%d) success", "all", rid)
}
}
aids, others, scores, err := s.rcmmnd.RankAppAll(context.TODO())
key := fmt.Sprintf(_initRank, "all", 0)
if err != nil || len(aids) < 5 {
log.Error("s.rcmmnd.RankAppAll(%s) len lt 20 OR error(%v)", "all", err)
return
}
tmp[key], tmpOsea[key] = s.fromRankAids(context.TODO(), aids, others, scores)
log.Info("loadRank(%s) success", "all")
aids, others, scores, err = s.rcmmnd.RankAppOrigin(context.TODO())
key = fmt.Sprintf(_initRank, "origin", 0)
if err != nil || len(aids) < 5 {
log.Error("s.rcmmnd.RankAppOrigin(%s) len lt 20 OR error(%v)", "all", err)
return
}
tmp[key], tmpOsea[key] = s.fromRankAids(context.TODO(), aids, others, scores)
log.Info("loadRank(%s) success", "origin")
if len(tmp) > 0 {
s.rankCache = tmp
}
if len(tmpOsea) > 0 {
s.rankOseaCache = tmpOsea
}
}
// fromRankAids
func (s *Service) fromRankAids(ctx context.Context, aids []int64, others, scores map[int64]int64) (sis, sisOsea []*region.ShowItem) {
var (
aid int64
as map[int64]*api.Arc
arc *api.Arc
ok bool
err error
paid int64
)
if as, err = s.arc.ArchivesPB(ctx, aids); err != nil {
log.Error("s.arc.ArchivesPB error(%v)", err)
return
}
if len(as) == 0 {
log.Warn("s.arc.ArchivesPB(%v) length is 0", aids)
return
}
child := map[int64][]*region.ShowItem{}
childOsea := map[int64][]*region.ShowItem{}
for _, aid = range aids {
if arc, ok = as[aid]; ok {
if paid, ok = others[arc.Aid]; ok {
i := &region.ShowItem{}
i.FromArchivePBRank(arc, scores)
child[paid] = append(child[paid], i)
if arc.AttrVal(archive.AttrBitOverseaLock) == 0 {
childOsea[paid] = append(childOsea[paid], i)
}
}
}
}
for _, aid = range aids {
if arc, ok = as[aid]; ok {
if _, ok = others[arc.Aid]; !ok {
i := &region.ShowItem{}
i.FromArchivePBRank(arc, scores)
if arc.AttrVal(archive.AttrBitOverseaLock) == 0 {
if tmpchild, ok := childOsea[arc.Aid]; ok {
i.Children = tmpchild
}
sisOsea = append(sisOsea, i)
}
if tmpchild, ok := child[arc.Aid]; ok {
i.Children = tmpchild
}
sis = append(sis, i)
}
}
}
return
}

View File

@@ -0,0 +1,37 @@
package rank
import (
"context"
"flag"
"go-common/app/interface/main/app-show/conf"
"path/filepath"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-show-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestRankShow(t *testing.T) {
Convey("get RankShow data", t, WithService(func(s *Service) {
res := s.RankShow(context.TODO(), 0, 1, 1, 20, 0, "all")
So(res, ShouldNotBeEmpty)
}))
}

View File

@@ -0,0 +1,87 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"region_test.go",
"show_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//app/interface/main/app-show/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"audit.go",
"banner.go",
"cache.go",
"infoc.go",
"region.go",
"service.go",
"show.go",
],
importpath = "go-common/app/interface/main/app-show/service/region",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//app/interface/main/app-show/dao/activity:go_default_library",
"//app/interface/main/app-show/dao/ad:go_default_library",
"//app/interface/main/app-show/dao/archive:go_default_library",
"//app/interface/main/app-show/dao/audit:go_default_library",
"//app/interface/main/app-show/dao/bangumi:go_default_library",
"//app/interface/main/app-show/dao/card:go_default_library",
"//app/interface/main/app-show/dao/dynamic:go_default_library",
"//app/interface/main/app-show/dao/location:go_default_library",
"//app/interface/main/app-show/dao/recommend:go_default_library",
"//app/interface/main/app-show/dao/region:go_default_library",
"//app/interface/main/app-show/dao/resource:go_default_library",
"//app/interface/main/app-show/dao/search:go_default_library",
"//app/interface/main/app-show/dao/tag:go_default_library",
"//app/interface/main/app-show/model:go_default_library",
"//app/interface/main/app-show/model/bangumi:go_default_library",
"//app/interface/main/app-show/model/banner:go_default_library",
"//app/interface/main/app-show/model/card:go_default_library",
"//app/interface/main/app-show/model/region:go_default_library",
"//app/interface/main/app-show/model/tag: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/resource/model:go_default_library",
"//app/service/openplatform/pgc-season/api/grpc/season/v1: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/time:go_default_library",
"//vendor/github.com/dgryski/go-farm: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,391 @@
package region
import (
"context"
"strconv"
"time"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/banner"
"go-common/app/interface/main/app-show/model/region"
"go-common/app/service/main/archive/api"
"go-common/library/log"
)
var (
_auditRids = map[int8]map[int]struct{}{
model.PlatIPad: map[int]struct{}{
153: struct{}{},
168: struct{}{},
169: struct{}{},
170: struct{}{},
33: struct{}{},
32: struct{}{},
51: struct{}{},
152: struct{}{},
37: struct{}{},
178: struct{}{},
179: struct{}{},
180: struct{}{},
147: struct{}{},
145: struct{}{},
146: struct{}{},
83: struct{}{},
185: struct{}{},
187: struct{}{},
13: struct{}{},
167: struct{}{},
177: struct{}{},
23: struct{}{},
1: struct{}{},
160: struct{}{},
119: struct{}{},
155: struct{}{},
165: struct{}{},
5: struct{}{},
181: struct{}{},
},
model.PlatIPhone: map[int]struct{}{
153: struct{}{},
168: struct{}{},
169: struct{}{},
170: struct{}{},
33: struct{}{},
32: struct{}{},
51: struct{}{},
152: struct{}{},
37: struct{}{},
178: struct{}{},
179: struct{}{},
180: struct{}{},
147: struct{}{},
145: struct{}{},
146: struct{}{},
83: struct{}{},
185: struct{}{},
187: struct{}{},
1: struct{}{},
160: struct{}{},
119: struct{}{},
155: struct{}{},
165: struct{}{},
5: struct{}{},
181: struct{}{},
},
}
)
// Audit region data list.
func (s *Service) auditRegion(mobiApp string, plat int8, build, rid int) (isAudit bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
if rids, ok := _auditRids[plat]; ok {
if _, ok = rids[rid]; ok {
return true
}
}
}
}
return false
}
func (s *Service) loadAuditCache() {
as, err := s.adt.Audits(context.TODO())
if err != nil {
log.Error("s.adt.Audits error(%v)", err)
return
}
s.auditCache = as
}
// Audit check audit plat and ip, then return audit data.
func (s *Service) Audit(c context.Context, mobiApp string, plat int8, build, rid int, isShow bool) (res *region.Show, ok bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
res = s.auditData(c, plat, rid, auditShowAids)
if isShow {
res.Banner = audirRegionBanners[rid]
}
return res, true
}
}
return nil, false
}
// AuditChild check audit plat and ip, then return audit data.
func (s *Service) AuditChild(c context.Context, mobiApp, order string, plat int8, build, rid, tid int) (res *region.Show, ok bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
res = s.auditData(c, plat, rid, auditChildShowAids)
res.New = s.auditRegionRPCList(c, rid, 1, 8)
return res, true
}
}
return nil, false
}
// AuditChildList check audit plat and ip, then return audit data.
func (s *Service) AuditChildList(c context.Context, mobiApp, order string, plat int8, build, rid, tid, pn, ps int) (res []*region.ShowItem, ok bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
res = s.auditRegionChildList(c, rid, tid, pn, ps)
return res, true
}
}
return nil, false
}
// auditData some data for audit.
func (s *Service) auditData(c context.Context, p int8, rid int, auditAids map[int][]int64) (res *region.Show) {
aids := auditAids[rid]
// archive
as, err := s.arc.ArchivesPB(c, aids)
if err != nil {
log.Error("s.arc.ArchivesPB error(%v)", err)
as = map[int64]*api.Arc{}
}
res = &region.Show{}
for _, aid := range aids {
if aid == 0 {
continue
}
item := &region.ShowItem{}
item.Goto = model.GotoAv
item.Param = strconv.FormatInt(aid, 10)
item.URI = model.FillURI(item.Goto, item.Param, nil)
if a, ok := as[aid]; ok {
item.Title = a.Title
item.Cover = a.Pic
item.Name = a.Author.Name
item.Play = int(a.Stat.View)
item.Danmaku = int(a.Stat.Danmaku)
item.Reply = int(a.Stat.Reply)
item.Fav = int(a.Stat.Fav)
}
res.Recommend = append(res.Recommend, item)
}
return
}
func (s *Service) auditRegionChildList(c context.Context, rid, tid, pn, ps int) (res []*region.ShowItem) {
if tid == 0 {
arcs, _, err := s.arc.RanksArcs(c, rid, pn, ps)
if err != nil {
log.Error("s.rcmmnd.RegionArcList(%d, %d, %d, %d) error(%v)", rid, pn, ps, err)
return
}
res = s.fromArchivesPBOsea(arcs, false)
} else {
as, err := s.tag.NewArcs(c, rid, tid, pn, ps, time.Now())
if err != nil {
log.Error("s.tag.NewArcs(%d, %d) error(%v)", rid, tid, err)
return
}
res = s.fromAidsOsea(c, as, false, false, 0)
}
return
}
func (s *Service) auditRegionRPCList(c context.Context, rid, pn, ps int) (res []*region.ShowItem) {
arcs, err := s.arc.RankTopArcs(c, rid, pn, ps)
if err != nil {
log.Error("s.arc.RankTopArcs(%d) error(%v)", rid, err)
return
}
res, _ = s.fromArchivesPB(arcs)
return
}
var (
auditShowAids = map[int][]int64{
// rid
1: []int64{575891, 744286, 663583, 666946, 559050, 744299},
3: []int64{881693, 756287, 785484, 402851, 887618, 853895},
4: []int64{861290, 861306, 861410, 861538, 861711, 861945},
5: []int64{791621, 795406, 797933, 800658, 832103, 833520},
11: []int64{1961205, 2028734},
13: []int64{2434272, 7408756, 2222558, 845204, 862063, 845034},
36: []int64{834839, 838077, 872364, 852955, 877423, 881182},
119: []int64{638240, 1959692, 78287, 1979757},
129: []int64{966192, 936016, 1958897, 886841},
}
auditChildShowAids = map[int][]int64{
20: []int64{936016, 886841, 1773160, 1958897, 1406019, 1935680, 1976153, 1985297, 1984555, 1964367, 29013765, 27379226, 25886650, 27684044, 20203945},
21: []int64{689694, 829135, 743922, 876565, 690522, 686220, 286616, 339727, 668054, 288602},
22: []int64{1911041, 1976535, 913421},
24: []int64{258271, 462832, 430248},
25: []int64{190257, 432195},
26: []int64{638240, 1959692, 78287, 1979757},
27: []int64{775898, 199852, 539880, 2469560, 306718, 2460323, 851414, 2471090, 591021, 286678},
28: []int64{221107, 221106, 884789, 364379, 465230, 26437, 29009413, 28965015, 28087847, 27837553, 24691347},
29: []int64{1984330, 1966586, 1984971, 28935962, 28818825, 26514923, 23288906, 18043554},
30: []int64{308040, 850424, 360940, 482844, 887861, 539600, 869576, 400161, 644935, 333069, 28659609, 24929108, 23068834, 26659364, 25386207},
31: []int64{1968681, 1986904, 1986802, 2473751, 2473083, 24910218, 25409335, 25043881, 27384682, 23474776},
37: []int64{1968901, 1969254, 1971484},
47: []int64{364103, 621797, 557774, 620545, 291630, 853831, 627451, 789570, 582598, 666971},
54: []int64{2294239, 2210977, 21297755, 21678914, 22000250, 19929241, 18039794},
59: []int64{1969748, 1966643, 1964781, 1969527, 25814802, 25991412, 26577780, 23922472, 28934467},
71: []int64{1986816, 1985288, 1986516, 1985717},
75: []int64{200595, 721477, 668533, 803294, 708986, 581574, 588820, 718877, 6336, 592586},
76: []int64{800617, 817625, 853774, 808176, 810174, 737783, 792994, 811825, 794302, 817814},
95: []int64{880857, 26317616, 26697725, 24670946, 13562204, 24136940},
96: []int64{2313588, 2314237, 2316089, 28917042, 20177394, 27839524, 25866526, 22021244},
98: []int64{875076, 873174, 580862, 289024, 28868117, 26404621, 17229132, 28810408, 27710623},
122: []int64{1986932, 1985610, 22034719, 19980487, 19841525, 23328696, 29249512},
124: []int64{842756, 875624, 880558, 862316, 876708, 883418, 403120, 855131, 876867, 833785, 29064835, 27464818, 28055879, 18081681, 22968172},
126: []int64{1636345, 1985956, 1975358, 1982533},
127: []int64{1743126, 1625784, 1986533, 1727650},
128: []int64{2031210, 2034983, 1916941, 2030610, 2015734, 2016150, 1982576, 2039658, 1981156, 1964927},
130: []int64{1984887, 1985685, 1985886, 25276379, 17119215, 24949925, 25058065, 2929013},
131: []int64{1980280, 1975409},
137: []int64{2316922, 2318219},
138: []int64{2317125, 2317283, 2315385, 2317914, 2317194},
153: []int64{2429129, 7408756, 2426501, 2425990, 2387429, 2425770, 2219211, 878914, 880182, 2240189},
154: []int64{1960912, 1984928, 29240625, 26192654, 24211477, 23746281, 23871787},
156: []int64{28960012, 26624032, 25520347, 23567968, 23706035},
17: []int64{28989880, 25158325, 23947116, 27052563, 24237900},
171: []int64{29027059, 26486853, 19641793, 26432920, 27107785},
172: []int64{28280704, 28667051, 27462689, 22870782, 17703340},
65: []int64{28386938, 28832756, 27894258, 23401066, 24434703},
173: []int64{28938351, 28945212, 28149415, 17717106, 26227357},
121: []int64{27148774, 24729449, 24544576, 23651344, 21672258},
136: []int64{26033272, 26422598, 26804826, 25773023, 22961192},
19: []int64{28942929, 26325161, 24502096, 22364954, 19289951},
39: []int64{29120624, 26300313, 25504214, 9447066, 20786390},
176: []int64{28811447, 27569816, 11984355, 10788852, 29346662},
}
audirRegionBanners = map[int]map[string][]*banner.Banner{
1: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "四月再见",
Image: "http://i0.hdslb.com/bfs/archive/8bbc82a30720f8c2cdcca1576e25917f7bbdfb96.jpg",
Hash: "db6e4dcc120fcd954a5c2d454b618f09",
URI: "http://www.bilibili.com/video/av2471080/",
},
},
},
3: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "【洛天依原创】夜寂",
Image: "http://i0.hdslb.com/bfs/archive/6fa8a51c9adf6eeda36636ed7fffae5b1888c154.jpg",
Hash: "c925b57dbaa1198e8cdedc84c4781313",
URI: "http://www.bilibili.com/video/av2126431/",
},
},
},
4: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "释放内心中的熊孩子吧",
Image: "http://i0.hdslb.com/bfs/archive/b94d053b289184d498236de100af383bd25cfb13.jpg",
Hash: "f246e2f10d19e30dc7311c9f1ee8385e",
URI: "http://www.bilibili.com/video/av2459834/",
},
},
},
5: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "巅峰料理对决~~~",
Image: "http://i0.hdslb.com/bfs/archive/a91501598fb180f61f234e31f94731b74235b461.jpg",
Hash: "8664c0bd979f62c02cf6711ac0a55219",
URI: "http://www.bilibili.com/video/av2607073/?br",
},
&banner.Banner{
Title: "首轮淘汰赛,谁将会离开",
Image: "http://i0.hdslb.com/bfs/archive/ae6d1ef420a5bfdca969a31ecd7449384cfcd580.jpg",
Hash: "346b456dea567a32a11a9427ebe3246f",
URI: "http://www.bilibili.com/video/av2609994/?br",
},
&banner.Banner{
Title: "孙红雷罗志祥乡村女装秀",
Image: "http://i0.hdslb.com/bfs/archive/3ea355584e26376df6cccbb1a2574f03f7e0a41d.jpg",
Hash: "45e70e0f72dd1fa4621e13986df03b30",
URI: "http://www.bilibili.com/video/av2598211/?br",
},
&banner.Banner{
Title: "帅哥萌妹齐驾到 HK君强势出境",
Image: "http://i0.hdslb.com/bfs/archive/ae6d1ef420a5bfdca969a31ecd7449384cfcd580.jpg",
Hash: "7e7f8fa57dfffa0ca141e12f43088851",
URI: "http://www.bilibili.com/video/av2598658/?br",
},
&banner.Banner{
Title: "林丹谢霆锋上演锅铲大战 容祖儿情绪崩溃大哭",
Image: "http://i0.hdslb.com/bfs/archive/959930c687c172a28d9f24e6a53aceb7fca4f728.jpg",
Hash: "512a11b81e053d52c2ad836c453c18ad",
URI: "http://www.bilibili.com/video/av2588446/?br",
},
&banner.Banner{
Title: "【绅士大概一分钟】尽情舞蹈吧少年",
Image: "http://i0.hdslb.com/bfs/archive/40878881827105f576e0346932cf693c3033e1ca.jpg",
Hash: "147763f8003e6f88385cd438e8b6c7e4",
URI: "http://www.bilibili.com/video/av2614367/?br",
},
},
},
11: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "亚瑟王",
Image: "http://i0.hdslb.com/bfs/archive/60b1339a3eeb8d0de287b7c305e0671082946bfc.jpg",
Hash: "634684fe0fd4fb3b7501daf9a9b4ab5d",
URI: "http://www.bilibili.com/video/av2128802/",
},
},
},
13: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "少女终末旅行",
Image: "http://i0.hdslb.com/bfs/archive/c0c33be60527c377277048c04ee222c9ec76a82c.jpg",
Hash: "2e772627851aa7da8a75f7b5403a5ed3",
URI: "http://bangumi.bilibili.com/anime/6463",
},
},
},
23: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "像素大战",
Image: "http://i0.hdslb.com/bfs/archive/0c8f1e05dfdba3b58fc15159523d0ccceed1e9ac.jpg",
Hash: "f62bbb0578beb4bc63550d5632960480",
URI: "http://www.bilibili.com/video/av2124091/",
},
},
},
36: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "梦回仙剑",
Image: "http://i0.hdslb.com/bfs/archive/76145de97ff917a6e603009376f4ca174dd4ed51.jpg",
Hash: "6334c8c08ffa8eaa6c13f8c14bd0fae0",
URI: "http://www.bilibili.com/video/av2448057/",
},
},
},
119: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "魔都地铁偷走了重要的东西",
Image: "http://i0.hdslb.com/bfs/archive/f84dd391351a00d69cfb44616c1a64419ad4611c.jpg",
Hash: "5de70c2b24a155d7958943b85bf8facc",
URI: "http://www.bilibili.com/video/av2106417/",
},
},
},
129: map[string][]*banner.Banner{
"top": []*banner.Banner{
&banner.Banner{
Title: "元气少女",
Image: "http://i0.hdslb.com/bfs/archive/014c0793bdaf5930e0edca54755da3c25eafcb2e.jpg",
Hash: "46e48cee8d5b344af3a41636e96a60ca",
URI: "http://www.bilibili.com/video/av2448328/",
},
},
},
}
)

View File

@@ -0,0 +1,254 @@
package region
import (
"context"
"strconv"
"time"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/banner"
resource "go-common/app/service/main/resource/model"
"go-common/library/log"
)
var (
_banners = map[int]map[int8]int{
13: map[int8]int{
model.PlatIPhone: 454,
model.PlatIPad: 788,
model.PlatAndroid: 617,
model.PlatIPhoneI: 1022,
model.PlatAndroidG: 1360,
model.PlatAndroidI: 1791,
model.PlatIPadI: 1192,
},
1: map[int8]int{
model.PlatIPhone: 453,
model.PlatIPad: 787,
model.PlatAndroid: 616,
model.PlatIPhoneI: 1017,
model.PlatAndroidG: 1355,
model.PlatAndroidI: 1785,
model.PlatIPadI: 1187,
},
3: map[int8]int{
model.PlatIPhone: 455,
model.PlatIPad: 789,
model.PlatAndroid: 618,
model.PlatIPhoneI: 1028,
model.PlatAndroidG: 1366,
model.PlatAndroidI: 1798,
model.PlatIPadI: 1198,
},
129: map[int8]int{
model.PlatIPhone: 456,
model.PlatIPad: 790,
model.PlatAndroid: 619,
model.PlatIPhoneI: 1033,
model.PlatAndroidG: 1371,
model.PlatAndroidI: 1804,
model.PlatIPadI: 1203,
},
4: map[int8]int{
model.PlatIPhone: 457,
model.PlatIPad: 791,
model.PlatAndroid: 620,
model.PlatIPhoneI: 1038,
model.PlatAndroidG: 1376,
model.PlatAndroidI: 1810,
model.PlatIPadI: 1208,
},
36: map[int8]int{
model.PlatIPhone: 458,
model.PlatIPad: 792,
model.PlatAndroid: 621,
model.PlatIPhoneI: 1043,
model.PlatAndroidG: 1381,
model.PlatAndroidI: 1816,
model.PlatIPadI: 1213,
},
160: map[int8]int{
model.PlatIPhone: 459,
model.PlatIPad: 793,
model.PlatAndroid: 622,
model.PlatIPhoneI: 1048,
model.PlatAndroidG: 1386,
model.PlatAndroidI: 1822,
model.PlatIPadI: 1218,
},
119: map[int8]int{
model.PlatIPhone: 460,
model.PlatIPad: 794,
model.PlatAndroid: 623,
model.PlatIPhoneI: 1053,
model.PlatAndroidG: 1391,
model.PlatAndroidI: 1828,
model.PlatIPadI: 1223,
},
155: map[int8]int{
model.PlatIPhone: 462,
model.PlatIPad: 795,
model.PlatAndroid: 624,
model.PlatIPhoneI: 1058,
model.PlatAndroidG: 1396,
model.PlatAndroidI: 1834,
model.PlatIPadI: 1228,
},
5: map[int8]int{
model.PlatIPhone: 463,
model.PlatIPad: 796,
model.PlatAndroid: 625,
model.PlatIPhoneI: 1063,
model.PlatAndroidG: 1401,
model.PlatAndroidI: 1840,
model.PlatIPadI: 1233,
},
23: map[int8]int{
model.PlatIPhone: 464,
model.PlatIPad: 797,
model.PlatAndroid: 626,
model.PlatIPhoneI: 1068,
model.PlatAndroidG: 1406,
model.PlatAndroidI: 1846,
model.PlatIPadI: 1238,
},
11: map[int8]int{
model.PlatIPhone: 465,
model.PlatIPad: 798,
model.PlatAndroid: 627,
model.PlatIPhoneI: 1073,
model.PlatAndroidG: 1411,
model.PlatAndroidI: 1852,
model.PlatIPadI: 1243,
},
655: map[int8]int{
model.PlatIPhone: 466,
model.PlatIPad: 799,
model.PlatAndroid: 628,
model.PlatIPhoneI: 1079,
model.PlatAndroidG: 1417,
model.PlatAndroidI: 1859,
model.PlatIPadI: 1249,
},
165: map[int8]int{
model.PlatIPhone: 1473,
model.PlatIPad: 1485,
model.PlatAndroid: 1479,
model.PlatIPhoneI: 1491,
model.PlatAndroidG: 1497,
model.PlatAndroidI: 1873,
model.PlatIPadI: 1503,
},
167: map[int8]int{
model.PlatIPhone: 1934,
model.PlatIPad: 1932,
model.PlatAndroid: 1933,
},
181: map[int8]int{
model.PlatIPhone: 2225,
model.PlatIPad: 2239,
model.PlatAndroid: 2232,
},
177: map[int8]int{
model.PlatIPhone: 2275,
model.PlatIPad: 2289,
model.PlatAndroid: 2282,
},
188: map[int8]int{
model.PlatIPhone: 2996,
model.PlatIPad: 3008,
model.PlatAndroid: 3002,
model.PlatIPhoneI: 3014,
model.PlatAndroidG: 3020,
model.PlatAndroidI: 3032,
model.PlatIPadI: 3026,
},
}
_bannersPlat = map[int8]string{
model.PlatIPhone: "454,453,455,456,457,458,459,460,462,463,464,465,466,1473,1934,2225,2275",
model.PlatIPad: "788,787,789,790,791,792,793,794,795,796,797,798,799,1485,1932,2239,2289",
model.PlatAndroid: "617,616,618,619,620,621,622,623,624,625,626,627,628,1479,1933,2232,2282",
model.PlatIPhoneI: "1022,1017,1028,1033,1038,1043,1048,1053,1058,1063,1068,1073,1079,1491",
model.PlatAndroidG: "1360,1355,1366,1371,1376,1381,1386,1391,1396,1401,1406,1411,1417,1497",
model.PlatAndroidI: "1791,1785,1798,1804,1810,1816,1822,1828,1834,1840,1846,1852,1859,1873",
model.PlatIPadI: "1192,1187,1198,1203,1208,1213,1218,1223,1228,1233,1238,1243,1249,1503",
}
_bannersPGC = map[int8]map[int]int{
model.PlatAndroid: map[int]int{
13: 83,
167: 85,
177: 232,
11: 220,
23: 49,
},
model.PlatIPhone: map[int]int{
13: 97,
167: 98,
177: 233,
11: 221,
23: 50,
},
model.PlatIPad: map[int]int{
13: 332,
167: 333,
177: 334,
11: 336,
23: 335,
},
}
)
// getBanners get banners by plat, build channel, ip.
func (s *Service) getBanners(c context.Context, plat int8, build, rid int, mid int64, channel, ip, buvid, network, mobiApp, device, adExtra string) (res map[string][]*banner.Banner) {
var (
resID = _banners[rid][plat]
bs []*banner.Banner
)
res = map[string][]*banner.Banner{}
if bs = s.bgmBanners(c, plat, rid); len(bs) == 0 {
bs = s.resBanners(c, plat, build, mid, resID, channel, ip, buvid, network, mobiApp, device, adExtra)
}
if len(bs) > 0 {
res["top"] = bs
}
return
}
// resBannersplat
func (s *Service) resBanners(c context.Context, plat int8, build int, mid int64, resID int, channel, ip, buvid, network, mobiApp, device, adExtra string) (res []*banner.Banner) {
var (
plm = s.bannerCache[plat] // operater banner
err error
resbs map[int][]*resource.Banner
tmp []*resource.Banner
)
resIDStr := strconv.Itoa(resID)
if resbs, err = s.res.ResBanner(c, plat, build, mid, resIDStr, channel, ip, buvid, network, mobiApp, device, adExtra, true); err != nil || len(resbs) == 0 {
log.Error("s.res.ResBanner is null or err(%v)", err)
resbs = plm
}
tmp = resbs[resID]
for _, rb := range tmp {
b := &banner.Banner{}
b.ResChangeBanner(rb)
res = append(res, b)
}
return
}
// bgmBanners bangumi banner
func (s *Service) bgmBanners(c context.Context, plat int8, rid int) (bgmBanner []*banner.Banner) {
var (
bgmb = s.bannerBmgCache[plat][rid]
resID = _banners[rid][plat]
)
for i, bb := range bgmb {
b := &banner.Banner{}
b.BgmChangeBanner(bb)
b.RequestId = strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
b.Index = i + 1
b.ResourceID = resID
bgmBanner = append(bgmBanner, b)
}
return
}

View File

@@ -0,0 +1,610 @@
package region
import (
"context"
"fmt"
"strconv"
"time"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/bangumi"
"go-common/app/interface/main/app-show/model/card"
"go-common/app/interface/main/app-show/model/region"
"go-common/app/interface/main/app-show/model/tag"
"go-common/app/service/main/archive/api"
resource "go-common/app/service/main/resource/model"
"go-common/library/log"
)
var (
// 番剧 动画,音乐,舞蹈,游戏,科技,娱乐,鬼畜,电影,时尚, 生活,国漫
_tids = []int{13, 1, 3, 129, 4, 36, 5, 119, 23, 155, 160, 11, 167}
)
// loadBanner1 load banner cache.
func (s *Service) loadBanner() {
var (
resbs = map[int8]map[int][]*resource.Banner{}
)
for plat, resIDStr := range _bannersPlat {
mobiApp := model.MobiApp(plat)
res, err := s.res.ResBanner(context.TODO(), plat, 515007, 0, resIDStr, "master", "", "", "", mobiApp, "", "", false)
if err != nil || len(res) == 0 {
log.Error("s.res.ResBanner is null or err(%v)", err)
return
}
resbs[plat] = res
}
if len(resbs) > 0 {
s.bannerCache = resbs
}
log.Info("loadBannerCahce success")
}
func (s *Service) loadbgmBanner() {
bgmBanners := map[int8]map[int][]*bangumi.Banner{}
for plat, b := range _bannersPGC {
ridBanners := map[int][]*bangumi.Banner{}
for rid, pgcID := range b {
bBanner, err := s.bgm.Banners(context.TODO(), pgcID)
if err != nil {
log.Error("s.bgmdao.Banners is null or err(%v)", err)
return
}
ridBanners[rid] = bBanner
}
bgmBanners[plat] = ridBanners
}
s.bannerBmgCache = bgmBanners
}
// loadRegionShow
func (s *Service) loadShow() {
// default use android regions TODO
regionkey := fmt.Sprintf(_initRegionKey, model.PlatAndroid, _initlanguage)
res := s.cachelist[regionkey]
var (
// region tmp
showTmp = map[int][]*region.ShowItem{} // tmp hotCache
showNTmp = map[int][]*region.ShowItem{} // tmp newCache
showD = map[int][]*region.ShowItem{} // tmp dynamicCache
sTmp = map[int]*region.Show{}
// region tmp overseas
showTmpOsea = map[int][]*region.ShowItem{} // tmp overseas hotCache
showNTmpOsea = map[int][]*region.ShowItem{} // tmp overseas newCache
showDOsea = map[int][]*region.ShowItem{} // tmp overseas dynamicCache
sTmpOsea = map[int]*region.Show{}
// aids
showDynamicAids = map[int][]int64{}
// new region feed
regionFeedTmp = map[int]*region.Show{}
regionFeedTmpOsea = map[int]*region.Show{}
)
for _, v := range res {
if v.Reid == 0 {
if v.Rid == 65537 || v.Rid == 65539 || v.Rid == 65541 || v.Rid == 65543 {
continue
}
var (
tmp, tmpOsea []*region.ShowItem
aidsTmp []int64
)
tmp, tmpOsea = s.loadShowHot(v.Rid)
showTmp[v.Rid], showTmpOsea[v.Rid] = s.upCache(tmp, tmpOsea, s.hotCache[v.Rid], s.hotOseaCache[v.Rid])
tmp, tmpOsea = s.loadShowNewRpc(v.Rid)
showNTmp[v.Rid], showNTmpOsea[v.Rid] = s.upCache(tmp, tmpOsea, s.newCache[v.Rid], s.newOseaCache[v.Rid])
tmp, tmpOsea, aidsTmp = s.loadShowDynamic(v.Rid)
showDynamicAids[v.Rid] = s.upAidsCache(aidsTmp, s.showDynamicAidsCache[v.Rid])
showD[v.Rid], showDOsea[v.Rid] = s.upCache(tmp, tmpOsea, s.dynamicCache[v.Rid], s.dynamicOseaCache[v.Rid])
sTmp[v.Rid] = s.mergeShow(showTmp[v.Rid], showNTmp[v.Rid], showD[v.Rid])
// overseas
sTmpOsea[v.Rid] = s.mergeShow(showTmpOsea[v.Rid], showNTmpOsea[v.Rid], showDOsea[v.Rid])
// new region feed
regionFeedTmp[v.Rid], _ = s.mergeChildShow(showTmp[v.Rid], showNTmp[v.Rid])
regionFeedTmpOsea[v.Rid], _ = s.mergeChildShow(showTmpOsea[v.Rid], showNTmpOsea[v.Rid])
}
}
s.showCache = sTmp
s.hotCache = showTmp
s.newCache = showNTmp
s.dynamicCache = showD
// overseas
s.showOseaCache = sTmpOsea
s.hotOseaCache = showTmpOsea
s.newOseaCache = showNTmpOsea
s.dynamicOseaCache = showDOsea
// new region feed
s.regionFeedCache = regionFeedTmp
s.regionFeedOseaCache = regionFeedTmpOsea
// aids
s.showDynamicAidsCache = showDynamicAids
}
// loadShowChild
func (s *Service) loadShowChild() {
// default use android regions TODO
regionkey := fmt.Sprintf(_initRegionKey, model.PlatAndroid, _initlanguage)
res := s.cachelist[regionkey]
var (
scTmp = map[int]*region.Show{}
showC = map[int][]*region.ShowItem{} // tmp childHotCache
showCN = map[int][]*region.ShowItem{} // tmp childNewCache
// region tmp overseas
scTmpOsea = map[int]*region.Show{}
showCOsea = map[int][]*region.ShowItem{} // tmp overseas childHotCache
showCNOsea = map[int][]*region.ShowItem{} // tmp overseas childNewCache
// aids
showChildAids = map[int][]int64{}
showNewAids = map[int][]int64{}
)
for _, v := range res {
if v.Reid != 0 {
var (
tmp, tmpOsea []*region.ShowItem
aidsTmp []int64
)
tmp, tmpOsea, aidsTmp = s.loadShowChileHot(v.Rid)
showChildAids[v.Rid] = s.upAidsCache(aidsTmp, s.childHotAidsCache[v.Rid])
showC[v.Rid], showCOsea[v.Rid] = s.upCache(tmp, tmpOsea, s.childHotCache[v.Rid], s.childHotOseaCache[v.Rid])
tmp, tmpOsea, aidsTmp = s.loadShowChildNew(v.Rid)
showNewAids[v.Rid] = s.upAidsCache(aidsTmp, s.childNewAidsCache[v.Rid])
showCN[v.Rid], showCNOsea[v.Rid] = s.upCache(tmp, tmpOsea, s.childNewCache[v.Rid], s.childNewOseaCache[v.Rid])
scTmp[v.Rid], showCN[v.Rid] = s.mergeChildShow(showC[v.Rid], showCN[v.Rid])
// overseas
scTmpOsea[v.Rid], showCNOsea[v.Rid] = s.mergeChildShow(showCOsea[v.Rid], showCNOsea[v.Rid])
}
}
s.childShowCache = scTmp
s.childHotCache = showC
s.childNewCache = showCN
// overseas
s.childShowOseaCache = scTmpOsea
s.childHotOseaCache = showCOsea
s.childNewOseaCache = showCNOsea
// region child aids
s.childHotAidsCache = showChildAids
s.childNewAidsCache = showNewAids
}
func (s *Service) loadShowChildTagsInfo() {
// default use android regions TODO
regionkey := fmt.Sprintf(_initRegionKey, model.PlatAndroid, _initlanguage)
res := s.cachelist[regionkey]
reslist := s.regionListCache[regionkey]
var (
// tag tmp
tagsRegionTmp = map[int][]*region.SimilarTag{} // region tags
tagsTmp = map[string]string{} // tagid cache
)
for _, v := range res {
if v.Reid != 0 {
//tag
var rTmp *region.Region
if r, ok := reslist[v.Reid]; ok {
rTmp = r
}
if tids := s.loadShowChildTagIDs(v.Rid); len(tids) > 0 {
for _, tag := range tids {
tagInfo := &region.SimilarTag{
TagId: int(tag.Tid),
TagName: tag.Name,
Rid: v.Rid,
Rname: v.Name,
}
if rTmp != nil {
tagInfo.Reid = rTmp.Rid
tagInfo.Rename = rTmp.Name
}
//tags info
tagsRegionTmp[v.Rid] = append(tagsRegionTmp[v.Rid], tagInfo)
key := fmt.Sprintf(_initRegionTagKey, v.Rid, tag.Tid)
tagsTmp[key] = tag.Name
}
}
}
}
// region child aids
s.regionTagCache = tagsRegionTmp
s.tagsCache = tagsTmp
}
// loadShowHot
func (s *Service) loadShowHot(rid int) (resData, resOseaData []*region.ShowItem) {
res, err := s.rcmmnd.RegionHots(context.TODO(), rid)
if err != nil {
log.Error("s.rcmmnd.RegionHot(%d) error(%v)", rid, err)
return
}
if len(res) > 8 {
res = res[:8]
}
resData, resOseaData = s.fromAids(context.TODO(), res, false, 0)
log.Info("loadShowHot(%d) success", rid)
return
}
// loadShowNewRpc
func (s *Service) loadShowNewRpc(rid int) (resData, resOseaData []*region.ShowItem) {
arcs, err := s.arc.RankTopArcs(context.TODO(), rid, 1, 20)
if err != nil {
log.Error("s.arc.RankTopArcs(%d) error(%v)", rid, err)
return
}
if len(arcs) > 20 {
arcs = arcs[:20]
}
resData, resOseaData = s.fromArchivesPB(arcs)
log.Info("loadShowNewRpc(%d) success", rid)
return
}
// loadShowDynamic
func (s *Service) loadShowDynamic(rid int) (resData, resOseaData []*region.ShowItem, arcAids []int64) {
var (
err error
arcs []*api.Arc
)
arcs, arcAids, err = s.dyn.RegionDynamic(context.TODO(), rid, 1, 100)
if err != nil || len(arcs) < 20 {
log.Error("s.rcmmnd.RegionDynamic(%d) error(%v)", rid, err)
return
}
resData, resOseaData = s.fromArchivesPB(arcs)
log.Info("loadShowRPCDynamic(%d) success", rid)
return
}
// loadShowChileHot
func (s *Service) loadShowChileHot(rid int) (resData, resOseaData []*region.ShowItem, arcAids []int64) {
var err error
arcAids, err = s.rcmmnd.RegionChildHots(context.TODO(), rid)
if err != nil || len(arcAids) < 4 {
log.Error("s.rcmmnd.RegionChildHots(%d) error(%v)", rid, err)
return
}
resData, resOseaData = s.fromAids(context.TODO(), arcAids, false, 0)
log.Info("loadShowChileHot(%d) success", rid)
return
}
// loadShowChildNew
func (s *Service) loadShowChildNew(rid int) (resData, resOseaData []*region.ShowItem, arcAids []int64) {
var (
err error
arcs []*api.Arc
)
arcs, arcAids, err = s.arc.RanksArcs(context.TODO(), rid, 1, 300)
if err != nil || len(arcAids) < 20 {
log.Error("s.arc.RanksArc(%d) error(%v)", rid, err)
return
}
resData, resOseaData = s.fromArchivesPB(arcs)
log.Info("loadShowChildNew(%d) success", rid)
return
}
// loadShowChildTagIDs
func (s *Service) loadShowChildTagIDs(rid int) (tags []*tag.Tag) {
tags, err := s.tag.TagHotsId(context.TODO(), rid, time.Now())
if err != nil || len(tags) == 0 {
log.Error("s.tag.loadShowChildTagIDs(%d) error(%v)", rid, err)
return
}
return
}
// loadRankRegionCache
func (s *Service) loadRankRegionCache() {
var (
tmp = map[int][]*region.ShowItem{}
tmpOsea = map[int][]*region.ShowItem{}
)
for _, rid := range _tids {
aids, others, scores, err := s.rcmmnd.RankAppRegion(context.TODO(), rid)
if err != nil {
log.Error("s.rcmmnd.RankAppRegion rid (%v) error(%v)", rid, err)
return
}
tRank, tOseaRank := s.fromRankAids(context.TODO(), aids, others, scores)
tmp[rid] = tRank
tmpOsea[rid] = tOseaRank
}
if len(tmp) > 0 {
s.rankCache = tmp
}
if len(tmpOsea) > 0 {
s.rankOseaCache = tmpOsea
}
}
// loadRegionListCache
func (s *Service) loadRegionListCache() {
res, err := s.dao.RegionPlat(context.TODO())
if err != nil {
log.Error("s.dao.RegionPlat error(%v)", err)
return
}
tmpRegion := map[int]*region.Region{}
tmp := map[int]*region.Region{}
for _, v := range res {
// region list map
tmpRegion[v.Rid] = v
}
for _, r := range res {
if r.Reid != 0 {
if rerg, ok := tmpRegion[r.Reid]; ok {
tmp[r.Rid] = rerg
}
}
}
s.reRegionCache = tmp
}
func (s *Service) loadColumnListCache(now time.Time) {
var (
tmpChild = map[int]*card.ColumnList{}
)
columns, err := s.cdao.ColumnList(context.TODO(), now)
if err != nil {
log.Error("s.cdao.ColumnList error(%v)", err)
return
}
for _, column := range columns {
tmpChild[column.Cid] = column
}
s.columnListCache = tmpChild
}
// loadCardCache load all card cache
func (s *Service) loadCardCache(now time.Time) {
hdm, err := s.cdao.PosRecs(context.TODO(), now)
if err != nil {
log.Error("s.cdao.PosRecs error(%v)", err)
return
}
itm, aids, err := s.cdao.RecContents(context.TODO(), now)
if err != nil {
log.Error("s.cdao.RecContents error(%v)", err)
return
}
tmpItem := map[int]map[int64]*region.ShowItem{}
for recid, aid := range aids {
tmpItem[recid] = s.fromCardAids(context.TODO(), aid)
}
tmp := s.mergeCard(context.TODO(), hdm, itm, tmpItem, now)
s.cardCache = tmp
}
func (s *Service) mergeCard(c context.Context, hdm map[int8]map[int][]*card.Card, itm map[int][]*card.Content, tmpItems map[int]map[int64]*region.ShowItem, now time.Time) (res map[string][]*region.Head) {
// default use android regions TODO
var (
_topic = 1
_activity = 0
regionkey = fmt.Sprintf(_initRegionKey, model.PlatAndroid, _initlanguage)
regionList = s.cachelist[regionkey]
)
res = map[string][]*region.Head{}
for _, v := range regionList {
if v.Reid != 0 {
continue
}
for plat, phds := range hdm {
hds, ok := phds[v.Rid]
if !ok {
continue
}
for _, hd := range hds {
key := fmt.Sprintf(_initCardKey, plat, v.Rid)
var (
sis []*region.ShowItem
)
its, ok := itm[hd.ID]
if !ok {
its = []*card.Content{}
}
tmpItem, ok := tmpItems[hd.ID]
if !ok {
tmpItem = map[int64]*region.ShowItem{}
}
// 1 daily 2 topic 3 activity 4 rank 5 polymeric_card
switch hd.Type {
case 1:
for _, ci := range its {
si := s.fillCardItem(ci, tmpItem)
if si.Title != "" {
sis = append(sis, si)
}
}
case 2:
if topicID, err := strconv.ParseInt(hd.Rvalue, 10, 64); err == nil {
if actm, err := s.act.Activitys(c, []int64{topicID}, _topic, ""); err != nil {
log.Error("s.act.Activitys topicID error (%v)", topicID, err)
} else {
if act, ok := actm[topicID]; ok && act.H5Cover != "" && act.H5URL != "" {
si := &region.ShowItem{}
si.FromTopic(act)
sis = []*region.ShowItem{si}
}
}
}
case 3:
if topicID, err := strconv.ParseInt(hd.Rvalue, 10, 64); err == nil {
if actm, err := s.act.Activitys(c, []int64{topicID}, _activity, ""); err != nil {
log.Error("s.act.Activitys topicID error (%v)", topicID, err)
} else {
if act, ok := actm[topicID]; ok && act.H5Cover != "" && act.H5URL != "" {
si := &region.ShowItem{}
si.FromActivity(act, now)
sis = []*region.ShowItem{si}
}
}
}
case 4:
if tmpRank, ok := s.rankCache[v.Rid]; ok {
if len(tmpRank) > 3 {
sis = tmpRank[:3]
} else {
sis = tmpRank
}
}
case 5, 6, 8:
for _, ci := range its {
si := s.fillCardItem(ci, tmpItem)
if si.Title != "" {
sis = append(sis, si)
}
}
case 7:
si := &region.ShowItem{
Title: hd.Title,
Cover: hd.Cover,
Desc: hd.Desc,
Goto: hd.Goto,
Param: hd.Param,
}
if hd.Goto == model.GotoColumnStage {
paramInt, _ := strconv.Atoi(hd.Param)
if c, ok := s.columnListCache[paramInt]; ok {
cidStr := strconv.Itoa(c.Ceid)
si.URI = model.FillURICategory(hd.Goto, cidStr, hd.Param)
}
} else {
si.URI = hd.URi
}
sis = append(sis, si)
default:
continue
}
if len(sis) == 0 {
continue
}
sw := &region.Head{
CardID: hd.ID,
Title: hd.Title,
Type: hd.TypeStr,
Build: hd.Build,
Condition: hd.Condition,
Plat: hd.Plat,
}
if hd.Cover != "" {
sw.Cover = hd.Cover
}
switch sw.Type {
case model.GotoDaily:
sw.Date = now.Unix()
sw.Param = hd.Rvalue
sw.URI = hd.URi
sw.Goto = hd.Goto
case model.GotoCard:
sw.URI = hd.URi
sw.Goto = hd.Goto
sw.Param = hd.Param
case model.GotoRank:
sw.Param = strconv.Itoa(v.Rid)
case model.GotoTopic, model.GotoActivity:
if sw.Title == "" {
if len(sis) > 0 {
sw.Title = sis[0].Title
}
}
case model.GotoVeidoCard:
sw.Param = hd.Param
if hd.Goto == model.GotoColumnStage {
paramInt, _ := strconv.Atoi(hd.Param)
if c, ok := s.columnListCache[paramInt]; ok {
cidStr := strconv.Itoa(c.Ceid)
sw.URI = model.FillURICategory(hd.Goto, cidStr, hd.Param)
}
sw.Goto = model.GotoColumn
} else {
sw.Goto = hd.Goto
sw.URI = hd.URi
}
if sisLen := len(sis); sisLen > 1 {
if sisLen%2 != 0 {
sis = sis[:sisLen-1]
}
} else {
continue
}
case model.GotoSpecialCard:
sw.Cover = ""
case model.GotoTagCard:
if hd.TagID > 0 {
var tagIDInt int64
sw.Title, tagIDInt = s.fromTagIDByName(c, hd.TagID, now)
sw.Param = strconv.FormatInt(tagIDInt, 10)
sw.Goto = model.GotoTagID
}
}
sw.Body = sis
res[key] = append(res[key], sw)
}
}
}
return
}
// fillCardItem
func (s *Service) fillCardItem(csi *card.Content, tsi map[int64]*region.ShowItem) (si *region.ShowItem) {
si = &region.ShowItem{}
switch csi.Type {
case model.CardGotoAv:
si.Goto = model.GotoAv
si.Param = csi.Value
}
si.URI = model.FillURI(si.Goto, si.Param, nil)
if si.Goto == model.GotoAv {
aid, err := strconv.ParseInt(si.Param, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", si.Param, err)
} else {
if it, ok := tsi[aid]; ok {
si = it
if csi.Title != "" {
si.Title = csi.Title
}
} else {
si = &region.ShowItem{}
}
}
}
return
}
// fromTagIDByName from tag_id by tag_name
func (s *Service) fromTagIDByName(ctx context.Context, tagID int, now time.Time) (tagName string, tagIDInt int64) {
tag, err := s.tag.TagInfo(ctx, 0, tagID, now)
if err != nil {
log.Error("s.tag.TagInfo(%d) error(%v)", tagID, err)
return
}
tagName = tag.Name
tagIDInt = tag.Tid
return
}
// upCahce update cache
func (s *Service) upCache(new, newOsea, old, oldOsea []*region.ShowItem) (res, resOsea []*region.ShowItem) {
if len(new) > 0 {
res = new
} else {
res = old
}
if len(newOsea) > 0 {
resOsea = newOsea
} else {
resOsea = oldOsea
}
return
}
// upAidsCache update aids cache
func (s *Service) upAidsCache(new, old []int64) (aids []int64) {
if len(new) > 0 {
aids = new
} else {
aids = old
}
return
}

View File

@@ -0,0 +1,101 @@
package region
import (
"bytes"
"strconv"
"time"
"go-common/app/interface/main/app-show/conf"
"go-common/library/log"
binfoc "go-common/library/log/infoc"
)
type infoc struct {
mid string
rid string
tid string
pn string
hotavid []int64
newavid []int64
now string
}
// Infoc write data for Hadoop do analytics
func (s *Service) infoc(mid int64, hotavid, newavid []int64, rid, tid int, pull bool, now time.Time) {
var pn string
if pull {
pn = "1"
} else {
pn = "2"
}
select {
case s.logCh <- infoc{strconv.FormatInt(mid, 10), strconv.Itoa(rid), strconv.Itoa(tid), pn, hotavid, newavid, strconv.FormatInt(now.Unix(), 10)}:
default:
log.Warn("infoc log buffer is full")
}
}
// writeInfoc
func (s *Service) infocproc() {
const (
noItem1 = `{"section":{"rid":`
noItem2 = `,"tagid":`
noItem3 = `,"mid":`
noItem4 = `,"pn":`
noItem5 = `,"hot_avids":[],"item_avids":[]}}`
)
var (
msg1 = []byte(`{"section":{"rid":`)
msg2 = []byte(`,"tagid":`)
msg3 = []byte(`,"mid":`)
msg4 = []byte(`,"pn":`)
msg5 = []byte(`,"hot_avids":[`)
msg6 = []byte(`,`)
msg7 = []byte(`],"item_avids":[`)
msg8 = []byte(`,`)
msg9 = []byte(`]}}`)
inf2 = binfoc.New(conf.Conf.FeedInfoc2)
buf bytes.Buffer
list string
)
for {
i, ok := <-s.logCh
if !ok {
log.Warn("infoc proc exit")
return
}
switch v := i.(type) {
case infoc:
if len(v.newavid) > 0 {
buf.Write(msg1)
buf.WriteString(v.rid)
buf.Write(msg2)
buf.WriteString(v.tid)
buf.Write(msg3)
buf.WriteString(v.mid)
buf.Write(msg4)
buf.WriteString(v.pn)
buf.Write(msg5)
for _, v := range v.hotavid {
buf.WriteString(strconv.FormatInt(v, 10))
buf.Write(msg6)
}
if len(v.hotavid) > 0 {
buf.Truncate(buf.Len() - 1)
}
buf.Write(msg7)
for _, v := range v.newavid {
buf.WriteString(strconv.FormatInt(v, 10))
buf.Write(msg8)
}
buf.Truncate(buf.Len() - 1)
buf.Write(msg9)
list = buf.String()
buf.Reset()
} else {
list = noItem1 + v.rid + noItem2 + v.tid + noItem3 + v.mid + noItem4 + v.pn + noItem5
}
inf2.Info(v.now, list)
}
}
}

View File

@@ -0,0 +1,362 @@
package region
import (
"context"
"encoding/json"
"fmt"
"strconv"
"strings"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/region"
locmdl "go-common/app/service/main/location/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
farm "github.com/dgryski/go-farm"
)
const (
_initRegionKey = "region_key_%d_%v"
_initlanguage = "hans"
_initVersion = "region_version"
_regionAll = int8(0)
_isRegion = int8(1)
_isRank = int8(2)
_initRegionlimit = "%d_%v"
_regionRepeat = "r_%d_%d"
)
var (
_emptyRegions = []*region.Region{}
_isBangumi = map[int]struct{}{
13: struct{}{},
177: struct{}{},
23: struct{}{},
11: struct{}{},
}
_isBangumiIndex = map[int]struct{}{
13: struct{}{},
23: struct{}{},
11: struct{}{},
167: struct{}{},
}
_regionlimit = map[int8]map[string]map[int]string{
model.PlatIPhone: map[string]map[int]string{
"65542_bilibili://cliparea": map[int]string{
5960: "gt",
6570: "lt",
},
"65541_bilibili://category/65541": map[int]string{
5960: "gt",
6570: "lt",
},
"65544_bilibili://albumarea": map[int]string{
6090: "gt",
6570: "lt",
},
},
}
)
// Regions get regions.
func (s *Service) Regions(c context.Context, plat int8, build int, ver, mobiApp, device, language string) (rs []*region.Region, version string, err error) {
ip := metadata.String(c, metadata.RemoteIP)
rs, version, err = s.getCache(c, plat, build, ver, ip, mobiApp, device, language, "", false)
return
}
// Regions get regions.
func (s *Service) RegionsList(c context.Context, plat int8, build int, ver, mobiApp, device, language, entrance string) (rs []*region.Region, version string, err error) {
ip := metadata.String(c, metadata.RemoteIP)
rs, version, err = s.getCache(c, plat, build, ver, ip, mobiApp, device, language, entrance, true)
return
}
// getCache get region from cache.
func (s *Service) getCache(c context.Context, plat int8, build int, ver, ip, mobiApp, device, language, entrance string, isNew bool) (res []*region.Region, version string, err error) {
if language == "" {
language = _initlanguage
}
var (
rs = s.cache[fmt.Sprintf(_initRegionKey, plat, language)]
child = map[int][]*region.Region{}
entranceShow = _isRegion
ridlimit = _regionlimit[plat]
ridtmp = map[string]struct{}{}
pids []string
auths map[string]*locmdl.Auth
)
switch entrance {
case "region":
entranceShow = _isRegion
case "rank":
entranceShow = _isRank
}
for _, rtmp := range rs {
if rtmp.Area != "" {
pids = append(pids, rtmp.Area)
}
}
if len(pids) > 0 {
auths, _ = s.loc.AuthPIDs(c, strings.Join(pids, ","), ip)
}
Retry:
for _, rtmp := range rs {
r := &region.Region{}
*r = *rtmp
if _, isgbm := _isBangumi[r.Rid]; isgbm {
r.IsBangumi = 1
}
if isNew {
if r.Entrance != _regionAll && entranceShow != r.Entrance {
continue
}
} else {
switch r.Rid {
case 65545, 65542, 65541, 65543, 65544, 65546:
if mobiApp == "android" {
continue
}
}
}
if r.Rid != 165 || ((mobiApp != "iphone" || device != "pad") || build <= 3590) {
if model.InvalidBuild(build, r.Build, r.Condition) {
continue
}
}
key := fmt.Sprintf(_initRegionlimit, r.Rid, r.URI)
if rlimit, ok := ridlimit[key]; ok {
for blimit, climit := range rlimit {
if model.InvalidBuild(build, blimit, climit) {
continue Retry
}
}
}
if r.Rid == 65541 && (plat == model.PlatIPhone && build == 7040) {
continue
}
if r.Rid == 65543 && ((plat == model.PlatIPhone && (build == 7070 || build == 7040 || build == 7030)) ||
(plat == model.PlatAndroid && (build == 591182 || build == 591181 || build == 591178 || build == 591177))) {
continue
}
if auth, ok := auths[r.Area]; ok && auth.Play == locmdl.Forbidden {
log.Warn("s.invalid area(%v) ip(%v) error(%v)", r.Area, ip, err)
continue
}
if isAudit := s.auditRegion(mobiApp, plat, build, r.Rid); isAudit {
continue
}
rkey := fmt.Sprintf(_regionRepeat, r.Rid, r.Reid)
if _, ok := ridtmp[rkey]; !ok {
ridtmp[rkey] = struct{}{}
} else {
continue
}
if r.Reid != 0 {
cl, ok := child[r.Reid]
if !ok {
cl = []*region.Region{}
}
cl = append(cl, r)
child[r.Reid] = cl
} else {
res = append(res, r)
}
}
if len(res) == 0 {
res = _emptyRegions
} else {
for _, r := range res {
r.Children = child[r.Rid]
}
}
if version = s.hash(res); version == ver {
err = ecode.NotModified
res = nil
}
return
}
// NewRegionList get region from cache.
func (s *Service) NewRegionList(c context.Context, plat int8, build int, ver, mobiApp, device, language string) (res []*region.Region, version string, err error) {
ip := metadata.String(c, metadata.RemoteIP)
var (
hantlanguage = "hant"
)
if ok := model.IsOverseas(plat); ok && language != _initlanguage && language != hantlanguage {
language = hantlanguage
} else if language == "" {
language = _initlanguage
}
var (
rs = s.cachelist[fmt.Sprintf(_initRegionKey, plat, language)]
child = map[int][]*region.Region{}
ridtmp = map[string]struct{}{}
pids []string
auths map[string]*locmdl.Auth
)
for _, rtmp := range rs {
if rtmp.Area != "" {
pids = append(pids, rtmp.Area)
}
}
if len(pids) > 0 {
auths, _ = s.loc.AuthPIDs(c, strings.Join(pids, ","), ip)
}
LOOP:
for _, rtmp := range rs {
r := &region.Region{}
*r = *rtmp
if _, isgbm := _isBangumiIndex[r.Rid]; isgbm {
r.IsBangumi = 1
}
var tmpl, limitshow bool
if limit, ok := s.limitCache[r.ID]; ok {
for i, l := range limit {
if i+1 <= len(limit)-1 {
if ((l.Condition == "gt" && limit[i+1].Condition == "lt") && (l.Build < limit[i+1].Build)) ||
((l.Condition == "lt" && limit[i+1].Condition == "gt") && (l.Build > limit[i+1].Build)) {
if (l.Condition == "gt" && limit[i+1].Condition == "lt") &&
(build > l.Build && build < limit[i+1].Build) {
break
} else if (l.Condition == "lt" && limit[i+1].Condition == "gt") &&
(build < l.Build && build > limit[i+1].Build) {
break
} else {
tmpl = true
continue
}
}
}
if tmpl {
if i == len(limit)-1 {
limitshow = true
// continue LOOP
break
}
tmpl = false
continue
}
if model.InvalidBuild(build, l.Build, l.Condition) {
limitshow = true
continue
// continue LOOP
} else {
limitshow = false
break
}
}
}
if limitshow {
continue LOOP
}
if auth, ok := auths[r.Area]; ok && auth.Play == locmdl.Forbidden {
log.Warn("s.invalid area(%v) ip(%v) error(%v)", r.Area, ip, err)
continue
}
if isAudit := s.auditRegion(mobiApp, plat, build, r.Rid); isAudit {
continue
}
if config, ok := s.configCache[r.ID]; ok {
r.Config = config
}
key := fmt.Sprintf(_regionRepeat, r.Rid, r.Reid)
if _, ok := ridtmp[key]; !ok {
ridtmp[key] = struct{}{}
} else {
continue
}
if r.Reid != 0 {
cl, ok := child[r.Reid]
if !ok {
cl = []*region.Region{}
}
cl = append(cl, r)
child[r.Reid] = cl
} else {
res = append(res, r)
}
}
if len(res) == 0 {
res = _emptyRegions
} else {
for _, r := range res {
r.Children = child[r.Rid]
}
}
if version = s.hash(res); version == ver {
err = ecode.NotModified
res = nil
}
return
}
func (s *Service) hash(v []*region.Region) string {
bs, err := json.Marshal(v)
if err != nil {
log.Error("json.Marshal error(%v)", err)
return _initVersion
}
return strconv.FormatUint(farm.Hash64(bs), 10)
}
// loadRegion regions cache.
func (s *Service) loadRegion() {
res, err := s.dao.All(context.TODO())
if err != nil {
log.Error("s.dao.All error(%v)", err)
return
}
tmp := map[string][]*region.Region{}
for _, v := range res {
key := fmt.Sprintf(_initRegionKey, v.Plat, v.Language)
tmp[key] = append(tmp[key], v)
}
if len(tmp) > 0 {
s.cache = tmp
}
log.Info("region cacheproc success")
}
func (s *Service) loadRegionlist() {
res, err := s.dao.AllList(context.TODO())
if err != nil {
log.Error("s.dao.All error(%v)", err)
return
}
tmp := map[string][]*region.Region{}
tmpRegion := map[string]map[int]*region.Region{}
for _, v := range res {
key := fmt.Sprintf(_initRegionKey, v.Plat, v.Language)
tmp[key] = append(tmp[key], v)
// region list map
if r, ok := tmpRegion[key]; ok {
r[v.Rid] = v
} else {
tmpRegion[key] = map[int]*region.Region{
v.Rid: v,
}
}
}
if len(tmp) > 0 && len(tmpRegion) > 0 {
s.cachelist = tmp
s.regionListCache = tmpRegion
}
log.Info("region list cacheproc success")
limit, err := s.dao.Limit(context.TODO())
if err != nil {
log.Error("s.dao.limit error(%v)", err)
return
}
s.limitCache = limit
log.Info("region limit cacheproc success")
config, err := s.dao.Config(context.TODO())
if err != nil {
log.Error("s.dao.Config error(%v)", err)
return
}
s.configCache = config
log.Info("region config cacheproc success")
}

View File

@@ -0,0 +1,38 @@
package region
import (
"context"
"flag"
"go-common/app/interface/main/app-show/conf"
"path/filepath"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
func init() {
dir, _ := filepath.Abs("../../cmd/app-show-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestRegions(t *testing.T) {
Convey("get Regions data", t, WithService(func(s *Service) {
res, ver, err := s.Regions(context.TODO(), 0, 11111, "", "android", "", _initlanguage)
So(res, ShouldNotBeEmpty)
So(ver, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestRegionsList(t *testing.T) {
Convey("get RegionsList data", t, WithService(func(s *Service) {
res, ver, err := s.RegionsList(context.TODO(), 0, 11111, "", "android", "", _initlanguage, "region")
So(res, ShouldNotBeEmpty)
So(ver, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,338 @@
package region
import (
"time"
"go-common/app/interface/main/app-show/conf"
actdao "go-common/app/interface/main/app-show/dao/activity"
addao "go-common/app/interface/main/app-show/dao/ad"
arcdao "go-common/app/interface/main/app-show/dao/archive"
adtdao "go-common/app/interface/main/app-show/dao/audit"
bgmdao "go-common/app/interface/main/app-show/dao/bangumi"
carddao "go-common/app/interface/main/app-show/dao/card"
dyndao "go-common/app/interface/main/app-show/dao/dynamic"
locdao "go-common/app/interface/main/app-show/dao/location"
rcmmndao "go-common/app/interface/main/app-show/dao/recommend"
rgdao "go-common/app/interface/main/app-show/dao/region"
resdao "go-common/app/interface/main/app-show/dao/resource"
searchdao "go-common/app/interface/main/app-show/dao/search"
tagdao "go-common/app/interface/main/app-show/dao/tag"
"go-common/app/interface/main/app-show/model/bangumi"
"go-common/app/interface/main/app-show/model/card"
"go-common/app/interface/main/app-show/model/region"
resource "go-common/app/service/main/resource/model"
"go-common/library/stat/prom"
)
const (
_initRegionTagKey = "region_tag_%d_%d"
)
// Service is region service.
type Service struct {
c *conf.Config
// prom
pHit *prom.Prom
pMiss *prom.Prom
prmobi *prom.Prom
// dao
dao *rgdao.Dao
// bnnr *bnnrdao.Dao
rcmmnd *rcmmndao.Dao
ad *addao.Dao // cptbanner
tag *tagdao.Dao
adt *adtdao.Dao
arc *arcdao.Dao
dyn *dyndao.Dao
search *searchdao.Dao
cdao *carddao.Dao
act *actdao.Dao
bgm *bgmdao.Dao
res *resdao.Dao
loc *locdao.Dao
// tick
tick time.Duration
// regions cache
cache map[string][]*region.Region
// new region list cache
cachelist map[string][]*region.Region
limitCache map[int64][]*region.Limit
configCache map[int64][]*region.Config
regionListCache map[string]map[int]*region.Region
verCache map[string]string
// audit cache
auditCache map[string]map[int]struct{} // audit mobi_app builds
// region show item cache
bannerCache map[int8]map[int][]*resource.Banner
bannerBmgCache map[int8]map[int][]*bangumi.Banner
hotCache map[int][]*region.ShowItem
newCache map[int][]*region.ShowItem
dynamicCache map[int][]*region.ShowItem
// overseas
hotOseaCache map[int][]*region.ShowItem
newOseaCache map[int][]*region.ShowItem
dynamicOseaCache map[int][]*region.ShowItem
// region child show item cache
childHotCache map[int][]*region.ShowItem
childNewCache map[int][]*region.ShowItem
childHotAidsCache map[int][]int64
childNewAidsCache map[int][]int64
showDynamicAidsCache map[int][]int64
// overseas region child show item cache
childHotOseaCache map[int][]*region.ShowItem
childNewOseaCache map[int][]*region.ShowItem
// region tag show item cache
tagHotCache map[string][]*region.ShowItem
tagNewCache map[string][]*region.ShowItem
tagHotAidsCache map[string][]int64
tagNewAidsCache map[string][]int64
// overseas region tag show item cache
tagHotOseaCache map[string][]*region.ShowItem
tagNewOseaCache map[string][]*region.ShowItem
// new region feed
regionFeedCache map[int]*region.Show
regionFeedOseaCache map[int]*region.Show
// tags cache
tagsCache map[string]string
// region show
showCache map[int]*region.Show
childShowCache map[int]*region.Show
// overseas region show
showOseaCache map[int]*region.Show
childShowOseaCache map[int]*region.Show
// region dynamic show
showDynamicCache map[int]*region.Show
childShowDynamicCache map[int]*region.Show
// overseas region dynamic show
showDynamicOseaCache map[int]*region.Show
childShowDynamicOseaCache map[int]*region.Show
// similar tag
similarTagCache map[string][]*region.SimilarTag
// similar tag
regionTagCache map[int][]*region.SimilarTag
// ranking
rankCache map[int][]*region.ShowItem
rankOseaCache map[int][]*region.ShowItem
// card
cardCache map[string][]*region.Head
columnListCache map[int]*card.ColumnList
// region
reRegionCache map[int]*region.Region
// json tick
jsonOn bool
jsonCh chan int64
jsonIdsCache map[int64]struct{} // rid<<32 | tid
// cpm percentage 0~100
cpmNum int
cpmMid map[int64]struct{}
cpmAll bool
adIsPost bool
// infoc
logCh chan interface{}
}
// New new a region service.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
pHit: prom.CacheHit,
pMiss: prom.CacheMiss,
prmobi: prom.BusinessInfoCount,
// dao
dao: rgdao.New(c),
// bnnr: bnnrdao.New(c),
rcmmnd: rcmmndao.New(c),
ad: addao.New(c),
adt: adtdao.New(c),
arc: arcdao.New(c),
tag: tagdao.New(c),
dyn: dyndao.New(c),
search: searchdao.New(c),
cdao: carddao.New(c),
act: actdao.New(c),
bgm: bgmdao.New(c),
res: resdao.New(c),
loc: locdao.New(c),
// tick
tick: time.Duration(c.Tick),
// audit cache
auditCache: map[string]map[int]struct{}{},
// regions cache
cache: map[string][]*region.Region{},
// new region list cache
cachelist: map[string][]*region.Region{},
limitCache: map[int64][]*region.Limit{},
configCache: map[int64][]*region.Config{},
regionListCache: map[string]map[int]*region.Region{},
verCache: map[string]string{},
// region show item cache
bannerCache: map[int8]map[int][]*resource.Banner{},
bannerBmgCache: map[int8]map[int][]*bangumi.Banner{},
hotCache: map[int][]*region.ShowItem{},
newCache: map[int][]*region.ShowItem{},
dynamicCache: map[int][]*region.ShowItem{},
// overseas
hotOseaCache: map[int][]*region.ShowItem{},
newOseaCache: map[int][]*region.ShowItem{},
dynamicOseaCache: map[int][]*region.ShowItem{},
// region child show item cache
childHotCache: map[int][]*region.ShowItem{},
childNewCache: map[int][]*region.ShowItem{},
childHotAidsCache: map[int][]int64{},
childNewAidsCache: map[int][]int64{},
showDynamicAidsCache: map[int][]int64{},
// overseas region child show item cache
childHotOseaCache: map[int][]*region.ShowItem{},
childNewOseaCache: map[int][]*region.ShowItem{},
// region tag show item cache
tagHotCache: map[string][]*region.ShowItem{},
tagNewCache: map[string][]*region.ShowItem{},
tagHotAidsCache: map[string][]int64{},
tagNewAidsCache: map[string][]int64{},
// overseas region tag show item cache
tagHotOseaCache: map[string][]*region.ShowItem{},
tagNewOseaCache: map[string][]*region.ShowItem{},
// new region feed
regionFeedCache: map[int]*region.Show{},
regionFeedOseaCache: map[int]*region.Show{},
// tags cache
tagsCache: map[string]string{},
// region show
showCache: map[int]*region.Show{},
childShowCache: map[int]*region.Show{},
// overseas region show
showOseaCache: map[int]*region.Show{},
childShowOseaCache: map[int]*region.Show{},
// region dynamic show
showDynamicCache: map[int]*region.Show{},
childShowDynamicCache: map[int]*region.Show{},
// overseas region dynamic show
showDynamicOseaCache: map[int]*region.Show{},
childShowDynamicOseaCache: map[int]*region.Show{},
// similar tag
similarTagCache: map[string][]*region.SimilarTag{},
// similar tag
regionTagCache: map[int][]*region.SimilarTag{},
// ranking
rankCache: map[int][]*region.ShowItem{},
rankOseaCache: map[int][]*region.ShowItem{},
// card
cardCache: map[string][]*region.Head{},
columnListCache: map[int]*card.ColumnList{},
// region
reRegionCache: map[int]*region.Region{},
// json tick
jsonOn: false,
jsonCh: make(chan int64, 128),
jsonIdsCache: map[int64]struct{}{},
// cpm percentage 0~100
cpmNum: 0,
cpmMid: map[int64]struct{}{},
cpmAll: true,
adIsPost: false,
// infoc
logCh: make(chan interface{}, 1024),
}
now := time.Now()
s.loadRegionlist()
s.loadRegion()
s.loadShow()
s.loadShowChild()
s.loadShowChildTagsInfo()
s.loadBanner()
s.loadbgmBanner()
s.loadAuditCache()
s.loadRegionListCache()
s.loadRankRegionCache()
s.loadColumnListCache(now)
s.loadCardCache(now)
go s.loadproc()
go s.infocproc()
return
}
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
now := time.Now()
s.loadRegionlist()
s.loadRegion()
s.loadShow()
s.loadShowChild()
s.loadShowChildTagsInfo()
s.loadBanner()
s.loadbgmBanner()
s.loadAuditCache()
s.loadRegionListCache()
s.loadRankRegionCache()
s.loadColumnListCache(now)
s.loadCardCache(now)
}
}
// Close dao
func (s *Service) Close() {
s.dao.Close()
}
// SetCpm percentage 0~100
func (s *Service) SetCpmNum(num int) {
s.cpmNum = num
if s.cpmNum < 0 {
s.cpmNum = 0
} else if s.cpmNum > 100 {
s.cpmNum = 100
}
}
// GetCpm percentage
func (s *Service) CpmNum() int {
return s.cpmNum
}
// SetCpm percentage 0~100
func (s *Service) SetCpmMid(mid int64) {
var mids = map[int64]struct{}{}
mids[mid] = struct{}{}
for mid, _ := range s.cpmMid {
if _, ok := mids[mid]; !ok {
mids[mid] = struct{}{}
}
}
s.cpmMid = mids
}
// GetCpm percentage
func (s *Service) CpmMid() []int {
var mids []int
for mid, _ := range s.cpmMid {
mids = append(mids, int(mid))
}
return mids
}
// SetCpm All
func (s *Service) SetCpmAll(isAll bool) {
s.cpmAll = isAll
}
// GetCpm All
func (s *Service) CpmAll() int {
if s.cpmAll {
return 1
}
return 0
}
// SetIsPost Get or Post
func (s *Service) SetAdIsPost(isPost bool) {
s.adIsPost = isPost
}
// IsPost Get or Post
func (s *Service) AdIsPost() int {
if s.adIsPost {
return 1
}
return 0
}

View File

@@ -0,0 +1,926 @@
package region
import (
"context"
"fmt"
"time"
"go-common/app/interface/main/app-show/model"
seasongrpc "go-common/app/service/openplatform/pgc-season/api/grpc/season/v1"
"go-common/app/interface/main/app-show/model/region"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/log"
"go-common/library/net/metadata"
xtime "go-common/library/time"
)
const (
_initCardKey = "card_key_%d_%d"
_bangumiSeasonID = 1
_bangumiEpisodeID = 2
)
var (
_emptyShow = &region.Show{}
_emptyShowItems = []*region.ShowItem{}
_bangumiRids = map[int]struct{}{
33: struct{}{},
32: struct{}{},
153: struct{}{},
51: struct{}{},
152: struct{}{},
168: struct{}{},
169: struct{}{},
170: struct{}{},
}
_bangumiReids = map[int]struct{}{
13: struct{}{},
167: struct{}{},
}
)
// Show region show
func (s *Service) Show(c context.Context, plat int8, rid, build int, mid int64, channel, buvid, network, mobiApp, device, adExtra string) (res *region.Show) {
ip := metadata.String(c, metadata.RemoteIP)
if model.IsOverseas(plat) {
res = s.showOseaCache[rid]
} else {
res = s.showCache[rid]
}
if res == nil {
res = _emptyShow
return
}
if !model.IsIPad(plat) && len(res.Recommend) >= 4 {
res = &region.Show{
Recommend: res.Recommend[:4],
New: res.New,
Dynamic: res.Dynamic,
}
} else if model.IsIPad(plat) && len(res.Recommend) < 8 {
var (
max = 8
hotlen = len(res.Recommend)
)
if last := max - hotlen; last < len(res.New) {
res.Recommend = append(res.Recommend, res.New[:last]...)
} else if len(res.New) > 0 {
res.Recommend = append(res.Recommend, res.New...)
} else {
if last < len(res.Dynamic) {
res.Recommend = append(res.Recommend, res.Dynamic[:last]...)
} else if len(res.Dynamic) > 0 {
res.Recommend = append(res.Recommend, res.Dynamic...)
}
}
}
res.Banner = s.getBanners(c, plat, build, rid, mid, channel, ip, buvid, network, mobiApp, device, adExtra)
return
}
// ShowDynamic show dynamic page
func (s *Service) ShowDynamic(c context.Context, plat int8, build, rid, pn, ps int) (res []*region.ShowItem) {
var (
isOsea = model.IsOverseas(plat) //is overseas
bangumiType = 0
)
if _, isBangumi := _bangumiReids[rid]; isBangumi {
if (plat == model.PlatIPhone && build > 6090) || (plat == model.PlatAndroid && build > 514000) {
bangumiType = _bangumiEpisodeID
}
}
start := (pn - 1) * ps
end := start + ps
if bangumiType != 0 {
if end < len(s.showDynamicAidsCache[rid]) {
aids := s.showDynamicAidsCache[rid][start:end]
res = s.fromAidsOsea(c, aids, false, isOsea, bangumiType)
if len(res) > 0 {
return
}
}
}
if !isOsea {
if end < len(s.dynamicCache[rid]) {
res = s.dynamicCache[rid][start:end]
return
}
} else {
if end < len(s.dynamicOseaCache[rid]) {
res = s.dynamicOseaCache[rid][start:end]
return
}
}
as, aids, err := s.dyn.RegionDynamic(c, rid, pn, ps)
if err != nil {
log.Error("s.rcmmnd.RegionDynamic(%d, %d, %d) error(%v)", rid, pn, ps, err)
return
}
if bangumiType != 0 {
res = s.fromArchivesPBBangumiOsea(c, as, aids, isOsea, bangumiType)
} else {
res = s.fromArchivesPBOsea(as, isOsea)
}
return
}
// ChildShow region child show
func (s *Service) ChildShow(c context.Context, plat int8, mid int64, rid, tid, build int, channel, mobiApp string, now time.Time) (res *region.Show) {
var (
isOsea = model.IsOverseas(plat) //is overseas
bangumiType = 0
max = 20
)
if _, isBangumi := _bangumiRids[rid]; isBangumi {
if (plat == model.PlatIPhone && build > 6050) || (plat == model.PlatAndroid && build > 512007) {
bangumiType = _bangumiEpisodeID
} else {
bangumiType = _bangumiSeasonID
}
}
if (mobiApp == "iphone" && build <= 4280) || (mobiApp == "ipad" && build <= 10400) || (mobiApp == "white" && build <= 101320) ||
(mobiApp == "android" && build <= 501020) || (mobiApp == "android_tv" && build <= 1310) || mobiApp == "android_G" || mobiApp == "win" {
bangumiType = 0
}
if tid == 0 {
if bangumiType != 0 {
var (
hotTmp, newTmp []*region.ShowItem
aids []int64
hotOk, newOk bool
)
if aids, hotOk = s.childHotAidsCache[rid]; hotOk {
if len(aids) > max {
aids = aids[:max]
}
hotTmp = s.fromAidsOsea(c, aids, false, isOsea, bangumiType)
}
if aids, newOk = s.childNewAidsCache[rid]; newOk {
if len(aids) > max {
aids = aids[:max]
}
newTmp = s.fromAidsOsea(c, aids, false, isOsea, bangumiType)
}
if hotOk && newOk && len(hotTmp) > 0 && len(newTmp) > 0 {
res, _ = s.mergeChildShow(hotTmp, newTmp)
return
}
}
if !isOsea {
if res = s.childShowCache[rid]; res == nil {
res = _emptyShow
return
}
} else {
if res = s.childShowOseaCache[rid]; res == nil {
res = _emptyShow
return
}
}
return
}
res = s.mergeTagShow(c, rid, tid, bangumiType, isOsea, now)
if mid > 0 {
var err error
if res.Tag, err = s.tag.TagInfo(c, mid, tid, now); err != nil {
log.Error("s.tag.TagInfo(%d, %d) error(%v)", mid, tid, err)
}
}
return
}
// ChildListShow region childList show
func (s *Service) ChildListShow(c context.Context, plat int8, rid, tid, pn, ps, build int, mid int64, order, platform, mobiApp, device string) (res []*region.ShowItem) {
ip := metadata.String(c, metadata.RemoteIP)
var (
isOsea = model.IsOverseas(plat) //is overseas
bangumiType = 0
)
start := (pn - 1) * ps
end := start + ps
key := fmt.Sprintf(_initRegionTagKey, rid, tid)
if _, isBangumi := _bangumiRids[rid]; isBangumi {
if (plat == model.PlatIPhone && build > 6050) || (plat == model.PlatAndroid && build > 512007) {
bangumiType = _bangumiEpisodeID
} else {
bangumiType = _bangumiSeasonID
}
}
if (mobiApp == "iphone" && build <= 4280) || (mobiApp == "ipad" && build <= 10400) || (mobiApp == "white" && build <= 101320) ||
(mobiApp == "android" && build <= 501020) || (mobiApp == "android_tv" && build <= 1310) || mobiApp == "android_G" || mobiApp == "win" {
bangumiType = 0
}
if bangumiType != 0 {
if tid == 0 && (order == "" || order == "new") && end < len(s.childNewAidsCache[rid]) {
aids := s.childNewAidsCache[rid][start:end]
res = s.fromAidsOsea(c, aids, false, isOsea, bangumiType)
if len(res) > 0 {
return
}
}
if tid > 0 && (order == "" || order == "new") && end < len(s.tagNewAidsCache[key]) {
aids := s.tagNewAidsCache[key][start:end]
res = s.fromAidsOsea(c, aids, false, isOsea, bangumiType)
if len(res) > 0 {
return
}
}
}
if !isOsea {
if tid == 0 && (order == "" || order == "new") && end < len(s.childNewCache[rid]) {
res = s.childNewCache[rid][start:end]
return
}
if tid > 0 && (order == "" || order == "new") && end < len(s.tagNewCache[key]) {
res = s.tagNewCache[key][start:end]
return
}
} else {
if tid == 0 && (order == "" || order == "new") && end < len(s.childNewOseaCache[rid]) {
res = s.childNewOseaCache[rid][start:end]
return
}
if tid > 0 && (order == "" || order == "new") && end < len(s.tagNewOseaCache[key]) {
res = s.tagNewOseaCache[key][start:end]
return
}
}
if (order == "" || order == "new") && tid == 0 {
arcs, aids, err := s.arc.RanksArcs(c, rid, pn, ps)
if err != nil {
log.Error("s.rcmmnd.RegionArcList(%d, %d, %d, %d) error(%v)", rid, pn, ps, err)
}
if bangumiType != 0 {
res = s.fromArchivesPBBangumiOsea(c, arcs, aids, isOsea, bangumiType)
} else {
res = s.fromArchivesPBOsea(arcs, isOsea)
}
return
} else if (order == "" || order == "new") && tid > 0 {
as, err := s.tag.NewArcs(c, rid, tid, pn, ps, time.Now())
if err != nil {
log.Error("s.tag.NewArcs(%d, %d) error(%v)", rid, tid, err)
return
}
res = s.fromAidsOsea(c, as, false, isOsea, bangumiType)
return
}
var (
tname string
ok bool
)
if tid > 0 {
if tname, ok = s.tagsCache[key]; !ok {
return
}
}
as, err := s.search.SearchList(c, rid, build, pn, ps, mid, time.Now(), ip, order, tname, platform, mobiApp, device)
if err != nil {
log.Error("s.search.SearchList(%d, %d, %v, %d, %d) error(%v)", rid, tid, tname, pn, ps, err)
}
res = s.fromAidsOsea(c, as, false, isOsea, bangumiType)
return
}
// Dynamic region dynamic
func (s *Service) Dynamic(c context.Context, plat int8, rid, build int, mid int64, channel, buvid, network, mobiApp, device, adExtra string, now time.Time) (res *region.Show) {
ip := metadata.String(c, metadata.RemoteIP)
var (
isOsea = model.IsOverseas(plat) //is overseas
resCache *region.Show
)
s.prmobi.Incr("region_dynamic_plat_" + mobiApp)
if isOsea {
if resCache = s.regionFeedOseaCache[rid]; resCache == nil {
resCache = _emptyShow
}
} else {
if resCache = s.regionFeedCache[rid]; resCache == nil {
resCache = _emptyShow
}
}
if dyn, err := s.feedRegionDynamic(c, plat, rid, 0, 0, false, true, 0, mid, resCache.Recommend, now); err == nil && dyn != nil {
res = dyn
} else {
res = resCache
}
if res != nil {
res.Banner = s.getBanners(c, plat, build, rid, mid, channel, ip, buvid, network, mobiApp, device, adExtra)
res.Card = s.regionCardDisplay(plat, build, rid)
}
return
}
// regionCardDisplay
func (s *Service) regionCardDisplay(plat int8, build, rid int) (res []*region.Head) {
var ss []*region.Head
key := fmt.Sprintf(_initCardKey, plat, rid)
ss = s.cardCache[key]
if len(ss) == 0 {
res = []*region.Head{}
return
}
res = []*region.Head{}
for _, sw := range ss {
if model.InvalidBuild(build, sw.Build, sw.Condition) {
continue
}
tmp := &region.Head{}
*tmp = *sw
tmp.FillBuildURI(plat, build)
res = append(res, tmp)
}
return
}
// DynamicList show dynamic list
func (s *Service) DynamicList(c context.Context, plat int8, rid int, pull bool, ctime, mid int64, now time.Time) (res *region.Show) {
var (
err error
)
if res, err = s.feedRegionDynamic(c, plat, rid, 0, 0, pull, false, ctime, mid, nil, now); err != nil || res == nil {
res = _emptyShow
return
}
return
}
// DynamicChild region show dynamic
func (s *Service) DynamicChild(c context.Context, plat int8, rid, tid, build int, mid int64, mobiApp string, now time.Time) (res *region.Show) {
var (
isOsea = model.IsOverseas(plat) //is overseas
bangumiType = 0
resCache *region.Show
max = 20
)
s.prmobi.Incr("region_dynamic_child_plat_" + mobiApp)
if _, isBangumi := _bangumiRids[rid]; isBangumi {
if (plat == model.PlatIPhone && build > 6050) || (plat == model.PlatAndroid && build > 512007) {
bangumiType = _bangumiEpisodeID
} else {
bangumiType = _bangumiSeasonID
}
}
if tid == 0 {
if bangumiType != 0 {
var (
hotTmp, newTmp []*region.ShowItem
aids []int64
hotOk, newOk bool
)
if aids, hotOk = s.childHotAidsCache[rid]; hotOk {
if len(aids) > max {
aids = aids[:max]
}
hotTmp = s.fromAidsOsea(c, aids, false, isOsea, bangumiType)
}
if aids, newOk = s.childNewAidsCache[rid]; newOk {
if len(aids) > max {
aids = aids[:max]
}
newTmp = s.fromAidsOsea(c, aids, false, isOsea, bangumiType)
}
if len(hotTmp) > 0 && len(newTmp) > 0 {
resCache, _ = s.mergeChildShow(hotTmp, newTmp)
}
}
if resCache == nil {
if !isOsea {
if resCache = s.childShowCache[rid]; resCache == nil {
resCache = _emptyShow
}
} else {
if resCache = s.childShowOseaCache[rid]; resCache == nil {
resCache = _emptyShow
}
}
}
} else {
resCache = s.mergeTagShow(c, rid, tid, bangumiType, isOsea, now)
}
if resCache == nil {
resCache = _emptyShow
}
if dyn, err := s.feedRegionDynamic(c, plat, rid, tid, bangumiType, false, true, 0, mid, nil, now); err == nil && dyn != nil {
res = dyn
s.pHit.Incr("feed_region_dynamic")
} else {
res = resCache
s.pMiss.Incr("feed_region_dynamic")
}
if res != nil {
if tid == 0 {
if tags, ok := s.regionTagCache[rid]; ok {
res.TopTag = tags
}
} else if mid > 0 {
var err error
if res.Tag, err = s.tag.TagInfo(c, mid, tid, now); err != nil {
log.Error("s.tag.TagInfo(%d, %d) error(%v)", mid, tid, err)
}
}
}
return
}
// DynamicListChild dynamic childList show
func (s *Service) DynamicListChild(c context.Context, plat int8, rid, tid, build int, pull bool, ctime, mid int64, now time.Time) (res *region.Show) {
var (
err error
bangumiType = 0
)
if _, isBangumi := _bangumiRids[rid]; isBangumi {
if (plat == model.PlatIPhone && build > 6050) || (plat == model.PlatAndroid && build > 512007) {
bangumiType = _bangumiEpisodeID
} else {
bangumiType = _bangumiSeasonID
}
}
if res, err = s.feedRegionDynamic(c, plat, rid, tid, bangumiType, pull, false, ctime, mid, nil, now); err != nil || res == nil {
res = _emptyShow
return
}
return
}
// feedRegionDynamic
func (s *Service) feedRegionDynamic(c context.Context, plat int8, rid, tid, bangumiType int, pull, isRecommend bool, ctime, mid int64, items []*region.ShowItem, now time.Time) (res *region.Show, err error) {
var (
smTagNum = 10
smTagPos = 4
)
if res, err = s.feedDynamic(c, plat, rid, tid, bangumiType, pull, isRecommend, ctime, mid, items, now); err != nil || res == nil {
log.Error("s.feedDynamic is null rid:%v tid:%v", rid, tid)
} else {
if isRecommend && tid > 0 {
if st := s.similarTags(c, rid, tid, now); st != nil {
if len(st) > smTagNum {
res.TopTag = st[:smTagNum]
res.NewTag = &region.NewTag{
Position: smTagPos,
Tag: st[smTagNum:],
}
} else {
res.TopTag = st
}
}
}
}
return
}
// feedRegionDynamic
func (s *Service) feedDynamic(c context.Context, plat int8, rid, tid, bangumiType int, pull, isRecommend bool, ctime, mid int64, items []*region.ShowItem, now time.Time) (res *region.Show, err error) {
var (
isOsea = model.IsOverseas(plat) //is overseas
newAids = []int64{}
hotAids = []int64{}
ctop, cbottom xtime.Time
)
if hotAids, newAids, ctop, cbottom, err = s.rcmmnd.FeedDynamic(c, pull, rid, tid, ctime, mid, now); err != nil || len(newAids) == 0 {
log.Error("s.rcmmnd.FeedDynamic(%v) error(%v)", rid, err)
return
}
newItems := s.fromAidsOsea(c, newAids, false, isOsea, bangumiType)
hotItems := s.fromAidsOsea(c, hotAids, false, isOsea, bangumiType)
if isRecommend && (len(newItems) > 0 || len(hotItems) > 4) && len(newItems) > 0 {
if len(hotItems) >= 4 {
res = s.mergeDynamicShow(hotItems, newItems, ctop, cbottom)
} else {
log.Error("feedDynamic_hot is null rid:%v tid:%v", rid, tid)
res = s.mergeDynamicShow(items, newItems, ctop, cbottom)
}
} else if !isRecommend && len(newItems) > 0 {
res = s.mergeDynamicShow(_emptyShowItems, newItems, ctop, cbottom)
} else {
log.Error("feedDynamic_newItems is null rid:%v tid:%v", rid, tid)
}
s.infoc(mid, hotAids, newAids, rid, tid, pull, now)
return
}
// fromArchives return region show items from archive archives.
func (s *Service) fromArchivesPB(as []*api.Arc) (is, isOsea []*region.ShowItem) {
var asLen = len(as)
if asLen == 0 {
is = _emptyShowItems
return
}
is = make([]*region.ShowItem, 0, asLen)
for _, a := range as {
i := &region.ShowItem{}
i.FromArchivePB(a)
if a.AttrVal(archive.AttrBitOverseaLock) == 0 {
isOsea = append(isOsea, i)
}
is = append(is, i)
}
return
}
// fromArchivesPBBangumi aid to sid
func (s *Service) fromArchivesPBBangumi(c context.Context, as []*api.Arc, aids []int64, bangumiType int) (is, isOsea []*region.ShowItem) {
var (
asLen = len(as)
err error
// bangumi
// sids map[int64]int64
sids map[int32]*seasongrpc.CardInfoProto
)
if asLen == 0 {
is = _emptyShowItems
return
}
if sids, err = s.fromSeasonID(c, aids); err != nil {
log.Error("s.fromSeasonID error(%v)", err)
return
}
is = make([]*region.ShowItem, 0, asLen)
for _, a := range as {
if sid, ok := sids[int32(a.Aid)]; ok && sid.SeasonId != 0 {
i := &region.ShowItem{}
i.FromBangumiArchivePB(a, sid, bangumiType)
if a.AttrVal(archive.AttrBitOverseaLock) == 0 {
isOsea = append(isOsea, i)
}
is = append(is, i)
}
}
return
}
// mergeShow merge show
func (s *Service) mergeShow(hotTmp, newTmp, dynTmp []*region.ShowItem) (rs *region.Show) {
rs = &region.Show{}
if len(hotTmp) >= 4 {
rs.Recommend = hotTmp
} else {
rs.Recommend = _emptyShowItems
}
if len(newTmp) >= 4 {
rs.New = newTmp[:4]
} else {
rs.New = _emptyShowItems
}
if len(dynTmp) > 20 {
rs.Dynamic = dynTmp[:20]
} else if len(dynTmp) > 0 {
rs.Dynamic = dynTmp
} else {
rs.Dynamic = _emptyShowItems
}
return
}
// mergeChildShow merge child show
func (s *Service) mergeChildShow(recTmp, newTmp []*region.ShowItem) (rs *region.Show, new []*region.ShowItem) {
var (
last int
)
rs = &region.Show{}
if len(recTmp) >= 4 {
rs.Recommend = recTmp[:4]
} else if len(newTmp) >= 4 {
var (
max = 4
hotlen = len(recTmp)
)
rs.Recommend = recTmp
if last = max - hotlen; last < len(newTmp) {
rs.Recommend = append(rs.Recommend, newTmp[:last]...)
} else {
rs.Recommend = append(rs.Recommend, newTmp...)
}
} else {
rs.Recommend = _emptyShowItems
}
new = newTmp
if last > 0 {
if len(new) > last {
new = new[last:]
}
}
if len(new) >= 20 {
rs.New = new[:20]
} else if len(new) > 0 {
rs.New = new
} else {
rs.New = _emptyShowItems
}
return
}
// mergeDynamicShow
func (s *Service) mergeDynamicShow(recTmp, dynTmp []*region.ShowItem, ctop, cbottom xtime.Time) (rs *region.Show) {
if ctop == 0 || cbottom == 0 {
rs = &region.Show{}
} else {
rs = &region.Show{
Ctop: ctop,
Cbottom: cbottom,
}
}
if len(recTmp) >= 4 {
rs.Recommend = recTmp[:4]
} else {
rs.Recommend = _emptyShowItems
}
if len(dynTmp) > 0 {
rs.New = dynTmp
} else {
rs.New = _emptyShowItems
}
return
}
// mergeTagShow merge tag show
func (s *Service) mergeTagShow(c context.Context, rid, tid, bangumiType int, isOsea bool, now time.Time) (rs *region.Show) {
const (
strtNum = 1
hotNum = 4
newNum = 20
maxNum = 50
smTagNum = 10
smTagPos = 4
)
rs = &region.Show{}
// hots
key := fmt.Sprintf(_initRegionTagKey, rid, tid)
var (
is []*region.ShowItem
ok = false
)
if bangumiType != 0 {
var aids []int64
if aids, ok = s.tagHotAidsCache[key]; ok {
is = s.fromAidsOsea(c, aids, false, isOsea, bangumiType)
}
} else if bangumiType == 0 || !ok {
is, ok = s.tagHotCache[key]
if isOsea {
is, ok = s.tagHotOseaCache[key]
}
}
if !ok {
arcAids, err := s.tag.Hots(c, rid, tid, strtNum, hotNum, now)
if err != nil {
log.Error("s.tag.Hots(%d, %d) error(%v)", rid, tid, err)
} else if is = s.fromAidsOsea(c, arcAids, true, isOsea, bangumiType); len(is) > 0 {
if len(is) > hotNum {
is = is[:hotNum]
}
}
}
rs.Recommend = is
// news
if bangumiType != 0 {
var aids []int64
if aids, ok = s.tagNewAidsCache[key]; ok {
is = s.fromAidsOsea(c, aids, false, isOsea, bangumiType)
}
} else if bangumiType == 0 || !ok {
is, ok = s.tagNewCache[key]
if isOsea {
is, ok = s.tagNewOseaCache[key]
}
}
if !ok {
as, err := s.tag.NewArcs(c, rid, tid, strtNum, maxNum, now)
if err != nil {
log.Error("s.tag.NewArcs(%d, %d) error(%v)", rid, tid, err)
return
}
is = s.fromAidsOsea(c, as, false, isOsea, bangumiType)
}
var (
hotlen = len(rs.Recommend)
last int
)
if hotlen < hotNum {
if last = hotNum - hotlen; last < len(is) {
rs.Recommend = append(rs.Recommend, is[:last]...)
} else {
rs.Recommend = append(rs.Recommend, is...)
}
}
if last > 0 {
if len(is) > last {
is = is[last:]
}
}
if len(is) >= newNum {
is = is[:newNum]
}
rs.New = is
// similar tags
if st := s.similarTags(c, rid, tid, now); st != nil {
if len(st) > smTagNum {
rs.TopTag = st[:smTagNum]
rs.NewTag = &region.NewTag{
Position: smTagPos,
Tag: st[smTagNum+1:],
}
} else {
rs.TopTag = st
}
}
return
}
// fromAids get Aids. bangumiType 1 seasonid 2 epid
func (s *Service) fromAids(c context.Context, arcAids []int64, isCheck bool, bangumiType int) (data, dataOsea []*region.ShowItem) {
if len(arcAids) == 0 {
return
}
var (
ok bool
aid int64
arc *api.Arc
as map[int64]*api.Arc
err error
// bangumi
sids map[int32]*seasongrpc.CardInfoProto
)
if as, err = s.arc.ArchivesPB(c, arcAids); err != nil {
log.Error("s.arc.ArchivesPB aids(%v) error(%v)", arcAids, err)
return
}
data = make([]*region.ShowItem, 0, len(arcAids))
if bangumiType != 0 {
if sids, err = s.fromSeasonID(c, arcAids); err != nil {
log.Error("s.fromSeasonID error(%v)", err)
return
}
}
for _, aid = range arcAids {
if arc, ok = as[aid]; ok {
if isCheck && !arc.IsNormal() {
continue
}
i := &region.ShowItem{}
if sid, ok := sids[int32(aid)]; ok && bangumiType != 0 && sid.SeasonId != 0 {
i.FromBangumiArchivePB(arc, sid, bangumiType)
} else {
i.FromArchivePB(arc)
}
data = append(data, i)
if arc.AttrVal(archive.AttrBitOverseaLock) == 0 {
dataOsea = append(dataOsea, i)
}
}
}
return
}
// fromSeasonID
func (s *Service) fromSeasonID(c context.Context, arcAids []int64) (seasonID map[int32]*seasongrpc.CardInfoProto, err error) {
if seasonID, err = s.bgm.CardsByAids(c, arcAids); err != nil {
log.Error("s.bmg.CardsByAids error %v", err)
}
return
}
// similarTags similar tags
func (s *Service) similarTags(c context.Context, rid, tid int, now time.Time) (res []*region.SimilarTag) {
key := fmt.Sprintf(_initRegionTagKey, rid, tid)
res, ok := s.similarTagCache[key]
if !ok {
sts, err := s.tag.SimilarTag(c, rid, tid, now)
if err != nil {
log.Error("s.tag.SimilarTag error(%v)", err)
return
}
res = sts
}
return
}
// isOverseas
func (s *Service) fromAidsOsea(ctx context.Context, aids []int64, isCheck, isOsea bool, bangumiType int) (data []*region.ShowItem) {
tmp, tmpOsea := s.fromAids(ctx, aids, isCheck, bangumiType)
if isOsea {
data = tmpOsea
} else {
data = tmp
}
if data == nil {
data = _emptyShowItems
}
return
}
// fromArchivesOsea isOverseas
func (s *Service) fromArchivesPBOsea(as []*api.Arc, isOsea bool) (data []*region.ShowItem) {
tmp, tmpOsea := s.fromArchivesPB(as)
if isOsea {
data = tmpOsea
} else {
data = tmp
}
if data == nil {
data = _emptyShowItems
}
return
}
// fromArchivesOsea isOverseas
func (s *Service) fromArchivesPBBangumiOsea(c context.Context, as []*api.Arc, aids []int64, isOsea bool, bangumiType int) (data []*region.ShowItem) {
tmp, tmpOsea := s.fromArchivesPBBangumi(c, as, aids, bangumiType)
if isOsea {
data = tmpOsea
} else {
data = tmp
}
if data == nil {
data = _emptyShowItems
}
return
}
// fromRankAids
func (s *Service) fromRankAids(ctx context.Context, aids []int64, others, scores map[int64]int64) (sis, sisOsea []*region.ShowItem) {
var (
aid int64
as map[int64]*api.Arc
arc *api.Arc
ok bool
err error
paid int64
)
if as, err = s.arc.ArchivesPB(ctx, aids); err != nil {
log.Error("s.arc.ArchivesPB aids(%v) error(%v)", aids, err)
return
}
if len(as) == 0 {
log.Warn("s.arc.ArchivesPB aids(%v) length is 0", aids)
return
}
child := map[int64][]*region.ShowItem{}
childOsea := map[int64][]*region.ShowItem{}
for _, aid = range aids {
if arc, ok = as[aid]; ok {
if paid, ok = others[arc.Aid]; ok {
i := &region.ShowItem{}
i.FromArchivePBRank(arc, scores)
child[paid] = append(child[paid], i)
if arc.AttrVal(archive.AttrBitOverseaLock) == 0 {
childOsea[paid] = append(childOsea[paid], i)
}
}
}
}
for _, aid = range aids {
if arc, ok = as[aid]; ok {
if _, ok = others[arc.Aid]; !ok {
i := &region.ShowItem{}
i.FromArchivePBRank(arc, scores)
if arc.AttrVal(archive.AttrBitOverseaLock) == 0 {
if tmpchild, ok := childOsea[arc.Aid]; ok {
i.Children = tmpchild
}
sisOsea = append(sisOsea, i)
}
if tmpchild, ok := child[arc.Aid]; ok {
i.Children = tmpchild
}
sis = append(sis, i)
}
}
}
return
}
// fromCardAids get Aids.
func (s *Service) fromCardAids(ctx context.Context, aids []int64) (data map[int64]*region.ShowItem) {
var (
arc *api.Arc
ok bool
)
as, err := s.arc.ArchivesPB(ctx, aids)
if err != nil {
log.Error("s.arc.ArchivesPB error(%v)", err)
return
}
if len(as) == 0 {
log.Warn("s.arc.ArchivesPB(%v) length is 0", aids)
return
}
data = map[int64]*region.ShowItem{}
for _, aid := range aids {
if arc, ok = as[aid]; ok {
if !arc.IsNormal() {
continue
}
i := &region.ShowItem{}
i.FromArchivePB(arc)
if region, ok := s.reRegionCache[int(arc.TypeID)]; ok {
i.Reid = region.Rid
}
i.Desc = i.Rname
data[aid] = i
}
}
return
}

View File

@@ -0,0 +1,108 @@
package region
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-show/conf"
"go-common/app/interface/main/app-show/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-show-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestChildShow(t *testing.T) {
Convey("get ChildShow data", t, WithService(func(s *Service) {
res := s.ChildShow(context.TODO(), model.PlatIPhone, 0, 1, 0, 111, "", "iphone", time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestShow(t *testing.T) {
Convey("get Show data", t, WithService(func(s *Service) {
res := s.Show(context.TODO(), model.PlatIPhone, 1, 0, 0, "channel", "", "", "iphone", "phone", "")
So(res, ShouldNotBeEmpty)
}))
}
func TestShowDynamic(t *testing.T) {
Convey("get ShowDynamic data", t, WithService(func(s *Service) {
res := s.ShowDynamic(context.TODO(), model.PlatIPhone, 0, 1, 1, 20)
So(res, ShouldNotBeEmpty)
}))
}
func TestChildListShow(t *testing.T) {
Convey("get ChildListShow data", t, WithService(func(s *Service) {
res := s.ChildListShow(context.TODO(), model.PlatIPhone, 1, 0, 1, 20, 0, 0, "new", "ios", "iphone", "phone")
So(res, ShouldNotBeEmpty)
}))
}
func TestDynamic(t *testing.T) {
Convey("get Dynamic data", t, WithService(func(s *Service) {
res := s.Dynamic(context.TODO(), model.PlatIPhone, 1, 0, 0, "channel", "", "", "iphone", "phone", "", time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestDynamicList(t *testing.T) {
Convey("get DynamicList data", t, WithService(func(s *Service) {
res := s.DynamicList(context.TODO(), model.PlatIPhone, 1, true, 0, 0, time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestDynamicChild(t *testing.T) {
Convey("get DynamicChild data", t, WithService(func(s *Service) {
res := s.DynamicChild(context.TODO(), model.PlatIPhone, 1, 0, 0, 0, "iphone", time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestDynamicListChild(t *testing.T) {
Convey("get DynamicListChild data", t, WithService(func(s *Service) {
res := s.DynamicListChild(context.TODO(), model.PlatIPhone, 1, 0, 0, true, 0, 0, time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestAudit(t *testing.T) {
Convey("get Audit data", t, WithService(func(s *Service) {
res, _ := s.Audit(context.TODO(), "iphone", model.PlatIPhone, 1, 1, false)
So(res, ShouldNotBeEmpty)
}))
}
func TestAuditChild(t *testing.T) {
Convey("get AuditChild data", t, WithService(func(s *Service) {
res, _ := s.AuditChild(context.TODO(), "iphone", "", model.PlatIPhone, 1, 1, 0)
So(res, ShouldNotBeEmpty)
}))
}
func TestAuditChildList(t *testing.T) {
Convey("get AuditChildList data", t, WithService(func(s *Service) {
res, _ := s.AuditChildList(context.TODO(), "iphone", "", model.PlatIPhone, 1, 1, 0, 1, 1)
So(res, ShouldNotBeEmpty)
}))
}

View File

@@ -0,0 +1,100 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["show_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-show/conf:go_default_library",
"//app/interface/main/app-show/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"ad.go",
"audit.go",
"banner.go",
"cache.go",
"feed.go",
"feed2.go",
"infoc.go",
"manager.go",
"service.go",
"show.go",
],
importpath = "go-common/app/interface/main/app-show/service/show",
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/live: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-show/conf:go_default_library",
"//app/interface/main/app-show/dao/account:go_default_library",
"//app/interface/main/app-show/dao/activity:go_default_library",
"//app/interface/main/app-show/dao/ad:go_default_library",
"//app/interface/main/app-show/dao/archive:go_default_library",
"//app/interface/main/app-show/dao/audit:go_default_library",
"//app/interface/main/app-show/dao/bangumi:go_default_library",
"//app/interface/main/app-show/dao/card:go_default_library",
"//app/interface/main/app-show/dao/databus:go_default_library",
"//app/interface/main/app-show/dao/dynamic:go_default_library",
"//app/interface/main/app-show/dao/live:go_default_library",
"//app/interface/main/app-show/dao/location:go_default_library",
"//app/interface/main/app-show/dao/recommend:go_default_library",
"//app/interface/main/app-show/dao/region:go_default_library",
"//app/interface/main/app-show/dao/relation:go_default_library",
"//app/interface/main/app-show/dao/resource:go_default_library",
"//app/interface/main/app-show/dao/show:go_default_library",
"//app/interface/main/app-show/dao/tag:go_default_library",
"//app/interface/main/app-show/model:go_default_library",
"//app/interface/main/app-show/model/banner:go_default_library",
"//app/interface/main/app-show/model/card:go_default_library",
"//app/interface/main/app-show/model/feed:go_default_library",
"//app/interface/main/app-show/model/recommend:go_default_library",
"//app/interface/main/app-show/model/region:go_default_library",
"//app/interface/main/app-show/model/show:go_default_library",
"//app/interface/main/creative/api: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/relation/model:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//app/service/openplatform/pgc-season/api/grpc/season/v1:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/stat/prom: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,95 @@
package show
import (
"context"
"strconv"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/show"
locmdl "go-common/app/service/main/location/model"
"go-common/library/log"
)
// cpmRecommend
func (s *Service) cpmRecommend(c context.Context, mid int64, build int, buvid, resource, network, mobiApp, device, ipaddr string) (sis map[int]*show.Item) {
if _, ok := s.cpmRcmmndMid[mid]; !ok && (mid == 0 || int(mid)%100 >= s.cpmRcmmndNum) && !s.cpmRcmmndAll {
return
}
var (
info *locmdl.Info
country, province, city string
err error
)
if info, err = s.loc.Info(c, ipaddr); err != nil {
log.Warn("s.loc.Info(%v) error(%v)", ipaddr, err)
err = nil
}
if info != nil {
country = info.Country
province = info.Province
city = info.Province
}
adr, err := s.ad.ADRequest(c, mid, build, buvid, resource, ipaddr, country, province, city, network, mobiApp, device, s.adIsPost)
if err != nil {
log.Error("s.ad.ADRequest error(%v)", err)
return
}
sis = map[int]*show.Item{}
sAdis := adr.ADIndexs[resource]
if len(sAdis) == 0 {
log.Info("mobi_app:%v-build:%v-resource:%v-is_ad_loc:%v", mobiApp, build, resource, false)
return
}
var aids []int64
for sidStr, adi := range sAdis {
sid, _ := strconv.Atoi(sidStr)
var si = &show.Item{
IsAdLoc: true,
IsAd: adi.IsAd,
IsAdReplace: false,
CmMark: adi.CmMark,
Rank: adi.Index,
SrcId: sid,
RequestId: adr.RequestID,
ClientIp: ipaddr,
}
if adInfo := adi.Info; adInfo != nil {
aids = append(aids, adInfo.CreativeContent.VideoID)
// si
si.Goto = model.GotoAv
si.Param = strconv.FormatInt(adInfo.CreativeContent.VideoID, 10)
si.URI = model.FillURI(model.GotoAv, si.Param, nil)
si.Title = adInfo.CreativeContent.Title
si.Cover = model.CoverURL(adInfo.CreativeContent.ImageURL)
si.IsAdReplace = true
si.AdCb = adInfo.AdCb
si.CreativeId = adInfo.CreativeID
si.ShowUrl = adInfo.CreativeContent.ShowURL
si.ClickUrl = adInfo.CreativeContent.ClickURL
}
sis[si.Rank] = si
log.Info("mobi_app:%v-build:%v-resource:%v-is_ad_loc:%v", mobiApp, build, resource, true)
}
if len(aids) == 0 {
return
}
as, err := s.arc.ArchivesPB(c, aids)
if err != nil {
log.Error("s.arc.ArchivesPB(%v) error(%v)", aids, err)
return
}
for _, si := range sis {
aid, _ := strconv.ParseInt(si.Param, 10, 64)
if a, ok := as[aid]; ok && a != nil {
si.Play = int(a.Stat.View)
si.Danmaku = int(a.Stat.Danmaku)
if si.Title == "" {
si.Title = a.Title
}
if si.Cover == "" {
si.Cover = model.CoverURL(a.Pic)
}
}
}
return
}

View File

@@ -0,0 +1,299 @@
package show
import (
"context"
"strconv"
cdm "go-common/app/interface/main/app-card/model"
cardm "go-common/app/interface/main/app-card/model/card"
"go-common/app/interface/main/app-card/model/card/ai"
operate "go-common/app/interface/main/app-card/model/card/operate"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/banner"
"go-common/app/interface/main/app-show/model/feed"
"go-common/app/interface/main/app-show/model/show"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/log"
)
var (
_auditBanner = &banner.Banner{
Title: "充电",
Image: "http://i0.hdslb.com/bfs/archive/9ce8f6cdf76e6cbd50ce7db76262d5a35e594c79.png",
Hash: "3c4990d06c46de0080e3821fca6bedca",
URI: "bilibili://video/813060",
}
_auditRids = map[int8]map[string]struct{}{
model.PlatIPhone: map[string]struct{}{
"13": struct{}{},
"167": struct{}{},
"177": struct{}{},
"23": struct{}{},
"11": struct{}{},
},
}
)
// GetAudit check audit plat and ip, then return audit data.
func (s *Service) Audit(c context.Context, mobiApp string, plat int8, build int) (ss []*show.Show, ok bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
return s.auditData(c, plat), true
}
}
return nil, false
}
func (s *Service) AuditChild(c context.Context, mobiApp string, plat int8, build int) (res []*show.Item, ok bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
res = s.auditList(c)
return res, true
}
}
return nil, false
}
// AuditFeed check audit plat and ip, then return audit data.
func (s *Service) AuditFeed(c context.Context, mobiApp string, plat int8, build int) (res []*feed.Item, ok bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
return s.auditFeed(c), true
}
}
return nil, false
}
// AuditFeed check audit plat and ip, then return audit data.
func (s *Service) AuditFeed2(c context.Context, mobiApp string, plat int8, build int) (res []cardm.Handler, ok bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
return s.auditFeed2(c, plat), true
}
}
return nil, false
}
// Audit region data list.
func (s *Service) auditRegion(mobiApp string, plat int8, build int, rid string) (isAudit bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
if params, ok := _auditRids[plat]; ok {
if _, ok = params[rid]; ok {
return true
}
}
}
}
return false
}
func (s *Service) loadAuditCache() {
as, err := s.adt.Audits(context.TODO())
if err != nil {
log.Error("s.adt.Audits error(%v)", err)
return
}
s.auditCache = as
}
// auditData some data for audit.
func (s *Service) auditData(c context.Context, p int8) (ss []*show.Show) {
ss = []*show.Show{
&show.Show{
Head: &show.Head{
Param: "",
Type: "recommend",
Style: "medium",
Title: "热门推荐",
},
},
&show.Show{
Head: &show.Head{
Param: "3",
Type: "region",
Style: "medium",
Title: "音乐区",
},
},
&show.Show{
Head: &show.Head{
Param: "129",
Type: "region",
Style: "medium",
Title: "舞蹈区",
},
},
&show.Show{
Head: &show.Head{
Param: "4",
Type: "region",
Style: "medium",
Title: "游戏区",
},
},
&show.Show{
Head: &show.Head{
Param: "36",
Type: "region",
Style: "medium",
Title: "游戏区",
},
},
}
aids := []int64{308040, 2431658, 2432648, 2427553, 539600, 1968681, 850424, 887861, 1960912, 1935680, 1406019, 1985297, 1977493, 2312184, 2316891, 864845, 1986932, 2314237, 880857, 875624}
n := 4
if p == model.PlatIPad {
aids = []int64{2455179, 2473608, 1711253, 2476389, 0, 0, 0, 0, 308040, 360940, 482844, 221107, 539600, 1968681, 850424, 887861, 936016, 1773160, 886841, 1958897, 1960912, 1935680,
1406019, 1985297, 1635344, 572952, 2316655, 2317928, 1977493, 2312184, 2316891, 864845, 2313588, 875076, 2312249, 842756, 1986932, 2314237, 880857, 875624}
n = 8
// ss[0].Head.Type = ""
// banner
ss[0].Banner = map[string][]*banner.Banner{
"top": []*banner.Banner{_auditBanner, _auditBanner},
}
} else if p == model.PlatIPhone {
aids = []int64{308040, 2431658, 2432648, 2427553, 2455179, 2473608, 539600, 1968681, 850424, 887861, 0, 0, 1960912, 1935680, 1406019, 1985297, 0, 0, 1977493, 2312184, 2316891, 864845, 0, 0,
1986932, 2314237, 880857, 875624, 0, 0}
n = 6
// banner
ss[0].Banner = map[string][]*banner.Banner{
"top": []*banner.Banner{_auditBanner},
}
}
as, err := s.arc.ArchivesPB(c, aids)
if err != nil {
log.Error("s.arc.ArchivesPB error(%v)", err)
as = map[int64]*api.Arc{}
}
for i, aid := range aids {
if aid == 0 {
continue
}
item := &show.Item{}
item.Goto = model.GotoAv
item.Param = strconv.FormatInt(aid, 10)
item.URI = model.FillURI(item.Goto, item.Param, nil)
if a, ok := as[aid]; ok {
item.Title = a.Title
item.Cover = a.Pic
item.Play = int(a.Stat.View)
item.Danmaku = int(a.Stat.Danmaku)
}
ss[i/n].Body = append(ss[i/n].Body, item)
}
return
}
func (s *Service) auditList(c context.Context) (ss []*show.Item) {
aids := []int64{308040, 2431658, 2432648, 2427553, 2455179, 2473608, 539600, 1968681, 850424, 887861, 1960912, 1935680, 1406019, 1985297, 1977493, 2312184, 2316891, 864845,
1986932, 2314237, 880857, 875624}
as, err := s.arc.ArchivesPB(c, aids)
if err != nil {
log.Error("s.arc.ArchivesPB error(%v)", err)
as = map[int64]*api.Arc{}
}
for _, aid := range aids {
if aid == 0 {
continue
}
item := &show.Item{}
item.Goto = model.GotoAv
item.Param = strconv.FormatInt(aid, 10)
item.URI = model.FillURI(item.Goto, item.Param, nil)
if a, ok := as[aid]; ok {
item.Title = a.Title
item.Cover = a.Pic
item.Play = int(a.Stat.View)
item.Danmaku = int(a.Stat.Danmaku)
}
ss = append(ss, item)
}
return
}
func (s *Service) auditFeed(c context.Context) (res []*feed.Item) {
var (
aids = []int64{2455179, 2473608, 1711253, 2476389, 0, 0, 0, 0, 308040, 360940, 482844, 221107, 539600, 1968681, 850424, 887861, 936016, 1773160, 886841, 1958897, 1960912, 1935680,
1406019, 1985297, 1635344, 572952, 2316655, 2317928, 1977493, 2312184, 2316891, 864845, 2313588, 875076, 2312249, 842756, 1986932, 2314237, 880857, 875624}
as map[int64]*api.Arc
err error
)
if as, err = s.arc.ArchivesPB(c, aids); err != nil {
log.Error("hottab s.arc.ArchivesPB aids(%v) error(%v)", aids, err)
return
}
if len(as) == 0 {
log.Warn("hottab s.arc.ArchivesPB(%v) length is 0", aids)
return
}
for i, aid := range aids {
item := &feed.Item{}
item.Idx = int64(i + 1)
item.Pos = i + 1
if aid == 0 {
continue
}
if a, ok := as[aid]; ok {
item.FromPlayerAv(a, "")
// if tag, ok := s.hotArcTag[a.Aid]; ok {
// item.Tag = &feed.Tag{TagID: tag.ID, TagName: tag.Name}
// }
item.Goto = model.GotoAv
res = append(res, item)
}
}
if len(res) == 0 {
res = _emptyList
return
}
return
}
func (s *Service) auditFeed2(c context.Context, plat int8) (res []cardm.Handler) {
var (
aids = []int64{2455179, 2473608, 1711253, 2476389, 0, 0, 0, 0, 308040, 360940, 482844, 221107, 539600, 1968681, 850424, 887861, 936016, 1773160, 886841, 1958897, 1960912, 1935680,
1406019, 1985297, 1635344, 572952, 2316655, 2317928, 1977493, 2312184, 2316891, 864845, 2313588, 875076, 2312249, 842756, 1986932, 2314237, 880857, 875624}
as map[int64]*api.Arc
err error
)
if as, err = s.arc.ArchivesPB(c, aids); err != nil {
log.Error("hottab s.arc.ArchivesPB aids(%v) error(%v)", aids, err)
return
}
if len(as) == 0 {
log.Warn("hottab s.arc.ArchivesPB(%v) length is 0", aids)
return
}
for i, aid := range aids {
if aid == 0 {
continue
}
var (
r = &ai.Item{Goto: model.GotoAv, ID: aid}
h = cardm.Handle(plat, cdm.CardGt(r.Goto), "", 1, r, nil, nil, nil, nil)
main interface{}
)
if h == nil {
continue
}
op := &operate.Card{}
op.From(cdm.CardGt(r.Goto), r.ID, 0, model.PlatIPhone, 0)
if a, ok := as[aid]; ok && (a.AttrVal(archive.AttrBitOverseaLock) == 0) {
main = map[int64]*archive.ArchiveWithPlayer{a.Aid: &archive.ArchiveWithPlayer{Archive3: archive.BuildArchive3(a)}}
}
if main != nil {
h.From(main, op)
}
h.Get().Idx = int64(i + 1)
if h.Get().Right {
res = append(res, h)
}
}
if len(res) == 0 {
res = _emptyList2
return
}
return
}

View File

@@ -0,0 +1,891 @@
package show
import (
"context"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/banner"
resource "go-common/app/service/main/resource/model"
"go-common/library/log"
)
var (
_banners = map[string]map[int8]map[string]int{
"-1": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 467,
},
model.PlatAndroid: map[string]int{
"bottom": 631,
},
model.PlatIPad: map[string]int{
"bottom": 771,
},
model.PlatIPhoneI: map[string]int{
"bottom": 947,
},
model.PlatAndroidG: map[string]int{
"bottom": 1285,
},
model.PlatAndroidI: map[string]int{
"bottom": 1707,
},
model.PlatIPadI: map[string]int{
"bottom": 1117,
},
},
"0": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 467,
"center": 468,
"bottom": 469,
},
model.PlatAndroid: map[string]int{
"top": 631,
"center": 632,
"bottom": 633,
},
model.PlatIPad: map[string]int{
"top": 771,
"center": 772,
"bottom": 773,
},
model.PlatIPhoneI: map[string]int{
"top": 947,
"center": 952,
"bottom": 957,
},
model.PlatAndroidG: map[string]int{
"top": 1285,
"center": 1290,
"bottom": 1295,
},
model.PlatAndroidI: map[string]int{
"top": 1707,
"center": 1712,
"bottom": 1717,
},
model.PlatIPadI: map[string]int{
"top": 1117,
"center": 1122,
"bottom": 1127,
},
},
"65537": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 482,
},
model.PlatAndroid: map[string]int{
"bottom": 646,
},
model.PlatIPad: map[string]int{
"bottom": 786,
},
model.PlatIPhoneI: map[string]int{
"bottom": 1013,
},
model.PlatAndroidG: map[string]int{
"bottom": 1351,
},
model.PlatAndroidI: map[string]int{
"bottom": 1773,
},
model.PlatIPadI: map[string]int{
"bottom": 1183,
},
},
"13": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 471,
},
model.PlatAndroid: map[string]int{
"bottom": 635,
},
model.PlatIPad: map[string]int{
"bottom": 775,
},
model.PlatIPhoneI: map[string]int{
"bottom": 967,
},
model.PlatAndroidG: map[string]int{
"bottom": 1305,
},
model.PlatAndroidI: map[string]int{
"bottom": 1727,
},
model.PlatIPadI: map[string]int{
"bottom": 1137,
},
},
"1": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 470,
},
model.PlatAndroid: map[string]int{
"bottom": 634,
},
model.PlatIPad: map[string]int{
"bottom": 774,
},
model.PlatIPhoneI: map[string]int{
"bottom": 962,
},
model.PlatAndroidG: map[string]int{
"bottom": 1300,
},
model.PlatAndroidI: map[string]int{
"bottom": 1722,
},
model.PlatIPadI: map[string]int{
"bottom": 1132,
},
},
"3": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 472,
},
model.PlatAndroid: map[string]int{
"bottom": 636,
},
model.PlatIPad: map[string]int{
"bottom": 776,
},
model.PlatIPhoneI: map[string]int{
"bottom": 971,
},
model.PlatAndroidG: map[string]int{
"bottom": 1309,
},
model.PlatAndroidI: map[string]int{
"bottom": 1731,
},
model.PlatIPadI: map[string]int{
"bottom": 1141,
},
},
"129": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 473,
},
model.PlatAndroid: map[string]int{
"bottom": 637,
},
model.PlatIPad: map[string]int{
"bottom": 777,
},
model.PlatIPhoneI: map[string]int{
"bottom": 975,
},
model.PlatAndroidG: map[string]int{
"bottom": 1313,
},
model.PlatAndroidI: map[string]int{
"bottom": 1735,
},
model.PlatIPadI: map[string]int{
"bottom": 1145,
},
},
"4": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 474,
},
model.PlatAndroid: map[string]int{
"bottom": 638,
},
model.PlatIPad: map[string]int{
"bottom": 778,
},
model.PlatIPhoneI: map[string]int{
"bottom": 979,
},
model.PlatAndroidG: map[string]int{
"bottom": 1317,
},
model.PlatAndroidI: map[string]int{
"bottom": 1739,
},
model.PlatIPadI: map[string]int{
"bottom": 1149,
},
},
"36": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 475,
},
model.PlatAndroid: map[string]int{
"bottom": 639,
},
model.PlatIPad: map[string]int{
"bottom": 779,
},
model.PlatIPhoneI: map[string]int{
"bottom": 983,
},
model.PlatAndroidG: map[string]int{
"bottom": 1321,
},
model.PlatAndroidI: map[string]int{
"bottom": 1706,
},
model.PlatIPadI: map[string]int{
"bottom": 1153,
},
},
"160": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 476,
},
model.PlatAndroid: map[string]int{
"bottom": 640,
},
model.PlatIPad: map[string]int{
"bottom": 780,
},
model.PlatIPhoneI: map[string]int{
"bottom": 987,
},
model.PlatAndroidG: map[string]int{
"bottom": 1325,
},
model.PlatAndroidI: map[string]int{
"bottom": 1747,
},
model.PlatIPadI: map[string]int{
"bottom": 1157,
},
},
"119": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 477,
},
model.PlatAndroid: map[string]int{
"bottom": 641,
},
model.PlatIPad: map[string]int{
"bottom": 781,
},
model.PlatIPhoneI: map[string]int{
"bottom": 992,
},
model.PlatAndroidG: map[string]int{
"bottom": 1330,
},
model.PlatAndroidI: map[string]int{
"bottom": 1752,
},
model.PlatIPadI: map[string]int{
"bottom": 1162,
},
},
"155": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 478,
},
model.PlatAndroid: map[string]int{
"bottom": 642,
},
model.PlatIPad: map[string]int{
"bottom": 782,
},
model.PlatIPhoneI: map[string]int{
"bottom": 997,
},
model.PlatAndroidG: map[string]int{
"bottom": 1335,
},
model.PlatAndroidI: map[string]int{
"bottom": 1757,
},
model.PlatIPadI: map[string]int{
"bottom": 1167,
},
},
"5": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 479,
},
model.PlatAndroid: map[string]int{
"bottom": 643,
},
model.PlatIPad: map[string]int{
"bottom": 783,
},
model.PlatIPhoneI: map[string]int{
"bottom": 1001,
},
model.PlatAndroidG: map[string]int{
"bottom": 1339,
},
model.PlatAndroidI: map[string]int{
"bottom": 1761,
},
model.PlatIPadI: map[string]int{
"bottom": 1171,
},
},
"23": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 480,
},
model.PlatAndroid: map[string]int{
"bottom": 644,
},
model.PlatIPad: map[string]int{
"bottom": 784,
},
model.PlatIPhoneI: map[string]int{
"bottom": 1005,
},
model.PlatAndroidG: map[string]int{
"bottom": 1343,
},
model.PlatAndroidI: map[string]int{
"bottom": 1765,
},
model.PlatIPadI: map[string]int{
"bottom": 1175,
},
},
"11": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 481,
},
model.PlatAndroid: map[string]int{
"bottom": 645,
},
model.PlatIPad: map[string]int{
"bottom": 785,
},
model.PlatIPhoneI: map[string]int{
"bottom": 1009,
},
model.PlatAndroidG: map[string]int{
"bottom": 1347,
},
model.PlatAndroidI: map[string]int{
"bottom": 1769,
},
model.PlatIPadI: map[string]int{
"bottom": 1179,
},
},
"165": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 1643,
},
model.PlatAndroid: map[string]int{
"bottom": 1639,
},
model.PlatIPad: map[string]int{
"bottom": 1647,
},
model.PlatIPhoneI: map[string]int{
"bottom": 1643,
},
model.PlatAndroidG: map[string]int{
"bottom": 1639,
},
model.PlatIPadI: map[string]int{
"bottom": 1647,
},
},
"167": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 1950,
},
model.PlatAndroid: map[string]int{
"bottom": 1952,
},
model.PlatIPad: map[string]int{
"bottom": 1951,
},
},
"181": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 2245,
},
model.PlatAndroid: map[string]int{
"bottom": 2249,
},
model.PlatIPad: map[string]int{
"bottom": 2253,
},
},
"177": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"bottom": 2295,
},
model.PlatAndroid: map[string]int{
"bottom": 2299,
},
model.PlatIPad: map[string]int{
"bottom": 2303,
},
},
}
_bannersIndex = map[string]map[int8]map[string]int{
"-1": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 467,
},
model.PlatAndroid: map[string]int{
"top": 631,
},
model.PlatIPad: map[string]int{
"top": 771,
},
model.PlatIPhoneI: map[string]int{
"top": 947,
},
model.PlatAndroidG: map[string]int{
"top": 1285,
},
model.PlatAndroidI: map[string]int{
"top": 1707,
},
model.PlatIPadI: map[string]int{
"top": 1117,
},
},
"0": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 467,
"center": 468,
"bottom": 469,
},
model.PlatAndroid: map[string]int{
"top": 631,
"center": 632,
"bottom": 633,
},
model.PlatIPad: map[string]int{
"top": 771,
"center": 772,
"bottom": 773,
},
model.PlatIPhoneI: map[string]int{
"top": 947,
"center": 952,
"bottom": 957,
},
model.PlatAndroidG: map[string]int{
"top": 1285,
"center": 1290,
"bottom": 1295,
},
model.PlatAndroidI: map[string]int{
"top": 1707,
"center": 1712,
"bottom": 1717,
},
model.PlatIPadI: map[string]int{
"top": 1117,
"center": 1122,
"bottom": 1127,
},
},
"65537": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 482,
},
model.PlatAndroid: map[string]int{
"top": 646,
},
model.PlatIPad: map[string]int{
"top": 786,
},
model.PlatIPhoneI: map[string]int{
"top": 1013,
},
model.PlatAndroidG: map[string]int{
"top": 1351,
},
model.PlatAndroidI: map[string]int{
"top": 1773,
},
model.PlatIPadI: map[string]int{
"top": 1183,
},
},
"13": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 471,
},
model.PlatAndroid: map[string]int{
"top": 635,
},
model.PlatIPad: map[string]int{
"top": 775,
},
model.PlatIPhoneI: map[string]int{
"top": 967,
},
model.PlatAndroidG: map[string]int{
"top": 1305,
},
model.PlatAndroidI: map[string]int{
"top": 1727,
},
model.PlatIPadI: map[string]int{
"top": 1137,
},
},
"1": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 470,
},
model.PlatAndroid: map[string]int{
"top": 634,
},
model.PlatIPad: map[string]int{
"top": 774,
},
model.PlatIPhoneI: map[string]int{
"top": 962,
},
model.PlatAndroidG: map[string]int{
"top": 1300,
},
model.PlatAndroidI: map[string]int{
"top": 1722,
},
model.PlatIPadI: map[string]int{
"top": 1132,
},
},
"3": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 472,
},
model.PlatAndroid: map[string]int{
"top": 636,
},
model.PlatIPad: map[string]int{
"top": 776,
},
model.PlatIPhoneI: map[string]int{
"top": 971,
},
model.PlatAndroidG: map[string]int{
"top": 1309,
},
model.PlatAndroidI: map[string]int{
"top": 1731,
},
model.PlatIPadI: map[string]int{
"top": 1141,
},
},
"129": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 473,
},
model.PlatAndroid: map[string]int{
"top": 637,
},
model.PlatIPad: map[string]int{
"top": 777,
},
model.PlatIPhoneI: map[string]int{
"top": 975,
},
model.PlatAndroidG: map[string]int{
"top": 1313,
},
model.PlatAndroidI: map[string]int{
"top": 1735,
},
model.PlatIPadI: map[string]int{
"top": 1145,
},
},
"4": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 474,
},
model.PlatAndroid: map[string]int{
"top": 638,
},
model.PlatIPad: map[string]int{
"top": 778,
},
model.PlatIPhoneI: map[string]int{
"top": 979,
},
model.PlatAndroidG: map[string]int{
"top": 1317,
},
model.PlatAndroidI: map[string]int{
"top": 1739,
},
model.PlatIPadI: map[string]int{
"top": 1149,
},
},
"36": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 475,
},
model.PlatAndroid: map[string]int{
"top": 639,
},
model.PlatIPad: map[string]int{
"top": 779,
},
model.PlatIPhoneI: map[string]int{
"top": 983,
},
model.PlatAndroidG: map[string]int{
"top": 1321,
},
model.PlatAndroidI: map[string]int{
"top": 1706,
},
model.PlatIPadI: map[string]int{
"top": 1153,
},
},
"160": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 476,
},
model.PlatAndroid: map[string]int{
"top": 640,
},
model.PlatIPad: map[string]int{
"top": 780,
},
model.PlatIPhoneI: map[string]int{
"top": 987,
},
model.PlatAndroidG: map[string]int{
"top": 1325,
},
model.PlatAndroidI: map[string]int{
"top": 1747,
},
model.PlatIPadI: map[string]int{
"top": 1157,
},
},
"119": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 477,
},
model.PlatAndroid: map[string]int{
"top": 641,
},
model.PlatIPad: map[string]int{
"top": 781,
},
model.PlatIPhoneI: map[string]int{
"top": 992,
},
model.PlatAndroidG: map[string]int{
"top": 1330,
},
model.PlatAndroidI: map[string]int{
"top": 1752,
},
model.PlatIPadI: map[string]int{
"top": 1162,
},
},
"155": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 478,
},
model.PlatAndroid: map[string]int{
"top": 642,
},
model.PlatIPad: map[string]int{
"top": 782,
},
model.PlatIPhoneI: map[string]int{
"top": 997,
},
model.PlatAndroidG: map[string]int{
"top": 1335,
},
model.PlatAndroidI: map[string]int{
"top": 1757,
},
model.PlatIPadI: map[string]int{
"top": 1167,
},
},
"5": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 479,
},
model.PlatAndroid: map[string]int{
"top": 643,
},
model.PlatIPad: map[string]int{
"top": 783,
},
model.PlatIPhoneI: map[string]int{
"top": 1001,
},
model.PlatAndroidG: map[string]int{
"top": 1339,
},
model.PlatAndroidI: map[string]int{
"top": 1761,
},
model.PlatIPadI: map[string]int{
"top": 1171,
},
},
"23": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 480,
},
model.PlatAndroid: map[string]int{
"top": 644,
},
model.PlatIPad: map[string]int{
"top": 784,
},
model.PlatIPhoneI: map[string]int{
"top": 1005,
},
model.PlatAndroidG: map[string]int{
"top": 1343,
},
model.PlatAndroidI: map[string]int{
"top": 1765,
},
model.PlatIPadI: map[string]int{
"top": 1175,
},
},
"11": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 481,
},
model.PlatAndroid: map[string]int{
"top": 645,
},
model.PlatIPad: map[string]int{
"top": 785,
},
model.PlatIPhoneI: map[string]int{
"top": 1009,
},
model.PlatAndroidG: map[string]int{
"top": 1347,
},
model.PlatAndroidI: map[string]int{
"top": 1769,
},
model.PlatIPadI: map[string]int{
"top": 1179,
},
},
"165": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 1643,
},
model.PlatAndroid: map[string]int{
"top": 1639,
},
model.PlatIPad: map[string]int{
"top": 1647,
},
model.PlatIPhoneI: map[string]int{
"top": 1643,
},
model.PlatAndroidG: map[string]int{
"top": 1639,
},
model.PlatIPadI: map[string]int{
"top": 1647,
},
},
"167": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 1950,
},
model.PlatAndroid: map[string]int{
"top": 1952,
},
model.PlatIPad: map[string]int{
"top": 1951,
},
},
"181": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 2245,
},
model.PlatAndroid: map[string]int{
"top": 2249,
},
model.PlatIPad: map[string]int{
"top": 2253,
},
},
"177": map[int8]map[string]int{
model.PlatIPhone: map[string]int{
"top": 2295,
},
model.PlatAndroid: map[string]int{
"top": 2299,
},
model.PlatIPad: map[string]int{
"top": 2303,
},
},
}
_bannersPlat = map[int8]string{
model.PlatIPhone: "467,482,471,470,472,473,474,475,476,477,478,479,480,481,1643,1950,2245,2295",
model.PlatAndroid: "631,646,635,634,636,637,638,639,640,641,642,643,644,645,1639,1952,2249,2299",
model.PlatIPad: "771,786,775,774,776,777,778,779,780,781,782,783,784,785,1647,1951,2253,2303",
model.PlatIPhoneI: "947,1013,967,962,971,975,979,983,987,992,997,1001,1005,1009,1643",
model.PlatAndroidG: "1285,1351,1305,1300,1309,1313,1317,1321,1325,1330,1335,1339,1343,1347,1639",
model.PlatAndroidI: "1707,1773,1727,1722,1731,1735,1739,1706,1747,1752,1757,1761,1765,1769,1639",
model.PlatIPadI: "1117,1183,1137,1132,1141,1145,1149,1153,1157,1162,1167,1171,1175,1179,1647",
}
)
// getBanners get banners by plat, build channel, ip.
func (s *Service) getBanners(c context.Context, plat int8, build int, module, channel, ip string, resbs map[int][]*resource.Banner, isIndex bool) (res map[string][]*banner.Banner) {
var (
bannerIds = _banners
)
if isIndex {
bannerIds = _bannersIndex
}
res = map[string][]*banner.Banner{}
for pos, bID := range bannerIds[module][plat] {
if rbs, ok := resbs[bID]; ok {
var bs []*banner.Banner
for _, rb := range rbs {
b := &banner.Banner{}
b.ResChangeBanner(rb)
bs = append(bs, b)
}
res[pos] = bs
}
}
return
}
// resBannersplat
func (s *Service) resBanners(c context.Context, plat int8, build int, mid int64, resIDStr, channel, ip, buvid, network, mobiApp, device, adExtra string) (res map[int][]*resource.Banner) {
var (
plm = s.bannerCache[plat] // operater banner
err error
isAd = true
)
if plat == model.PlatAndroid && build <= 430000 {
isAd = false
}
if res, err = s.res.ResBanner(c, plat, build, mid, resIDStr, channel, ip, buvid, network, mobiApp, device, adExtra, isAd); err != nil || len(res) == 0 {
log.Error("s.res.ResBanner is null or err(%v)", err)
res = plm
return
}
return
}

View File

@@ -0,0 +1,920 @@
package show
import (
"context"
"fmt"
"math/rand"
"runtime"
"strconv"
"strings"
"time"
clive "go-common/app/interface/main/app-card/model/card/live"
"go-common/app/interface/main/app-card/model/card/operate"
"go-common/app/interface/main/app-card/model/card/rank"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/card"
recmod "go-common/app/interface/main/app-show/model/recommend"
"go-common/app/interface/main/app-show/model/region"
"go-common/app/interface/main/app-show/model/show"
creativeAPI "go-common/app/interface/main/creative/api"
"go-common/app/service/main/archive/api"
resource "go-common/app/service/main/resource/model"
seasongrpc "go-common/app/service/openplatform/pgc-season/api/grpc/season/v1"
"go-common/library/log"
)
const (
_blackUrl = "http://172.18.7.208/privatedata/reco-deny-arcs.json"
)
var (
// 动画,音乐,舞蹈,游戏,科技,娱乐,鬼畜,电影,时尚, 生活,广告,国漫,影视,纪录片
_tids = []string{"1", "3", "129", "4", "36", "5", "119", "23", "155", "160", "11", "165", "167", "181", "177"}
_emptyItems = []*show.Item{&show.Item{}, &show.Item{}, &show.Item{}, &show.Item{}}
)
// loadRcmmndCache load recommend cahce.
func (s *Service) loadRcmmndCache(now time.Time) {
aids, err := s.rcmmnd.Hots(context.TODO())
if err != nil {
log.Error("s.rcmmnd.Hots(%v) error(%v)", now, err)
return
}
if len(aids) > 200 {
aids = aids[:200]
}
if len(aids) < 60 {
return
}
tmp, tmpOsea := s.fromAids(context.TODO(), aids)
if len(tmp) > 0 {
s.rcmmndCache = tmp
}
if len(tmpOsea) > 0 {
s.rcmmndOseaCache = tmpOsea
}
log.Info("loadRcmmndCache success")
}
// loadRegionCache load region cahce.
func (s *Service) loadRegionCache(now time.Time) {
var (
tmp = map[string][]*show.Item{}
tmpOsea = map[string][]*show.Item{}
tmpBg = map[string][]*show.Item{}
tmpBgOsea = map[string][]*show.Item{}
tmpBgEp = map[string][]*show.Item{}
tmpBgEpOsea = map[string][]*show.Item{}
sids = map[int32]*seasongrpc.CardInfoProto{}
)
for _, tid := range _tids {
rs, err := s.rcmmnd.Region(context.TODO(), tid)
if len(rs) > 8 {
rs = rs[:8]
}
tidInt, _ := strconv.Atoi(tid)
if err != nil || len(rs) < 4 {
log.Error("s.rcmmnd.Region(%v) error(%v)", now, err)
res, aids, err := s.dyn.RegionDynamic(context.TODO(), tidInt, 1, 8)
if err != nil || len(res) < 4 {
log.Error("s.dyn.RegionDynamic(%v) error(%v)", now, err)
continue
}
if len(res) > 8 {
res = res[:8]
}
if _, isBangumi := _bangumiReids[tidInt]; isBangumi {
sids, _ = s.fromSeasonID(context.TODO(), aids)
}
tmp[tid], tmpOsea[tid] = s.fromArchivesPB(res)
tmpBg[tid], tmpBgOsea[tid] = s.fromArchivesBangumi(context.TODO(), res, aids, sids, _bangumiSeasonID)
tmpBgEp[tid], tmpBgEpOsea[tid] = s.fromArchivesBangumi(context.TODO(), res, aids, sids, _bangumiEpisodeID)
} else {
if _, isBangumi := _bangumiReids[tidInt]; isBangumi {
sids, _ = s.fromSeasonID(context.TODO(), rs)
}
tmp[tid], tmpOsea[tid], tmpBg[tid], tmpBgOsea[tid], tmpBgEp[tid], tmpBgEpOsea[tid] =
s.fromBgAids(context.TODO(), rs, sids, _bangumiSeasonID)
}
log.Info("load show index region(%s) success", tid)
}
if len(tmp) > 0 {
s.regionCache = tmp
}
if len(tmpOsea) > 0 {
s.regionOseaCache = tmpOsea
}
if len(tmpBg) > 0 {
s.regionBgCache = tmpBg
}
if len(tmpBgOsea) > 0 {
s.regionBgOseaCache = tmpBgOsea
}
if len(tmpBgEp) > 0 {
s.regionBgEpCache = tmpBgEp
}
if len(tmpBgEpOsea) > 0 {
s.regionBgEpOseaCache = tmpBgEpOsea
}
log.Info("loadRegionCache success")
}
// loadBannerCahce load banner cache.
func (s *Service) loadBannerCahce() {
var (
resbs = map[int8]map[int][]*resource.Banner{}
)
for plat, resIDStr := range _bannersPlat {
mobiApp := model.MobiApp(plat)
res, err := s.res.ResBanner(context.TODO(), plat, 515007, 0, resIDStr, "master", "", "", "", mobiApp, "", "", false)
if err != nil || len(res) == 0 {
log.Error("s.res.ResBanner is null or err(%v)", err)
return
}
resbs[plat] = res
}
if len(resbs) > 0 {
s.bannerCache = resbs
}
log.Info("loadBannerCahce success")
}
// loadBgmCache load bangumi cache
func (s *Service) loadBgmCache(now time.Time) {
bgms, err := s.bgm.Recommend(now)
if err != nil {
log.Error("s.bgm.Recommend(%v) error(%v)", now, err)
return
}
if len(bgms) < 8 {
return
}
var (
tmp = map[int8][]*show.Item{}
si *show.Item
)
for _, bgm := range bgms {
si = &show.Item{}
si.FromBangumi(bgm)
tmp[model.PlatAndroid] = append(tmp[model.PlatAndroid], si)
tmp[model.PlatIPhone] = append(tmp[model.PlatIPhone], si)
tmp[model.PlatAndroidG] = append(tmp[model.PlatAndroidG], si)
tmp[model.PlatAndroidI] = append(tmp[model.PlatAndroidI], si)
tmp[model.PlatIPhoneI] = append(tmp[model.PlatIPhoneI], si)
si = &show.Item{}
si.FromBangumi(bgm)
si.Cover = bgm.Cover // pad hd get bangumi cover
tmp[model.PlatIPad] = append(tmp[model.PlatIPad], si)
tmp[model.PlatIPadI] = append(tmp[model.PlatIPadI], si)
tmp[model.PlatAndroidTV] = append(tmp[model.PlatAndroidTV], si)
}
s.bgmCache = tmp
log.Info("loadBgmCache success")
}
// loadLiveCache load live cache .
func (s *Service) loadLiveCache(now time.Time) {
lrs, err := s.lv.Recommend(now)
if err != nil {
log.Error("s.live.Recommend(%v) error(%v)", now, err)
return
}
if lrs == nil {
return
}
s.liveCount = lrs.Count
if subLen := len(lrs.Lives.Subject); subLen > 0 {
tmp := make([]*show.Item, 0, subLen)
for _, l := range lrs.Lives.Subject {
si := &show.Item{}
si.FromLive(l)
tmp = append(tmp, si)
}
s.liveMoeCache = tmp
}
if hotLen := len(lrs.Lives.Hot); hotLen >= 4 {
tmp := make([]*show.Item, 0, hotLen)
for _, l := range lrs.Lives.Hot {
si := &show.Item{}
si.FromLive(l)
tmp = append(tmp, si)
}
s.liveHotCache = tmp
}
log.Info("loadLiveCache success")
}
// loadShowCache load all show cache
func (s *Service) loadShowCache() {
hdm, err := s.dao.Heads(context.TODO())
if err != nil {
log.Error("s.dao.Heads error(%v)", err)
return
}
itm, err := s.dao.Items(context.TODO())
if err != nil {
log.Error("s.dao.Items error(%v)", err)
return
}
tmp, tmpbg, tmpbgep := s.mergeShow(hdm, itm)
if len(tmp) > 0 {
s.cache = tmp
}
if len(tmpbg) > 0 {
s.cacheBg = tmpbg
}
if len(tmpbgep) > 0 {
s.cacheBgEp = tmpbgep
}
log.Info("loadShowCache success")
}
// loadShowTempCache load all show temp cache
func (s *Service) loadShowTempCache() {
hdm, err := s.dao.TempHeads(context.TODO())
if err != nil {
log.Error("s.dao.TempHeads error(%v)", err)
return
}
itm, err := s.dao.TempItems(context.TODO())
if err != nil {
log.Error("s.dao.TempItems error(%v)", err)
return
}
s.tempCache, _, _ = s.mergeShow(hdm, itm)
log.Info("loadShowTempCache success")
}
// loadRegionListCache
func (s *Service) loadRegionListCache() {
res, err := s.rg.RegionPlat(context.TODO())
if err != nil {
log.Error("s.rg.RegionPlat error(%v)", err)
return
}
tmpRegion := map[int]*region.Region{}
tmp := map[int]*region.Region{}
for _, v := range res {
// region list map
tmpRegion[v.Rid] = v
}
for _, r := range res {
if r.Reid != 0 {
if rerg, ok := tmpRegion[r.Reid]; ok {
tmp[r.Rid] = rerg
}
}
}
s.reRegionCache = tmp
}
// loadRankAllCache
func (s *Service) loadRankAllCache() {
var (
rankAids []int64
err error
as map[int64]*api.Arc
c = context.TODO()
trankCache = []*rank.Rank{}
)
aids, others, scores, err := s.rcmmnd.RankAppAll(c)
if err != nil {
log.Error("s.rcmmnd.RankAppAll error(%v)", err)
return
}
for _, aid := range aids {
if _, ok := others[aid]; !ok {
rankAids = append(rankAids, aid)
}
}
if len(rankAids) == 0 {
return
}
s.rankAidsCache = rankAids
s.rankScoreCache = scores
if as, err = s.arc.ArchivesPB(c, rankAids); err != nil {
log.Error("s.arc.ArchivesPB aids(%v) error(%v)", aids, err)
return
}
if len(as) == 0 {
log.Warn("s.arc.ArchivesPB(%v) length is 0", rankAids)
return
}
s.rankArchivesCache = as
tmp, tmpOsea := s.fromRankAids(c, rankAids, scores, as)
if len(tmp) > 0 {
s.rankCache = tmp
}
if len(tmpOsea) > 0 {
s.rankOseaCache = tmpOsea
}
log.Info("loadRankAllCache success")
// new cache
for _, aid := range rankAids {
r := &rank.Rank{
Aid: aid,
Score: int32(scores[aid]),
}
trankCache = append(trankCache, r)
}
s.rankCache2 = trankCache
}
// loadColumnListCache
func (s *Service) loadColumnListCache(now time.Time) {
var (
tmpChild = map[int]*card.ColumnList{}
)
columns, err := s.cdao.ColumnList(context.TODO(), now)
if err != nil {
log.Error("s.cdao.ColumnList error(%v)", err)
return
}
for _, column := range columns {
tmpChild[column.Cid] = column
}
s.columnListCache = tmpChild
}
// loadCardCache load all card cache
func (s *Service) loadCardCache(now time.Time) {
hdm, err := s.cdao.PosRecs(context.TODO(), now)
if err != nil {
log.Error("s.cdao.PosRecs error(%v)", err)
return
}
itm, aids, err := s.cdao.RecContents(context.TODO(), now)
if err != nil {
log.Error("s.cdao.RecContents error(%v)", err)
return
}
tmpItem := map[int]map[int64]*show.Item{}
for recid, aid := range aids {
tmpItem[recid] = s.fromCardAids(context.TODO(), aid)
}
tmp := s.mergeCard(context.TODO(), hdm, itm, tmpItem, now)
s.cardCache = tmp
}
func (s *Service) mergeCard(c context.Context, hdm map[int8]map[int][]*card.Card, itm map[int][]*card.Content, tmpItems map[int]map[int64]*show.Item, now time.Time) (res map[string][]*show.Show) {
var (
_topic = 1
_activity = 0
)
res = map[string][]*show.Show{}
for plat, phds := range hdm {
hds, ok := phds[0]
if !ok {
continue
}
for _, hd := range hds {
key := fmt.Sprintf(_initCardKey, plat)
var (
sis []*show.Item
)
its, ok := itm[hd.ID]
if !ok {
its = []*card.Content{}
}
tmpItem, ok := tmpItems[hd.ID]
if !ok {
tmpItem = map[int64]*show.Item{}
}
// 1 daily 2 topic 3 activity 4 rank 5 polymeric_card
switch hd.Type {
case 1:
for _, ci := range its {
si := s.fillCardItem(ci, tmpItem)
if si.Title != "" {
sis = append(sis, si)
}
}
case 2:
if topicID, err := strconv.ParseInt(hd.Rvalue, 10, 64); err == nil {
if actm, err := s.act.Activitys(c, []int64{topicID}, _topic, ""); err != nil {
} else {
if act, ok := actm[topicID]; ok && act.H5Cover != "" && act.H5URL != "" {
si := &show.Item{}
si.FromTopic(act)
sis = []*show.Item{si}
}
}
}
case 3:
if topicID, err := strconv.ParseInt(hd.Rvalue, 10, 64); err == nil {
if actm, err := s.act.Activitys(c, []int64{topicID}, _activity, ""); err != nil {
} else {
if act, ok := actm[topicID]; ok && act.H5Cover != "" && act.H5URL != "" {
si := &show.Item{}
si.FromActivity(act, now)
sis = []*show.Item{si}
}
}
}
case 4:
if len(s.rankCache) > 3 {
sis = s.rankCache[:3]
} else {
sis = s.rankCache
}
case 5, 6, 8:
for _, ci := range its {
si := s.fillCardItem(ci, tmpItem)
if si.Title != "" {
sis = append(sis, si)
}
}
case 7:
si := &show.Item{
Title: hd.Title,
Cover: hd.Cover,
Desc: hd.Desc,
Goto: hd.Goto,
Param: hd.Param,
}
if hd.Goto == model.GotoColumnStage {
paramInt, _ := strconv.Atoi(hd.Param)
if c, ok := s.columnListCache[paramInt]; ok {
cidStr := strconv.Itoa(c.Ceid)
si.URI = model.FillURICategory(hd.Goto, cidStr, hd.Param)
}
} else {
si.URI = hd.URi
}
sis = append(sis, si)
default:
continue
}
if len(sis) == 0 {
continue
}
sw := &show.Show{}
sw.Head = &show.Head{
CardID: hd.ID,
Title: hd.Title,
Type: hd.TypeStr,
Build: hd.Build,
Condition: hd.Condition,
Plat: hd.Plat,
Style: "small",
}
if hd.Cover != "" {
sw.Head.Cover = hd.Cover
}
switch sw.Head.Type {
case model.GotoDaily:
sw.Head.Date = now.Unix()
sw.Head.Param = hd.Rvalue
case model.GotoCard:
sw.Head.URI = hd.URi
sw.Head.Goto = hd.Goto
sw.Head.Param = hd.Param
case model.GotoRank:
sw.Head.Param = "all"
case model.GotoTopic, model.GotoActivity:
if sw.Head.Title == "" {
if len(sis) > 0 {
sw.Head.Title = sis[0].Title
}
}
case model.GotoVeidoCard:
sw.Head.Param = hd.Param
if hd.Goto == model.GotoColumnStage {
paramInt, _ := strconv.Atoi(hd.Param)
if c, ok := s.columnListCache[paramInt]; ok {
cidStr := strconv.Itoa(c.Ceid)
sw.Head.URI = model.FillURICategory(hd.Goto, cidStr, hd.Param)
}
sw.Head.Goto = model.GotoColumn
} else {
sw.Head.Goto = hd.Goto
sw.Head.URI = hd.URi
}
if sisLen := len(sis); sisLen > 1 {
if sisLen%2 != 0 {
sis = sis[:sisLen-1]
}
} else {
continue
}
case model.GotoSpecialCard:
sw.Head.Cover = ""
case model.GotoTagCard:
if hd.TagID > 0 {
var tagIDInt int64
sw.Head.Title, tagIDInt = s.fromTagIDByName(c, hd.TagID, now)
sw.Head.Param = strconv.FormatInt(tagIDInt, 10)
sw.Head.Goto = model.GotoTagID
}
}
if len(sis) == 0 {
sis = _emptyShowItems
}
sw.Body = sis
res[key] = append(res[key], sw)
}
}
return
}
func (s *Service) fillCardItem(csi *card.Content, tsi map[int64]*show.Item) (si *show.Item) {
si = &show.Item{}
switch csi.Type {
case model.CardGotoAv:
si.Goto = model.GotoAv
si.Param = csi.Value
}
si.URI = model.FillURI(si.Goto, si.Param, nil)
if si.Goto == model.GotoAv {
aid, err := strconv.ParseInt(si.Param, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", si.Param, err)
} else {
if it, ok := tsi[aid]; ok {
si = it
if csi.Title != "" {
si.Title = csi.Title
}
} else {
si = &show.Item{}
}
}
}
return
}
// fromTagIDByName from tag_id by tag_name
func (s *Service) fromTagIDByName(ctx context.Context, tagID int, now time.Time) (tagName string, tagIDInt int64) {
tag, err := s.tag.TagInfo(ctx, 0, tagID, now)
if err != nil {
log.Error("s.tag.TagInfo(%d) error(%v)", tagID, err)
return
}
tagName = tag.Name
tagIDInt = tag.Tid
return
}
// mergeShow merge heads and items
func (s *Service) mergeShow(hdm map[int8][]*show.Head, itm map[int][]*show.Item) (res, resbg, resbgep map[string][]*show.Show) {
res = map[string][]*show.Show{}
resbg = map[string][]*show.Show{}
resbgep = map[string][]*show.Show{}
for plat, hds := range hdm {
for _, hd := range hds {
key := fmt.Sprintf(_initShowKey, plat, hd.Language)
its, ok := itm[hd.ID]
if !ok {
continue
}
var (
sis []*show.Item
sisbg []*show.Item
sisbgep []*show.Item
ext *show.Ext
)
switch hd.Type {
case "recommend":
for _, si := range its {
if si.IsRandom() {
continue
}
s.fillItem(plat, si)
sis = append(sis, si)
}
sisbg = sis
sisbgep = sis
case "live":
if plat == model.PlatAndroidTV {
continue
}
ext = &show.Ext{
LiveCnt: s.liveCount,
}
case "bangumi":
sis = s.sliceCache(plat, s.bgmCache[plat])
sisbg = sis
sisbgep = sis
case "region":
if model.IsOverseas(plat) {
sis = s.sliceCache(plat, s.regionOseaCache[hd.Param])
sisbg = s.sliceCache(plat, s.regionBgOseaCache[hd.Param])
sisbgep = s.sliceCache(plat, s.regionBgEpOseaCache[hd.Param])
} else {
sis = s.sliceCache(plat, s.regionCache[hd.Param])
sisbg = s.sliceCache(plat, s.regionBgCache[hd.Param])
sisbgep = s.sliceCache(plat, s.regionBgEpCache[hd.Param])
}
case "sp":
for _, si := range its {
spidIdx := strings.Split(si.Param, ",")
si.Goto = model.GotoSp
si.Param = spidIdx[0]
si.URI = model.FillURI(model.GotoSp, spidIdx[0], nil)
if len(spidIdx) == 2 {
si.Index = spidIdx[1]
}
sis = append(sis, si)
}
sisbg = sis
sisbgep = sis
case "activity":
for _, si := range its {
if si.IsRandom() {
continue
}
si.Goto = model.GotoWeb
si.URI = model.FillURI(model.GotoWeb, si.Param, nil)
sis = append(sis, si)
}
sisbg = sis
sisbgep = sis
case "topic":
for _, si := range its {
si.Goto = model.GotoWeb
si.URI = model.FillURI(model.GotoWeb, si.Param, nil)
sis = append(sis, si)
}
sisbg = sis
sisbgep = sis
case "focus":
for _, si := range its {
if si.IsRandom() {
continue
}
pp := strings.Split(si.Param, ",")
si.Param = pp[0]
if len(pp) == 2 {
si.Goto = pp[1]
} else {
si.Goto = model.GotoAv
}
si.URI = model.FillURI(si.Goto, si.Param, nil)
sisbg = append(sisbg, si)
}
sisbgep = sisbg
default:
continue
}
sw := &show.Show{}
sw.Head = hd
sw.Body = sis
sw.Ext = ext
swbg := &show.Show{}
swbg.Head = hd
swbg.Body = sisbg
swbg.Ext = ext
swbgep := &show.Show{}
swbgep.Head = hd
swbgep.Body = sisbgep
swbgep.Ext = ext
// append show.Show
res[key] = append(res[key], sw)
resbg[key] = append(resbg[key], swbg)
resbgep[key] = append(resbgep[key], swbgep)
}
}
return
}
// fillItem used by loadShowCache
func (s *Service) fillItem(plat int8, si *show.Item) {
pp := strings.Split(si.Param, ",")
si.Param = pp[0]
if len(pp) == 2 {
si.Goto = pp[1]
} else {
si.Goto = model.GotoAv
}
si.URI = model.FillURI(si.Goto, si.Param, nil)
if si.Goto == model.GotoAv {
aid, err := strconv.ParseInt(si.Param, 10, 64)
if err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", si.Param, err)
} else {
a, err := s.arc.Archive(context.TODO(), aid)
if err != nil || a == nil {
log.Error("s.arc.Archive(%d) error(%v)", aid, err)
} else {
si.Play = int(a.Stat.View)
si.Danmaku = int(a.Stat.Danmaku)
if si.Title == "" {
si.Title = a.Title
}
if si.Cover == "" {
si.Cover = a.Pic
}
}
}
} else {
si.Play = rand.Intn(1000)
si.Danmaku = rand.Intn(1000)
}
}
// sliceCache used by loadShowCache
func (s *Service) sliceCache(plat int8, chc []*show.Item) []*show.Item {
if len(chc) == 0 {
return _emptyItems
}
cnt := 4
if plat == model.PlatIPad {
cnt = 8
}
if len(chc) < cnt {
cnt = len(chc)
}
return chc[:cnt]
}
func (s *Service) loadBlackCache() {
var res []int64
if err := s.client.Get(context.TODO(), _blackUrl, "", nil, &res); err != nil {
log.Error("recommend ranking url(%s) error(%v)", _blackUrl, err)
return
}
if len(res) == 0 {
return
}
tmp := map[int64]struct{}{}
for _, aid := range res {
tmp[aid] = struct{}{}
}
s.blackCache = tmp
log.Info("reBlackList success")
}
// rcmmndproc get recommend aids and add into cache.
func (s *Service) rcmmndproc() {
var ctx = context.TODO()
for i := 0; i < runtime.NumCPU(); i++ {
go func() {
for {
r := <-s.rcmmndCh
s.dao.AddRcmmndCache(ctx, r.key, r.aids...)
}
}()
}
}
// // loadPopularCard load popular card
// func (s *Service) loadPopularCard(now time.Time) {
// var (
// c = context.TODO()
// err error
// tmp, tmpcache []*card.PopularCard
// tmpPlat = map[int64]map[int8][]*card.PopularCardPlat{}
// )
// if tmp, err = s.cdao.Card(c, now); err != nil {
// log.Error("popular card s.cd.Card error(%v)", err)
// return
// }
// if tmpPlat, err = s.cdao.CardPlat(c); err != nil {
// log.Error("popular card s.cd.CardPlat error(%v)", err)
// return
// }
// for _, t := range tmp {
// tc := &card.PopularCard{}
// *tc = *t
// if pconfig, ok := tmpPlat[t.ID]; ok {
// tc.PopularCardPlat = pconfig
// }
// tmpcache = append(tmpcache, tc)
// }
// s.hotCache = tmpcache
// log.Info("hotCache success")
// }
func (s *Service) loadHotTenTabAids() {
var tmpList = make(map[int][]*recmod.CardList)
for i := 0; i < 10; i++ {
var (
c = context.TODO()
err error
hottabAids []*recmod.CardList
flowResp *creativeAPI.FlowResponse
oids []int64
forbidAids = make(map[int64]struct{})
)
if hottabAids, err = s.rcmmnd.HotHeTongTabCard(c, i); err != nil {
log.Error("%+v", err)
continue
}
for _, hot := range hottabAids {
if hot.Goto == model.GotoAv {
oids = append(oids, hot.ID)
}
}
if flowResp, err = s.creativeClient.FlowJudge(context.Background(), &creativeAPI.FlowRequest{
Oids: oids,
Business: 4,
Gid: 24,
}); err != nil {
log.Error("s.creativeClient.FlowJudge error(%v)", err)
tmpList[i] = hottabAids
} else {
for _, oid := range flowResp.Oids {
forbidAids[oid] = struct{}{}
}
for _, list := range hottabAids {
if list.Goto == model.GotoAv {
if _, ok := forbidAids[list.ID]; ok {
log.Info("aid(%d) is flowJundged", list.ID)
continue
}
}
tmpList[i] = append(tmpList[i], list)
}
}
log.Info("buildHotSuccess(%d) len(%d)", i, len(tmpList[i]))
}
if len(tmpList) == 10 {
s.hotTenTabCardCache = tmpList
}
}
func (s *Service) loadHotTopicCache() {
var (
c = context.TODO()
err error
topics []*clive.TopicHot
)
if topics, err = s.lv.TopicHots(c); err != nil {
log.Error("topichots s.lv.TopicHots error(%v)", err)
return
}
if len(topics) > 8 {
s.hottopicsCache = topics[:8]
} else {
s.hottopicsCache = topics
}
log.Info("loadHotTopicCache success")
}
func (s *Service) loadHotTenMergeRcmdCache(i int) {
// mc
var (
c = context.TODO()
hcards []*recmod.CardList
rcmdcard []*card.PopularCard
ok bool
err error
)
if hcards, ok = s.hotTenTabCardCache[i]; ok {
for _, hcard := range hcards {
rcmdcard = append(rcmdcard, hcard.CardListChange())
}
if err = s.cdao.AddPopularCardTenCache(c, i, rcmdcard); err != nil {
log.Error("cards mc s.cdao.AddPopularCardCache error(%v)", err)
return
}
}
}
// PopularCardList cards
func (s *Service) PopularCardTenList(c context.Context, i int) (res []*card.PopularCard) {
var err error
if res, err = s.cdao.PopularCardTenCache(c, i); err != nil {
log.Error("%+v", err)
return
}
return
}
func (s *Service) loadCardSetCache() {
var (
cards map[int64]*operate.CardSet
err error
)
if cards, err = s.cdao.CardSet(context.TODO()); err != nil {
log.Error("%+v", err)
return
}
s.cardSetCache = cards
}
func (s *Service) loadDynamicHotCache() {
var (
liveList []*clive.DynamicHot
err error
)
if liveList, err = s.lv.DynamicHot(context.TODO()); err != nil {
log.Error("s.lv.dynamichot error(%v)", err)
return
}
s.dynamicHotCache = liveList
}
func (s *Service) loadEventTopicCache() {
var (
eventtopic map[int64]*operate.EventTopic
err error
)
if eventtopic, err = s.cdao.EventTopic(context.TODO()); err != nil {
log.Error("s.cdao.eventtopic error(%v)", err)
return
}
s.eventTopicCache = eventtopic
}

View File

@@ -0,0 +1,150 @@
package show
import (
"context"
"hash/crc32"
"strconv"
"time"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/card"
"go-common/app/interface/main/app-show/model/feed"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
)
var (
_emptyList = []*feed.Item{}
)
// FeedIndex feed index
func (s *Service) FeedIndex(c context.Context, mid, idx int64, plat int8, build, loginEvent int, lastParam, mobiApp, device, buvid string, now time.Time) (res []*feed.Item) {
var (
ps = 10
isIpad = plat == model.PlatIPad
cards, cardCache []*card.PopularCard
)
if isIpad {
ps = 20
}
var key int
if mid > 0 {
key = int((mid / 1000) % 10)
} else {
key = int((crc32.ChecksumIEEE([]byte(buvid)) / 1000) % 10)
}
cardCache = s.PopularCardTenList(c, key)
if len(cardCache) > int(idx) {
cards = cardCache[idx:]
} else {
res = _emptyList
return
}
res = s.dealItem(c, plat, build, ps, cards, idx, lastParam, now)
if len(res) == 0 {
res = _emptyList
return
}
//infoc
infoc := &feedInfoc{
mobiApp: mobiApp,
device: device,
build: strconv.Itoa(build),
now: now.Format("2006-01-02 15:04:05"),
loginEvent: strconv.Itoa(loginEvent),
mid: strconv.FormatInt(mid, 10),
buvid: buvid,
page: strconv.Itoa((int(idx) / ps) + 1),
feed: res,
}
s.infocfeed(infoc)
return
}
// dealItem feed item
func (s *Service) dealItem(c context.Context, plat int8, build, ps int, cards []*card.PopularCard, idx int64, lastParam string, now time.Time) (is []*feed.Item) {
const _rankCount = 3
var (
uri map[int64]string
// key
max = int64(100)
_fTypeOperation = "operation"
aids []int64
am map[int64]*api.Arc
feedcards []*card.PopularCard
err error
)
LOOP:
for pos, ca := range cards {
var cardIdx = idx + int64(pos+1)
if cardIdx > max && ca.FromType != _fTypeOperation {
continue
}
if config, ok := ca.PopularCardPlat[plat]; ok {
for _, l := range config {
if model.InvalidBuild(build, l.Build, l.Condition) {
continue LOOP
}
}
} else if ca.FromType == _fTypeOperation {
continue LOOP
}
tmp := &card.PopularCard{}
*tmp = *ca
tmp.Idx = cardIdx
feedcards = append(feedcards, tmp)
switch ca.Type {
case model.GotoAv:
aids = append(aids, ca.Value)
}
if len(feedcards) == ps {
break
}
}
if len(aids) != 0 {
if am, err = s.arc.ArchivesPB(c, aids); err != nil {
s.pMiss.Incr("popularcard_Archives")
err = nil
} else {
s.pHit.Incr("popularcard_Archives")
}
}
for _, ca := range feedcards {
i := &feed.Item{}
i.FromType = ca.FromType
i.Idx = ca.Idx
i.Pos = ca.Pos
switch ca.Type {
case model.GotoAv:
a := am[ca.Value]
isOsea := model.IsOverseas(plat)
if a != nil && a.IsNormal() && (!isOsea || (isOsea && a.AttrVal(archive.AttrBitOverseaLock) == 0)) {
i.FromPlayerAv(a, uri[a.Aid])
i.FromRcmdReason(ca)
// if tag, ok := s.hotArcTag[a.Aid]; ok {
// i.Tag = &feed.Tag{TagID: tag.ID, TagName: tag.Name}
// }
i.Goto = ca.Type
is = append(is, i)
}
case model.GotoRank:
if rankAids := s.rankAidsCache; len(rankAids) >= _rankCount {
i.FromRank(rankAids, s.rankScoreCache, s.rankArchivesCache)
// i.Param = strconv.FormatInt(ca.ID, 10)
if i.Goto != "" {
is = append(is, i)
}
}
case model.GotoHotTopic:
if hotTopics := s.hottopicsCache; len(hotTopics) > 0 {
i.FromHotTopic(hotTopics)
is = append(is, i)
}
}
}
if rl := len(is); rl == 0 {
is = _emptyList
return
}
return
}

View File

@@ -0,0 +1,306 @@
package show
import (
"context"
"hash/crc32"
"strconv"
"time"
cdm "go-common/app/interface/main/app-card/model"
cardm "go-common/app/interface/main/app-card/model/card"
operate "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-show/model"
"go-common/app/interface/main/app-show/model/card"
"go-common/app/interface/main/app-show/model/feed"
account "go-common/app/service/main/account/model"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
relation "go-common/app/service/main/relation/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
var (
_emptyList2 = []cardm.Handler{}
)
// FeedIndex feed index
func (s *Service) FeedIndex2(c context.Context, mid, idx int64, plat int8, build, loginEvent int, lastParam, mobiApp, device, buvid string, now time.Time) (res []cardm.Handler, ver string, err error) {
var (
ps = 10
isIpad = plat == model.PlatIPad
cards, cardCache []*card.PopularCard
infocs []*feed.Item
style int8
)
if isIpad {
ps = 20
}
var key int
if mid > 0 {
key = int((mid / 1000) % 10)
} else {
key = int((crc32.ChecksumIEEE([]byte(buvid)) / 1000) % 10)
}
cardCache = s.PopularCardTenList(c, key)
if len(cardCache) > int(idx) {
cards = cardCache[idx:]
} else {
err = ecode.AppNotData
res = _emptyList2
return
}
// HotDynamic====================
// cards = append(cards[:0], append([]*card.PopularCard{&card.PopularCard{Type: model.GotoHotDynamic, ReasonType: 0, FromType: "recommend"}}, cards[0:]...)...)
// HotDynamic====================
//build
if plat == model.PlatIPhone && build > 8230 || plat == model.PlatAndroid && build > 5345000 {
// switch key {
// // case 0, 3:
// // style = cdm.HotCardStyleShowUp
// case 2, 5:
// style = cdm.HotCardStyleHideUp
// default:
// style = cdm.HotCardStyleOld
// }
style = cdm.HotCardStyleHideUp
} else {
style = cdm.HotCardStyleOld
}
//build
res, infocs = s.dealItem2(c, plat, build, ps, cards, mid, idx, lastParam, now, style)
ver = strconv.FormatInt(now.Unix(), 10)
if len(res) == 0 {
err = ecode.AppNotData
res = _emptyList2
return
}
//infoc
infoc := &feedInfoc{
mobiApp: mobiApp,
device: device,
build: strconv.Itoa(build),
now: now.Format("2006-01-02 15:04:05"),
loginEvent: strconv.Itoa(loginEvent),
mid: strconv.FormatInt(mid, 10),
buvid: buvid,
page: strconv.Itoa((int(idx) / ps) + 1),
feed: infocs,
}
s.infocfeed(infoc)
return
}
// dealItem feed item
func (s *Service) dealItem2(c context.Context, plat int8, build, ps int, cards []*card.PopularCard, mid, idx int64, lastParam string, now time.Time, style int8) (is []cardm.Handler, infocs []*feed.Item) {
var (
max = int64(100)
_fTypeOperation = "operation"
aids, avUpIDs, upIDs, rnUpIDs []int64
am map[int64]*archive.ArchiveWithPlayer
feedcards []*card.PopularCard
err error
rank *operate.Card
accountm map[int64]*account.Card
isAtten map[int64]int8
statm map[int64]*relation.Stat
)
cardSet := map[int64]*operate.Card{}
eventTopic := map[int64]*operate.Card{}
LOOP:
for pos, ca := range cards {
var cardIdx = idx + int64(pos+1)
if cardIdx > max && ca.FromType != _fTypeOperation {
continue
}
if config, ok := ca.PopularCardPlat[plat]; ok {
for _, l := range config {
if model.InvalidBuild(build, l.Build, l.Condition) {
continue LOOP
}
}
} else if ca.FromType == _fTypeOperation {
continue LOOP
}
tmp := &card.PopularCard{}
*tmp = *ca
if plat == model.PlatIPhone && build > 8290 || plat == model.PlatAndroid && build > 5365000 {
switch ca.Type {
case model.GotoUpRcmdNew:
tmp.Type = model.GotoUpRcmdNewV2
}
}
tmp.Idx = cardIdx
feedcards = append(feedcards, tmp)
switch ca.Type {
case model.GotoAv:
aids = append(aids, ca.Value)
case model.GotoRank:
rank = &operate.Card{}
rank.FromRank(s.rankCache2)
case model.GotoUpRcmdNew, model.GotoUpRcmdNewV2:
cardm, as, upid := s.cardSetChange(c, ca.Value)
aids = append(aids, as...)
for id, card := range cardm {
cardSet[id] = card
}
rnUpIDs = append(rnUpIDs, upid)
case model.GotoEventTopic:
eventTopic = s.eventTopicChange(c, ca.Value)
}
if len(feedcards) == ps {
break
}
}
if len(aids) != 0 {
var as map[int64]*api.Arc
if as, err = s.arc.ArchivesPB(c, aids); err != nil {
log.Error("%+v", err)
err = nil
} else {
am = map[int64]*archive.ArchiveWithPlayer{}
for _, a := range as {
avUpIDs = append(avUpIDs, a.Author.Mid)
am[a.Aid] = &archive.ArchiveWithPlayer{Archive3: archive.BuildArchive3(a)}
}
}
}
switch style {
case cdm.HotCardStyleShowUp, cdm.HotCardStyleHideUp:
upIDs = append(upIDs, avUpIDs...)
}
upIDs = append(upIDs, rnUpIDs...)
avUpIDs = append(avUpIDs, rnUpIDs...)
g, ctx := errgroup.WithContext(c)
if len(avUpIDs) > 0 {
g.Go(func() (err error) {
if accountm, err = s.acc.Cards3(ctx, avUpIDs); err != nil {
log.Error("%+v", err)
err = nil
}
return nil
})
}
if len(upIDs) > 0 {
g.Go(func() (err error) {
if statm, err = s.reldao.Stats(ctx, upIDs); err != nil {
log.Error("%+v", err)
err = nil
}
return nil
})
if mid != 0 {
g.Go(func() error {
isAtten = s.acc.IsAttention(ctx, upIDs, mid)
return nil
})
}
}
g.Wait()
for _, ca := range feedcards {
var (
r = ca.PopularCardToAiChange()
main interface{}
cardType cdm.CardType
)
r.Style = style
op := &operate.Card{}
op.From(cdm.CardGt(r.Goto), r.ID, 0, plat, build)
switch r.Style {
case cdm.HotCardStyleShowUp, cdm.HotCardStyleHideUp:
switch r.Goto {
case model.GotoAv:
cardType = cdm.SmallCoverV5
}
}
switch r.Goto {
case model.GotoAv:
if a, ok := am[r.ID]; ok && (a.AttrVal(archive.AttrBitOverseaLock) == 0 || !model.IsOverseas(plat)) {
main = map[int64]*archive.ArchiveWithPlayer{a.Aid: a}
// op.Tid = a.Aid
r.HideButton = true
if (plat == model.PlatIPhone && build > 8290 || plat == model.PlatAndroid && build > 5365000) && cardType == cdm.SmallCoverV5 {
op.Switch = cdm.SwitchCooperationShow
} else {
op.Switch = cdm.SwitchCooperationHide
}
}
case model.GotoRank:
ams := map[int64]*archive.ArchiveWithPlayer{}
for aid, a := range s.rankArchivesCache {
ams[aid] = &archive.ArchiveWithPlayer{Archive3: archive.BuildArchive3(a)}
}
main = map[cdm.Gt]interface{}{cdm.GotoAv: ams}
op = rank
case model.GotoHotTopic:
main = s.hottopicsCache
case model.GotoUpRcmdNew, model.GotoUpRcmdNewV2:
main = am
op = cardSet[r.ID]
case model.GotoHotDynamic:
main = s.dynamicHotCache
case model.GotoEventTopic:
op = eventTopic[r.ID]
}
h := cardm.Handle(plat, cdm.CardGt(r.Goto), cardType, cdm.ColumnSvrSingle, r, nil, isAtten, statm, accountm)
if h == nil {
continue
}
h.From(main, op)
h.Get().FromType = ca.FromType
h.Get().Idx = ca.Idx
if h.Get().Right {
h.Get().ThreePointWatchLater()
is = append(is, h)
}
// infoc
tinfo := &feed.Item{
Goto: ca.Type,
Param: strconv.FormatInt(ca.Value, 10),
URI: h.Get().URI,
FromType: ca.FromType,
Idx: h.Get().Idx,
CornerMark: ca.CornerMark,
CardStyle: r.Style,
}
if r.RcmdReason != nil {
tinfo.RcmdContent = r.RcmdReason.Content
}
if op != nil {
switch r.Goto {
case model.GotoEventTopic:
tinfo.Item = append(tinfo.Item, &feed.Item{Param: op.URI, Goto: string(op.Goto)})
default:
for _, tmp := range op.Items {
tinfo.Item = append(tinfo.Item, &feed.Item{Param: strconv.FormatInt(tmp.ID, 10), Goto: string(tmp.Goto)})
}
}
}
infocs = append(infocs, tinfo)
if len(is) == ps {
break
}
}
rl := len(is)
if rl == 0 {
is = _emptyList2
return
}
return
}
func (s *Service) RankCard() (ranks []*rank.Rank, aids []int64) {
const _limit = 3
ranks = make([]*rank.Rank, 0, _limit)
aids = make([]int64, 0, _limit)
for _, rank := range s.rankCache2 {
ranks = append(ranks, rank)
aids = append(aids, rank.Aid)
if len(ranks) == _limit {
break
}
}
return
}

View File

@@ -0,0 +1,178 @@
package show
import (
"bytes"
"strconv"
"time"
"go-common/app/interface/main/app-show/conf"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/feed"
"go-common/app/interface/main/app-show/model/show"
"go-common/library/log"
binfoc "go-common/library/log/infoc"
)
type infoc struct {
mid string
client string
buvid string
disid string
ip string
api string
now string
isRcmmnd string
items []*show.Item
}
type feedInfoc struct {
mobiApp string
device string
build string
now string
loginEvent string
mid string
buvid string
page string
feed []*feed.Item
}
// Infoc write data for Hadoop do analytics
func (s *Service) Infoc(mid int64, plat int8, buvid, disid, ip, api string, items []*show.Item, now time.Time) {
select {
case s.logCh <- infoc{strconv.FormatInt(mid, 10), strconv.Itoa(int(plat)), buvid, disid, ip, api, strconv.FormatInt(now.Unix(), 10), "1", items}:
default:
log.Warn("infoc log buffer is full")
}
}
func (s *Service) infocfeed(i interface{}) {
select {
case s.logFeedCh <- i:
default:
log.Warn("infocfeed chan full")
}
}
// writeInfoc
func (s *Service) infocproc() {
const (
// infoc format {"section":{"id":"热门推荐","pos":1,"items":[{"id":%s,"pos":%d,"type":1,"url":""}]}}
noItem = `{"section":{"id":"热门推荐","pos":1,"items":[""]}}`
)
var (
msg1 = []byte(`{"section":{"id":"热门推荐","pos":1,"items":[`)
msg2 = []byte(`{"id":`)
msg3 = []byte(`,"pos":`)
msg4 = []byte(`,"type":1,"url":""},`)
inf2 = binfoc.New(conf.Conf.Infoc2)
buf bytes.Buffer
list string
)
for {
i := <-s.logCh
if len(i.items) > 0 {
buf.Write(msg1)
for i, v := range i.items {
if v.Goto != model.GotoAv {
continue
}
buf.Write(msg2)
buf.WriteString(v.Param)
buf.Write(msg3)
buf.WriteString(strconv.Itoa(i + 1))
buf.Write(msg4)
}
buf.Truncate(buf.Len() - 1)
buf.WriteString(`]}}`)
list = buf.String()
buf.Reset()
} else {
list = noItem
}
inf2.Info(i.ip, i.now, i.api, i.buvid, i.mid, i.client, "1", list, i.disid, i.isRcmmnd)
}
}
func (s *Service) infocfeedproc() {
const (
noItem = `[]`
)
var (
msg1 = []byte(`[`)
msg2 = []byte(`{"goto":"`)
msg3 = []byte(`","param":"`)
msg4 = []byte(`","uri":"`)
msg5 = []byte(`","r_pos":`)
msg6 = []byte(`,"from_type":"`)
msg9 = []byte(`","corner_mark":`)
msg10 = []byte(`,"rcmd_content":"`)
msg11 = []byte(`","card_style":`)
msg12 = []byte(`,"items":[`)
msg13 = []byte(`{"goto":"`)
msg14 = []byte(`","param":"`)
msg17 = []byte(`","pos":`)
msg15 = []byte(`},`)
msg16 = []byte(`]`)
msg7 = []byte(`},`)
msg8 = []byte(`]`)
buf bytes.Buffer
list string
feedInf = binfoc.New(s.c.FeedTabInfoc)
)
for {
i, ok := <-s.logFeedCh
if !ok {
log.Warn("infoc proc exit")
return
}
switch l := i.(type) {
case *feedInfoc:
if f := l.feed; len(f) == 0 {
list = noItem
} else {
buf.Write(msg1)
for _, item := range f {
buf.Write(msg2)
buf.WriteString(item.Goto)
buf.Write(msg3)
buf.WriteString(item.Param)
buf.Write(msg4)
buf.WriteString(item.URI)
buf.Write(msg5)
buf.WriteString(strconv.FormatInt(item.Idx, 10))
buf.Write(msg6)
buf.WriteString(item.FromType)
buf.Write(msg9)
buf.WriteString(strconv.Itoa(int(item.CornerMark)))
buf.Write(msg10)
buf.WriteString(item.RcmdContent)
buf.Write(msg11)
buf.WriteString(strconv.Itoa(int(item.CardStyle)))
if len(item.Item) > 0 {
buf.Write(msg12)
for pos, it := range item.Item {
buf.Write(msg13)
buf.WriteString(it.Goto)
buf.Write(msg14)
buf.WriteString(it.Param)
buf.Write(msg17)
buf.WriteString(strconv.Itoa(pos + 1))
buf.Write(msg15)
}
buf.Truncate(buf.Len() - 1)
buf.Write(msg16)
}
buf.Write(msg7)
}
buf.Truncate(buf.Len() - 1)
buf.Write(msg8)
list = buf.String()
buf.Reset()
}
log.Info("showtab_infoc_index(%s,%s,%s,%s,%s,%s,%s,%s)_list(%s)", l.mobiApp, l.device, l.build, l.now, l.loginEvent, l.mid, l.buvid, l.page, list)
feedInf.Info(l.mobiApp, l.device, l.build, l.now, l.loginEvent, l.mid, l.buvid, list, l.page)
}
}
}

View File

@@ -0,0 +1,44 @@
package show
import (
"context"
"go-common/app/interface/main/app-card/model/card/operate"
)
func (s *Service) cardSetChange(c context.Context, ids ...int64) (cardm map[int64]*operate.Card, aids []int64, upid int64) {
if len(ids) == 0 {
return
}
cardm = make(map[int64]*operate.Card, len(ids))
for _, id := range ids {
if cs, ok := s.cardSetCache[id]; ok {
card := &operate.Card{}
card.FromCardSet(cs)
cardm[id] = card
upid = card.ID
for _, item := range card.Items {
switch cs.Type {
case "up_rcmd_new":
aids = append(aids, item.ID)
}
}
}
}
return
}
func (s *Service) eventTopicChange(c context.Context, ids ...int64) (cardm map[int64]*operate.Card) {
if len(ids) == 0 {
return
}
cardm = make(map[int64]*operate.Card, len(ids))
for _, id := range ids {
if st, ok := s.eventTopicCache[id]; ok {
card := &operate.Card{}
card.FromEventTopic(st)
cardm[id] = card
}
}
return
}

View File

@@ -0,0 +1,443 @@
package show
import (
"strconv"
"time"
clive "go-common/app/interface/main/app-card/model/card/live"
"go-common/app/interface/main/app-card/model/card/operate"
"go-common/app/interface/main/app-card/model/card/rank"
"go-common/app/interface/main/app-show/conf"
accdao "go-common/app/interface/main/app-show/dao/account"
actdao "go-common/app/interface/main/app-show/dao/activity"
addao "go-common/app/interface/main/app-show/dao/ad"
arcdao "go-common/app/interface/main/app-show/dao/archive"
adtdao "go-common/app/interface/main/app-show/dao/audit"
bgmdao "go-common/app/interface/main/app-show/dao/bangumi"
carddao "go-common/app/interface/main/app-show/dao/card"
dbusdao "go-common/app/interface/main/app-show/dao/databus"
dyndao "go-common/app/interface/main/app-show/dao/dynamic"
livedao "go-common/app/interface/main/app-show/dao/live"
locdao "go-common/app/interface/main/app-show/dao/location"
rcmmdao "go-common/app/interface/main/app-show/dao/recommend"
regiondao "go-common/app/interface/main/app-show/dao/region"
reldao "go-common/app/interface/main/app-show/dao/relation"
resdao "go-common/app/interface/main/app-show/dao/resource"
showdao "go-common/app/interface/main/app-show/dao/show"
tagdao "go-common/app/interface/main/app-show/dao/tag"
"go-common/app/interface/main/app-show/model/card"
recmod "go-common/app/interface/main/app-show/model/recommend"
"go-common/app/interface/main/app-show/model/region"
"go-common/app/interface/main/app-show/model/show"
creativeAPI "go-common/app/interface/main/creative/api"
"go-common/app/service/main/archive/api"
resource "go-common/app/service/main/resource/model"
httpx "go-common/library/net/http/blademaster"
"go-common/library/stat/prom"
)
type recommend struct {
key string
aids []int64
}
type rcmmndCfg struct {
Aid int64 `json:"aid"`
Goto string `json:"goto"`
Title string `json:"title"`
Cover string `json:"cover"`
}
// Service is show service.
type Service struct {
c *conf.Config
creativeClient creativeAPI.CreativeClient
dao *showdao.Dao
rcmmnd *rcmmdao.Dao
ad *addao.Dao // cptbanner
bgm *bgmdao.Dao
lv *livedao.Dao
// bnnr *bnnrdao.Dao
adt *adtdao.Dao
tag *tagdao.Dao
arc *arcdao.Dao
dbus *dbusdao.Dao
dyn *dyndao.Dao
res *resdao.Dao
// artic *articledao.Dao
client *httpx.Client
rg *regiondao.Dao
cdao *carddao.Dao
act *actdao.Dao
acc *accdao.Dao
// relation
reldao *reldao.Dao
loc *locdao.Dao
tick time.Duration
rcmmndCache []*show.Item
rcmmndOseaCache []*show.Item
regionCache map[string][]*show.Item
regionOseaCache map[string][]*show.Item
regionBgCache map[string][]*show.Item
regionBgOseaCache map[string][]*show.Item
regionBgEpCache map[string][]*show.Item
regionBgEpOseaCache map[string][]*show.Item
bgmCache map[int8][]*show.Item
liveCount int
liveMoeCache []*show.Item // TODO change to liveMoeCache
liveHotCache []*show.Item // TODO change to liveHotCache
bannerCache map[int8]map[int][]*resource.Banner
cache map[string][]*show.Show
cacheBg map[string][]*show.Show
cacheBgEp map[string][]*show.Show
tempCache map[string][]*show.Show
auditCache map[string]map[int]struct{} // audit mobi_app builds
blackCache map[int64]struct{} // black aids
logCh chan infoc
logFeedCh chan interface{}
rcmmndCh chan recommend
logPath string
// loadfile
jsonOn bool
// cpm percentage 0~100
cpmNum int
cpmMid map[int64]struct{}
cpmAll bool
cpmRcmmndNum int
cpmRcmmndMid map[int64]struct{}
cpmRcmmndAll bool
adIsPost bool
// recommend api
rcmmndOn bool
rcmmndGroup map[int64]int // mid -> group
rcmmndHosts map[int][]string // group -> hosts
// region
reRegionCache map[int]*region.Region
// ranking
rankCache []*show.Item
rankOseaCache []*show.Item
// card
cardCache map[string][]*show.Show
columnListCache map[int]*card.ColumnList
cardSetCache map[int64]*operate.CardSet
eventTopicCache map[int64]*operate.EventTopic
// hot card
hotTenTabCardCache map[int][]*recmod.CardList
rankAidsCache []int64
rankScoreCache map[int64]int64
rankArchivesCache map[int64]*api.Arc
// hotCache []*card.PopularCard
rcmdCache []*card.PopularCard
hottopicsCache []*clive.TopicHot
rankCache2 []*rank.Rank
dynamicHotCache []*clive.DynamicHot
// prom
pHit *prom.Prom
pMiss *prom.Prom
}
// New new a show service.
func New(c *conf.Config) (s *Service) {
rcmmndHosts := make(map[int][]string, len(c.Recommend.Host))
for k, v := range c.Recommend.Host {
key, err := strconv.Atoi(k)
if err != nil {
continue
}
rcmmndHosts[key] = v
}
rcmmndGroup := make(map[int64]int, len(c.Recommend.Group))
for k, v := range c.Recommend.Group {
key, err := strconv.Atoi(k)
if err != nil {
continue
}
rcmmndGroup[int64(key)] = v
}
s = &Service{
c: c,
dao: showdao.New(c),
rcmmnd: rcmmdao.New(c),
ad: addao.New(c),
bgm: bgmdao.New(c),
lv: livedao.New(c),
// bnnr: bnnrdao.New(c),
adt: adtdao.New(c),
tag: tagdao.New(c),
arc: arcdao.New(c),
dbus: dbusdao.New(c),
dyn: dyndao.New(c),
res: resdao.New(c),
// artic: articledao.New(c),
rg: regiondao.New(c),
cdao: carddao.New(c),
act: actdao.New(c),
acc: accdao.New(c),
// relation
reldao: reldao.New(c),
loc: locdao.New(c),
client: httpx.NewClient(c.HTTPData),
tick: time.Duration(c.Tick),
jsonOn: false,
logCh: make(chan infoc, 1024),
logFeedCh: make(chan interface{}, 1024),
rcmmndCh: make(chan recommend, 1024),
logPath: c.ShowLog,
rcmmndOn: false,
rcmmndGroup: rcmmndGroup,
rcmmndHosts: rcmmndHosts,
// cpm percentage 0~100
cpmNum: 0,
cpmMid: map[int64]struct{}{},
cpmAll: true,
cpmRcmmndNum: 0,
cpmRcmmndMid: map[int64]struct{}{},
cpmRcmmndAll: true,
adIsPost: false,
// region
reRegionCache: map[int]*region.Region{},
// ranking
rankCache: []*show.Item{},
rankOseaCache: []*show.Item{},
//card
cardCache: map[string][]*show.Show{},
columnListCache: map[int]*card.ColumnList{},
cardSetCache: map[int64]*operate.CardSet{},
eventTopicCache: map[int64]*operate.EventTopic{},
// hot card
hotTenTabCardCache: make(map[int][]*recmod.CardList),
rankAidsCache: []int64{},
rankScoreCache: map[int64]int64{},
rankArchivesCache: map[int64]*api.Arc{},
// hotCache: []*card.PopularCard{},
rcmdCache: []*card.PopularCard{},
hottopicsCache: []*clive.TopicHot{},
rankCache2: []*rank.Rank{},
dynamicHotCache: []*clive.DynamicHot{},
// prom
pHit: prom.CacheHit,
pMiss: prom.CacheMiss,
}
var err error
if s.creativeClient, err = creativeAPI.NewClient(nil); err != nil {
panic("creativeGRPC not found!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
}
now := time.Now()
s.loadCache(now)
go s.cacheproc()
go s.infocproc()
go s.rcmmndproc()
go s.infocfeedproc()
return s
}
// cacheproc load all cache.
func (s *Service) cacheproc() {
for {
time.Sleep(s.tick)
now := time.Now()
s.loadCache(now)
}
}
func (s *Service) loadCache(now time.Time) {
s.loadRcmmndCache(now)
s.loadRegionCache(now)
s.loadBgmCache(now)
s.loadLiveCache(now)
s.loadBannerCahce()
s.loadShowCache()
s.loadShowTempCache()
s.loadBlackCache()
s.loadAuditCache()
s.loadRegionListCache()
s.loadRankAllCache()
s.loadColumnListCache(now)
s.loadCardCache(now)
s.loadCardSetCache()
// hot
// s.loadPopularCard(now)
s.loadHotTenTabAids()
s.loadHotTopicCache()
for i := 0; i < 10; i++ {
s.loadHotTenMergeRcmdCache(i)
}
s.loadDynamicHotCache()
s.loadEventTopicCache()
}
// SetRcmmndOn
func (s *Service) SetRcmmndOn(on bool) {
s.rcmmndOn = on
}
// GetRcmmndOn
func (s *Service) RcmmndOn() bool {
return s.rcmmndOn
}
// Close dao
func (s *Service) Close() error {
return s.dao.Close()
}
// SetRcmmndGroup set rcmmnd group data.
func (s *Service) SetRcmmndGroup(m int64, g int) {
tmp := map[int64]int{}
tmp[m] = g
for k, v := range s.rcmmndGroup {
if k != m {
tmp[k] = v
}
}
s.rcmmndGroup = tmp
}
// GetRcmmndGroup get rcmmnd group data.
func (s *Service) GetRcmmndGroup() map[string]int {
tmp := map[string]int{}
for k, v := range s.rcmmndGroup {
tmp[strconv.FormatInt(k, 10)] = v
}
return tmp
}
// SetRcmmndHost set rcmmnd host data.
func (s *Service) SetRcmmndHost(g int, hosts []string) {
tmp := map[int][]string{}
tmp[g] = hosts
for k, v := range s.rcmmndHosts {
if k != g {
tmp[k] = v
}
}
s.rcmmndHosts = tmp
}
// GetRcmmndHost get rcmmnd host data.
func (s *Service) GetRcmmndHost() map[string][]string {
tmp := map[string][]string{}
for k, v := range s.rcmmndHosts {
tmp[strconv.Itoa(k)] = v
}
return tmp
}
// SetCpm percentage 0~100
func (s *Service) SetCpmNum(num int) {
s.cpmNum = num
if s.cpmNum < 0 {
s.cpmNum = 0
} else if s.cpmNum > 100 {
s.cpmNum = 100
}
}
// GetCpm percentage
func (s *Service) CpmNum() int {
return s.cpmNum
}
// SetCpm percentage 0~100
func (s *Service) SetCpmMid(mid int64) {
var mids = map[int64]struct{}{}
mids[mid] = struct{}{}
for mid, _ := range s.cpmMid {
if _, ok := mids[mid]; !ok {
mids[mid] = struct{}{}
}
}
s.cpmMid = mids
}
// GetCpm percentage
func (s *Service) CpmMid() []int {
var mids []int
for mid, _ := range s.cpmMid {
mids = append(mids, int(mid))
}
return mids
}
// SetCpm All
func (s *Service) SetCpmAll(isAll bool) {
s.cpmAll = isAll
}
// GetCpm All
func (s *Service) CpmAll() int {
if s.cpmAll {
return 1
}
return 0
}
// RcmmndNum percentage
func (s *Service) RcmmndNum() int {
return s.cpmRcmmndNum
}
// SetRcmmndNum percentage 0~100
func (s *Service) SetRcmmndNum(num int) {
s.cpmRcmmndNum = num
if s.cpmRcmmndNum < 0 {
s.cpmRcmmndNum = 0
} else if s.cpmRcmmndNum > 100 {
s.cpmRcmmndNum = 100
}
}
// CpmRcmmndMid Mid
func (s *Service) CpmRcmmndMid() []int {
var mids []int
for mid, _ := range s.cpmRcmmndMid {
mids = append(mids, int(mid))
}
return mids
}
// SetCpmRcmmndMid Mid
func (s *Service) SetCpmRcmmndMid(mid int64) {
var mids = map[int64]struct{}{}
mids[mid] = struct{}{}
for mid, _ := range s.cpmRcmmndMid {
if _, ok := mids[mid]; !ok {
mids[mid] = struct{}{}
}
}
s.cpmRcmmndMid = mids
}
// CpmRcmmnd All
func (s *Service) CpmRcmmndAll() int {
if s.cpmRcmmndAll {
return 1
}
return 0
}
// SetCpmRcmmnd All
func (s *Service) SetCpmRcmmndAll(isAll bool) {
s.cpmRcmmndAll = isAll
}
// SetIsPost Get or Post
func (s *Service) SetAdIsPost(isPost bool) {
s.adIsPost = isPost
}
// IsPost Get or Post
func (s *Service) AdIsPost() int {
if s.adIsPost {
return 1
}
return 0
}

View File

@@ -0,0 +1,918 @@
package show
import (
"context"
"fmt"
"math/rand"
"net/url"
"strconv"
"time"
"go-common/app/interface/main/app-show/conf"
"go-common/app/interface/main/app-show/model"
"go-common/app/interface/main/app-show/model/show"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
resource "go-common/app/service/main/resource/model"
seasongrpc "go-common/app/service/openplatform/pgc-season/api/grpc/season/v1"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const (
_cnt = 4
_initShowKey = "show_key_%d_%v"
_initCardKey = "card_key_%d"
_initlanguage = "hans"
_bangumiSeasonID = 1
_bangumiEpisodeID = 2
)
var (
_emptyShow = []*show.Show{}
_emptyItem = &show.Item{}
_emptyShowItems = []*show.Item{}
// ad
_recommend = map[int8]string{
model.PlatIPhone: "1508",
model.PlatAndroid: "1515",
model.PlatIPad: "1522",
model.PlatIPhoneI: "1529",
model.PlatAndroidG: "1543",
model.PlatAndroidI: "1777",
model.PlatIPadI: "1536",
}
_bangumiReids = map[int]struct{}{
167: struct{}{},
}
)
// Display display show data.
func (s *Service) Display(c context.Context, mid int64, plat int8, build int, buvid, channel, ip, ak, network, mobiApp,
device, language, adExtra string, isTmp bool, now time.Time) (res []*show.Show) {
res = s.showDisplay(c, mid, plat, build, buvid, channel, ip, ak, network, mobiApp, device, language, adExtra, isTmp, false, false, now)
return
}
// RegionDisplay display region show data.
func (s *Service) RegionDisplay(c context.Context, mid int64, plat int8, build int, buvid, channel, ip, ak, network, mobiApp,
device, language, adExtra string, isTmp bool, now time.Time) (res []*show.Show) {
res = s.showDisplay(c, mid, plat, build, buvid, channel, ip, ak, network, mobiApp, device, language, adExtra, isTmp, true, false, now)
return
}
func (s *Service) Index(c context.Context, mid int64, plat int8, build int, buvid, channel, ip, ak, network, mobiApp,
device, language, adExtra string, isTmp bool, now time.Time) (res []*show.Show) {
res = s.showDisplay(c, mid, plat, build, buvid, channel, ip, ak, network, mobiApp, device, language, adExtra, isTmp, true, true, now)
if cards := s.showCardDisplay(plat, build); len(cards) > 0 {
cards = append(cards, res...)
res = cards
}
return
}
// Display display show data.
func (s *Service) showDisplay(c context.Context, mid int64, plat int8, build int, buvid, channel, ip, ak, network, mobiApp,
device, language, adExtra string, isTmp, isRegion, isIndex bool, now time.Time) (res []*show.Show) {
var (
bnr string
banners map[int][]*resource.Banner
showRec []*show.Item
showLive []*show.Item
isBangumi = false
isRegionBanner = false
ss []*show.Show
resIDStr = _bannersPlat[plat]
)
if language == "" {
language = _initlanguage
}
key := fmt.Sprintf(_initShowKey, plat, language)
if (plat == model.PlatIPhone && build > 6050) || (plat == model.PlatAndroid && build > 512007) {
ss = s.cacheBgEp[key]
} else if ((mobiApp == "iphone" && build > 5600) || (mobiApp == "android" && build > 507000)) && isIndex {
ss = s.cacheBg[key]
} else {
ss = s.cache[key]
}
if isTmp {
ss = s.tempCache[key]
}
if len(ss) == 0 {
res = _emptyShow
return
}
res = make([]*show.Show, 0, len(ss))
if (mobiApp == "iphone" && build > 4310) || (mobiApp == "android" && build > 502000) || isIndex {
isBangumi = true
}
if (mobiApp == "iphone" && build > 4350) || (mobiApp == "android" && build > 503000) {
isRegionBanner = true
}
g, ctx := errgroup.WithContext(c)
g.Go(func() error {
banners = s.resBanners(ctx, plat, build, mid, resIDStr, channel, ip, buvid, network, mobiApp, device, adExtra)
return nil
})
if !isRegion {
g.Go(func() error {
showRec = s.getRecommend(ctx, mid, build, plat, buvid, network, mobiApp, device, ip)
return nil
})
g.Go(func() error {
showLive = s.getLive(ctx, mid, ak, ip, 0, now)
return nil
})
}
if err := g.Wait(); err != nil {
log.Error("showDisplay errgroup.WithContext error(%v)", err)
}
for i, sw := range ss {
if mobiApp == "white" && 101220 >= build && sw.Param == "165" { // 165 ad region
continue
} else if sw.Param != "165" || ((mobiApp != "iphone" || device != "pad") || build <= 3590) {
if model.InvalidBuild(build, sw.Build, sw.Condition) {
continue
}
}
if sw.Type == "recommend" {
if isRegion {
continue
}
sw = s.dealRecommend(c, sw, plat, mid, build, buvid, network, mobiApp, device, ip, showRec)
bnr = "0"
} else if sw.Type == "live" {
if isRegion {
continue
}
sw = s.dealLive(c, sw, showLive)
bnr = "65537"
} else if sw.Type == "bangumi" {
if ok := s.auditRegion(mobiApp, plat, build, "13"); ok {
continue
}
if isRegion && isBangumi && !isRegionBanner {
bnr = "-1"
} else if isRegion && !isBangumi && !isRegionBanner {
continue
} else {
bnr = "13"
}
} else {
bnr = sw.Param
if isRegion {
if ok := s.auditRegion(mobiApp, plat, build, sw.Param); ok {
continue
}
if !isRegionBanner {
if sw.Param == "1" && !isBangumi {
bnr = "-1"
}
if sw.Type == "topic" && i > 0 && (ss[i-1].Type == "bangumi" || ss[i-1].Type == "1") {
continue
}
}
}
}
sw.Banner = s.getBanners(c, plat, build, bnr, channel, ip, banners, isIndex)
res = append(res, sw)
}
return
}
// showCardDisplay
func (s *Service) showCardDisplay(plat int8, build int) (res []*show.Show) {
var ss []*show.Show
key := fmt.Sprintf(_initCardKey, plat)
ss = s.cardCache[key]
if len(ss) == 0 {
res = _emptyShow
return
}
res = []*show.Show{}
for _, sw := range ss {
if model.InvalidBuild(build, sw.Build, sw.Condition) {
continue
}
tmp := &show.Show{}
*tmp = *sw
tmp.FillBuildURI(plat, build)
res = append(res, tmp)
}
return
}
// Change change display show data.
func (s *Service) Change(c context.Context, mid int64, build int, plat int8, rand int, buvid, ip, network, mobiApp, device string) (sis []*show.Item) {
cnt := s.itemNum(plat)
// first get recommend data.
tmp := s.userRecommend(c, mid, build, plat, buvid, network, mobiApp, device, ip, cnt)
if len(tmp) == cnt {
sis = append(sis, tmp...)
}
if len(sis) < cnt {
start := cnt * rand
end := start + cnt
rcLen := len(s.rcmmndCache)
if rcLen < end {
rand = 0
start = cnt * rand
end = start + cnt
}
if rcLen > end {
sis = s.rcmmndCache[start:end]
}
}
return
}
// RegionChange change show region data.
func (s *Service) RegionChange(c context.Context, rid, rand int, plat int8, build int, mobiApp string) (sis []*show.Item) {
if rand < 0 {
rand = 0
}
var (
cnt = 4
pn = rand + 1
isOsea = model.IsOverseas(plat)
bangumiType = 0
tmp []*show.Item
)
if (mobiApp == "iphone" && build > 5600) || (mobiApp == "android" && build > 507000) {
if _, isBangumi := _bangumiReids[rid]; isBangumi {
if (plat == model.PlatIPhone && build > 6050) || (plat == model.PlatAndroid && build > 512007) {
bangumiType = _bangumiEpisodeID
} else {
bangumiType = _bangumiSeasonID
}
}
}
if model.IsIPad(plat) {
cnt = 8
}
as, aids, err := s.dyn.RegionDynamic(c, rid, pn, cnt)
if err != nil {
log.Error("s.rcmmnd.RegionDynamic(%d, %d, %d) error(%v)", rid, pn, cnt, err)
sis = []*show.Item{}
return
}
if bangumiType != 0 {
tmp = s.fromArchivesBangumiOsea(c, as, aids, isOsea, bangumiType)
} else {
tmp = s.fromArchivesOsea(as, isOsea)
}
sis = append(sis, tmp...)
return
}
// BangumiChange change show bangumi data.
func (s *Service) BangumiChange(c context.Context, rand int, plat int8) (sis []*show.Item) {
if rand < 0 {
rand = 0
}
rand = rand + 1
var (
cnt = 4
)
if model.IsIPad(plat) {
cnt = 8
}
start := cnt * rand
end := start + cnt
if bgms, ok := s.bgmCache[plat]; ok {
bcLen := len(bgms)
if bcLen < end {
rand = 0
start = cnt * rand
end = start + cnt
}
if bcLen > end {
sis = bgms[start:end]
}
}
return
}
// Dislike dislike show data
func (s *Service) Dislike(c context.Context, mid int64, plat int8, id int64, buvid, mobiApp, device, gt, ip string) (si *show.Item) {
var (
cnt = 1
changeAid string
port string
)
// first get recommend data.
tmp := s.userRecommend(c, mid, 0, plat, buvid, "", mobiApp, device, ip, cnt)
if len(tmp) > 0 {
si = tmp[0]
port = "userRecommend"
} else {
si = s.rcmmndCache[0]
port = "loadRcmmndCache"
}
if si != nil {
changeAid = si.Param
}
if err := s.dbus.Pub(c, buvid, gt, id, mid); err != nil {
log.Error("s.dbus.Pub(%s,%s,%d,%d) error(%v)", buvid, gt, id, mid, err)
log.Error("dbus_Pub_dislike error mid:%v , dislike_aid:%v , change_aid:%v , interface_name:%v", mid, id, changeAid, port)
return
}
log.Info("dbus_Pub_dislike success mid:%v , dislike_aid:%v , change_aid:%v , interface_name:%v", mid, id, changeAid, port)
return
}
// Widget
func (s *Service) Widget(c context.Context, plat int8) (res []*show.Item) {
var (
isOsea = model.IsOverseas(plat) //is overseas
resCache []*show.Item
randID int
)
if isOsea {
resCache = s.rcmmndOseaCache
} else {
resCache = s.rcmmndCache
}
resCacheLen := len(resCache)
if resCacheLen >= 3 {
for {
if len(res) >= 3 || len(resCache) == 0 {
log.Info("Widget len 3")
break
}
if randInt := rand.Intn(resCacheLen); randInt != randID && resCache[randInt] != nil {
randID = randInt
res = append(res, resCache[randInt])
}
}
} else if resCacheLen > 0 {
log.Info("Widget resCache")
res = resCache
} else {
log.Info("Widget is null")
res = _emptyShowItems
}
return
}
// LiveChange live change.
func (s *Service) LiveChange(c context.Context, mid int64, ak, ip string, rand int, now time.Time) (sis []*show.Item) {
return s.getLive(c, mid, ak, ip, rand, now)
}
// dealRecommend deal recommend.
func (s *Service) dealRecommend(c context.Context, sw *show.Show, plat int8, mid int64, build int, buvid, network, mobiApp, device, ipaddr string, showRec []*show.Item) (rs *show.Show) {
cnt := s.itemNum(plat)
sis := make([]*show.Item, 0, cnt)
// first get recommend data.
if len(showRec) == cnt {
sis = append(sis, showRec...)
}
// if recommend data not enough, get from @hetongzi.
if len(sis) < cnt {
rcLen := len(s.rcmmndCache)
if rcLen < cnt {
sis = s.rcmmndCache[0:rcLen]
} else {
sis = s.rcmmndCache[0:cnt]
}
if rcLen > 0 {
sis = s.adVideo(c, mid, build, plat, buvid, network, mobiApp, device, ipaddr, sis)
}
}
if len(sis) == 0 {
sis = []*show.Item{}
}
rs = &show.Show{
Head: sw.Head,
Body: sis,
}
return
}
// getRecommend user recommend data
func (s *Service) getRecommend(c context.Context, mid int64, build int, plat int8, buvid, network, mobiApp, device, ipaddr string) (sis []*show.Item) {
cnt := s.itemNum(plat)
// first get recommend data.
sis = s.userRecommend(c, mid, build, plat, buvid, network, mobiApp, device, ipaddr, cnt)
return
}
// userRecommend user recommend data.
func (s *Service) userRecommend(ctx context.Context, mid int64, build int, plat int8, buvid, network, mobiApp, device, ipaddr string, cnt int) (sis []*show.Item) {
// get redis seed whether or not hit
if !s.rcmmndOn {
return
}
var (
key = buvid
i int
aids []int64
rcs []*rcmmndCfg
err error
)
if mid > 0 {
key = strconv.FormatInt(mid, 10)
}
if key == "" {
return
}
Retry:
for i = 0; i < 2; i++ {
if aids, err = s.dao.PopRcmmndCache(ctx, key, cnt); err != nil {
log.Error("s.dao.PopRcmmndCache(%d) error(%v)", key, err)
return
}
if len(aids) < cnt {
break
}
for _, aid := range aids {
if _, ok := s.blackCache[aid]; ok {
continue Retry
}
}
var isOsea = model.IsOverseas(plat)
if sis = s.fromAidsOsea(ctx, aids, isOsea); len(sis) < cnt {
log.Warn("recommend aids(%v) get from archive have not normal(%v)", aids, sis)
continue Retry
}
return
}
// if i==2, mean retry two counts, else if i<2, means break and recommend not enough.
if i == 2 {
return
}
if host := s.rcmmndHost(mid); host != "" {
rcs, aids = s.apiRecommend(ctx, plat, key, host, mid)
}
var (
clen = len(rcs)
caids = make([]int64, 0, cnt)
fill = cnt - clen
)
if clen+len(aids) < cnt {
return
}
if cnt < clen {
fill = 0
}
for _, rc := range rcs {
if rc.Goto == "" || rc.Goto == model.GotoAv {
caids = append(caids, rc.Aid)
if len(caids) == cnt {
break
}
}
}
if fill > 0 {
caids = append(caids, aids[:fill]...)
}
if aids = aids[fill:]; len(aids) >= cnt {
select {
case s.rcmmndCh <- recommend{key: key, aids: aids[fill:]}:
default:
log.Warn("recommendProc chan full")
}
}
var isOsea = model.IsOverseas(plat) //is overseas
if sis = s.fromAidsOsea(ctx, caids, isOsea); len(sis) < clen { // NOTE: if cnt=1 means dislike change one
for {
var (
over = cnt - len(sis)
start = 0
)
if over == 0 || start+over > len(aids) {
break
}
if tmp := s.fromAidsOsea(ctx, aids[start:over], isOsea); len(tmp) > 0 {
sis = append(sis, tmp...)
}
}
return
}
for i, rc := range rcs {
if rc.Goto != "" && rc.Goto != model.GotoAv {
sis[i].Param = strconv.FormatInt(rc.Aid, 10)
sis[i].Goto = rc.Goto
sis[i].URI = model.FillURI(rc.Goto, sis[i].Param, nil)
}
if rc.Title != "" {
sis[i].Title = rc.Title
}
if rc.Cover != "" {
sis[i].Cover = rc.Cover
}
}
sis = s.adVideo(ctx, mid, build, plat, buvid, network, mobiApp, device, ipaddr, sis)
return
}
// rcmmndHost get recommend host
func (s *Service) rcmmndHost(mid int64) (host string) {
// if mid=0, let host is 1: base recommend
yu := mid % 20
g := s.rcmmndGroup[yu]
if hosts, ok := s.rcmmndHosts[g]; ok {
if len(hosts) == 1 {
host = hosts[0]
} else {
host = hosts[rand.Intn(len(hosts))]
}
}
return
}
// apiRecommend get recommend fron big data.
func (s *Service) apiRecommend(ctx context.Context, plat int8, key, host string, mid int64) (rcs []*rcmmndCfg, aids []int64) {
var (
uri string
recURL = conf.Conf.Host.Data + "/mobile/home/%s"
)
uri = fmt.Sprintf(recURL, key)
params := url.Values{}
params.Set("plat", strconv.Itoa(int(plat)))
params.Set("v2", "1")
var res struct {
Code int `json:"code"`
Data []int64 `json:"data"`
Configs []*rcmmndCfg `json:"config"`
}
if err := s.client.Post(ctx, uri, "", params, &res); err != nil {
log.Error("recommend url(%s) error(%v)", uri+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("url(%s) res code(%d) or res.result(%v,%v)", uri, res.Code, res.Data, res.Configs)
return
}
aids = res.Data
rcs = res.Configs
return
}
// itemNum get item number by plat.
func (s *Service) itemNum(plat int8) int {
// cnt is items number
cnt := 6
if plat == model.PlatAndroid || plat == model.PlatAndroidI || plat == model.PlatAndroidG {
cnt = 4
} else if plat == model.PlatIPad || plat == model.PlatIPadI {
cnt = 8
} else if plat == model.PlatAndroidTV {
cnt = 16
}
return cnt
}
// dealLive dela live data
func (s *Service) dealLive(c context.Context, sw *show.Show, sis []*show.Item) (rs *show.Show) {
rs = &show.Show{
Head: sw.Head,
Body: sis,
Ext: sw.Ext,
}
return
}
// getLive get lives: feed, moe, hot.
func (s *Service) getLive(c context.Context, mid int64, ak, ip string, rand int, now time.Time) (sis []*show.Item) {
const (
_halfCnt = 2
)
sis = make([]*show.Item, _cnt) // _cnt=4 [0,1,2,3]: 0 1 feed and hot, 2 3 moe and hot
feed, err := s.lv.Feed(c, mid, ak, ip, now)
if err != nil {
log.Error("s.live.Feed(%d) error(%d)", mid, err)
}
var have int
// get two feed
if feed != nil {
for i := 0; i < _halfCnt && i < len(feed.Lives); i++ {
si := &show.Item{}
si.FromLive(feed.Lives[i])
sis[i] = si
have++
}
}
// get two moe
fdCnt := have
start := _halfCnt * rand
if len(s.liveMoeCache) < start+_halfCnt {
start = 0
}
index := _halfCnt
MOENEXT:
for _, l := range s.liveMoeCache[start:] {
for i := 0; i < fdCnt; i++ {
if sis[i].Param == l.Param {
continue MOENEXT
}
}
sis[index] = l
index++
have++
if index >= _cnt {
break
}
}
// if feed and moe not enough, get hot
yu := _cnt - have
if yu > 0 {
start := yu * rand
if len(s.liveHotCache) < start+yu {
start = 0
}
var nilI int
HOTNEXT:
for _, l := range s.liveHotCache[start:] {
nilI = -1
for i := len(sis) - 1; i >= 0; i-- {
if sis[i] == nil {
nilI = i
} else if sis[i].Param == l.Param {
continue HOTNEXT
}
}
if nilI != -1 {
sis[nilI] = l
have++
} else {
return
}
}
}
if have < _cnt {
for k, v := range sis {
if v == nil {
sis[k] = _emptyItem
}
}
}
return
}
// fromArchives return region show items from archive archives.
func (s *Service) fromArchivesPB(as []*api.Arc) (sis, sisOsea []*show.Item) {
var asLen = len(as)
if asLen == 0 {
sis = []*show.Item{}
return
}
sis = make([]*show.Item, 0, asLen)
for _, a := range as {
i := &show.Item{}
i.FromArchivePB(a)
if a.AttrVal(archive.AttrBitOverseaLock) == 0 {
sisOsea = append(sisOsea, i)
}
sis = append(sis, i)
}
return
}
// fromArchivesBangumi aid to sid
func (s *Service) fromArchivesBangumi(c context.Context, as []*api.Arc, aids []int64, sids map[int32]*seasongrpc.CardInfoProto, bangumiType int) (sis, sisOsea []*show.Item) {
var (
asLen = len(as)
err error
// bangumi
)
if asLen == 0 {
sis = []*show.Item{}
return
}
if sids == nil {
if sids, err = s.fromSeasonID(c, aids); err != nil {
log.Error("s.fromSeasonID error(%v)", err)
return
}
}
sis = make([]*show.Item, 0, asLen)
for _, a := range as {
i := &show.Item{}
if sid, ok := sids[int32(a.Aid)]; ok && sid.SeasonId != 0 {
i.FromArchivePBBangumi(a, sid, bangumiType)
} else {
i.FromArchivePB(a)
}
sis = append(sis, i)
if a.AttrVal(archive.AttrBitOverseaLock) == 0 {
sisOsea = append(sisOsea, i)
}
}
return
}
// fromArchivesOsea isOverseas
func (s *Service) fromArchivesOsea(as []*api.Arc, isOsea bool) (sis []*show.Item) {
tmp, tmpOsea := s.fromArchivesPB(as)
if isOsea {
sis = tmpOsea
} else {
sis = tmp
}
return
}
// fromArchivesOsea isOverseas
func (s *Service) fromArchivesBangumiOsea(c context.Context, as []*api.Arc, aids []int64, isOsea bool, bangumiType int) (sis []*show.Item) {
tmp, tmpOsea := s.fromArchivesBangumi(c, as, aids, nil, bangumiType)
if isOsea {
sis = tmpOsea
} else {
sis = tmp
}
return
}
// fromAids get Aids.
func (s *Service) fromAids(ctx context.Context, aids []int64) (sis, sisOsea []*show.Item) {
as, err := s.arc.ArchivesPB(ctx, aids)
if err != nil {
log.Error("s.arc.ArchivesPB aids(%v) error(%v)", aids, err)
return
}
if len(as) == 0 {
log.Warn("s.arc.ArchivesPB(%v) length is 0", aids)
return
}
sis = make([]*show.Item, 0, len(aids))
for _, aid := range aids {
var isOverseas int32
si := &show.Item{}
si.Goto = model.GotoAv
si.Param = strconv.FormatInt(aid, 10)
si.URI = model.FillURI(si.Goto, si.Param, nil)
if v, ok := as[aid]; ok {
isOverseas = v.AttrVal(archive.AttrBitOverseaLock)
si.Danmaku = int(v.Stat.Danmaku)
si.Play = int(v.Stat.View)
si.Title = v.Title
si.Duration = v.Duration
si.Rname = v.TypeName
si.Name = v.Author.Name
si.Like = int(v.Stat.Like)
si.Cover = model.CoverURL(v.Pic)
}
if isOverseas == 0 {
sisOsea = append(sisOsea, si)
}
sis = append(sis, si)
}
return
}
// fromCardAids get Aids.
func (s *Service) fromCardAids(ctx context.Context, aids []int64) (sis map[int64]*show.Item) {
as, err := s.arc.ArchivesPB(ctx, aids)
if err != nil {
log.Error("s.arc.ArchivesPB aids(%v) error(%v)", aids, err)
return
}
if len(as) == 0 {
log.Warn("s.arc.ArchivesPB(%v) length is 0", aids)
return
}
sis = map[int64]*show.Item{}
for _, aid := range aids {
si := &show.Item{}
si.Goto = model.GotoAv
si.Param = strconv.FormatInt(aid, 10)
si.URI = model.FillURI(si.Goto, si.Param, nil)
if v, ok := as[aid]; ok {
if !v.IsNormal() {
continue
}
si.Danmaku = int(v.Stat.Danmaku)
si.Play = int(v.Stat.View)
si.Title = v.Title
si.Duration = v.Duration
if region, ok := s.reRegionCache[int(v.TypeID)]; ok {
si.Desc = region.Name
si.Reid = region.Rid
}
si.Rid = int(v.TypeID)
si.Rname = v.TypeName
si.Name = v.Author.Name
si.Like = int(v.Stat.Like)
si.Cover = model.CoverURL(v.Pic)
}
sis[aid] = si
}
return
}
// fromRankAids
func (s *Service) fromRankAids(ctx context.Context, aids []int64, scores map[int64]int64, as map[int64]*api.Arc) (sis, sisOsea []*show.Item) {
var (
aid int64
arc *api.Arc
ok bool
)
for _, aid = range aids {
if arc, ok = as[aid]; ok {
i := &show.Item{}
if region, ok := s.reRegionCache[int(arc.TypeID)]; ok {
i.Desc = region.Name
}
i.FromArchiveRank(arc, scores)
if arc.AttrVal(archive.AttrBitOverseaLock) == 0 {
sisOsea = append(sisOsea, i)
}
sis = append(sis, i)
}
}
return
}
// fromAids get Aids.
func (s *Service) fromBgAids(ctx context.Context, aids []int64, sids map[int32]*seasongrpc.CardInfoProto, bangumiType int) (sis, sisOsea, sisbg, sisbgOsea, sisbgep, sisbgepOsea []*show.Item) {
var (
err error
)
as, err := s.arc.ArchivesPB(ctx, aids)
if err != nil {
log.Error("s.arc.ArchivesPB aids(%v) error(%v)", aids, err)
return
}
if len(as) == 0 {
log.Warn("s.arc.ArchivesPB(%v) length is 0", aids)
return
}
sis = make([]*show.Item, 0, len(aids))
if sids == nil {
if sids, err = s.fromSeasonID(ctx, aids); err != nil {
log.Error("s.fromSeasonID error(%v)", err)
return
}
}
for _, aid := range aids {
var isOverseas int32
si := &show.Item{}
sibg := &show.Item{}
sibgep := &show.Item{}
if v, ok := as[aid]; ok {
isOverseas = v.AttrVal(archive.AttrBitOverseaLock)
if sid, ok := sids[int32(aid)]; ok && sid.SeasonId != 0 {
sibg.FromArchivePBBangumi(v, sid, _bangumiSeasonID)
sibgep.FromArchivePBBangumi(v, sid, _bangumiEpisodeID)
} else {
sibg.FromArchivePB(v)
sibgep.FromArchivePB(v)
}
si.FromArchivePB(v)
if isOverseas == 0 {
sisOsea = append(sisOsea, si)
sisbgOsea = append(sisbgOsea, sibg)
sisbgepOsea = append(sisbgepOsea, sibg)
}
sis = append(sis, si)
sisbg = append(sisbg, sibg)
sisbgep = append(sisbgep, sibgep)
}
}
return
}
// fromSeasonID
func (s *Service) fromSeasonID(c context.Context, arcAids []int64) (seasonID map[int32]*seasongrpc.CardInfoProto, err error) {
if seasonID, err = s.bgm.CardsByAids(c, arcAids); err != nil {
log.Error("s.bgm.Seasonid CardsByAids %v", err)
}
return
}
// isOverseas
func (s *Service) fromAidsOsea(ctx context.Context, aids []int64, isOsea bool) (sis []*show.Item) {
tmp, tmpOsea := s.fromAids(ctx, aids)
if isOsea {
sis = tmpOsea
} else {
sis = tmp
}
return
}
// adVideo
func (s *Service) adVideo(ctx context.Context, mid int64, build int, plat int8, buvid, network, mobiApp, device, ipaddr string, sis []*show.Item) (res []*show.Item) {
var cpmsis map[int]*show.Item
if resID, ok := _recommend[plat]; ok {
cpmsis = s.cpmRecommend(ctx, mid, build, buvid, resID, network, mobiApp, device, ipaddr)
}
for rank, ad := range cpmsis {
if len(sis) >= rank {
if ad.IsAdReplace {
sis[rank-1] = ad
} else {
sis[rank-1].IsAdLoc = true
sis[rank-1].IsAd = ad.IsAd
sis[rank-1].CmMark = ad.CmMark
sis[rank-1].SrcId = ad.SrcId
sis[rank-1].RequestId = ad.RequestId
sis[rank-1].ClientIp = ad.ClientIp
}
}
}
res = sis
return
}

View File

@@ -0,0 +1,66 @@
package show
import (
"context"
"flag"
"go-common/app/interface/main/app-show/conf"
"go-common/app/interface/main/app-show/model"
"path/filepath"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-show-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestIndex(t *testing.T) {
Convey("get Index data", t, WithService(func(s *Service) {
res := s.Index(context.TODO(), 0, model.PlatIPhone, 0, "", "", "", "", "", "iphone", "phone", _initlanguage, "", false, time.Now())
So(res, ShouldNotBeEmpty)
}))
}
func TestChange(t *testing.T) {
Convey("get Change data", t, WithService(func(s *Service) {
res := s.Change(context.TODO(), 1, 1, 1, 1, "", "", "", "", "")
So(res, ShouldNotBeEmpty)
}))
}
func TestRegionChange(t *testing.T) {
Convey("get RegionChange data", t, WithService(func(s *Service) {
res := s.RegionChange(context.TODO(), 1, 1, 1, 1, "")
So(res, ShouldNotBeEmpty)
}))
}
func TestBangumiChange(t *testing.T) {
Convey("get BangumiChange data", t, WithService(func(s *Service) {
res := s.BangumiChange(context.TODO(), 1, 1)
So(res, ShouldNotBeEmpty)
}))
}
func TestFeedIndex(t *testing.T) {
Convey("get FeedIndex data", t, WithService(func(s *Service) {
res := s.FeedIndex(context.TODO(), 1, 1, 1, 1, 1, "", "", "", "", time.Now())
So(res, ShouldNotBeEmpty)
}))
}