go-common/app/admin/main/videoup/service/extra_func.go

534 lines
15 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
package service
import (
"context"
"errors"
"hash/crc32"
"strconv"
"strings"
"time"
"go-common/app/admin/main/videoup/model/archive"
mngmdl "go-common/app/admin/main/videoup/model/manager"
accApi "go-common/app/service/main/account/api"
upsrpc "go-common/app/service/main/up/api/v1"
"go-common/library/log"
"go-common/library/sync/errgroup"
xtime "go-common/library/time"
"go-common/library/xstr"
)
//ERROR
var (
ErrRPCEmpty = errors.New("rpc reply empty")
)
func (s *Service) archiveRound(c context.Context, a *archive.Archive, aid, mid int64, typeID int16, nowRound, newState int8, cancelMission bool) (round int8) {
//非特殊分区私单定时发布时,稿件进入四审
//一个私单且定时发布的稿件 应该是先通过待审 传递到 私单四审 ,私单四审开放浏览后到达设置的定时时间最后再自动发布
if s.isPorder(a) && newState == archive.StateForbidUserDelay && !s.isAuditType(typeID) {
round = archive.RoundReviewFlow
return
}
//定时发布的付费稿件 投上来就是round24 admin提交不需要再走付费审核
//定时发布
if newState == archive.StateForbidAdminDelay || newState == archive.StateForbidUserDelay {
round = nowRound
return
}
var addit *archive.Addit
//活动稿件(非私单且非付费) | pgc 稿件 up_from(1,5,6) 直接round 99 简单流程业务
if addit, _ = s.arc.Addit(c, aid); addit != nil && (addit.UpFrom == archive.UpFromPGC || addit.UpFrom == archive.UpFromSecretPGC || addit.UpFrom == archive.UpFromCoopera || (addit.MissionID > 0 && !s.isPorder(a) && !s.isUGCPay(a))) {
if addit.UpFrom == archive.UpFromSecretPGC && newState == archive.StateForbidWait {
//pgc 机密待审state=-1 不变更round
round = nowRound
return
}
if archive.NormalState(newState) {
//pgc 生产组机密稿件(番剧、付费版权,严格要求时效和保密性) up_from=5 开放回查流程 90
if addit.UpFrom == archive.UpFromSecretPGC && nowRound < archive.RoundTriggerClick {
//三查
round = archive.RoundTriggerClick
return
}
}
//pgc 生产组常规稿件(片包等其他内容) up_from=1 进三审
if addit.UpFrom == archive.UpFromPGC && nowRound < archive.RoundAuditThird {
round = archive.RoundAuditThird
return
}
//pgc 合作方嵌套,终结
if addit.UpFrom == archive.UpFromCoopera && nowRound < archive.RoundAuditThird {
round = archive.RoundEnd
return
}
round = archive.RoundEnd
return
}
//其他稿件 非定时活动pgc
if nowRound == archive.RoundAuditSecond {
//二审阶段
if newState == archive.StateForbidWait {
//1、非特殊分区私单进入私单四审2、私单活动稿件进入私单四审
if (s.isPorder(a) && !s.isAuditType(typeID)) || (s.isPorder(a) && !cancelMission && addit.MissionID > 0) {
//私单四审
round = archive.RoundReviewFlow
} else if s.isUGCPay(a) && (!s.isAuditType(typeID) || !s.isPorder(a) || (!cancelMission && addit.MissionID > 0)) {
//付费稿件 非特殊分区 非私单
round = archive.RoundAuditUGCPayFlow
} else if s.isAuditType(typeID) || (addit != nil && addit.OrderID > 0) {
//特殊分区 ,商单到三审 二审到三审
round = archive.RoundAuditThird
} else {
//不变
round = archive.RoundAuditSecond
}
} else if archive.NormalState(newState) {
//回查控制
round = s.normalRound(c, aid, mid, typeID, nowRound, newState)
} else if newState == archive.StateForbidFixed {
//1、非特殊分区私单进入私单四审修复待审2、私单+活动稿件进入私单四审修复待审
if (s.isPorder(a) && !s.isAuditType(typeID)) || (s.isPorder(a) && !cancelMission && addit.MissionID > 0) {
round = archive.RoundReviewFlow
} else if s.isAuditType(typeID) && !(!cancelMission && addit.MissionID > 0) {
//特殊分区 二审到三审
round = archive.RoundAuditThird
} else if s.isUGCPay(a) && (!s.isAuditType(typeID) || !s.isPorder(a) || (!cancelMission && addit.MissionID > 0)) {
//付费稿件 非特殊分区 非私单
round = archive.RoundAuditUGCPayFlow
} else {
//不变
round = archive.RoundAuditSecond
}
} else {
round = archive.RoundEnd
}
} else if nowRound == archive.RoundReviewFlow {
//私单四审21
if archive.NormalState(newState) {
if s.isAuditType(typeID) || addit.MissionID > 0 {
round = archive.RoundEnd
} else {
round = s.normalRound(c, aid, mid, typeID, nowRound, newState)
}
} else {
round = archive.RoundEnd
}
} else if nowRound == archive.RoundAuditUGCPayFlow {
//付费待审 24
if archive.NormalState(newState) {
if s.isAuditType(typeID) || addit.MissionID > 0 {
round = archive.RoundEnd
} else {
round = s.normalRound(c, aid, mid, typeID, nowRound, newState)
}
} else {
round = archive.RoundEnd
}
} else if nowRound == archive.RoundReviewFirst {
//一查
if archive.NormalState(newState) {
round = archive.RoundReviewFirstWaitTrigger
} else {
round = archive.RoundEnd
}
} else if nowRound == archive.RoundAuditThird {
//三审
if s.isPorder(a) {
//私单四审
round = archive.RoundReviewFlow
} else if s.isUGCPay(a) {
round = archive.RoundAuditUGCPayFlow
} else {
round = archive.RoundEnd
}
} else if nowRound == archive.RoundReviewSecond || nowRound == archive.RoundTriggerClick {
//二查 三查
round = archive.RoundEnd
} else {
round = nowRound
}
return
}
//normalRound 回查逻辑
func (s *Service) normalRound(c context.Context, aid, mid int64, typeID int16, nowRound, newState int8) (round int8) {
if s.isWhite(mid) || s.isBlack(mid) {
round = archive.RoundReviewSecond
} else if plf, _ := s.profile(c, mid); plf != nil && plf.Follower >= s.fansCache {
//社区回查 粉丝阈值
round = archive.RoundReviewSecond
} else if plf != nil && plf.Follower < s.fansCache && s.isRoundType(typeID) {
//回查分区
round = archive.RoundReviewFirst // NOTE: if audit type, state must not open!!! so cannot execute here...
} else {
//点击量回查
round = archive.RoundReviewFirstWaitTrigger
if plf == nil {
log.Info("archive(%d) card(%d) is nil", aid, mid)
} else {
log.Info("archive(%d) card(%d) fans(%d) little than config(%d)", aid, mid, plf.Follower, s.fansCache)
}
}
return
}
func (s *Service) hadPassed(c context.Context, aid int64) (had bool) {
id, err := s.arc.GetFirstPassByAID(c, aid)
if err != nil {
log.Error("hadPassed s.arc.GetFirstPassByAID error(%v) aid(%d)", err, aid)
return
}
had = id > 0
return
}
func (s *Service) isPorder(a *archive.Archive) bool {
if a == nil {
return false
}
return a.AttrVal(archive.AttrBitIsPorder) == archive.AttrYes
}
//ugc pay only
func (s *Service) isUGCPay(a *archive.Archive) bool {
if a == nil {
return false
}
return a.AttrVal(archive.AttrBitUGCPay) == archive.AttrYes
}
func (s *Service) profile(c context.Context, mid int64) (card *accApi.ProfileStatReply, err error) {
if card, err = s.accRPC.ProfileWithStat3(c, &accApi.MidReq{Mid: mid}); err != nil {
log.Error("s.accRPC.ProfileWithStat3(%d) error(%v)", mid, err)
}
return
}
func (s *Service) upCards(c context.Context, mids []int64) (p map[int64]*accApi.Card, err error) {
p = make(map[int64]*accApi.Card)
if len(mids) == 0 {
return
}
var res *accApi.CardsReply
if res, err = s.accRPC.Cards3(c, &accApi.MidsReq{Mids: mids}); err != nil {
p = nil
log.Error("s.accRPC.Cards3(%v) error(%v)", mids, err)
return
}
p = res.Cards
return
}
func (s *Service) archivePtime(c context.Context, aid int64, newState int8, newPtime xtime.Time) (ptime xtime.Time) {
if newState >= archive.StateOpen {
if !s.hadPassed(c, aid) {
ptime = xtime.Time(time.Now().Unix())
return
}
}
ptime = newPtime
return
}
func (s *Service) archiveAttr(c context.Context, ap *archive.ArcParam, isExt bool) (attrs map[uint]int32, forbidAttrs map[string]map[uint]int32) {
//批量和单个提交都需要补全对应属性值
attrs = make(map[uint]int32)
attrs[archive.AttrBitNoRank] = ap.Attrs.NoRank
attrs[archive.AttrBitNoDynamic] = ap.Attrs.NoDynamic
attrs[archive.AttrBitNoWeb] = ap.Attrs.NoWeb
attrs[archive.AttrBitNoMobile] = ap.Attrs.NoMobile
attrs[archive.AttrBitNoSearch] = ap.Attrs.NoSearch
attrs[archive.AttrBitOverseaLock] = ap.Attrs.OverseaLock
attrs[archive.AttrBitNoRecommend] = ap.Attrs.NoRecommend
attrs[archive.AttrBitNoReprint] = ap.Attrs.NoReprint
attrs[archive.AttrBitHasHD5] = ap.Attrs.HasHD5
attrs[archive.AttrBitAllowBp] = ap.Attrs.AllowBp
attrs[archive.AttrBitIsPorder] = ap.Attrs.IsPorder
attrs[archive.AttrBitLimitArea] = ap.Attrs.LimitArea
attrs[archive.AttrBitPushBlog] = ap.Attrs.PushBlog
attrs[archive.AttrBitUGCPay] = ap.Attrs.UGCPay
attrs[archive.AttrBitParentMode] = ap.Attrs.ParentMode
// pgc
attrs[archive.AttrBitIsMovie] = ap.Attrs.IsMovie
attrs[archive.AttrBitBadgepay] = ap.Attrs.BadgePay
attrs[archive.AttrBitIsBangumi] = ap.Attrs.IsBangumi
attrs[archive.AttrBitIsPGC] = ap.Attrs.IsPGC
if isExt {
attrs[archive.AttrBitAllowTag] = ap.Attrs.AllowTag
attrs[archive.AttrBitJumpURL] = ap.Attrs.JumpURL
}
forbidAttrs = make(map[string]map[uint]int32, 4)
forbidAttrs[archive.ForbidRank] = map[uint]int32{
archive.ForbidRankMain: ap.Forbid.Rank.Main,
archive.ForbidRankRecentArc: ap.Forbid.Rank.RecentArc,
archive.ForbidRankAllArc: ap.Forbid.Rank.AllArc,
}
forbidAttrs[archive.ForbidDynamic] = map[uint]int32{
archive.ForbidDynamicMain: ap.Forbid.Dynamic.Main,
}
forbidAttrs[archive.ForbidRecommend] = map[uint]int32{
archive.ForbidRecommendMain: ap.Forbid.Recommend.Main,
}
forbidAttrs[archive.ForbidShow] = map[uint]int32{
archive.ForbidShowMain: ap.Forbid.Show.Main,
archive.ForbidShowMobile: ap.Forbid.Show.Mobile,
archive.ForbidShowWeb: ap.Forbid.Show.Web,
archive.ForbidShowOversea: ap.Forbid.Show.Oversea,
archive.ForbidShowOnline: ap.Forbid.Show.Online,
}
return
}
func (s *Service) isAccess(c context.Context, aid int64) (wm bool) {
var vs []*archive.Video
if vs, _ = s.arc.NewVideosByAid(c, aid); len(vs) <= 0 {
return
}
for _, v := range vs {
if v.Status == 10000 {
wm = true
return
}
}
return
}
// CheckArchive check typeid
func (s *Service) CheckArchive(aps []*archive.ArcParam) bool {
for _, ap := range aps {
if ap.Aid == 0 || ap.UID == 0 {
return false
}
}
return true
}
// CheckVideo check video
func (s *Service) CheckVideo(vps []*archive.VideoParam) bool {
for _, vp := range vps {
if vp.ID == 0 || vp.Aid == 0 || vp.Filename == "" || vp.Cid == 0 || vp.UID == 0 {
return false
}
}
return true
}
// CheckStaff check
func (s *Service) CheckStaff(vps []*archive.StaffParam) bool {
//允许为空 不允许为Nil
if len(vps) == 0 {
return true
}
for _, vp := range vps {
if vp.MID == 0 || vp.Title == "" {
return false
}
}
return true
}
// TypeTopParent get archive type's first level type
func (s *Service) TypeTopParent(tid int16) (tp *archive.Type, err error) {
if _, ok := s.typeCache[tid]; !ok {
err = errors.New("archive type id not exist. id:" + strconv.Itoa(int(tid)))
return
}
if s.typeCache[tid].PID == 0 {
tp = s.typeCache[tid]
} else {
tp, err = s.TypeTopParent(s.typeCache[tid].PID)
if err != nil {
return
}
}
return
}
//StringHandler handle two strings 以s1顺序为准
func StringHandler(s1 string, s2 string, delimiter string, subtraction bool) string {
if strings.TrimSpace(s2) == "" {
return s1
}
var (
res []string
duplicate []int
)
s1Arr := strings.Split(s1, delimiter)
s2Arr := strings.Split(s2, delimiter)
for _, s1Item := range s1Arr {
dupIndex := -1
for k, s2Item := range s2Arr {
if s1Item == s2Item {
dupIndex = k
break
}
}
if dupIndex >= 0 && subtraction {
continue
}
if dupIndex >= 0 {
duplicate = append(duplicate, dupIndex)
}
res = append(res, s1Item)
}
if !subtraction {
for k, s2Item := range s2Arr {
s2Item = strings.TrimSpace(s2Item)
if s2Item == "" {
continue
}
add := true
for _, dup := range duplicate {
if k == dup {
add = false
break
}
}
if add {
res = append(res, s2Item)
}
}
}
return strings.Join(res, delimiter)
}
// SplitInts 去掉id字符串中的空白字符
func (s *Service) SplitInts(str string) ([]int64, error) {
empties := []string{" ", "\n", "\t", "\r"}
for _, v := range empties {
str = strings.Replace(str, v, "", -1)
}
str = strings.Trim(str, ",")
return xstr.SplitInts(str)
}
// coverURL convert cover url to full url.
func coverURL(uri string) (cover string) {
if uri == "" {
cover = "http://static.hdslb.com/images/transparent.gif"
return
}
cover = uri
if strings.Index(uri, "http://") == 0 {
return
}
if len(uri) >= 10 && uri[:10] == "/templets/" {
return
}
if strings.HasPrefix(uri, "group1") {
cover = "http://i0.hdslb.com/" + uri
return
}
if pos := strings.Index(uri, "/uploads/"); pos != -1 && (pos == 0 || pos == 3) {
cover = uri[pos+8:]
}
cover = strings.Replace(cover, "{IMG}", "", -1)
cover = "http://i" + strconv.FormatInt(int64(crc32.ChecksumIEEE([]byte(cover)))%3, 10) + ".hdslb.com" + cover
return
}
func (s *Service) upGroupMids(c context.Context, gid int64) (mids []int64, err error) {
var (
total int
maxps = 10000
req = &upsrpc.UpGroupMidsReq{
Pn: 1,
GroupID: gid,
Ps: maxps,
}
reply *upsrpc.UpGroupMidsReply
)
for {
reply, err = s.upsRPC.UpGroupMids(c, req)
if err == nil && (reply == nil || reply.Mids == nil) {
err = ErrRPCEmpty
}
if err != nil {
log.Error("UpGroupMids req(%+v) error(%v)", req, err)
return
}
total = reply.Total
mids = append(mids, reply.Mids...)
if reply.Size() != maxps {
break
}
req.Pn++
}
log.Info("upGroupMids(%d) reply total(%d) len(%d)", gid, total, len(mids))
return
}
func (s *Service) upSpecial(c context.Context) (ups map[int8]map[int64]struct{}, err error) {
var (
g errgroup.Group
whitegroup, blackgroup, pgcgroup, ugcxgroup, policygroup, dangergroup, twoforbidgroup, pgcwhitegroup map[int64]struct{}
)
ups = make(map[int8]map[int64]struct{})
f := func(gid int8) (map[int64]struct{}, error) {
group := make(map[int64]struct{})
mids, e := s.upGroupMids(c, int64(gid))
if e != nil {
return group, e
}
for _, mid := range mids {
group[mid] = struct{}{}
}
return group, nil
}
g.Go(func() error {
whitegroup, err = f(mngmdl.UpperTypeWhite)
return err
})
g.Go(func() error {
blackgroup, err = f(mngmdl.UpperTypeBlack)
return err
})
g.Go(func() error {
pgcgroup, err = f(mngmdl.UpperTypePGC)
return err
})
g.Go(func() error {
ugcxgroup, err = f(mngmdl.UpperTypeUGCX)
return err
})
g.Go(func() error {
policygroup, err = f(mngmdl.UpperTypePolity)
return err
})
g.Go(func() error {
dangergroup, err = f(mngmdl.UpperTypeDanger)
return err
})
g.Go(func() error {
twoforbidgroup, err = f(mngmdl.UpperTypeTwoForbid)
return err
})
g.Go(func() error {
pgcwhitegroup, err = f(mngmdl.UpperTypePGCWhite)
return err
})
if err = g.Wait(); err != nil {
return
}
ups[mngmdl.UpperTypeWhite] = whitegroup
ups[mngmdl.UpperTypeBlack] = blackgroup
ups[mngmdl.UpperTypePGC] = pgcgroup
ups[mngmdl.UpperTypeUGCX] = ugcxgroup
ups[mngmdl.UpperTypePolity] = policygroup
ups[mngmdl.UpperTypeDanger] = dangergroup
ups[mngmdl.UpperTypeTwoForbid] = twoforbidgroup
ups[mngmdl.UpperTypePGCWhite] = pgcwhitegroup
return
}