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,131 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"account_test.go",
"archive_test.go",
"article_test.go",
"coin_test.go",
"dynamic_test.go",
"elec_test.go",
"feedback_test.go",
"help_test.go",
"icon_test.go",
"ip_test.go",
"nav_test.go",
"newlist_test.go",
"online_test.go",
"ranking_test.go",
"resource_test.go",
"search_test.go",
"tag_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/web/conf:go_default_library",
"//app/interface/main/web/model:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"archive.go",
"article.go",
"bnj.go",
"broadcast.go",
"coin.go",
"dynamic.go",
"elec.go",
"feedback.go",
"help.go",
"icon.go",
"ip.go",
"like.go",
"nav.go",
"newlist.go",
"online.go",
"ranking.go",
"resource.go",
"search.go",
"service.go",
"tag.go",
"wechat.go",
],
importpath = "go-common/app/interface/main/web/service",
tags = ["automanaged"],
deps = [
"//app/interface/main/dm2/model:go_default_library",
"//app/interface/main/dm2/rpc/client:go_default_library",
"//app/interface/main/tag/model:go_default_library",
"//app/interface/main/tag/rpc/client:go_default_library",
"//app/interface/main/web/conf:go_default_library",
"//app/interface/main/web/dao:go_default_library",
"//app/interface/main/web/model:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/interface/openplatform/article/rpc/client:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/archive/api/gorpc:go_default_library",
"//app/service/main/archive/model/archive:go_default_library",
"//app/service/main/broadcast/api/grpc/v1:go_default_library",
"//app/service/main/coin/api:go_default_library",
"//app/service/main/coupon/model:go_default_library",
"//app/service/main/coupon/rpc/client:go_default_library",
"//app/service/main/dynamic/model:go_default_library",
"//app/service/main/dynamic/rpc/client:go_default_library",
"//app/service/main/favorite/api/gorpc:go_default_library",
"//app/service/main/favorite/model:go_default_library",
"//app/service/main/location/model:go_default_library",
"//app/service/main/location/rpc/client:go_default_library",
"//app/service/main/relation/model:go_default_library",
"//app/service/main/relation/rpc/client:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//app/service/main/resource/rpc/client:go_default_library",
"//app/service/main/share/api:go_default_library",
"//app/service/main/thumbup/model:go_default_library",
"//app/service/main/thumbup/rpc/client:go_default_library",
"//app/service/main/ugcpay/api/grpc/v1:go_default_library",
"//library/conf/env:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/anticheat:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/metadata:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/sync/pipeline/fanout: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"],
)
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)

View File

@@ -0,0 +1,152 @@
package service
import (
"context"
"go-common/app/interface/main/web/model"
artmdl "go-common/app/interface/openplatform/article/model"
accmdl "go-common/app/service/main/account/api"
"go-common/app/service/main/archive/model/archive"
relmdl "go-common/app/service/main/relation/model"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
)
const _cardBakCacheRand = 10
// Attentions get attention list.
func (s *Service) Attentions(c context.Context, mid int64) (rs []int64, err error) {
var (
attentions []*relmdl.Following
remoteIP = metadata.String(c, metadata.RemoteIP)
)
if attentions, err = s.relation.Followings(c, &relmdl.ArgMid{Mid: mid, RealIP: remoteIP}); err != nil {
log.Error("s.relation.Followings(%d,%s) error %v", mid, remoteIP, err)
} else {
rs = make([]int64, 0)
for _, v := range attentions {
rs = append(rs, v.Mid)
}
}
return
}
// Card get card relation archive count data.
func (s *Service) Card(c context.Context, mid, loginID int64, topPhoto, article bool) (rs *model.Card, err error) {
var (
cardReply *accmdl.CardReply
relResp *accmdl.RelationReply
card *model.AccountCard
space *model.Space
arcCount int
group *errgroup.Group
infoErr, statErr, spaceErr, relErr, upcErr, artErr error
cacheRs *model.Card
remoteIP = metadata.String(c, metadata.RemoteIP)
)
relation := &accmdl.RelationReply{}
stat := &relmdl.Stat{}
upArts := &artmdl.UpArtMetas{}
group, errCtx := errgroup.WithContext(c)
card = new(model.AccountCard)
card.Attentions = make([]int64, 0)
group.Go(func() error {
if cardReply, infoErr = s.accClient.Card3(errCtx, &accmdl.MidReq{Mid: mid}); infoErr != nil {
log.Error("s.accClient.Card3(%d,%s) error %v", mid, remoteIP, infoErr)
} else {
card.FromCard(cardReply.Card)
}
return nil
})
group.Go(func() error {
if stat, statErr = s.relation.Stat(errCtx, &relmdl.ArgMid{Mid: mid, RealIP: remoteIP}); statErr != nil {
log.Error("s.relation.Stat(%d) error(%v)", mid, statErr)
} else {
card.Fans = int(stat.Follower)
card.Attention = int(stat.Following)
card.Friend = int(stat.Following)
}
return nil
})
if topPhoto {
group.Go(func() error {
space, spaceErr = s.dao.TopPhoto(errCtx, mid)
return nil
})
}
if loginID > 0 {
group.Go(func() error {
if relResp, relErr = s.accClient.Relation3(errCtx, &accmdl.RelationReq{Mid: loginID, Owner: mid, RealIp: remoteIP}); relErr != nil {
log.Error("s.accClient.Relation3(%d,%d,%s) error %v", loginID, mid, remoteIP, relErr)
} else if relResp != nil {
relation = relResp
}
return nil
})
}
group.Go(func() error {
if arcCount, upcErr = s.arc.UpCount2(errCtx, &archive.ArgUpCount2{Mid: mid}); upcErr != nil {
log.Error("s.arc.UpCount2(%d) error %v", mid, upcErr)
}
return nil
})
if article {
group.Go(func() error {
if upArts, artErr = s.art.UpArtMetas(errCtx, &artmdl.ArgUpArts{Mid: mid, Pn: _samplePn, Ps: _samplePs, RealIP: remoteIP}); artErr != nil {
log.Error("s.art.UpArtMetas(%d) error(%v)", mid, artErr)
}
if upArts == nil {
upArts = &artmdl.UpArtMetas{Count: 0}
}
return nil
})
}
group.Wait()
addCache := true
if infoErr != nil || (topPhoto && spaceErr != nil) || (loginID > 0 && relErr != nil) || upcErr != nil {
if cacheRs, err = s.dao.CardBakCache(c, mid); err != nil {
addCache = false
log.Error("s.dao.CardBakCache(%d) error (%v)", mid, err)
err = nil
} else if cacheRs != nil {
if infoErr != nil {
card = cacheRs.Card
}
if statErr != nil {
stat = &relmdl.Stat{Follower: cacheRs.Follower}
}
if topPhoto && spaceErr != nil {
space = cacheRs.Space
}
if loginID > 0 && relErr != nil {
relation = &accmdl.RelationReply{Following: cacheRs.Following}
}
if upcErr != nil {
arcCount = cacheRs.ArchiveCount
}
if artErr != nil {
upArts = &artmdl.UpArtMetas{Count: cacheRs.ArticleCount}
}
}
if topPhoto && space == nil {
space = &model.Space{SImg: s.c.DefaultTop.SImg, LImg: s.c.DefaultTop.LImg}
}
}
rs = &model.Card{
Card: card,
Space: space,
Following: relation.Following,
ArchiveCount: arcCount,
ArticleCount: upArts.Count,
Follower: stat.Follower,
}
if addCache {
s.cache.Do(c, func(c context.Context) {
if s.r.Intn(_cardBakCacheRand) == 1 {
s.dao.SetCardBakCache(c, mid, rs)
}
})
}
return
}

View File

@@ -0,0 +1,32 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_Attentions(t *testing.T) {
Convey("test account attentions", t, WithService(func(s *Service) {
var mid int64 = 27515256
res, err := s.Attentions(context.Background(), mid)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
Println(len(res))
}))
}
func TestService_Card(t *testing.T) {
Convey("test account card", t, WithService(func(s *Service) {
var (
mid int64 = 27515256
loginID int64 = 37515257
topPhoto = true
article = true
)
res, err := s.Card(context.Background(), mid, loginID, topPhoto, article)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,775 @@
package service
import (
"context"
"encoding/json"
"strconv"
"time"
dm2mdl "go-common/app/interface/main/dm2/model"
tagmdl "go-common/app/interface/main/tag/model"
"go-common/app/interface/main/web/model"
accmdl "go-common/app/service/main/account/api"
infomdl "go-common/app/service/main/account/model"
arcmdl "go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
coinmdl "go-common/app/service/main/coin/api"
favmdl "go-common/app/service/main/favorite/model"
locmdl "go-common/app/service/main/location/model"
sharemdl "go-common/app/service/main/share/api"
thumbup "go-common/app/service/main/thumbup/model"
ugcmdl "go-common/app/service/main/ugcpay/api/grpc/v1"
"go-common/library/conf/env"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/log/infoc"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
)
var (
_emptyTags = make([]*tagmdl.Tag, 0)
_emptyReplyHot = new(model.ReplyHot)
_emptyArchive3 = make([]*arcmdl.Arc, 0)
_emptyArc = make([]*arcmdl.Arc, 0)
)
const (
_japan = "日本"
_businessAppeal = 1
_notForward = 0
_member = 10000
_viewBakCacheRand = 10
_shareArcType = 3
_hasUGCPay = 1
_ugcOtypeArc = "archive"
_ugcCurrencyBp = "bp"
_ugcAssetPaid = "paid"
_ugcPaidState = 1
)
// View get a view page by aid.
func (s *Service) View(c context.Context, aid, cid, mid int64, cdnIP, ck string) (rs *model.View, err error) {
var (
viewReply *arcmdl.ViewReply
video *arcmdl.Page
longDesc string
pDesc, forward, report bool
remoteIP = metadata.String(c, metadata.RemoteIP)
)
if viewReply, err = s.arcClient.View(c, &arcmdl.ViewRequest{Aid: aid}); err != nil {
log.Error("s.arcClient.View(%d) error %v", aid, err)
return
}
if viewReply != nil && viewReply.Arc != nil {
if _, ok := s.specialMids[viewReply.Arc.Author.Mid]; ok && env.DeployEnv == env.DeployEnvProd {
err = ecode.NothingFound
log.Warn("aid(%d) mid(%d) can not view on prod", viewReply.Arc.Aid, viewReply.Arc.Author.Mid)
return
}
if viewReply.Arc.FirstCid == 0 {
if len(viewReply.Pages) > 0 {
viewReply.Arc.FirstCid = viewReply.Pages[0].Cid
}
}
if viewReply.Arc.State == archive.StateForbidLock && viewReply.Arc.Forward > 0 {
forward = true
} else if viewReply.Arc.State == archive.StateForbidRecicle || viewReply.Arc.State == archive.StateForbidLock {
if viewReply.Arc.ReportResult == "" {
err = ecode.NothingFound
return
}
report = true
}
check := []int32{archive.StateForbidWait, archive.StateForbidFixed, archive.StateForbidLater, archive.StateForbidAdminDelay}
for _, v := range check {
if viewReply.Arc.State == v {
err = ecode.ArchiveChecking
return
}
}
if viewReply.Arc.State == archive.StateForbidUserDelay {
err = ecode.ArchivePass
return
} else if !viewReply.Arc.IsNormal() && !forward && !report {
err = ecode.ArchiveDenied
return
}
rs = &model.View{Arc: viewReply.Arc, Pages: viewReply.Pages}
group, errCtx := errgroup.WithContext(c)
if !forward && !report {
group.Go(func() error {
return s.zlimit(errCtx, rs, mid, remoteIP, cdnIP)
})
group.Go(func() error {
return s.checkAccess(errCtx, mid, rs, ck, remoteIP)
})
}
group.Go(func() error {
dmCid := cid
if dmCid == 0 {
dmCid = viewReply.Arc.FirstCid
}
rs.Subtitle = s.dmSubtitle(errCtx, aid, dmCid)
return nil
})
if rs.Arc.Rights.UGCPay == _hasUGCPay {
rs.Asset = s.ugcPayAsset(errCtx, aid, mid)
}
if err = group.Wait(); err != nil {
return
}
if cid > 0 {
if video, err = s.arc.Video3(c, &archive.ArgVideo2{Aid: aid, Cid: cid, RealIP: remoteIP}); err != nil {
err = nil
log.Error("s.arc.Video3(%d,%d,%s) error %v", aid, cid, remoteIP, err)
}
if video.Desc != "" {
rs.Desc = video.Desc
pDesc = true
}
}
if !pDesc {
if longDesc, err = s.arc.Description2(c, &archive.ArgAid{Aid: aid, RealIP: remoteIP}); err != nil {
err = nil
log.Error("view s.arc.Description2(%d) error(%v)", aid, err)
} else if longDesc != "" {
rs.Desc = longDesc
}
}
if rs.AttrVal(archive.AttrBitIsPGC) == archive.AttrNo {
if err = s.initDownload(c, rs, mid, remoteIP, cdnIP); err != nil {
log.Error("s.initDownload aid(%d) mid(%d) ip(%s) error(%+v)", rs.Aid, mid, remoteIP, err)
err = nil
}
}
if !forward {
rs.Forward = _notForward
}
if !report {
rs.ReportResult = ""
}
if rs.AttrVal(archive.AttrBitJumpUrl) == archive.AttrNo {
rs.RedirectURL = ""
}
if rs.Access >= _member {
rs.Stat.View = -1
}
if rs.AttrVal(archive.AttrBitLimitArea) == archive.AttrYes {
rs.NoCache = true
}
s.cache.Do(c, func(c context.Context) {
if s.r.Intn(_viewBakCacheRand) == 1 {
s.dao.SetViewBakCache(c, aid, rs)
}
})
} else {
rs, err = s.dao.ViewBakCache(c, aid)
}
return
}
func (s *Service) zlimit(c context.Context, view *model.View, mid int64, remoteIP, cdnIP string) (err error) {
var data *int64
if data, err = s.loc.Archive(c, &locmdl.Archive{Aid: view.Aid, Mid: mid, IP: remoteIP, CIP: cdnIP}); err != nil {
log.Error("s.loc.Archive(%d%d%s%s) error(%v)", view.Aid, mid, remoteIP, cdnIP, err)
return
}
if *data == locmdl.Forbidden {
log.Warn("s.loc.Archive aid(%d) zlimit.Forbidden", view.Aid)
err = ecode.NothingFound
} else {
err = s.specialLimit(c, view, remoteIP)
}
return
}
// specialLimit spacialLimit special type id limit in japan
func (s *Service) specialLimit(c context.Context, view *model.View, remoteIP string) (err error) {
var zone *locmdl.Info
for _, typeID := range model.LimitTypeIDs {
if int32(typeID) == view.TypeID {
// TODO all no cache
view.NoCache = true
if zone, err = s.loc.Info(c, &locmdl.ArgIP{IP: remoteIP}); err != nil || zone == nil {
log.Error("s.loc.Info(%s) error(%v) or zone is nil", remoteIP, err)
err = nil
} else if zone.Country == _japan {
err = ecode.NothingFound
}
break
}
}
return
}
// checkAccess check mid aid access
func (s *Service) checkAccess(c context.Context, mid int64, view *model.View, ck, ip string) (err error) {
var (
p *accmdl.CardReply
)
if view.Access == 0 {
return
}
view.NoCache = true
if mid <= 0 {
log.Warn("user not login aid(%d)", view.Aid)
err = ecode.AccessDenied
return
}
if p, err = s.accClient.Card3(c, &accmdl.MidReq{Mid: mid}); err != nil {
log.Error("s.accClient.Card3(%d) error(%v)", mid, err)
return
}
if p == nil {
log.Warn("Info2 result is null aid(%d) state(%d) access(%d)", view.Aid, view.State, view.Access)
err = ecode.AccessDenied
return
}
card := p.Card
isVip := (card.Vip.Type > 0) && (card.Vip.Status == 1)
if view.Access > 0 && card.Rank < view.Access && (!isVip) {
log.Warn("mid(%d) rank(%d) vip(tp:%d,status:%d) have not access(%d) view archive(%d) ", mid, card.Rank, card.Vip.Type, card.Vip.Status, view.Access, view.Aid)
if mid > 0 {
err = ecode.NothingFound
} else {
err = ecode.ArchiveNotLogin
}
}
return
}
func (s *Service) initDownload(c context.Context, v *model.View, mid int64, ip, cdnIP string) (err error) {
var download int64
if v.AttrVal(archive.AttrBitLimitArea) == archive.AttrYes {
if download, err = s.downLimit(c, mid, v.Aid, cdnIP); err != nil {
return
}
} else {
download = locmdl.AllowDown
}
if download == locmdl.ForbiddenDown {
v.Rights.Download = int32(download)
return
}
for _, p := range v.Pages {
if p.From == "qq" {
download = locmdl.ForbiddenDown
break
}
}
v.Rights.Download = int32(download)
return
}
// downLimit ip limit
func (s *Service) downLimit(c context.Context, mid, aid int64, cdnIP string) (down int64, err error) {
var (
auth *locmdl.Auth
ip = metadata.String(c, metadata.RemoteIP)
)
if auth, err = s.loc.Archive2(c, &locmdl.Archive{Aid: aid, Mid: mid, IP: ip, CIP: cdnIP}); err != nil {
log.Error("s.loc.Archive2(%d) error(%v)", mid, err)
return
}
if auth.Play == locmdl.Forbidden {
err = ecode.AccessDenied
} else {
down = auth.Down
}
return
}
func (s *Service) dmSubtitle(c context.Context, aid, cid int64) (subtitle *model.Subtitle) {
var (
dmSub *dm2mdl.VideoSubtitles
err error
mids []int64
infosReply *accmdl.InfosReply
subs []*model.SubtitleItem
)
subtitle = new(model.Subtitle)
if dmSub, err = s.dm2.SubtitleGet(c, &dm2mdl.ArgSubtitleGet{Aid: aid, Oid: cid, Type: dm2mdl.SubTypeVideo}); err != nil {
log.Warn("dmSubtitle s.dm2.SubtitleGet aid(%d) cid(%d) warn(%v)", aid, cid, err)
} else if dmSub != nil {
subtitle.AllowSubmit = dmSub.AllowSubmit
if len(dmSub.Subtitles) > 0 {
for _, v := range dmSub.Subtitles {
if v.AuthorMid > 0 {
mids = append(mids, v.AuthorMid)
}
}
infoData := make(map[int64]*infomdl.Info)
if len(mids) > 0 {
if infosReply, err = s.accClient.Infos3(c, &accmdl.MidsReq{Mids: mids, RealIp: metadata.String(c, metadata.RemoteIP)}); err != nil {
log.Error("dmSubtitle aid(%d) cid(%d) s.acc.Infos3 mids(%v) error(%v)", aid, cid, mids, err)
} else {
infoData = infosReply.Infos
}
}
for _, v := range dmSub.Subtitles {
sub := &model.SubtitleItem{VideoSubtitle: v, Author: &infomdl.Info{Mid: v.AuthorMid}}
if info, ok := infoData[v.AuthorMid]; ok && info != nil {
sub.Author = info
}
subs = append(subs, sub)
}
subtitle.List = subs
}
}
if len(subtitle.List) == 0 {
subtitle.List = make([]*model.SubtitleItem, 0)
}
return
}
// ArchiveStat get archive stat data by aid.
func (s *Service) ArchiveStat(c context.Context, aid int64) (stat *model.Stat, err error) {
var (
arcReply *arcmdl.ArcReply
view interface{}
)
if aid == s.c.Bnj2019.LiveAid && s.bnj2019LiveArc != nil {
arcReply = s.bnj2019LiveArc
} else {
if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
log.Error("s.arcClient.Arc(%d) error(%v)", aid, err)
return
}
}
arc := arcReply.Arc
if !model.CheckAllowState(arc) {
err = ecode.AccessDenied
return
}
view = arc.Stat.View
if arc.Access > 0 {
view = "--"
}
stat = &model.Stat{
Aid: arc.Stat.Aid,
View: view,
Danmaku: arc.Stat.Danmaku,
Reply: arc.Stat.Reply,
Fav: arc.Stat.Fav,
Coin: arc.Stat.Coin,
Share: arc.Stat.Share,
Like: arc.Stat.Like,
NowRank: arc.Stat.NowRank,
HisRank: arc.Stat.HisRank,
NoReprint: arc.Rights.NoReprint,
Copyright: arc.Copyright,
}
return
}
// AddShare share add count
func (s *Service) AddShare(c context.Context, aid, mid int64, ua, refer, path, buvid, sid string) (shares int64, err error) {
var (
shareReply *sharemdl.AddShareReply
remoteIP = metadata.String(c, metadata.RemoteIP)
)
// add Anti cheat
if s.CheatInfoc != nil {
ac := map[string]string{
"itemType": infoc.ItemTypeAv,
"action": infoc.ActionShare,
"ip": remoteIP,
"mid": strconv.FormatInt(mid, 10),
"fid": "",
"aid": strconv.FormatInt(aid, 10),
"sid": sid,
"ua": ua,
"buvid": buvid,
"refer": refer,
"url": path,
}
s.CheatInfoc.ServiceAntiCheat(ac)
}
if shareReply, err = s.shareClient.AddShare(c, &sharemdl.AddShareRequest{Oid: aid, Mid: mid, Type: _shareArcType, Ip: remoteIP}); err != nil {
log.Error("AddShare s.shareClient.AddShare (oid:%d,mid:%d) warn(%v)", aid, mid, err)
return
}
shares = shareReply.Shares
return
}
// Description get archive description by aid.
func (s *Service) Description(c context.Context, aid, page int64) (res string, err error) {
var (
viewReply *arcmdl.ViewReply
video *arcmdl.Page
cid int64
longDesc string
ip = metadata.String(c, metadata.RemoteIP)
)
if viewReply, err = s.arcClient.View(c, &arcmdl.ViewRequest{Aid: aid}); err != nil {
log.Error("s.arcClient.View(%d,%s) error %v", aid, ip, err)
return
}
if viewReply != nil && viewReply.Arc != nil {
if !viewReply.Arc.IsNormal() {
err = ecode.ArchiveDenied
return
}
}
if page > 0 {
if int(page-1) >= len(viewReply.Pages) || viewReply.Pages[page-1] == nil {
err = ecode.NothingFound
return
}
cid = viewReply.Pages[page-1].Cid
if cid > 0 {
if video, err = s.arc.Video3(c, &archive.ArgVideo2{Aid: aid, Cid: cid, RealIP: ip}); err != nil {
log.Error("s.arc.Video2(%d,%d,%s) error %v", aid, cid, ip, err)
}
if video.Desc != "" {
res = video.Desc
return
}
}
} else {
res = viewReply.Arc.Desc
}
if longDesc, err = s.arc.Description2(c, &archive.ArgAid{Aid: aid, RealIP: ip}); err != nil {
log.Error("s.arc.Description2(%d) error(%v)", aid, err)
} else if longDesc != "" {
res = longDesc
}
return
}
// ArcReport add archive report
func (s *Service) ArcReport(c context.Context, mid, aid, tp int64, reason, pics string) (err error) {
if err = s.dao.ArcReport(c, mid, aid, tp, reason, pics); err != nil {
log.Error("s.dao.ArcReport(%d,%d,%d,%s,%s) err (%v)", mid, aid, tp, reason, pics, err)
}
return
}
// AppealTags get appeal tags
func (s *Service) AppealTags(c context.Context) (rs json.RawMessage, err error) {
if rs, err = s.dao.AppealTags(c, _businessAppeal); err != nil {
log.Error("s.dao.AppealTags(1) error(%v)", err)
}
return
}
// ArcAppeal add archive appeal.
func (s *Service) ArcAppeal(c context.Context, mid int64, data map[string]string) (err error) {
aid, _ := strconv.ParseInt(data["oid"], 10, 64)
if err = s.dao.ArcAppealCache(c, mid, aid); err != nil {
if err == ecode.ArcAppealLimit {
log.Warn("s.arcAppealLimit mid(%d) aid(%d)", mid, aid)
return
}
err = nil
}
if err = s.dao.ArcAppeal(c, mid, data, _businessAppeal); err != nil {
log.Error("s.dao.ArcAppeal(%d,%v,1) error(%v)", mid, data, err)
return
}
if err = s.dao.SetArcAppealCache(c, mid, aid); err != nil {
log.Error("s.dao.SetArcAppealCache(%d,%d)", mid, aid)
err = nil
}
return
}
// AuthorRecommend get author recommend data
func (s *Service) AuthorRecommend(c context.Context, aid int64) (res []*arcmdl.Arc, err error) {
var (
arcReply *arcmdl.ArcReply
aids []int64
recArcs, upArcs []*arcmdl.Arc
arcs *arcmdl.ArcsReply
ip = metadata.String(c, metadata.RemoteIP)
)
defer func() {
if len(res) == 0 {
res = _emptyArchive3
}
}()
resAids := make(map[int64]int64)
if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
log.Error("s.arcClient.Arc(%d) error(%v)", aid, err)
return
}
resAids[aid] = aid
if recArcs, err = s.arc.Recommend3(c, &archive.ArgAid2{Aid: aid, RealIP: ip}); err != nil {
log.Error("s.arc.Recommend3(%d) error(%v)", aid, err)
err = nil
} else {
for _, v := range recArcs {
res = append(res, v)
resAids[v.Aid] = v.Aid
}
}
if len(res) < s.c.Rule.AuthorRecCnt {
if upArcs, err = s.arc.UpArcs3(c, &archive.ArgUpArcs2{Mid: arcReply.Arc.Author.Mid, Pn: _firstPn, Ps: s.c.Rule.AuthorRecCnt, RealIP: ip}); err != nil {
log.Error("s.arc.UpArcs3(%d) error(%v)", arcReply.Arc.Author.Mid, err)
err = nil
} else {
for _, v := range upArcs {
if _, ok := resAids[v.Aid]; !ok {
res = append(res, v)
resAids[v.Aid] = v.Aid
if len(res) >= s.c.Rule.AuthorRecCnt {
return
}
}
}
}
}
if len(res) < s.c.Rule.AuthorRecCnt {
if aids, err = s.dao.RelatedAids(c, aid); err != nil {
log.Error("s.dao.RelatedArchives(%d) error(%v)", aid, err)
err = nil
} else if len(aids) > 0 {
ps := s.c.Rule.AuthorRecCnt - len(res)
if len(aids) > ps {
aids = aids[0:ps]
}
archivesArgLog("AuthorRecommend", aids)
if arcs, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
log.Error("s.arcClient.Arcs(%v) error(%v)", aids, err)
err = nil
} else {
for _, aid := range aids {
if _, ok := resAids[aid]; !ok {
if arc, ok := arcs.Arcs[aid]; ok {
res = append(res, model.FmtArc(arc))
if len(res) >= s.c.Rule.AuthorRecCnt {
return
}
}
}
}
}
}
}
return
}
// RelatedArcs get related archives
func (s *Service) RelatedArcs(c context.Context, aid int64) (res []*arcmdl.Arc, err error) {
var (
aids []int64
arcReply *arcmdl.ArcReply
arcsReply *arcmdl.ArcsReply
)
if _, ok := s.noRelAids[aid]; ok {
res = _emptyArc
return
}
if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
log.Error("s.arcClient.Arc(%d) error(%v)", aid, err)
return
}
// StateForbidUpDelete can have related arc
if !arcReply.Arc.IsNormal() && arcReply.Arc.GetState() != archive.StateForbidUpDelete {
res = _emptyArc
return
}
if aids, err = s.dao.RelatedAids(c, aid); err != nil {
log.Error("s.dao.RelatedArchives(%d) error(%v)", aid, err)
err = nil
} else if len(aids) > 0 {
if len(aids) > s.c.Rule.RelatedArcCnt {
aids = aids[:s.c.Rule.RelatedArcCnt]
}
archivesArgLog("RelatedArcs", aids)
if arcsReply, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
log.Error("s.arcClient.Arcs(%v) error(%v)", aids, err)
err = nil
} else {
for _, aid := range aids {
if arc, ok := arcsReply.Arcs[aid]; ok && arc.IsNormal() {
res = append(res, arc)
}
}
}
}
if len(res) == 0 {
res = _emptyArc
}
return
}
// Detail get merge view card tag reply related.
func (s *Service) Detail(c context.Context, aid, mid int64, cdnIP, ck string) (rs *model.Detail, err error) {
var (
view *model.View
card *model.Card
tags []*tagmdl.Tag
reply *model.ReplyHot
related []*arcmdl.Arc
group *errgroup.Group
cardErr, relatedErr error
)
if view, err = s.View(c, aid, 0, mid, cdnIP, ck); err != nil {
log.Error("s.View(%d) error %+v", aid, err)
return
}
group, errCtx := errgroup.WithContext(c)
group.Go(func() error {
if card, cardErr = s.Card(c, view.Author.Mid, mid, false, false); cardErr != nil {
log.Error("s.Card(%d) error %+v", aid, cardErr)
}
return nil
})
group.Go(func() error {
tags, _ = s.arcTags(errCtx, aid, mid)
return nil
})
group.Go(func() error {
reply, _ = s.replyHot(errCtx, aid)
return nil
})
group.Go(func() error {
if related, relatedErr = s.RelatedArcs(errCtx, aid); relatedErr != nil {
log.Error("s.RelatedArcs(%d) error %+v", aid, relatedErr)
}
return nil
})
group.Wait()
rs = &model.Detail{
View: view,
Card: card,
Tags: tags,
Reply: reply,
Related: related,
}
return
}
// ArcUGCPay get arc ugc pay relation.
func (s *Service) ArcUGCPay(c context.Context, mid, aid int64) (data *model.AssetRelation, err error) {
var relation *ugcmdl.AssetRelationResp
data = new(model.AssetRelation)
if arcReply, e := s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); e != nil {
log.Error("s.arcClient.Arc(%d) error(%v)", aid, e)
} else if arcReply.Arc.Author.Mid == mid {
data.State = _ugcPaidState
return
}
if relation, err = s.ugcPayClient.AssetRelation(c, &ugcmdl.AssetRelationReq{Mid: mid, Oid: aid, Otype: _ugcOtypeArc}); err != nil {
log.Error("ArcUGCPay s.ugcPayClient.AssetRelation mid:%d aid:%d error(%v)", mid, aid, err)
err = nil
return
}
if relation.State == _ugcAssetPaid {
data.State = _ugcPaidState
}
return
}
// ArcRelation .
func (s *Service) ArcRelation(c context.Context, mid, aid int64) (data *model.ReqUser, err error) {
var arc *arcmdl.ArcReply
data = new(model.ReqUser)
if arc, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil || arc.Arc == nil || !arc.Arc.IsNormal() {
log.Error("ArcRelation s.arcClient.Arc(%d) error(%v)", aid, err)
err = nil
return
}
authorMid := arc.Arc.Author.Mid
ip := metadata.String(c, metadata.RemoteIP)
group, errCtx := errgroup.WithContext(c)
// attention
group.Go(func() error {
if resp, e := s.accClient.Relation3(errCtx, &accmdl.RelationReq{Mid: mid, Owner: authorMid, RealIp: ip}); e != nil {
log.Error("ArcRelation s.accClient.Relation3(%d,%d,%s) error(%v)", mid, authorMid, ip, e)
} else if resp != nil {
data.Attention = resp.Following
}
return nil
})
// favorite
group.Go(func() error {
if resp, e := s.fav.IsFav(errCtx, &favmdl.ArgIsFav{Type: favmdl.TypeVideo, Mid: mid, Oid: aid, RealIP: ip}); e != nil {
log.Error("ArcRelation s.fav.IsFav(%d,%d,%s) error(%v)", mid, aid, ip, e)
} else {
data.Favorite = resp
}
return nil
})
// like
group.Go(func() error {
if resp, e := s.thumbup.HasLike(errCtx, &thumbup.ArgHasLike{Business: _businessLike, MessageIDs: []int64{aid}, Mid: mid, RealIP: ip}); e != nil {
log.Error("ArcRelation s.thumbup.HasLike(%d,%d,%s) error %v", aid, mid, ip, e)
} else if resp != nil {
if v, ok := resp[aid]; ok {
switch v {
case thumbup.StateLike:
data.Like = true
case thumbup.StateDislike:
data.Dislike = true
}
}
}
return nil
})
// coin
group.Go(func() error {
if resp, e := s.coinClient.ItemUserCoins(errCtx, &coinmdl.ItemUserCoinsReq{Mid: mid, Aid: aid, Business: model.CoinArcBusiness}); e != nil {
log.Error("ArcRelation s.coinClient.ItemUserCoins(%d,%d,%s) error %v", mid, aid, ip, e)
} else if resp != nil {
data.Coin = resp.Number
}
return nil
})
group.Wait()
return
}
func (s *Service) replyHot(c context.Context, aid int64) (res *model.ReplyHot, err error) {
if res, err = s.dao.Hot(c, aid); err != nil {
log.Error("s.dao.Hot(%d) error %+v", aid, err)
}
if res == nil {
res = _emptyReplyHot
}
return
}
func (s *Service) arcTags(c context.Context, aid, mid int64) (res []*tagmdl.Tag, err error) {
remoteIP := metadata.String(c, metadata.RemoteIP)
var (
arg = &tagmdl.ArgAid{
Aid: aid,
Mid: mid,
RealIP: remoteIP,
}
)
if res, err = s.tag.ArcTags(c, arg); err != nil {
log.Error("s.tag.ArcTags(%v) error(%v)", arg, err)
}
if len(res) == 0 {
res = _emptyTags
}
return
}
func (s *Service) ugcPayAsset(c context.Context, aid, mid int64) (data *ugcmdl.AssetQueryResp) {
asset, err := s.ugcPayClient.AssetQuery(c, &ugcmdl.AssetQueryReq{Oid: aid, Otype: _ugcOtypeArc, Currency: _ugcCurrencyBp})
if err != nil {
log.Error("ugcPayAsset mid(%d) oid(%d) error(%v)", mid, aid, err)
data = new(ugcmdl.AssetQueryResp)
return
}
data = asset
return
}
func (s *Service) loadManager() {
for {
time.Sleep(time.Duration(s.c.WEB.SpecailInterval))
midsM, err := s.dao.Special(context.Background())
if err != nil {
log.Error("loadManager error(%+v)", err)
continue
}
log.Info("load special mids(%+v)", midsM)
s.specialMids = midsM
}
}

View File

@@ -0,0 +1,106 @@
package service
import (
"context"
"encoding/json"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_View(t *testing.T) {
Convey("test archive view", t, WithService(func(s *Service) {
var (
mid int64 = 27515256
aid int64 = 10110688
cid int64 = 1
)
res, err := s.View(context.Background(), aid, cid, mid, "", "")
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
str, _ := json.Marshal(res)
Printf("%s", str)
}))
}
func TestService_ArchiveStat(t *testing.T) {
Convey("test archive archiveStat", t, WithService(func(s *Service) {
var aid int64 = 5464686
res, err := s.ArchiveStat(context.Background(), aid)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func TestService_AddShare(t *testing.T) {
Convey("test archive AddShare", t, WithService(func(s *Service) {
var (
mid int64 = 27515256
aid int64 = 5464686
)
res, err := s.AddShare(context.Background(), aid, mid, "", "", "", "", "")
So(err, ShouldBeNil)
So(res, ShouldBeGreaterThan, 0)
}))
}
func TestService_Description(t *testing.T) {
Convey("test archive Description", t, WithService(func(s *Service) {
var (
aid int64 = 5464686
page int64 = 1
)
res, err := s.Description(context.Background(), aid, page)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
}))
}
func TestService_ArcReport(t *testing.T) {
Convey("test archive ArcReport", t, WithService(func(s *Service) {
var (
mid int64 = 27515256
aid int64 = 5464686
tp int64
reason string
pics string
)
err := s.ArcReport(context.Background(), mid, aid, tp, reason, pics)
So(err, ShouldBeNil)
}))
}
func TestService_AppealTags(t *testing.T) {
Convey("test archive AppealTags", t, WithService(func(s *Service) {
res, err := s.AppealTags(context.Background())
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_AuthorRecommend(t *testing.T) {
Convey("test archive AuthorRecommend", t, WithService(func(s *Service) {
var aid int64 = 5464686
res, err := s.AuthorRecommend(context.Background(), aid)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_RelatedArcs(t *testing.T) {
Convey("test archive RelatedArcs", t, WithService(func(s *Service) {
var aid int64 = 5464686
res, err := s.RelatedArcs(context.Background(), aid)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_Detail(t *testing.T) {
Convey("test archive Detail", t, WithService(func(s *Service) {
var aid int64 = 5464686
res, err := s.Detail(context.Background(), aid, 0, "", "")
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,195 @@
package service
import (
"context"
"go-common/app/interface/main/web/conf"
"go-common/app/interface/main/web/model"
artmdl "go-common/app/interface/openplatform/article/model"
accmdl "go-common/app/service/main/account/api"
"go-common/library/log"
"go-common/library/net/metadata"
)
const (
_sortNew = 1
_firstPn = 1
_samplePn = 1
_samplePs = 1
_cacheCnt = 20
)
var (
_emptyArticleList = make([]*model.Meta, 0)
_emptyAuthorList = make([]*model.Info, 0)
_emptyArtMetas = make([]*artmdl.Meta, 0)
)
// ArticleList get article list.
func (s *Service) ArticleList(c context.Context, rid, mid int64, sort, pn, ps int, aids []int64) (res []*model.Meta, err error) {
var (
artMetas []*artmdl.Meta
ip = metadata.String(c, metadata.RemoteIP)
)
if pn == _firstPn {
var arts []*artmdl.Meta
arg := &artmdl.ArgRecommends{Aids: aids, Cid: rid, Pn: _firstPn, Ps: _cacheCnt, Sort: sort, RealIP: ip}
if arts, err = s.art.Recommends(c, arg); err != nil {
log.Error("s.art.Recommends(%d,%d,%d,%d) error(%v)", rid, pn, ps, sort, err)
err = nil
} else if len(arts) > 0 {
s.cache.Do(c, func(c context.Context) {
s.dao.SetArticleListCache(c, rid, sort, arts)
})
} else {
arts, err = s.dao.ArticleListCache(c, rid, sort)
}
if len(arts) > ps {
artMetas = arts[:ps-1]
} else {
artMetas = arts
}
} else {
arg := &artmdl.ArgRecommends{Aids: aids, Cid: rid, Pn: pn, Ps: ps, Sort: sort, RealIP: ip}
if artMetas, err = s.art.Recommends(c, arg); err != nil {
log.Error("s.art.Recommends(%d,%d,%d,%d) error(%v)", rid, pn, ps, sort, err)
return
}
}
if len(artMetas) == 0 {
res = _emptyArticleList
} else {
var item *model.Meta
if mid > 0 {
var (
likes map[int64]int
aids []int64
)
for _, art := range artMetas {
if art != nil {
aids = append(aids, art.ID)
}
}
if likes, err = s.art.HadLikesByMid(c, &artmdl.ArgMidAids{Mid: mid, Aids: aids, RealIP: ip}); err != nil {
log.Error("s.art.HadLikesByMid(%d,%v) error(%v)", mid, aids, err)
err = nil
} else {
for _, art := range artMetas {
if art != nil {
if like, ok := likes[art.ID]; ok {
item = &model.Meta{Meta: art, Like: like}
} else {
item = &model.Meta{Meta: art}
}
res = append(res, item)
}
}
}
} else {
for _, art := range artMetas {
if art != nil {
res = append(res, &model.Meta{Meta: art})
}
}
}
}
return
}
// ArticleUpList get article up list.
func (s *Service) ArticleUpList(c context.Context, mid int64) (res []*model.Info, err error) {
if res, err = s.articleUps(c, mid); err != nil {
err = nil
} else if len(res) > 0 {
s.cache.Do(c, func(c context.Context) {
s.dao.SetArticleUpListCache(c, res)
})
return
}
res, err = s.dao.ArticleUpListCache(c)
if len(res) == 0 {
res = _emptyAuthorList
}
return
}
// Categories get article categories list
func (s *Service) Categories(c context.Context) (res *artmdl.Categories, err error) {
ip := metadata.String(c, metadata.RemoteIP)
if res, err = s.art.Categories(c, &artmdl.ArgIP{RealIP: ip}); err != nil {
log.Error("s.art.Categories error(%v)", err)
}
return
}
func (s *Service) articleUps(c context.Context, mid int64) (res []*model.Info, err error) {
var (
mids []int64
list []*artmdl.Meta
cardsReply *accmdl.CardsReply
relaReply *accmdl.RelationsReply
ip = metadata.String(c, metadata.RemoteIP)
)
res = make([]*model.Info, 0)
arg := &artmdl.ArgRecommends{Sort: _sortNew, Pn: 1, Ps: conf.Conf.Rule.ArtUpListGetCnt, RealIP: ip}
if list, err = s.art.Recommends(c, arg); err != nil {
log.Error("s.art.Recommends() error(%v)", err)
return
}
listMap := make(map[int64]*artmdl.Meta, conf.Conf.Rule.ArtUpListCnt)
for _, v := range list {
if len(listMap) == conf.Conf.Rule.ArtUpListCnt {
break
}
if _, ok := listMap[v.Author.Mid]; ok {
continue
}
listMap[v.Author.Mid] = v
mids = append(mids, v.Author.Mid)
}
if cardsReply, err = s.accClient.Cards3(c, &accmdl.MidsReq{Mids: mids}); err != nil {
log.Error("s.accClient.Cards3(%v) error(%v)", mids, err)
return
}
if mid > 0 {
if relaReply, err = s.accClient.Relations3(c, &accmdl.RelationsReq{Mid: mid, Owners: mids, RealIp: ip}); err != nil {
log.Error("s.accClient.Relations3(%d,%v) error(%v)", mid, mids, err)
err = nil
}
}
for _, mid := range mids {
if card, ok := cardsReply.Cards[mid]; ok {
info := &model.Info{ID: listMap[mid].ID, Title: listMap[mid].Title, PublishTime: listMap[mid].PublishTime}
info.FromCard(card)
if relaReply != nil {
if relation, ok := relaReply.Relations[mid]; ok {
info.Following = relation.Following
}
}
res = append(res, info)
}
}
return
}
// NewCount get new publish article count
func (s *Service) NewCount(c context.Context, pubTime int64) (count int64, err error) {
ip := metadata.String(c, metadata.RemoteIP)
if count, err = s.art.NewArticleCount(c, &artmdl.ArgNewArt{PubTime: pubTime, RealIP: ip}); err != nil {
log.Error("s.art.NewArticleCount(%d) error(%v)", pubTime, err)
}
return
}
// UpMoreArts get up more articles
func (s *Service) UpMoreArts(c context.Context, aid int64) (res []*artmdl.Meta, err error) {
ip := metadata.String(c, metadata.RemoteIP)
if res, err = s.art.UpMoreArts(c, &artmdl.ArgAid{Aid: aid, RealIP: ip}); err != nil {
log.Error("s.art.UpMoreArts(%d) error(%v)", aid, err)
return
}
if len(res) == 0 {
res = _emptyArtMetas
}
return
}

View File

@@ -0,0 +1,51 @@
package service
import (
"context"
"encoding/json"
"testing"
"go-common/app/interface/main/web/conf"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_ArticleList(t *testing.T) {
Convey("test article list", t, WithService(func(s *Service) {
aids := []int64{}
rid := 2
sort := 1
mid := 27515256
res, err := s.ArticleList(context.Background(), int64(rid), int64(mid), sort, 1, 20, aids)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
Println(len(res))
for _, v := range res {
Printf("%d,%+v", v.ID, v)
}
}))
}
func TestService_ArticleUpList(t *testing.T) {
Convey("test article up list", t, WithService(func(s *Service) {
res, err := s.ArticleUpList(context.Background(), 90085)
So(err, ShouldBeNil)
So(len(res), ShouldEqual, conf.Conf.Rule.ArtUpListCnt)
if bs, err := json.Marshal(res); err != nil {
Printf("%+v", err)
} else {
Println(string(bs))
}
}))
}
func TestService_Categories(t *testing.T) {
Convey("test categories", t, WithService(func(s *Service) {
res, err := s.Categories(context.Background())
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
for _, v := range *res {
Printf("%+v", v)
}
}))
}

View File

@@ -0,0 +1,210 @@
package service
import (
"context"
"time"
"go-common/app/interface/main/web/model"
accmdl "go-common/app/service/main/account/api"
arcmdl "go-common/app/service/main/archive/api"
coinmdl "go-common/app/service/main/coin/api"
favmdl "go-common/app/service/main/favorite/model"
thumbup "go-common/app/service/main/thumbup/model"
"go-common/library/conf/env"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
)
func (s *Service) checkBnjAccess(mid int64) bool {
if s.c.Bnj2019.Open {
return true
}
if env.DeployEnv == env.DeployEnvProd && len(s.bnjGrayUids) > 0 {
if mid == 0 {
return false
}
if _, ok := s.bnjGrayUids[mid]; !ok {
return false
}
}
return true
}
// Bnj2019Aids get bnj aids.3
func (s Service) Bnj2019Aids(c context.Context) []int64 {
aids := s.c.Bnj2019.BnjListAids
aids = append(aids, s.c.Bnj2019.BnjMainAid)
return aids
}
// Timeline get timeline.
func (s *Service) Timeline(c context.Context, mid int64) (data []*model.Timeline, err error) {
if !s.checkBnjAccess(mid) {
err = ecode.AccessDenied
return
}
for _, v := range s.c.Bnj2019.Timeline {
data = append(data, &model.Timeline{
Name: v.Name,
Start: v.Start.Unix(),
End: v.End.Unix(),
Cover: v.Cover,
H5Cover: v.H5Cover,
})
}
return
}
// Bnj2019 get bnj2019 data.
func (s *Service) Bnj2019(c context.Context, mid int64) (data *model.Bnj2019, err error) {
if !s.checkBnjAccess(mid) {
err = ecode.AccessDenied
return
}
if s.bnj2019View == nil || !s.bnj2019View.Arc.IsNormal() {
err = ecode.NothingFound
return
}
data = &model.Bnj2019{
Bnj2019View: s.bnj2019View,
Elec: s.BnjElecInfo,
Related: s.bnj2019List,
ReqUser: &model.ReqUser{},
}
if len(data.Related) == 0 {
data.Related = make([]*model.Bnj2019Related, 0)
}
if mid > 0 {
authorMid := s.bnj2019View.Author.Mid
aid := s.bnj2019View.Aid
ip := metadata.String(c, metadata.RemoteIP)
group, errCtx := errgroup.WithContext(c)
// attention
group.Go(func() error {
if resp, e := s.accClient.Relation3(errCtx, &accmdl.RelationReq{Mid: mid, Owner: authorMid, RealIp: ip}); e != nil {
log.Error("Bnj2019 s.accClient.Relation3(%d,%d,%s) error(%v)", mid, authorMid, ip, e)
} else if resp != nil {
data.ReqUser.Attention = resp.Following
}
return nil
})
// favorite
group.Go(func() error {
if resp, e := s.fav.IsFav(errCtx, &favmdl.ArgIsFav{Type: favmdl.TypeVideo, Mid: mid, Oid: aid, RealIP: ip}); e != nil {
log.Error("Bnj2019 s.fav.IsFav(%d,%d,%s) error(%v)", mid, aid, ip, e)
} else {
data.ReqUser.Favorite = resp
}
return nil
})
// like
group.Go(func() error {
if resp, e := s.thumbup.HasLike(errCtx, &thumbup.ArgHasLike{Business: _businessLike, MessageIDs: []int64{aid}, Mid: mid, RealIP: ip}); e != nil {
log.Error("Bnj2019 s.thumbup.HasLike(%d,%d,%s) error %v", aid, mid, ip, e)
} else if resp != nil {
if v, ok := resp[aid]; ok {
switch v {
case thumbup.StateLike:
data.ReqUser.Like = true
case thumbup.StateDislike:
data.ReqUser.Dislike = true
}
}
}
return nil
})
// coin
group.Go(func() error {
if resp, e := s.coinClient.ItemUserCoins(errCtx, &coinmdl.ItemUserCoinsReq{Mid: mid, Aid: aid, Business: model.CoinArcBusiness}); e != nil {
log.Error("Bnj2019 s.coinClient.ItemUserCoins(%d,%d,%s) error %v", mid, aid, ip, e)
} else if resp != nil {
data.ReqUser.Coin = resp.Number
}
return nil
})
group.Wait()
}
return
}
func (s *Service) bnj2019proc() {
// bnj gray uid
go func() {
for {
time.Sleep(time.Duration(s.c.Bnj2019.BnjTick))
if mids, err := s.dao.Bnj2019Conf(context.Background()); err != nil {
log.Error("bnj2019proc s.dao.Bnj2019Conf error(%v)", err)
continue
} else {
tmp := make(map[int64]struct{}, len(mids))
if len(mids) > 0 {
for _, mid := range mids {
tmp[mid] = struct{}{}
}
}
s.bnjGrayUids = tmp
}
}
}()
// main arc
go func() {
for {
time.Sleep(time.Duration(s.c.Bnj2019.BnjTick))
if s.c.Bnj2019.BnjMainAid == 0 {
continue
}
if viewReply, err := s.arcClient.View(context.Background(), &arcmdl.ViewRequest{Aid: s.c.Bnj2019.BnjMainAid}); err != nil {
log.Error("bnj2019proc main s.arcClient.View(%d) error(%v)", s.c.Bnj2019.BnjMainAid, err)
continue
} else if viewReply != nil {
s.bnj2019View = &model.Bnj2019View{Arc: viewReply.Arc, Pages: viewReply.Pages}
// elec
if elec, err := s.dao.ElecShow(context.Background(), viewReply.Arc.Author.Mid, viewReply.Arc.Aid, 0); err == nil {
s.BnjElecInfo = elec
s.BnjElecInfo.TotalCount += s.c.Bnj2019.FakeElec
} else {
log.Error("bnj2019proc s.dao.ElecShow(%d,%d) error(%v)", viewReply.Arc.Author.Mid, viewReply.Arc.Aid, err)
}
}
}
}()
// live arc
go func() {
for {
time.Sleep(time.Duration(s.c.Bnj2019.BnjTick))
if s.c.Bnj2019.LiveAid == 0 {
continue
}
if arcReply, err := s.arcClient.Arc(context.Background(), &arcmdl.ArcRequest{Aid: s.c.Bnj2019.LiveAid}); err != nil {
log.Error("bnj2019proc live arc s.arcClient.Arc(%d) error(%v)", s.c.Bnj2019.LiveAid, err)
continue
} else if arcReply != nil {
s.bnj2019LiveArc = arcReply
}
}
}()
// list arc
go func() {
for {
time.Sleep(time.Duration(s.c.Bnj2019.BnjTick))
if len(s.c.Bnj2019.BnjListAids) == 0 {
continue
}
if viewsReply, err := s.arcClient.Views(context.Background(), &arcmdl.ViewsRequest{Aids: s.c.Bnj2019.BnjListAids}); err != nil {
log.Error("bnj2019proc list s.arcClient.Views(%v) error(%v)", s.c.Bnj2019.BnjListAids, err)
continue
} else {
var tmpList []*model.Bnj2019Related
for _, aid := range s.c.Bnj2019.BnjListAids {
if view, ok := viewsReply.Views[aid]; ok && view.Arc.IsNormal() {
item := &model.Bnj2019Related{Arc: view.Arc, Pages: view.Pages}
tmpList = append(tmpList, item)
}
}
s.bnj2019List = tmpList
}
}
}()
}

View File

@@ -0,0 +1,19 @@
package service
import (
"context"
"go-common/app/interface/main/web/model"
warden "go-common/app/service/main/broadcast/api/grpc/v1"
"go-common/library/log"
)
// BroadServers broadcast server list.
func (s *Service) BroadServers(c context.Context, platform string) (res *warden.ServerListReply, err error) {
if res, err = s.broadcastClient.ServerList(c, &warden.ServerListReq{Platform: platform}); err != nil {
log.Error("s.broadCastClient.ServerList(%s) error(%v)", platform, err)
res = model.DefaultServer
err = nil
}
return
}

View File

@@ -0,0 +1,154 @@
package service
import (
"context"
"time"
"go-common/app/interface/main/web/model"
arcmdl "go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
coinmdl "go-common/app/service/main/coin/api"
thumbup "go-common/app/service/main/thumbup/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
var _emptyCoinArcList = make([]*model.CoinArc, 0)
// Coins get archive User added coins.
func (s *Service) Coins(c context.Context, mid, aid int64) (res *model.ArchiveUserCoins, err error) {
var rs *coinmdl.ItemUserCoinsReply
if rs, err = s.coinClient.ItemUserCoins(c, &coinmdl.ItemUserCoinsReq{Mid: mid, Aid: aid, Business: model.CoinArcBusiness}); err != nil {
log.Error("s.coinClient.ItemUserCoins(%d,%d) error(%v)", mid, aid, err)
return
}
res = new(model.ArchiveUserCoins)
if rs != nil {
res.Multiply = rs.Number
}
return
}
// AddCoin add coin to archive.
func (s *Service) AddCoin(c context.Context, aid, mid, upID, multiply, avtype int64, business, ck, ua, refer string, now time.Time, selectLike int) (like bool, err error) {
var (
pubTime int64
typeID int32
maxCoin int64 = 2
ip = metadata.String(c, metadata.RemoteIP)
)
switch avtype {
case model.CoinAddArcType:
var a *arcmdl.ArcReply
if a, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
log.Error("s.arcClient.Arc(%v) error(%v)", aid, err)
return
}
if !a.Arc.IsNormal() {
err = ecode.ArchiveNotExist
return
}
if a.Arc.Copyright == int32(archive.CopyrightCopy) {
maxCoin = 1
}
upID = a.Arc.Author.Mid
typeID = a.Arc.TypeID
pubTime = int64(a.Arc.PubDate)
case model.CoinAddArtType:
maxCoin = 1
}
arg := &coinmdl.AddCoinReq{
IP: ip,
Mid: mid,
Upmid: upID,
MaxCoin: maxCoin,
Aid: aid,
Business: business,
Number: multiply,
Typeid: typeID,
PubTime: pubTime,
}
if _, err = s.coinClient.AddCoin(c, arg); err == nil && avtype == model.CoinAddArcType && selectLike == 1 {
if err = s.thumbup.Like(c, &thumbup.ArgLike{Mid: mid, UpMid: upID, Business: _businessLike, MessageID: aid, Type: thumbup.TypeLike, RealIP: ip}); err != nil {
log.Error("AddCoin s.thumbup.Like mid(%d) upID(%d) aid(%d) error(%+v)", mid, upID, aid, err)
err = nil
} else {
like = true
}
}
return
}
// CoinExp get coin exp today
func (s *Service) CoinExp(c context.Context, mid int64) (exp int64, err error) {
var todayExp *coinmdl.TodayExpReply
if todayExp, err = s.coinClient.TodayExp(c, &coinmdl.TodayExpReq{Mid: mid}); err != nil {
log.Error("CoinExp s.coinClient.TodayExp mid(%d) error(%v)", mid, err)
err = nil
return
}
exp = todayExp.Exp
return
}
// CoinList get coin list.
func (s *Service) CoinList(c context.Context, mid int64, pn, ps int) (list []*model.CoinArc, count int, err error) {
var (
coinReply *coinmdl.ListReply
aids []int64
arcsReply *arcmdl.ArcsReply
)
if coinReply, err = s.coinClient.List(c, &coinmdl.ListReq{Mid: mid, Business: model.CoinArcBusiness, Ts: time.Now().Unix()}); err != nil {
log.Error("CoinList s.coinClient.List(%d) error(%v)", mid, err)
err = nil
list = _emptyCoinArcList
return
}
existAids := make(map[int64]int64, len(coinReply.List))
afVideos := make(map[int64]*coinmdl.ModelList, len(coinReply.List))
for _, v := range coinReply.List {
if _, ok := existAids[v.Aid]; ok {
afVideos[v.Aid].Number += v.Number
continue
}
afVideos[v.Aid] = v
aids = append(aids, v.Aid)
existAids[v.Aid] = v.Aid
}
count = len(aids)
start := (pn - 1) * ps
end := pn * ps
switch {
case start > count:
aids = aids[:0]
case end >= count:
aids = aids[start:]
default:
aids = aids[start:end]
}
if len(aids) == 0 {
list = _emptyCoinArcList
return
}
if arcsReply, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
log.Error("CoinList s.arcClient.Arcs(%v) error(%v)", aids, err)
err = nil
list = _emptyCoinArcList
return
}
for _, aid := range aids {
if arc, ok := arcsReply.Arcs[aid]; ok && arc.IsNormal() {
if arc.Access >= 10000 {
arc.Stat.View = 0
}
if item, ok := afVideos[aid]; ok {
list = append(list, &model.CoinArc{Arc: arc, Coins: item.Number, Time: item.Ts})
}
}
}
if len(list) == 0 {
list = _emptyCoinArcList
}
return
}

View File

@@ -0,0 +1,51 @@
package service
import (
"context"
"testing"
"time"
"go-common/app/interface/main/web/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_Coins(t *testing.T) {
Convey("test coin Coins", t, WithService(func(s *Service) {
var (
mid int64 = 27515256
aid int64 = 37515257
)
res, err := s.Coins(context.Background(), mid, aid)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func TestService_AddCoin(t *testing.T) {
Convey("test coin AddCoin", t, WithService(func(s *Service) {
var (
mid int64 = 27515256
aid int64 = 37515257
upID int64 = 37515257
multiply int64 = 1
avtype int64 = 1
business = model.CoinArcBusiness
selectLike = 1
)
like, err := s.AddCoin(context.Background(), aid, mid, upID, multiply, avtype, business, "", "", "", time.Now(), selectLike)
So(err, ShouldBeNil)
So(like, ShouldNotBeNil)
}))
}
func TestService_CoinExp(t *testing.T) {
Convey("test coin CoinExp", t, WithService(func(s *Service) {
var (
mid int64 = 27515256
)
res, err := s.CoinExp(context.Background(), mid)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,156 @@
package service
import (
"context"
"go-common/app/interface/main/web/conf"
"go-common/app/service/main/archive/api"
dymdl "go-common/app/service/main/dynamic/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
// DynamicRegion get dynamic region.
func (s *Service) DynamicRegion(c context.Context, rid int32, pn, ps int) (rs *dymdl.DynamicArcs3, err error) {
ip := metadata.String(c, metadata.RemoteIP)
if rs, err = s.dy.RegionArcs3(c, &dymdl.ArgRegion3{RegionID: rid, Pn: pn, Ps: ps, RealIP: ip}); err != nil {
log.Error("s.dy.RegionArcs3(%d,%d,%d) error(%v)", rid, pn, ps, err)
err = nil
} else if rs != nil && len(rs.Archives) > 0 {
fmtArcs3(rs.Archives)
s.cache.Do(c, func(c context.Context) {
s.dao.SetRegionBakCache(c, rid, pn, ps, rs)
})
return
}
if rs, err = s.dao.RegionBakCache(c, rid, pn, ps); err != nil {
return
}
if rs == nil {
err = ecode.NothingFound
}
return
}
func fmtArcs3(arcs []*api.Arc) {
for _, v := range arcs {
if v.Access >= 10000 {
v.Stat.View = -1
}
}
}
// DynamicRegionTag get dynamic region tag.
func (s *Service) DynamicRegionTag(c context.Context, tagID int64, rid int32, pn, ps int) (rs *dymdl.DynamicArcs3, err error) {
ip := metadata.String(c, metadata.RemoteIP)
if rs, err = s.dy.RegionTagArcs3(c, &dymdl.ArgRegionTag3{TagID: tagID, RegionID: rid, Pn: pn, Ps: ps, RealIP: ip}); err != nil {
log.Error("s.dy.RegionTagArcs3(%d,%d,%d,%d) error(%v)", tagID, rid, pn, ps, err)
err = nil
} else if rs != nil && len(rs.Archives) > 0 {
fmtArcs3(rs.Archives)
s.cache.Do(c, func(c context.Context) {
s.dao.SetRegionTagBakCache(c, tagID, rid, pn, ps, rs)
})
return
}
if rs, err = s.dao.RegionTagBakCache(c, tagID, rid, pn, ps); err != nil {
return
}
if rs == nil {
err = ecode.NothingFound
}
return
}
// DynamicRegionTotal get dynamic region total.
func (s *Service) DynamicRegionTotal(c context.Context) (map[string]int, error) {
rs, err := s.dy.RegionTotal(c, &dymdl.ArgRegionTotal{RealIP: metadata.String(c, metadata.RemoteIP)})
if err != nil {
log.Error("s.dy.RegionTotal error(%v)", err)
return nil, err
}
return rs, nil
}
// DynamicRegions get dynamic regions.
func (s *Service) DynamicRegions(c context.Context) (rs map[int32][]*api.Arc, err error) {
var (
rids []int32
common, bg map[int32][]*api.Arc
bgid = int32(13)
ip = metadata.String(c, metadata.RemoteIP)
)
// get first type id
for rid := range s.rids {
if rid == bgid { //bangumi ignore.
continue
} else if rid == 167 { //guochuang use second rid 168.
rid = 168
}
rids = append(rids, rid)
}
rs = make(map[int32][]*api.Arc, len(rids)+1)
if common, err = s.dy.RegionsArcs3(c, &dymdl.ArgRegions3{RegionIDs: rids, Count: 10, RealIP: ip}); err != nil {
log.Error("s.dy.RegionsArcs3(%v) error(%v)", rids, err)
err = nil
}
for _, rid := range rids {
rs[rid] = common[rid]
}
// bangumi type id 13 find 200,condition mid == 928123.
if bg, err = s.dy.RegionsArcs3(c, &dymdl.ArgRegions3{RegionIDs: []int32{bgid}, Count: conf.Conf.Rule.BangumiCount, RealIP: ip}); err != nil {
log.Error("s.dy.RegionsArcs3 error(%v)", err)
err = nil
} else {
n := 1
count := 1
for _, arc := range bg[bgid] {
count++
if arc.Author.Mid == 928123 {
rs[bgid] = append(rs[bgid], arc)
} else {
continue
}
n++
if n > conf.Conf.Rule.RegionsCount {
log.Info("s.dy.RegionsArcs bangumi count(%d)", count)
break
}
}
// not enough add other.
if n <= conf.Conf.Rule.RegionsCount {
for _, arc := range bg[bgid] {
count++
if arc.Author.Mid == 928123 {
continue
} else {
rs[bgid] = append(rs[bgid], arc)
}
n++
if n > conf.Conf.Rule.RegionsCount {
log.Info("s.dy.RegionsArcs bangumi count(%d)", count)
break
}
}
}
}
if len(rs) > 0 {
countCheck := true
for rid, region := range rs {
if len(region) < conf.Conf.Rule.MinDyCount {
countCheck = false
log.Info("countCheck rid(%d) len(%d) false", rid, len(region))
break
}
}
if countCheck {
s.cache.Do(c, func(c context.Context) {
s.dao.SetRegionsBakCache(c, rs)
})
return
}
}
rs, err = s.dao.RegionsBakCache(c)
return
}

View File

@@ -0,0 +1,47 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_DynamicRegion(t *testing.T) {
Convey("test dynamic DynamicRegion", t, WithService(func(s *Service) {
var rid int32 = 23
res, err := s.DynamicRegion(context.Background(), rid, 1, 10)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func TestService_DynamicRegionTag(t *testing.T) {
Convey("test dynamic DynamicRegionTag", t, WithService(func(s *Service) {
var (
tagID int64 = 10101
rid int32 = 23
)
res, err := s.DynamicRegionTag(context.Background(), tagID, rid, 1, 10)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func TestService_DynamicRegionTotal(t *testing.T) {
Convey("test dynamic DynamicRegionTotal", t, WithService(func(s *Service) {
res, err := s.DynamicRegionTotal(context.Background())
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
Println(len(res))
}))
}
func TestService_DynamicRegions(t *testing.T) {
Convey("test dynamic DynamicRegions", t, WithService(func(s *Service) {
res, err := s.DynamicRegions(context.Background())
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
Println(len(res))
}))
}

View File

@@ -0,0 +1,33 @@
package service
import (
"context"
"go-common/app/interface/main/web/model"
arcmdl "go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
)
// ElecShow elec show.
func (s *Service) ElecShow(c context.Context, mid, aid, loginID int64) (rs *model.ElecShow, err error) {
var arcReply *arcmdl.ArcReply
if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
log.Error("s.arcClient.Arc(%d) error(%v)", aid, err)
return
}
arc := arcReply.Arc
if arc.Copyright != int32(archive.CopyrightOriginal) || !arc.IsNormal() {
err = ecode.ElecDenied
return
}
if _, ok := s.elecShowTypeIds[arc.TypeID]; !ok {
err = ecode.ElecDenied
return
}
if rs, err = s.dao.ElecShow(c, mid, aid, loginID); err != nil {
log.Error("s.dao.ElecShow(%d,%d,%d) error(%v)", mid, aid, loginID, err)
}
return
}

View File

@@ -0,0 +1,21 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_ElecShow(t *testing.T) {
Convey("test elec ElecShow", t, WithService(func(s *Service) {
var (
mid int64 = 27515256
aid int64 = 5464686
loginID int64
)
res, err := s.ElecShow(context.Background(), mid, aid, loginID)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,34 @@
package service
import (
"context"
"time"
"go-common/app/interface/main/web/model"
"go-common/library/ecode"
"go-common/library/log"
)
// Feedback web player feedback.
func (s *Service) Feedback(c context.Context, feedParams *model.Feedback) (err error) {
var location string
if feedParams.Other != "" {
if location, err = s.upload(c, feedParams.Other); err != nil {
log.Error("s.upload error(%v)", err)
err = nil
} else {
feedParams.Content.URL = location
}
}
err = s.dao.Feedback(c, feedParams)
return
}
func (s *Service) upload(c context.Context, Other string) (location string, err error) {
if len(Other) > s.c.Bfs.MaxFileSize {
err = ecode.FeedbackBodyTooLarge
return
}
location, err = s.dao.Upload(c, Other, time.Now().Unix())
return
}

View File

@@ -0,0 +1,19 @@
package service
import (
"context"
"testing"
"go-common/app/interface/main/web/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_Feedback(t *testing.T) {
Convey("test feedback Feedback", t, WithService(func(s *Service) {
feedParams := &model.Feedback{Aid: 5464686, Mid: 27515256, TagID: 10101, Buvid: "", Browser: "",
Version: "1.1", Content: &model.Content{Reason: ""}, Email: "", QQ: "", Other: ""}
err := s.Feedback(context.Background(), feedParams)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,61 @@
package service
import (
"context"
"go-common/app/interface/main/web/model"
"go-common/library/log"
"go-common/library/net/metadata"
)
const _firstPage = 1
var _emptyHelpList = make([]*model.HelpList, 0)
// HelpList get help menu list
func (s *Service) HelpList(c context.Context, pTypeID string) (res []*model.HelpList, err error) {
if res, err = s.dao.HlCache(c, pTypeID); err != nil || len(res) == 0 {
if res, err = s.dao.HelpList(context.Background(), pTypeID); err != nil {
log.Error("s.do.HelpList(%s) error(%v)", pTypeID, err)
return
}
if len(res) > 0 {
s.cache.Do(c, func(c context.Context) {
s.dao.SetHlCache(c, pTypeID, res)
})
}
}
return
}
// HelpDetail get help detail
func (s *Service) HelpDetail(c context.Context, fID, qTypeID string, keyFlag, pn, ps int) (resD []*model.HelpDeatil, resL []*model.HelpList, total int, err error) {
remoteIP := metadata.String(c, metadata.RemoteIP)
if resD, total, err = s.dao.DetailCache(c, qTypeID, keyFlag, pn, ps); err != nil || len(resD) == 0 {
if resD, total, err = s.dao.HelpDetail(context.Background(), qTypeID, keyFlag, pn, ps, remoteIP); err != nil {
log.Error("s.do.HelpDetail(%s,%d,%d,%d) error(%v)", qTypeID, keyFlag, pn, ps, err)
}
if pn == _firstPage && len(resD) > 0 {
s.cache.Do(c, func(c context.Context) {
s.dao.SetDetailCache(c, qTypeID, keyFlag, pn, ps, total, resD)
})
}
}
if fID == "" {
resL = _emptyHelpList
} else {
if resL, err = s.HelpList(c, fID); err != nil {
log.Error("s.HelpList(%s) error(%v)", fID, err)
}
}
return
}
// HelpSearch get help search
func (s *Service) HelpSearch(c context.Context, pTypeID, keyWords string, keyFlag, pn, ps int) (res []*model.HelpDeatil, total int, err error) {
if res, total, err = s.dao.HelpSearch(context.Background(), pTypeID, keyWords, keyFlag, pn, ps); err != nil {
log.Error("s.do.HelpDetail(%s,%d,%d,%d) error(%v)", keyWords, keyFlag, pn, ps, err)
}
return
}

View File

@@ -0,0 +1,44 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_HelpList(t *testing.T) {
Convey("test help HelpList", t, WithService(func(s *Service) {
pTypeID := "39e79104ca5d433f9d9cdf9df4bf28a0"
res, err := s.HelpList(context.Background(), pTypeID)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
Println(len(res))
}))
}
func TestService_HelpDetail(t *testing.T) {
Convey("test help HelpDetail", t, WithService(func(s *Service) {
fID := "39e79104ca5d433f9d9cdf9df4bf28a0"
qTypeID := "39e79104ca5d433f9d9cdf9df4bf28a0"
resD, resL, total, err := s.HelpDetail(context.Background(), fID, qTypeID, 0, 1, 15)
So(err, ShouldBeNil)
So(total, ShouldBeGreaterThan, 0)
So(len(resD), ShouldBeGreaterThan, 0)
Println(len(resD))
So(len(resL), ShouldBeGreaterThan, 0)
Println(len(resL))
}))
}
func TestService_HelpSearch(t *testing.T) {
Convey("test help HelpSearch", t, WithService(func(s *Service) {
pTypeID := "39e79104ca5d433f9d9cdf9df4bf28a0"
keyWords := "aaa"
res, total, err := s.HelpSearch(context.Background(), pTypeID, keyWords, 0, 1, 15)
So(err, ShouldBeNil)
So(total, ShouldBeGreaterThan, 0)
So(len(res), ShouldBeGreaterThan, 0)
Println(len(res))
}))
}

View File

@@ -0,0 +1,108 @@
package service
import (
"context"
"sort"
"strings"
"sync"
"time"
"go-common/app/interface/main/web/model"
resmdl "go-common/app/service/main/resource/model"
"go-common/library/log"
)
const (
_iconFixType = "fix"
)
// IndexIcon get index icons
func (s *Service) IndexIcon() (res *model.IndexIcon) {
return s.indexIcon
}
func fmtIndexIcon(icons []*resmdl.IndexIcon) {
for _, v := range icons {
v.Icon = strings.Replace(v.Icon, "http://", "//", 1)
}
}
func (s *Service) randomIndexIcon(icons []*resmdl.IndexIcon) (icon *model.IndexIcon) {
var (
item *resmdl.IndexIcon
total, weight int
)
length := len(icons)
if length == 0 {
return new(model.IndexIcon)
}
for _, v := range icons {
if v.Weight == 0 {
total++
} else {
total += v.Weight
}
}
if total == length {
item = icons[s.r.Intn(length)]
return &model.IndexIcon{ID: item.ID, Title: item.Title, Links: item.Links, Icon: item.Icon, Weight: item.Weight}
}
randWeight := s.r.Intn(total)
for _, v := range icons {
if v.Weight == 0 {
weight++
} else {
weight += v.Weight
}
if weight > randWeight {
item = v
break
}
}
return &model.IndexIcon{ID: item.ID, Title: item.Title, Links: item.Links, Icon: item.Icon, Weight: item.Weight}
}
func (s *Service) indexIconproc() {
var (
data map[string][]*resmdl.IndexIcon
icons []*resmdl.IndexIcon
ok bool
err error
mutex = sync.RWMutex{}
)
go func() {
for {
if data, err = s.res.IndexIcon(context.Background()); err != nil {
log.Error("s.res.IndexIcon error(%v)", err)
time.Sleep(time.Second)
continue
}
mutex.Lock()
icons, ok = data[_iconFixType]
mutex.Unlock()
if ok {
if len(icons) == 0 {
log.Error("s.res.IndexIcon data error")
time.Sleep(time.Second)
continue
} else {
sort.Slice(icons, func(i, j int) bool { return icons[i].Weight > icons[j].Weight })
fmtIndexIcon(icons)
}
} else {
log.Error("s.res.IndexIcon data error")
time.Sleep(time.Second)
continue
}
time.Sleep(time.Duration(s.c.WEB.PullOnlineInterval))
}
}()
for {
mutex.RLock()
tempIcons := make([]*resmdl.IndexIcon, len(icons))
copy(tempIcons, icons)
mutex.RUnlock()
s.indexIcon = s.randomIndexIcon(tempIcons)
time.Sleep(500 * time.Millisecond)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
package service
import (
"context"
"go-common/app/service/main/location/model"
"go-common/library/log"
"go-common/library/net/metadata"
)
// IPZone get ip zone info by ip
func (s *Service) IPZone(c context.Context) (res *model.Info, err error) {
ip := metadata.String(c, metadata.RemoteIP)
if res, err = s.loc.Info(c, &model.ArgIP{IP: ip}); err != nil {
log.Error("s.loc.Info(%s) error(%v)", ip, err)
}
return
}

View File

@@ -0,0 +1,16 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_IPZone(t *testing.T) {
Convey("test ip IPZone", t, WithService(func(s *Service) {
res, err := s.IPZone(context.Background())
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,162 @@
package service
import (
"context"
"go-common/app/interface/main/web/model"
arcmdl "go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
coinmdl "go-common/app/service/main/coin/api"
favmdl "go-common/app/service/main/favorite/model"
thumbup "go-common/app/service/main/thumbup/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
)
const (
_businessLike = "archive"
)
// Like like archive.
func (s *Service) Like(c context.Context, aid, mid int64, like int8) (upperID int64, err error) {
var (
arcReply *arcmdl.ArcReply
ip = metadata.String(c, metadata.RemoteIP)
)
if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
log.Error("s.arcClient.Arc(%d) error(%v)", aid, err)
return
}
arc := arcReply.Arc
if !arc.IsNormal() {
err = ecode.ArchiveNotExist
return
}
upperID = arc.Author.Mid
err = s.thumbup.Like(c, &thumbup.ArgLike{Mid: mid, UpMid: upperID, Business: _businessLike, MessageID: aid, Type: like, RealIP: ip})
return
}
// LikeTriple like & coin & fav
func (s *Service) LikeTriple(c context.Context, aid, mid int64) (res *model.TripleRes, err error) {
var (
arcReply *arcmdl.ArcReply
ip = metadata.String(c, metadata.RemoteIP)
)
res = new(model.TripleRes)
maxCoin := int64(1)
multiply := int64(1)
if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
log.Error("s.arcClient.Arc(%d) error(%v)", aid, err)
return
}
a := arcReply.Arc
if !a.IsNormal() {
err = ecode.ArchiveNotExist
return
}
if a.Copyright == int32(archive.CopyrightOriginal) {
maxCoin = 2
multiply = 2
}
res.UpID = a.Author.Mid
eg := errgroup.Group{}
eg.Go(func() (err error) {
if multiply == 2 {
if userCoins, e := s.coinClient.UserCoins(c, &coinmdl.UserCoinsReq{Mid: mid}); e != nil {
log.Error("s.coinClient.UserCoins error(%v)", e)
} else if userCoins != nil {
if userCoins.Count < 1 {
return
}
if userCoins.Count < 2 {
multiply = 1
}
}
}
cArg := &coinmdl.AddCoinReq{
IP: ip,
Mid: mid,
Upmid: a.Author.Mid,
MaxCoin: maxCoin,
Aid: aid,
Business: model.CoinArcBusiness,
Number: multiply,
Typeid: a.TypeID,
PubTime: int64(a.PubDate),
}
if _, err = s.coinClient.AddCoin(c, cArg); err != nil {
log.Error("s.coinClient.AddCoin error(%v)", err)
err = nil
if arcUserCoins, e := s.coinClient.ItemUserCoins(c, &coinmdl.ItemUserCoinsReq{Mid: mid, Aid: aid, Business: model.CoinArcBusiness}); e != nil {
log.Error("s.coinClient.ItemUserCoins error(%v)", e)
} else {
if arcUserCoins != nil && arcUserCoins.Number > 0 {
res.Coin = true
}
}
} else {
res.Multiply = multiply
res.Anticheat = true
res.Coin = true
}
return
})
eg.Go(func() (err error) {
var isFav bool
if isFav, err = s.fav.IsFav(context.Background(), &favmdl.ArgIsFav{Type: favmdl.TypeVideo, Mid: mid, Oid: aid, RealIP: ip}); err != nil {
log.Error("s.fav.IsFav error(%v)", err)
err = nil
} else if isFav {
res.Fav = true
return
}
fArg := &favmdl.ArgAdd{Type: favmdl.TypeVideo, Mid: mid, Oid: aid, Fid: 0, RealIP: ip}
if err = s.fav.Add(c, fArg); err != nil {
if ecode.FavVideoExist.Equal(err) {
res.Fav = true
return
}
log.Error("s.fav.Add error(%v)", err)
err = nil
} else {
res.Fav = true
res.Anticheat = true
}
return
})
eg.Go(func() (err error) {
if err = s.thumbup.Like(c, &thumbup.ArgLike{Mid: mid, UpMid: res.UpID, Business: _businessLike, MessageID: aid, Type: thumbup.TypeLike, RealIP: ip}); err != nil {
if ecode.ThumbupDupLikeErr.Equal(err) {
res.Like = true
return
}
log.Error("s.thumbup.Like error(%v)", err)
err = nil
} else {
res.Like = true
res.Anticheat = true
}
return
})
eg.Wait()
return
}
// HasLike get if has like.
func (s *Service) HasLike(c context.Context, aid, mid int64) (like int8, err error) {
var (
data map[int64]int8
ip = metadata.String(c, metadata.RemoteIP)
)
if data, err = s.thumbup.HasLike(c, &thumbup.ArgHasLike{Business: _businessLike, MessageIDs: []int64{aid}, Mid: mid, RealIP: ip}); err != nil {
log.Error("s.thumbup.HasLike aid(%d) mid(%d) error(%v)", aid, mid, err)
return
}
if v, ok := data[aid]; ok {
like = v
}
return
}

View File

@@ -0,0 +1,100 @@
package service
import (
"context"
"go-common/app/interface/main/web/model"
accmdl "go-common/app/service/main/account/api"
coupon "go-common/app/service/main/coupon/model"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
// Nav api service
func (s *Service) Nav(c context.Context, mid int64, cookie string) (resp *model.NavResp, err error) {
var (
wallet *model.Wallet
hasShop bool
shopURL string
allowance int
)
profile := new(accmdl.ProfileStatReply)
eg, egCtx := errgroup.WithContext(c)
eg.Go(func() error {
var e error
if profile, e = s.accClient.ProfileWithStat3(egCtx, &accmdl.MidReq{Mid: mid}); e != nil {
log.Error("s.accClient.ProfileWithStat3(%d) error %v", mid, e)
profile = model.DefaultProfile
profile.Profile.Mid = mid
}
return nil
})
eg.Go(func() error {
var shop *model.ShopInfo
var e error
if shop, e = s.dao.ShopInfo(egCtx, mid); e == nil && shop != nil {
hasShop = true
shopURL = shop.JumpURL
} else {
log.Warn("s.dao.ShopInfo(%v) error(%+v)", mid, e)
}
return nil
})
eg.Go(func() error {
var e error
if wallet, e = s.dao.Wallet(egCtx, mid); e != nil || wallet == nil {
log.Error("s.dao.Wallet(%d) error(%v)", mid, e)
if wallet, e = s.dao.OldWallet(egCtx, mid); e != nil || wallet == nil {
log.Error("s.dao.OldWallet(%d) error(%v)", mid, e)
}
} else {
log.Info("account wallet mid(%d)", mid)
}
return nil
})
eg.Go(func() error {
var e error
if allowance, e = s.coupon.AllowanceCount(egCtx, &coupon.ArgAllowanceMid{Mid: mid}); e != nil {
log.Error("s.coupon.AllowanceCount(%d) error(%v)", mid, e)
}
return nil
})
eg.Wait()
resp = &model.NavResp{
IsLogin: true,
EmailVerified: int(profile.Profile.EmailStatus),
Face: profile.Profile.Face,
Mid: profile.Profile.Mid,
MobileVerified: int(profile.Profile.TelStatus),
Coins: profile.Coins,
Moral: float32(profile.Profile.Moral),
Pendant: profile.Profile.Pendant,
Uname: profile.Profile.Name,
VipDueDate: profile.Profile.Vip.DueDate,
VipStatus: int(profile.Profile.Vip.Status),
VipType: int(profile.Profile.Vip.Type),
VipPayType: profile.Profile.Vip.VipPayType,
Wallet: wallet,
HasShop: hasShop,
ShopURL: shopURL,
AllowanceCount: allowance,
}
if profile.Profile.Official.Role == 0 {
resp.OfficialVerify.Type = -1
} else {
if profile.Profile.Official.Role <= 2 {
resp.OfficialVerify.Type = 0
} else {
resp.OfficialVerify.Type = 1
}
resp.OfficialVerify.Desc = profile.Profile.Official.Title
}
resp.LevelInfo.Cur = int(profile.LevelInfo.Cur)
resp.LevelInfo.Min = int(profile.LevelInfo.Min)
resp.LevelInfo.NowExp = int(profile.LevelInfo.NowExp)
resp.LevelInfo.NextExp = profile.LevelInfo.NextExp
if profile.LevelInfo.NextExp == -1 {
resp.LevelInfo.NextExp = "--"
}
return
}

View File

@@ -0,0 +1,20 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_Nav(t *testing.T) {
Convey("test nav Nav", t, WithService(func(s *Service) {
var (
mid int64
ck = ""
)
res, err := s.Nav(context.Background(), mid, ck)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,134 @@
package service
import (
"context"
"go-common/app/interface/main/web/conf"
"go-common/app/interface/main/web/model"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
const _allRank = 0
// NewList get new list by region id.
func (s *Service) NewList(c context.Context, rid int32, tp int8, pn, ps int) (arcs []*api.Arc, count int, err error) {
var (
addCache = true
first bool
allArcs, moreArcs []*api.Arc
start, end, max int
ip = metadata.String(c, metadata.RemoteIP)
)
// check first or second region id.
if _, ok := s.rids[rid]; ok {
first = true
}
if first {
max = s.c.Rule.MaxFirstCacheSize
end = max
} else {
max = s.c.Rule.MaxSecondCacheSize
start = (pn - 1) * ps
end = start + ps - 1
if start < 0 || end < 0 {
err = ecode.RequestErr
return
}
}
// get from local cache.
if arcs, count, err = s.dao.NewListCache(c, rid, tp, start, end); err != nil {
err = nil
addCache = false
} else if len(arcs) > 0 {
return
}
// get from archive-service
if first {
if allArcs, count, err = s.rankTopArcs(c, rid, tp, 1, max, ip); err != nil {
err = nil
} else if tid, ok := model.NewListRid[rid]; ok && len(allArcs) < conf.Conf.Rule.MinNewListCnt {
if moreArcs, _, err = s.rankArcs(c, tid, tp, _samplePn, conf.Conf.Rule.MinNewListCnt, ip); err != nil {
err = nil
} else {
allAidMap := make(map[int64]int64, len(allArcs))
for _, arc := range allArcs {
allAidMap[arc.Aid] = arc.Aid
}
for _, v := range moreArcs {
if _, ok := allAidMap[v.Aid]; ok {
continue
}
allArcs = append(allArcs, v)
}
log.Info("NewList more arcs rid(%d) tid(%d) len allArcs(%d) len moreArcs(%d)", tid, rid, len(allArcs), len(moreArcs))
}
}
} else {
if start >= max {
if arcs, count, err = s.rankArcs(c, rid, tp, pn, ps, ip); err != nil {
return
}
fmtArcs3(arcs)
return
}
if allArcs, count, err = s.rankArcs(c, rid, tp, 1, max, ip); err != nil {
err = nil
}
}
if len(allArcs) > 0 {
fmtArcs3(allArcs)
length := len(allArcs)
if length < start {
arcs = []*api.Arc{}
return
}
if length > end {
arcs = allArcs[start : end+1]
} else {
arcs = allArcs[start:]
}
if addCache {
s.cache.Do(c, func(c context.Context) {
s.dao.SetNewListCache(c, rid, tp, allArcs, count)
})
}
return
}
// get from remote cache.
arcs, count, err = s.dao.NewListBakCache(c, rid, tp, start, end)
if len(arcs) == 0 {
arcs = []*api.Arc{}
}
return
}
func (s *Service) rankArcs(c context.Context, rid int32, tp int8, pn, ps int, ip string) (arcs []*api.Arc, count int, err error) {
var res = &archive.RankArchives3{}
if rid == _allRank {
if res, err = s.arc.RankAllArcs3(c, &archive.ArgRankAll2{Pn: pn, Ps: ps}); err != nil {
log.Error("arcrpc.RankAllArcs2(%d,%d) error(%v)", pn, ps, err)
return
}
} else {
arg := &archive.ArgRank2{Rid: int16(rid), Type: tp, Pn: pn, Ps: ps, RealIP: ip}
if res, err = s.arc.RankArcs3(c, arg); err != nil {
log.Error("arcrpc.RankArcs2(%d,%d,%d,%s) error(%v)", rid, pn, ps, ip, err)
return
}
}
arcs = res.Archives
count = res.Count
return
}
func (s *Service) rankTopArcs(c context.Context, rid int32, tp int8, pn, ps int, ip string) (arcs []*api.Arc, count int, err error) {
arg := &archive.ArgRankTop2{ReID: int16(rid), Pn: pn, Ps: ps}
if arcs, err = s.arc.RankTopArcs3(c, arg); err != nil {
log.Error("arcrpc.RankTopArcs3(%d,%d,%d,%s) error(%v)", rid, pn, ps, ip, err)
}
return
}

View File

@@ -0,0 +1,26 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_NewList1(t *testing.T) {
Convey("should return without err", t, WithService(func(svf *Service) {
res, count, err := svf.NewList(context.Background(), 129, 1, 1, 10)
So(err, ShouldBeNil)
So(count, ShouldBeGreaterThan, 0)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_NewList2(t *testing.T) {
Convey("should return without err", t, WithService(func(svf *Service) {
res, count, err := svf.NewList(context.Background(), 1, 1, 1, 10)
So(err, ShouldBeNil)
So(count, ShouldBeGreaterThan, 0)
So(len(res), ShouldBeGreaterThan, 0)
}))
}

View File

@@ -0,0 +1,161 @@
package service
import (
"context"
"sync/atomic"
"time"
"go-common/app/interface/main/web/model"
arcmdl "go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/log"
)
const (
_onlineListNum = 50
_onlinePubdateLimit = 86400
_onlineDanmuLimit = 3
)
// OnlineArchiveCount Get Archive Count.
func (s *Service) OnlineArchiveCount(c context.Context) (rs *model.Online) {
rs = &model.Online{
RegionCount: s.regionCount,
AllCount: s.allArchivesCount,
PlayOnline: s.playOnline,
WebOnline: s.webOnline,
}
return
}
// OnlineList online archive list.
func (s *Service) OnlineList(c context.Context) (res []*model.OnlineArc, err error) {
res = s.onlineArcs
if len(res) > 0 {
return
}
return s.dao.OnlineListBakCache(c)
}
func (s *Service) newCountproc() {
var (
allCount int64
reIDs []int16
err error
res map[int16]int
)
for {
for len(s.rids) == 0 {
time.Sleep(time.Second)
}
reIDs = []int16{}
allCount = 0
for regionID := range s.rids {
reIDs = append(reIDs, int16(regionID))
}
arg := &archive.ArgRankTopsCount2{ReIDs: reIDs}
if res, err = s.arc.RanksTopCount2(context.Background(), arg); err != nil {
log.Error("s.arc.RanksTopCount2(%v) error (%v)", arg, err)
time.Sleep(time.Second)
continue
} else if len(res) == 0 {
log.Error("s.arc.RanksTopCount2(%v) res len(%d) == 0", arg, res)
time.Sleep(time.Second)
continue
}
s.regionCount = res
for _, count := range res {
allCount += int64(count)
}
if allCount > 0 {
atomic.StoreInt64(&s.allArchivesCount, allCount)
}
time.Sleep(time.Duration(s.c.WEB.PullRegionInterval))
}
}
func (s *Service) onlineCountproc() {
var (
count *model.OnlineCount
liveCount *model.LiveOnlineCount
playOnline, webOnline int64
err error
)
for {
if count, err = s.dao.OnlineCount(context.Background()); err != nil {
time.Sleep(time.Second)
continue
} else if count != nil {
playOnline = count.ConnCount
webOnline = count.IPCount
}
if liveCount, err = s.dao.LiveOnlineCount(context.Background()); err != nil || liveCount == nil {
time.Sleep(time.Second)
continue
} else if liveCount != nil {
playOnline += liveCount.TotalOnline
webOnline += liveCount.IPConnect
}
if playOnline > 0 && webOnline > 0 {
atomic.StoreInt64(&s.playOnline, playOnline)
atomic.StoreInt64(&s.webOnline, webOnline)
}
time.Sleep(time.Duration(s.c.WEB.PullRegionInterval))
}
}
func (s *Service) onlineListproc() {
var (
err error
aids []*model.OnlineAid
arcs *arcmdl.ArcsReply
)
for {
if aids, err = s.dao.OnlineList(context.Background(), _onlineListNum); err != nil {
time.Sleep(time.Second)
continue
} else if len(aids) == 0 {
log.Error("s.dao.OnlineList data len == 0")
time.Sleep(time.Second)
continue
}
var aidArg []int64
for _, v := range aids {
aidArg = append(aidArg, v.Aid)
}
archivesArgLog("onlineListproc", aidArg)
if arcs, err = s.arcClient.Arcs(context.Background(), &arcmdl.ArcsRequest{Aids: aidArg}); err != nil {
log.Error("s.arcClient.Arcs(%v) error (%v)", aidArg, err)
time.Sleep(time.Second)
continue
} else {
var onlineArcs []*model.OnlineArc
for _, v := range aids {
if arc, ok := arcs.Arcs[v.Aid]; ok && arc != nil && arc.IsNormal() && arc.AttrVal(archive.AttrBitNoRank) == archive.AttrNo {
if arc.AttrVal(archive.AttrBitIsBangumi) == archive.AttrNo && arc.AttrVal(archive.AttrBitIsMovie) == archive.AttrNo {
if time.Now().Unix()-int64(arc.PubDate) > _onlinePubdateLimit {
if arc.Stat.Danmaku == 0 || v.Count/int64(arc.Stat.Danmaku) > _onlineDanmuLimit {
continue
}
}
}
onlineArcs = append(onlineArcs, &model.OnlineArc{Arc: arc, OnlineCount: v.Count})
if len(onlineArcs) >= s.c.WEB.OnlineCount {
break
}
}
}
if len(onlineArcs) >= s.c.WEB.OnlineCount {
s.onlineArcs = onlineArcs
s.cache.Do(context.Background(), func(c context.Context) {
s.dao.SetOnlineListBakCache(context.Background(), onlineArcs)
})
} else {
log.Error("s.dao.OnlineList data len(%d) error", len(onlineArcs))
time.Sleep(time.Second)
continue
}
}
time.Sleep(time.Duration(s.c.WEB.PullOnlineInterval))
}
}

View File

@@ -0,0 +1,23 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_OnlineList(t *testing.T) {
Convey("online list", t, WithService(func(s *Service) {
data, err := s.OnlineList(context.Background())
So(err, ShouldBeNil)
Printf("%v", data)
}))
}
func TestService_OnlineArchiveCount(t *testing.T) {
Convey("test online OnlineArchiveCount", t, WithService(func(s *Service) {
res := s.OnlineArchiveCount(context.Background())
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,572 @@
package service
import (
"context"
"strconv"
"time"
"go-common/app/interface/main/web/model"
arcmdl "go-common/app/service/main/archive/api"
"go-common/library/log"
)
const (
_rankIndexLen = 8
_rankLen = 100
_rankRegionLen = 10
_rankOtherLimit = 10
_avType = "av"
)
var (
_emptyRankArchive = make([]*model.RankArchive, 0)
)
// Ranking get ranking data.
func (s *Service) Ranking(c context.Context, rid int16, rankType, day, arcType int) (res *model.RankData, err error) {
var (
rankArc *model.RankNew
addCache = true
)
if res, err = s.dao.RankingCache(c, rid, rankType, day, arcType); err != nil {
err = nil
addCache = false
} else if res != nil && len(res.List) > 0 {
return
}
if rankArc, err = s.dao.Ranking(c, rid, rankType, day, arcType); err != nil {
err = nil
} else if rankArc != nil && len(rankArc.List) > s.c.Rule.MinRankCount {
res = &model.RankData{Note: rankArc.Note}
if res.List, err = s.fmtRankArcs(c, rankArc.List, _rankLen); err != nil {
err = nil
} else if len(res.List) > 0 {
if addCache {
s.cache.Do(c, func(c context.Context) {
s.dao.SetRankingCache(c, rid, rankType, day, arcType, res)
})
}
return
}
} else {
log.Error("s.dao.RankingNew(%d,%d,%d) len(aids) (%d)", rid, day, arcType, len(rankArc.List))
}
res, err = s.dao.RankingBakCache(c, rid, rankType, day, arcType)
if res == nil || len(res.List) == 0 {
res = &model.RankData{List: _emptyRankArchive}
}
return
}
// RankingIndex get index ranking data
func (s *Service) RankingIndex(c context.Context, day int) (res []*model.IndexArchive, err error) {
var (
addCache = true
rs []*model.NewArchive
arcs map[int64]*arcmdl.Arc
)
if res, err = s.dao.RankingIndexCache(c, day); err != nil {
err = nil
addCache = false
} else if len(res) > 0 {
return
}
if rs, err = s.dao.RankingIndex(c, day); err != nil {
err = nil
} else if len(rs) > s.c.Rule.MinRankIndexCount {
if arcs, err = s.fillArcs(c, rs); err != nil {
err = nil
} else if len(arcs) > 0 {
res = fmtIndexArcs(rs, arcs)
if addCache {
s.cache.Do(c, func(c context.Context) {
s.dao.SetRankingIndexCache(c, day, res)
})
}
return
}
} else {
log.Error("s.dao.RankingIndexCache(%d) len(aids) (%d)", day, len(res))
}
if res, err = s.dao.RankingIndexBakCache(c, day); err != nil {
return
}
if len(res) == 0 {
res = []*model.IndexArchive{}
}
return
}
// RankingRegion get region ranking data
func (s *Service) RankingRegion(c context.Context, rid int16, day, original int) (res []*model.RegionArchive, err error) {
var (
addCache = true
rs []*model.NewArchive
arcs map[int64]*arcmdl.Arc
)
defer func() {
if len(res) > 0 {
s.fmtRegionStats(c, res)
}
}()
if res, err = s.dao.RankingRegionCache(c, rid, day, original); err != nil {
err = nil
addCache = false
} else if len(res) > 0 {
return
}
if rs, err = s.dao.RankingRegion(c, rid, day, original); err != nil {
err = nil
} else if len(rs) > s.c.Rule.MinRankRegionCount {
if arcs, err = s.fillArcs(c, rs); err != nil {
err = nil
} else if len(arcs) > 0 {
res = fmtRegionArcs(rs, arcs)
if addCache {
s.cache.Do(c, func(c context.Context) {
s.dao.SetRankingRegionCache(c, rid, day, original, res)
})
}
return
}
} else {
log.Error("s.dao.RankingRegion(%d,%d,%d) len(aids) (%d)", rid, day, original, len(rs))
}
res, err = s.dao.RankingRegionBakCache(c, rid, day, original)
if len(res) == 0 {
res = []*model.RegionArchive{}
}
return
}
// RankingRecommend get rank recommend data.
func (s *Service) RankingRecommend(c context.Context, rid int16) (res []*model.IndexArchive, err error) {
var (
addCache = true
rs []*model.NewArchive
arcs map[int64]*arcmdl.Arc
)
if res, err = s.dao.RankingRecommendCache(c, rid); err != nil {
err = nil
addCache = false
} else if len(res) > 0 {
return
}
if rs, err = s.dao.RankingRecommend(c, rid); err != nil {
err = nil
} else if len(rs) > s.c.Rule.MinRankRecCount {
if arcs, err = s.fillArcs(c, rs); err != nil {
err = nil
} else if len(arcs) > 0 {
res = fmtIndexArcs(rs, arcs)
if addCache {
s.cache.Do(c, func(c context.Context) {
s.dao.SetRankingRecommendCache(c, rid, res)
})
}
return
}
} else {
log.Error("s.dao.RankingRecommend(%d) len(aids) (%d)", rid, len(res))
}
res, err = s.dao.RankingRecommendBakCache(c, rid)
if len(res) == 0 {
res = []*model.IndexArchive{}
}
return
}
// RankingTag get tag ranking data
func (s *Service) RankingTag(c context.Context, rid int16, tagID int64) (res []*model.TagArchive, err error) {
var (
addCache = true
tagArcs []*model.NewArchive
arcsReply *arcmdl.ArcsReply
)
defer func() {
s.fmtTagStats(c, res)
}()
if res, err = s.dao.RankingTagCache(c, rid, tagID); err != nil {
err = nil
addCache = false
} else if len(res) > 0 {
return
}
if tagArcs, err = s.dao.RankingTag(c, rid, tagID); err != nil {
err = nil
} else if len(tagArcs) > s.c.Rule.MinRankTagCount {
var aids []int64
for _, v := range tagArcs {
aids = append(aids, v.Aid)
}
if arcsReply, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
err = nil
} else if len(arcsReply.Arcs) > 0 {
res = fmtTagArchives(tagArcs, arcsReply.Arcs)
if addCache {
s.cache.Do(c, func(c context.Context) {
s.dao.SetRankingTagCache(c, rid, tagID, res)
})
}
}
return
} else {
log.Error("s.dao.RankingRecommend(%d) len(aids) (%d)", rid, len(res))
}
res, err = s.dao.RankingTagBakCache(c, rid, tagID)
if len(res) == 0 {
res = []*model.TagArchive{}
}
return
}
// RegionCustom region custom data
func (s *Service) RegionCustom(c context.Context) (res []*model.Custom, err error) {
var (
addCache = true
aids []int64
arcsReply *arcmdl.ArcsReply
)
if res, err = s.dao.RegionCustomCache(c); err != nil {
err = nil
addCache = false
} else if len(res) > 0 {
return
}
if res, err = s.dao.RegionCustom(c); err != nil {
log.Error("s.dao.RegionCustom error(%v)", err)
res = []*model.Custom{}
return
} else if len(res) > 0 {
for _, item := range res {
if item.Type == _avType && item.Aid > 0 {
aids = append(aids, item.Aid)
}
}
if len(aids) > 0 {
archivesArgLog("RegionCustom", aids)
if arcsReply, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
log.Error("s.arcClient.Arcs(%v) error(%v)", aids, err)
err = nil
} else {
for _, v := range res {
if arc, ok := arcsReply.Arcs[v.Aid]; ok && v.Type == _avType {
v.Pic = arc.Pic
v.Title = arc.Title
}
}
}
}
if addCache {
s.cache.Do(c, func(c context.Context) {
s.dao.SetRegionCustomCache(c, res)
})
}
return
}
res, err = s.dao.RegionCustomBakCache(c)
if len(res) == 0 {
res = []*model.Custom{}
}
return
}
func (s *Service) fillArcs(c context.Context, rankArchives []*model.NewArchive) (res map[int64]*arcmdl.Arc, err error) {
var (
aids []int64
arcsReply *arcmdl.ArcsReply
)
for _, arc := range rankArchives {
if arc == nil {
continue
}
aids = append(aids, arc.Aid)
}
archivesArgLog("fillArcs", aids)
if arcsReply, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
log.Error("s.arcClient.Arcs(%v) error(%v)", aids, err)
return
}
res = arcsReply.Arcs
return
}
func fmtRegionArcs(aids []*model.NewArchive, arcs map[int64]*arcmdl.Arc) (res []*model.RegionArchive) {
for _, arc := range aids {
if arc == nil {
continue
}
if len(res) > _rankRegionLen {
break
}
if _, ok := arcs[arc.Aid]; !ok {
continue
}
regionArchive := &model.RegionArchive{
Aid: strconv.FormatInt(arcs[arc.Aid].Aid, 10),
Typename: arcs[arc.Aid].TypeName,
Title: arcs[arc.Aid].Title,
Play: fmtArcView(arcs[arc.Aid]),
Review: arcs[arc.Aid].Stat.Reply,
VideoReview: arcs[arc.Aid].Stat.Danmaku,
Favorites: arcs[arc.Aid].Stat.Fav,
Mid: arcs[arc.Aid].Author.Mid,
Author: arcs[arc.Aid].Author.Name,
Description: arcs[arc.Aid].Desc,
Create: time.Unix(int64(arcs[arc.Aid].PubDate), 0).Format("2006-01-02 15:04"),
Pic: arcs[arc.Aid].Pic,
Coins: arcs[arc.Aid].Stat.Coin,
Duration: fmtDuration(arcs[arc.Aid].Duration),
Pts: arc.Score,
Rights: arcs[arc.Aid].Rights,
}
res = append(res, regionArchive)
}
return
}
func fmtIndexArcs(aids []*model.NewArchive, arcs map[int64]*arcmdl.Arc) (res []*model.IndexArchive) {
var (
typeName string
ok bool
)
for _, arc := range aids {
if arc == nil {
continue
}
if len(res) > _rankIndexLen {
break
}
if _, ok = arcs[arc.Aid]; !ok {
continue
}
if typeName, ok = model.RecSpecTypeName[arcs[arc.Aid].TypeID]; !ok {
typeName = arcs[arc.Aid].TypeName
}
indexArchive := &model.IndexArchive{
Aid: strconv.FormatInt(arcs[arc.Aid].Aid, 10),
Typename: typeName,
Title: arcs[arc.Aid].Title,
Play: fmtArcView(arcs[arc.Aid]),
Review: arcs[arc.Aid].Stat.Reply,
VideoReview: arcs[arc.Aid].Stat.Danmaku,
Favorites: arcs[arc.Aid].Stat.Fav,
Mid: arcs[arc.Aid].Author.Mid,
Author: arcs[arc.Aid].Author.Name,
Description: arcs[arc.Aid].Desc,
Create: time.Unix(int64(arcs[arc.Aid].PubDate), 0).Format("2006-01-02 15:04"),
Pic: arcs[arc.Aid].Pic,
Coins: arcs[arc.Aid].Stat.Coin,
Duration: fmtDuration(arcs[arc.Aid].Duration),
Rights: arcs[arc.Aid].Rights,
}
res = append(res, indexArchive)
}
return
}
func (s *Service) fmtRankArcs(c context.Context, rankArchives []*model.RankNewArchive, arcLen int) (res []*model.RankArchive, err error) {
var (
aids []int64
arcsReply *arcmdl.ArcsReply
)
for _, arc := range rankArchives {
if arc == nil {
continue
}
aids = append(aids, arc.Aid)
if len(arc.Others) > 0 {
i := 0
for _, a := range arc.Others {
if a == nil {
continue
}
aids = append(aids, a.Aid)
i++
if i >= _rankOtherLimit {
break
}
}
}
}
archivesArgLog("fmtRankArcs", aids)
if arcsReply, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
log.Error("s.arcClient.Arcs(%v) error(%v)", aids, err)
return
}
for _, arc := range rankArchives {
if arc == nil {
continue
}
if len(res) > arcLen {
break
}
if _, ok := arcsReply.Arcs[arc.Aid]; !ok {
continue
}
var coin, danmu int32
if arc.RankStat == nil {
coin = arcsReply.Arcs[arc.Aid].Stat.Coin
danmu = arcsReply.Arcs[arc.Aid].Stat.Danmaku
} else {
coin = arc.RankStat.Coin
danmu = arc.RankStat.Danmu
arcsReply.Arcs[arc.Aid].Stat.View = arc.RankStat.Play
}
rankArchive := &model.RankArchive{
Aid: strconv.FormatInt(arcsReply.Arcs[arc.Aid].Aid, 10),
Author: arcsReply.Arcs[arc.Aid].Author.Name,
Coins: coin,
Duration: fmtDuration(arcsReply.Arcs[arc.Aid].Duration),
Mid: arcsReply.Arcs[arc.Aid].Author.Mid,
Pic: arcsReply.Arcs[arc.Aid].Pic,
Play: fmtArcView(arcsReply.Arcs[arc.Aid]),
Pts: arc.Score,
Title: arcsReply.Arcs[arc.Aid].Title,
VideoReview: danmu,
Rights: arcsReply.Arcs[arc.Aid].Rights,
}
if len(arc.Others) > 0 {
for _, a := range arc.Others {
if a == nil {
continue
}
if _, ok := arcsReply.Arcs[a.Aid]; !ok {
continue
}
archive := &model.Other{
Aid: a.Aid,
Play: fmtArcView(arcsReply.Arcs[a.Aid]),
VideoReview: arcsReply.Arcs[a.Aid].Stat.Danmaku,
Coins: arcsReply.Arcs[a.Aid].Stat.Coin,
Pts: a.Score,
Title: arcsReply.Arcs[a.Aid].Title,
Pic: arcsReply.Arcs[a.Aid].Pic,
Duration: fmtDuration(arcsReply.Arcs[a.Aid].Duration),
Rights: arcsReply.Arcs[a.Aid].Rights,
}
rankArchive.Others = append(rankArchive.Others, archive)
}
}
res = append(res, rankArchive)
}
return
}
// fmtRegionStats get real time region archive stat
func (s *Service) fmtRegionStats(c context.Context, res []*model.RegionArchive) {
var (
aids []int64
aid int64
err error
statsReply *arcmdl.StatsReply
)
for _, arc := range res {
if arc == nil {
continue
}
if aid, err = strconv.ParseInt(arc.Aid, 10, 64); err != nil {
continue
}
aids = append(aids, aid)
}
if len(aids) == 0 {
return
}
if statsReply, err = s.arcClient.Stats(c, &arcmdl.StatsRequest{Aids: aids}); err != nil {
log.Error("s.arcClient.Stats(%v) error(%v)", aids, err)
return
}
arcStats := statsReply.Stats
for _, arc := range res {
if aid, err = strconv.ParseInt(arc.Aid, 10, 64); err != nil {
continue
}
if arcStat, ok := arcStats[aid]; ok {
arc.Play = arcStat.View
arc.VideoReview = arcStat.Danmaku
arc.Favorites = arcStat.Fav
arc.Coins = arcStat.Coin
}
}
}
func fmtTagArchives(tagArcs []*model.NewArchive, arcs map[int64]*arcmdl.Arc) (res []*model.TagArchive) {
for _, tagArc := range tagArcs {
if arc, ok := arcs[tagArc.Aid]; ok {
res = append(res, &model.TagArchive{
Title: arc.Title,
Author: arc.Author.Name,
Description: arc.Desc,
Pic: arc.Pic,
Play: strconv.FormatInt(int64(arc.Stat.View), 10),
Favorites: strconv.FormatInt(int64(arc.Stat.Fav), 10),
Mid: strconv.FormatInt(arc.Author.Mid, 10),
Review: strconv.FormatInt(int64(arc.Stat.Reply), 10),
CreatedAt: time.Unix(int64(arcs[arc.Aid].PubDate), 0).Format("2006-01-02 15:04"),
VideoReview: strconv.FormatInt(int64(arc.Stat.Danmaku), 10),
Coins: strconv.FormatInt(int64(arc.Stat.Coin), 10),
Duration: strconv.FormatInt(arc.Duration, 10),
Aid: arc.Aid,
Pts: tagArc.Score,
Rights: arc.Rights,
})
}
}
return
}
// fmtTagStats get real time tag archive stat
func (s *Service) fmtTagStats(c context.Context, res []*model.TagArchive) {
var (
aids []int64
err error
statsReply *arcmdl.StatsReply
)
for _, arc := range res {
if arc == nil {
continue
}
aids = append(aids, arc.Aid)
}
if len(aids) == 0 {
return
}
if statsReply, err = s.arcClient.Stats(c, &arcmdl.StatsRequest{Aids: aids}); err != nil {
log.Error("s.arcClient.Stats(%v) error(%v)", aids, err)
return
}
arcStats := statsReply.Stats
for _, arc := range res {
if arcStat, ok := arcStats[arc.Aid]; ok {
arc.Play = strconv.FormatInt(int64(arcStat.View), 10)
arc.VideoReview = strconv.FormatInt(int64(arcStat.Danmaku), 10)
arc.Favorites = strconv.FormatInt(int64(arcStat.Fav), 10)
arc.Coins = strconv.FormatInt(int64(arcStat.Coin), 10)
}
}
}
func fmtDuration(duration int64) (du string) {
if duration == 0 {
du = "00:00"
} else {
var min, sec string
min = strconv.Itoa(int(duration / 60))
if int(duration%60) < 10 {
sec = "0" + strconv.Itoa(int(duration%60))
} else {
sec = strconv.Itoa(int(duration % 60))
}
du = min + ":" + sec
}
return
}
func fmtArcView(a *arcmdl.Arc) interface{} {
var view interface{} = a.Stat.View
if a.Access > 0 {
view = "--"
}
return view
}

View File

@@ -0,0 +1,100 @@
package service
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/web/conf"
. "github.com/smartystreets/goconvey/convey"
)
var svf *Service
func init() {
dir, _ := filepath.Abs("../cmd/web-interface-test.toml")
flag.Set("conf", dir)
if err := conf.Init(); err != nil {
panic(err)
}
if svf == nil {
svf = New(conf.Conf)
}
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
f(svf)
}
}
func TestService_RankingRegion1(t *testing.T) {
Convey("should return without err", t, WithService(func(svf *Service) {
res, err := svf.RankingRegion(context.Background(), 129, 3, 0)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_RankingRegion2(t *testing.T) {
Convey("should return without err", t, WithService(func(svf *Service) {
res, err := svf.RankingRegion(context.Background(), 129, 3, 1)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_RankingTag(t *testing.T) {
rid := int16(24)
tagID := int64(358)
Convey("should return without err", t, WithService(func(svf *Service) {
res, err := svf.RankingTag(context.Background(), rid, tagID)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_Ranking(t *testing.T) {
var (
rid int16 = 23
rankType = 1
day = 1
arcType = 1
)
Convey("test ranking Ranking", t, WithService(func(s *Service) {
res, err := s.Ranking(context.Background(), rid, rankType, day, arcType)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}
func TestService_RankingIndex(t *testing.T) {
Convey("test ranking RankingIndex", t, WithService(func(s *Service) {
day := 1
res, err := s.RankingIndex(context.Background(), day)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_RankingRecommend(t *testing.T) {
Convey("test ranking RankingRecommend", t, WithService(func(s *Service) {
rid := 1
res, err := s.RankingRecommend(context.Background(), int16(rid))
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_RegionCustom(t *testing.T) {
Convey("test ranking ReginCustom", t, WithService(func(s *Service) {
res, err := s.RegionCustom(context.Background())
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,45 @@
package service
import (
"context"
"go-common/app/interface/main/web/model"
resmdl "go-common/app/service/main/resource/model"
"go-common/library/log"
)
const (
_kvID = 2326
)
var _emptyAssi = make([]*model.Kv, 0)
// Kv get baidu kv
func (s *Service) Kv(c context.Context) (res []*model.Kv, err error) {
var tmp *resmdl.Resource
if tmp, err = s.res.Resource(c, &resmdl.ArgRes{ResID: _kvID}); err != nil {
log.Error("s.res.Resource(%d) error(%v)", _kvID, err)
return
}
if len(tmp.Assignments) == 0 {
res = _emptyAssi
return
}
for _, assi := range tmp.Assignments {
res = append(res, &model.Kv{ID: assi.ID, Name: assi.Name, Pic: assi.Pic, URL: assi.URL, ResID: assi.ResID, STime: assi.STime, ETime: assi.STime})
}
return
}
// CmtBox get live dm box
func (s *Service) CmtBox(c context.Context, id int64) (res *resmdl.Cmtbox, err error) {
if res, err = s.res.Cmtbox(c, &resmdl.ArgCmtbox{ID: id}); err != nil {
log.Error("s.res.Cmtbox(%d) error(%v)", id, err)
}
return
}
// AbServer get ab server info.
func (s *Service) AbServer(c context.Context, mid int64, platform int, channel, buvid string) (data model.AbServer, err error) {
return s.dao.AbServer(c, mid, platform, channel, buvid)
}

View File

@@ -0,0 +1,24 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_Kv(t *testing.T) {
Convey("test baidu Kv", t, WithService(func(s *Service) {
res, err := s.Kv(context.Background())
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
}))
}
func TestService_CmtBox(t *testing.T) {
Convey("test cmtbox", t, WithService(func(s *Service) {
res, err := s.CmtBox(context.Background(), 1)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,170 @@
package service
import (
"context"
"go-common/app/interface/main/web/model"
accmdl "go-common/app/service/main/account/api"
relmdl "go-common/app/service/main/relation/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const _searchEggWebPlat = 6
var _emptyUpRec = make([]*model.UpRecInfo, 0)
// SearchAll search type all.
func (s *Service) SearchAll(c context.Context, mid int64, arg *model.SearchAllArg, buvid, ua, typ string) (data *model.Search, err error) {
data, err = s.dao.SearchAll(c, mid, arg, buvid, ua, typ)
return
}
// SearchByType type video,bangumi,pgc,live,live_user,article,special,topic,bili_user,photo
func (s *Service) SearchByType(c context.Context, mid int64, arg *model.SearchTypeArg, buvid, ua string) (res *model.SearchTypeRes, err error) {
switch arg.SearchType {
case model.SearchTypeVideo:
if res, err = s.dao.SearchVideo(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypeBangumi:
if res, err = s.dao.SearchBangumi(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypePGC:
if res, err = s.dao.SearchPGC(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypeLive:
if res, err = s.dao.SearchLive(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypeLiveRoom:
if res, err = s.dao.SearchLiveRoom(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypeLiveUser:
if res, err = s.dao.SearchLiveUser(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypeArticle:
if res, err = s.dao.SearchArticle(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypeSpecial:
if res, err = s.dao.SearchSpecial(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypeTopic:
if res, err = s.dao.SearchTopic(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypeUser:
if res, err = s.dao.SearchUser(c, mid, arg, buvid, ua); err != nil {
return
}
case model.SearchTypePhoto:
if res, err = s.dao.SearchPhoto(c, mid, arg, buvid, ua); err != nil {
return
}
default:
err = ecode.RequestErr
return
}
return
}
// SearchRec search recommend data.
func (s *Service) SearchRec(c context.Context, mid int64, pn, ps int, keyword, fromSource, buvid, ua string) (data *model.SearchRec, err error) {
data, err = s.dao.SearchRec(c, mid, pn, ps, keyword, fromSource, buvid, ua)
return
}
// SearchDefault get search default word.
func (s *Service) SearchDefault(c context.Context, mid int64, fromSource, buvid, ua string) (data *model.SearchDefault, err error) {
data, err = s.dao.SearchDefault(c, mid, fromSource, buvid, ua)
return
}
// UpRec get up recommend
func (s *Service) UpRec(c context.Context, mid int64, arg *model.SearchUpRecArg, buvid string) (data *model.UpRecData, err error) {
var (
ups []*model.SearchUpRecRes
trackID string
mids []int64
cardsReply *accmdl.CardsReply
cardErr error
)
if ups, trackID, err = s.dao.UpRecommend(c, mid, arg, buvid); err != nil {
return
}
data = &model.UpRecData{TrackID: trackID}
if len(ups) == 0 {
data.List = _emptyUpRec
return
}
for _, v := range ups {
mids = append(mids, v.UpID)
}
relInfos := make(map[int64]*relmdl.Stat, len(mids))
group, errCtx := errgroup.WithContext(c)
group.Go(func() error {
if cardsReply, cardErr = s.accClient.Cards3(errCtx, &accmdl.MidsReq{Mids: mids}); cardErr != nil {
log.Error("UpRec s.accClient.Cards3(%v) error(%v)", mids, cardErr)
return cardErr
}
return nil
})
group.Go(func() error {
if relReply, relErr := s.relation.Stats(errCtx, &relmdl.ArgMids{Mids: mids}); relErr != nil {
log.Error("UpRec s.relation.Stats(%d,%v) error(%v)", mid, mids, relErr)
} else if relReply != nil {
relInfos = relReply
}
return nil
})
if err = group.Wait(); err != nil {
return
}
for _, v := range ups {
if info, ok := cardsReply.Cards[v.UpID]; ok && info != nil && info.Silence == 0 {
upInfo := &model.UpRecInfo{
Mid: info.Mid,
Name: info.Name,
Face: info.Face,
Official: info.Official,
RecReason: v.RecReason,
Tid: v.Tid,
SecondTid: v.SecondTid,
Sign: info.Sign,
}
upInfo.Vip.Type = info.Vip.Type
upInfo.Vip.Status = info.Vip.Status
if stat, ok := relInfos[v.UpID]; ok {
upInfo.Follower = stat.Follower
}
if typ, ok := s.typeNames[int32(v.Tid)]; ok {
upInfo.Tname = typ.Name
}
if typ, ok := s.typeNames[int32(v.SecondTid)]; ok {
upInfo.SecondTname = typ.Name
}
data.List = append(data.List, upInfo)
}
}
if len(data.List) == 0 {
data.List = _emptyUpRec
}
return
}
//SearchEgg get search egg by egg id.
func (s *Service) SearchEgg(c context.Context, eggID int64) (data *model.SearchEggRes, err error) {
if _, ok := s.searchEggs[eggID]; !ok {
err = ecode.NothingFound
return
}
data = s.searchEggs[eggID]
return
}

View File

@@ -0,0 +1,22 @@
package service
import (
"context"
"encoding/json"
"testing"
"go-common/app/interface/main/web/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_UpRec(t *testing.T) {
Convey("test up rec", t, WithService(func(s *Service) {
mid := int64(908085)
arg := &model.SearchUpRecArg{ServiceArea: "reg_ok", Platform: "h5"}
data, err := s.UpRec(context.Background(), mid, arg, "")
So(err, ShouldBeNil)
str, _ := json.Marshal(data)
Printf("%+v", string(str))
}))
}

View File

@@ -0,0 +1,219 @@
package service
import (
"context"
"math/rand"
"sync"
"time"
dm2rpc "go-common/app/interface/main/dm2/rpc/client"
tagrpc "go-common/app/interface/main/tag/rpc/client"
"go-common/app/interface/main/web/conf"
"go-common/app/interface/main/web/dao"
"go-common/app/interface/main/web/model"
artrpc "go-common/app/interface/openplatform/article/rpc/client"
accclient "go-common/app/service/main/account/api"
arcclient "go-common/app/service/main/archive/api"
arcrpc "go-common/app/service/main/archive/api/gorpc"
brdrpc "go-common/app/service/main/broadcast/api/grpc/v1"
coinclient "go-common/app/service/main/coin/api"
couprpc "go-common/app/service/main/coupon/rpc/client"
dyrpc "go-common/app/service/main/dynamic/rpc/client"
favrpc "go-common/app/service/main/favorite/api/gorpc"
locrpc "go-common/app/service/main/location/rpc/client"
relrpc "go-common/app/service/main/relation/rpc/client"
resrpc "go-common/app/service/main/resource/rpc/client"
shareclient "go-common/app/service/main/share/api"
thumbrpc "go-common/app/service/main/thumbup/rpc/client"
ugcclient "go-common/app/service/main/ugcpay/api/grpc/v1"
"go-common/library/log"
"go-common/library/log/anticheat"
"go-common/library/sync/pipeline/fanout"
)
// Service service
type Service struct {
c *conf.Config
dao *dao.Dao
// rpc
arc *arcrpc.Service2
dy *dyrpc.Service
tag *tagrpc.Service
loc *locrpc.Service
art *artrpc.Service
res *resrpc.Service
relation *relrpc.Service
thumbup *thumbrpc.Service
coupon *couprpc.Service
dm2 *dm2rpc.Service
fav *favrpc.Service
// chans
rids map[int32]struct{}
// cache proc
cache *fanout.Fanout
regionCount map[int16]int
onlineArcs []*model.OnlineArc
allArchivesCount, playOnline, webOnline int64
// elec show typeids
elecShowTypeIds map[int32]struct{}
// no related data aids
noRelAids map[int64]struct{}
// rand source
r *rand.Rand
indexIcon *model.IndexIcon
// infoc2
CheatInfoc *anticheat.AntiCheat
// TypeNames
typeNames map[int32]*arcclient.Tp
// Broadcast grpc client
broadcastClient brdrpc.ZergClient
coinClient coinclient.CoinClient
arcClient arcclient.ArchiveClient
accClient accclient.AccountClient
shareClient shareclient.ShareClient
ugcPayClient ugcclient.UGCPayClient
// searchEggs
searchEggs map[int64]*model.SearchEggRes
// bnj
bnj2019View *model.Bnj2019View
BnjElecInfo *model.ElecShow
bnj2019List []*model.Bnj2019Related
bnj2019LiveArc *arcclient.ArcReply
bnjGrayUids map[int64]struct{}
specialMids map[int64]struct{}
}
// New new
func New(c *conf.Config) *Service {
s := &Service{
c: c,
dao: dao.New(c),
arc: arcrpc.New2(c.ArchiveRPC),
dy: dyrpc.New(c.DynamicRPC),
tag: tagrpc.New2(c.TagRPC),
loc: locrpc.New(c.LocationRPC),
art: artrpc.New(c.ArticleRPC),
res: resrpc.New(c.ResourceRPC),
relation: relrpc.New(c.RelationRPC),
thumbup: thumbrpc.New(c.ThumbupRPC),
coupon: couprpc.New(c.CouponRPC),
dm2: dm2rpc.New(c.Dm2RPC),
fav: favrpc.New2(c.FavRPC),
cache: fanout.New("cache"),
regionCount: make(map[int16]int),
r: rand.New(rand.NewSource(time.Now().Unix())),
specialMids: map[int64]struct{}{},
}
var err error
if s.broadcastClient, err = brdrpc.NewClient(c.BroadcastClient); err != nil {
panic(err)
}
if s.coinClient, err = coinclient.NewClient(c.CoinClient); err != nil {
panic(err)
}
if s.arcClient, err = arcclient.NewClient(c.ArcClient); err != nil {
panic(err)
}
if s.accClient, err = accclient.NewClient(c.AccClient); err != nil {
panic(err)
}
if s.shareClient, err = shareclient.NewClient(c.ShareClient); err != nil {
panic(err)
}
if s.ugcPayClient, err = ugcclient.NewClient(c.UGCClient); err != nil {
panic(err)
}
s.initRules()
go s.newCountproc()
go s.onlineCountproc()
go s.onlineListproc()
go s.indexIconproc()
go s.typeNameproc()
go s.searchEggproc()
go s.bnj2019proc()
go s.loadManager()
// init infoc
if c.Infoc2 != nil {
s.CheatInfoc = anticheat.New(c.Infoc2)
}
return s
}
func (s *Service) initRules() {
tmpRids := make(map[int32]struct{}, len(s.c.Rule.Rids))
for _, v := range s.c.Rule.Rids {
tmpRids[v] = struct{}{}
}
s.rids = tmpRids
tmpElec := make(map[int32]struct{}, len(s.c.Rule.ElecShowTypeIDs))
for _, id := range s.c.Rule.ElecShowTypeIDs {
tmpElec[id] = struct{}{}
}
s.elecShowTypeIds = tmpElec
tmpNoRel := make(map[int64]struct{}, len(s.c.Rule.NoRelAids))
for _, id := range s.c.Rule.NoRelAids {
tmpNoRel[id] = struct{}{}
}
s.noRelAids = tmpNoRel
}
func (s *Service) typeNameproc() {
for {
if typesReply, err := s.arcClient.Types(context.Background(), &arcclient.NoArgRequest{}); err != nil {
log.Error("s.arc.Types2 error(%v)", err)
time.Sleep(time.Second)
continue
} else {
s.typeNames = typesReply.Types
}
time.Sleep(time.Duration(s.c.WEB.PullOnlineInterval))
}
}
func (s *Service) searchEggproc() {
var mutex = sync.Mutex{}
for {
if eggs, err := s.dao.SearchEgg(context.Background()); err != nil {
log.Error("s.dao.SearchEgg error(%v)", err)
time.Sleep(5 * time.Second)
continue
} else {
data := make(map[int64]*model.SearchEggRes, len(eggs))
for _, v := range eggs {
if source, ok := v.Plat[_searchEggWebPlat]; ok {
for _, egg := range source {
if _, isSet := data[egg.EggID]; !isSet {
data[egg.EggID] = &model.SearchEggRes{
EggID: egg.EggID,
ShowCount: v.ShowCount,
}
}
source := &model.SearchEggSource{URL: egg.URL, MD5: egg.MD5, Size: egg.Size}
data[egg.EggID].Source = append(data[egg.EggID].Source, source)
}
}
}
mutex.Lock()
s.searchEggs = data
mutex.Unlock()
}
time.Sleep(time.Duration(s.c.WEB.SearchEggInterval))
}
}
// Ping check connection success.
func (s *Service) Ping(c context.Context) (err error) {
err = s.dao.Ping(c)
return
}
// Close close resource.
func (s *Service) Close() {
s.dao.Close()
}
func archivesArgLog(name string, aids []int64) {
if aidLen := len(aids); aidLen >= 50 {
log.Info("s.arc.Archives3 func(%s) len(%d), arg(%v)", name, aidLen, aids)
}
}

View File

@@ -0,0 +1,124 @@
package service
import (
"context"
tag "go-common/app/interface/main/tag/model"
"go-common/app/interface/main/web/model"
arcmdl "go-common/app/service/main/archive/api"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
// TagAids gets avids by tagID from bigdata or backup cache,
// and updates the cache after getting bigdata's data.
func (s *Service) TagAids(c context.Context, tagID int64, pn, ps int) (total int, arcs []*arcmdl.Arc, err error) {
defer func() {
if len(arcs) == 0 {
arcs = _emptyArc
}
}()
if err = s.checkTag(c, tagID); err != nil {
err = nil
return
}
return s.tagArcs(c, tagID, pn, ps)
}
func (s *Service) tagArcs(c context.Context, tagID int64, pn, ps int) (total int, arcs []*arcmdl.Arc, err error) {
var (
start = (pn - 1) * ps
end = start + ps - 1
aids, allAids []int64
)
if allAids, err = s.dao.TagAids(c, tagID); err != nil {
log.Error("s.dao.TagAids(%d) error(%v)", tagID, err)
if allAids, err = s.dao.TagAidsBakCache(c, tagID); err != nil {
log.Error("s.dao.TagAidsBakCache(%d) error(%v)", tagID, err)
return
}
} else if len(allAids) > 0 {
s.cache.Do(c, func(c context.Context) {
s.dao.SetTagAidsBakCache(c, tagID, allAids)
})
}
total = len(allAids)
if total < start {
err = ecode.NothingFound
return
}
if total > end {
aids = allAids[start : end+1]
} else {
aids = allAids[start:]
}
arcs, err = s.archives(c, aids)
return
}
func (s *Service) archives(c context.Context, aids []int64) (data []*arcmdl.Arc, err error) {
ip := metadata.String(c, metadata.RemoteIP)
var (
arg = &arcmdl.ArcsRequest{Aids: aids}
res *arcmdl.ArcsReply
)
archivesArgLog("TagAids", aids)
if res, err = s.arcClient.Arcs(c, arg); err != nil {
log.Error("arcrpc.Archives3(%v,%s) error(%v)", aids, ip, err)
return
}
for _, aid := range aids {
if _, ok := res.Arcs[aid]; !ok {
continue
}
data = append(data, res.Arcs[aid])
}
fmtArcs(data)
return
}
func fmtArcs(arcs []*arcmdl.Arc) {
for _, v := range arcs {
if v.Access >= 10000 {
v.Stat.View = -1
}
}
}
func (s *Service) checkTag(c context.Context, tid int64) (err error) {
ip := metadata.String(c, metadata.RemoteIP)
var (
t *tag.Tag
arg = &tag.ArgID{
ID: tid,
RealIP: ip,
}
)
if t, err = s.tag.InfoByID(c, arg); err != nil {
log.Error("tagState(%d) error(%v)", tid, err)
err = nil
return
}
if t.State == model.TagStateDeleted || t.State == model.TagStateBlocked {
err = ecode.TagIsSealing
}
return
}
// TagDetail group web tag data.
func (s *Service) TagDetail(c context.Context, tagID int64, ps int) (data *model.TagDetail, err error) {
var tagInfo *tag.TagTop
if tagInfo, err = s.tag.TagTop(c, &tag.ReqTagTop{Tid: tagID}); err != nil {
return
}
data = &model.TagDetail{TagTop: tagInfo}
data.Total, data.List, _ = s.tagArcs(c, tagID, _samplePn, ps)
if len(data.List) == 0 {
data.List = _emptyArc
}
if len(data.Similars) == 0 {
data.Similars = make([]*tag.SimilarTag, 0)
}
return
}

View File

@@ -0,0 +1,18 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_TagAids(t *testing.T) {
Convey("should return without err", t, WithService(func(svf *Service) {
total, res, err := svf.TagAids(context.Background(), 1, 1, 1)
So(err, ShouldBeNil)
So(total, ShouldBeGreaterThan, 0)
So(len(res), ShouldBeGreaterThan, 0)
}))
}

View File

@@ -0,0 +1,167 @@
package service
import (
"context"
"sync"
tagmdl "go-common/app/interface/main/tag/model"
"go-common/app/interface/main/web/model"
arcmdl "go-common/app/service/main/archive/api"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
)
const (
_tagBlkSize = 50
_tagArcType = 3
)
var (
_emptyWxArc = make([]*model.WxArchive, 0)
_emptyWxArcTag = make([]*model.WxArcTag, 0)
)
// WxHot get wx hot archives.
func (s *Service) WxHot(c context.Context, pn, ps int) (res []*model.WxArchive, count int, err error) {
var (
addCache = true
aids []int64
wxArcs, allRes []*model.WxArchive
arcs map[int64]*model.WxArchive
)
defer func() {
res, count = wxHotPage(allRes, pn, ps)
}()
if wxArcs, err = s.dao.WxHotCache(c); err != nil {
err = nil
addCache = false
} else if len(wxArcs) > 0 {
allRes = s.fmtWxArcs(c, wxArcs)
return
}
if aids, err = s.dao.WxHot(c); err != nil {
err = nil
} else if len(aids) > s.c.Rule.MinWxHotCount {
if arcs, err = s.archiveWithTag(c, aids); err != nil {
err = nil
} else if len(arcs) > 0 {
for _, aid := range aids {
if arc, ok := arcs[aid]; ok && arc != nil {
allRes = append(allRes, arc)
}
}
if addCache {
s.cache.Do(c, func(c context.Context) {
s.dao.SetWxHotCache(c, allRes)
})
}
return
}
} else {
log.Error("s.dao.WxHot len(%d)", len(allRes))
}
allRes, err = s.dao.WxHotBakCache(c)
return
}
func wxHotPage(list []*model.WxArchive, pn, ps int) (res []*model.WxArchive, count int) {
count = len(list)
start := (pn - 1) * ps
end := start + ps - 1
if count == 0 || count < start {
res = _emptyWxArc
return
}
if count > end {
res = list[start : end+1]
} else {
res = list[start:]
}
return
}
func (s *Service) archiveWithTag(c context.Context, aids []int64) (list map[int64]*model.WxArchive, err error) {
var (
arcErr, tagErr error
arcsReply *arcmdl.ArcsReply
tags map[int64][]*tagmdl.Tag
mutex = sync.Mutex{}
ip = metadata.String(c, metadata.RemoteIP)
)
group, errCtx := errgroup.WithContext(c)
group.Go(func() error {
if arcsReply, arcErr = s.arcClient.Arcs(errCtx, &arcmdl.ArcsRequest{Aids: aids}); arcErr != nil {
log.Error("s.arcClient.Arcs(%d) error %v", aids, err)
return arcErr
}
return nil
})
aidsLen := len(aids)
tags = make(map[int64][]*tagmdl.Tag, aidsLen)
for i := 0; i < aidsLen; i += _tagBlkSize {
var partAids []int64
if i+_tagBlkSize > aidsLen {
partAids = aids[i:]
} else {
partAids = aids[i : i+_tagBlkSize]
}
group.Go(func() (err error) {
var tmpRes map[int64][]*tagmdl.Tag
arg := &tagmdl.ArgResTags{Oids: partAids, Type: _tagArcType, RealIP: ip}
if tmpRes, tagErr = s.tag.ResTags(errCtx, arg); tagErr != nil {
log.Error("s.tag.ResTag(%+v) error(%v)", arg, tagErr)
return
}
mutex.Lock()
for aid, tmpTags := range tmpRes {
tags[aid] = tmpTags
}
mutex.Unlock()
return nil
})
}
if err = group.Wait(); err != nil {
return
}
list = make(map[int64]*model.WxArchive, len(aids))
for _, aid := range aids {
if arc, ok := arcsReply.Arcs[aid]; ok && arc.IsNormal() {
wxArc := new(model.WxArchive)
wxArc.FromArchive(arc)
if tag, ok := tags[aid]; ok {
for _, v := range tag {
wxArc.Tags = append(wxArc.Tags, &model.WxArcTag{ID: v.ID, Name: v.Name})
}
}
if len(wxArc.Tags) == 0 {
wxArc.Tags = _emptyWxArcTag
}
list[aid] = wxArc
}
}
return
}
func (s *Service) fmtWxArcs(c context.Context, arcs []*model.WxArchive) (res []*model.WxArchive) {
var (
aids []int64
newArcs map[int64]*model.WxArchive
err error
)
for _, arc := range arcs {
aids = append(aids, arc.Aid)
}
if newArcs, err = s.archiveWithTag(c, aids); err != nil {
log.Error("fmtWxArcStat archiveWithTag aids(%+v) error(%v)", aids, err)
return
}
for _, arc := range arcs {
if newArc, ok := newArcs[arc.Aid]; ok {
res = append(res, newArc)
} else {
res = append(res, arc)
}
}
return
}