go-common/app/interface/main/dm2/service/advance.go

369 lines
9.5 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
package service
import (
"context"
"fmt"
"go-common/app/interface/main/dm2/model"
account "go-common/app/service/main/account/api"
arcMdl "go-common/app/service/main/archive/model/archive"
coinmdl "go-common/app/service/main/coin/model"
relation "go-common/app/service/main/relation/model"
"go-common/library/ecode"
"go-common/library/log"
)
// BuyAdvance 购买高级弹幕
func (s *Service) BuyAdvance(c context.Context, mid, cid int64, mode string) (err error) {
var (
refund = int64(1)
coin = model.AdvSPCoin
reason = model.AdvSPCoinReason
advPermit int8
)
if !s.dao.AddAdvanceLock(c, cid, mid) {
return
}
defer s.dao.DelAdvanceLock(c, cid, mid)
reply, err := s.accountRPC.Info3(c, &account.MidReq{Mid: mid})
if err != nil {
log.Error("s.accRPC.Info3(%d) error(%v)", mid, err)
return
}
if s.isSuperUser(reply.GetInfo().GetRank()) {
return
}
if mode != model.AdvSpeMode { // pool=2 弹幕
coin = model.AdvCoin
reason = model.AdvCoinReason
}
typ, err := s.dao.AdvanceType(c, cid, mid, mode)
if err != nil {
log.Error("dao.AdvanceType(%d,%d,%s) error(%v)", cid, mid, mode, err)
return
}
sub, err := s.subject(c, model.SubTypeVideo, cid)
if err != nil {
return
}
if typ != "" { // 已有购买记录
if typ == model.AdvTypeRequest && mid != sub.Mid {
err = ecode.DMAdvConfirm
} else {
err = ecode.DMAdvBought
}
return
}
if mid != sub.Mid {
advPermit, err = s.dao.UpperConfig(c, sub.Mid)
if err != nil {
return
}
if err = s.checkAdvancePermit(c, advPermit, sub.Mid, mid); err != nil {
return
}
}
typ = model.AdvTypeRequest
if sub.Mid == mid {
typ = model.AdvTypeBuy
}
coins, err := s.coinRPC.UserCoins(c, &coinmdl.ArgCoinInfo{Mid: mid})
if err != nil {
log.Error("coinRPC.UserCoins(%v) error(%v)", mid, err)
return
}
if coins < float64(coin) {
err = ecode.LackOfCoins
return
}
if _, err = s.dao.BuyAdvance(c, mid, cid, sub.Mid, refund, typ, mode); err != nil {
return
}
if _, err = s.coinRPC.ModifyCoin(c, &coinmdl.ArgModifyCoin{Mid: mid, Count: -float64(coin), Reason: reason, CheckZero: 1}); err != nil {
log.Error("coinRPC.ModifyCoin(%v,%v,%v) error(%v)", mid, coin, reason, err)
return
}
if err = s.dao.DelAdvCache(c, mid, cid, mode); err != nil {
return
}
s.cache.Do(c, func(ctx context.Context) {
arc, err := s.arcRPC.Archive3(ctx, &arcMdl.ArgAid2{Aid: sub.Pid})
if err != nil {
log.Error("s.arcRPC.Archive3(aid:%d) error(%v)", sub.Pid, err)
return
}
title := "您收到了一条高级弹幕请求"
content := fmt.Sprintf(`您的稿件《%s》收到了一条高级弹幕请求#{立即处理}{"https://member.bilibili.com/v/#/danmu/report/advance"}`, arc.Title)
s.dao.SendNotify(ctx, title, content, "4", []int64{sub.Mid})
})
return
}
func (s *Service) checkAdvancePermit(c context.Context, advPermit int8, upid, mid int64) (err error) {
switch advPermit {
case model.AdvPermitAll:
return
case model.AdvPermitFollower, model.AdvPermitAttention:
var (
arg = &relation.ArgMid{Mid: upid}
res = make([]*relation.Following, 0)
follower *relation.Following
)
if res, err = s.relRPC.Followers(c, arg); err != nil {
log.Error("relRPC.Followers(%+v) error(%v)", arg, err)
return
}
for _, v := range res {
if v.Mid == mid {
follower = v
break
}
}
if follower == nil {
err = ecode.DMAdvNotAllow
return
}
if advPermit == model.AdvPermitAttention && follower.Attribute != 6 { // Attribute=6为相互关注
err = ecode.DMAdvNotAllow
return
}
case model.AdvPermitForbid:
err = ecode.DMAdvNotAllow
return
}
return
}
// AdvanceState 高级弹幕状态
func (s *Service) AdvanceState(c context.Context, mid, cid int64, mode string) (state *model.AdvState, err error) {
state = &model.AdvState{
Accept: true,
Coins: model.AdvSPCoin,
Confirm: model.AdvStatConfirmDefault,
}
if mode == model.AdvMode { // pool=2 弹幕
state.Coins = model.AdvCoin
}
reply, err := s.accountRPC.Info3(c, &account.MidReq{Mid: mid})
if err != nil {
log.Error("s.accRPC.Info3(%d) error(%v)", mid, err)
return
}
if s.isSuperUser(reply.GetInfo().GetRank()) {
state.HasBuy = true
state.Confirm = model.AdvStatConfirmAgree
return
}
typ, err := s.dao.AdvanceType(c, cid, mid, mode)
if err != nil {
return
}
switch typ {
case model.AdvTypeAccept, model.AdvTypeBuy: // 已通过
state.Confirm = model.AdvStatConfirmAgree
state.HasBuy = true
case model.AdvTypeRequest: // 正在确认中
state.Confirm = model.AdvStatConfirmRequest
state.HasBuy = true
case model.AdvTypeDeny: // up 主拒绝
state.Confirm = model.AdvStatConfirmDeny
state.HasBuy = true
}
return
}
// Advances 高级弹幕申请列表
func (s *Service) Advances(c context.Context, mid int64) (res []*model.Advance, err error) {
var (
cidMap = make(map[int64]bool)
midMap = make(map[int64]bool)
mids = make([]int64, 0)
cidAidMap = make(map[int64]int64)
aids = make([]int64, 0)
)
list, err := s.dao.Advances(c, mid)
if err != nil {
log.Error("dao.Advances(%d) error(%v)", mid, err)
return
}
if len(list) == 0 {
return
}
res = make([]*model.Advance, 0, len(list))
for _, l := range list {
if _, ok := midMap[l.Mid]; !ok {
midMap[l.Mid] = true
mids = append(mids, l.Mid)
}
cidMap[l.Cid] = true
}
for cid := range cidMap { // get cids->aids
var sub *model.Subject
if sub, err = s.subject(c, model.SubTypeVideo, cid); err != nil {
log.Error("s.subject(%d) error(%v)", cid, err)
return
}
if sub == nil {
err = ecode.NothingFound
continue
}
if _, ok := cidAidMap[sub.Oid]; !ok {
cidAidMap[sub.Oid] = sub.Pid
aids = append(aids, sub.Pid)
}
}
arcs, err := s.archiveInfos(c, aids) // get archiveinfos
if err != nil {
return
}
reply, err := s.accountRPC.Infos3(c, &account.MidsReq{
Mids: mids,
})
if err != nil {
log.Error("s.accRPC.Infos3(%v) error(%v)", mids, err)
return
}
for _, v := range list {
if aid, ok := cidAidMap[v.Cid]; ok {
v.Aid = aid
} else {
continue
}
if archive, ok := arcs[v.Aid]; ok {
v.Title = archive.Title
v.Cover = archive.Pic
}
if user, ok := reply.GetInfos()[v.Mid]; ok {
v.Uname = user.Name
}
res = append(res, v)
}
return
}
// PassAdvance 通过高级弹幕申请
func (s *Service) PassAdvance(c context.Context, mid, id int64) (err error) {
adv, err := s.dao.Advance(c, mid, id)
if err != nil {
log.Error("dao.Advance(%d,%d) error(%v)", mid, id, err)
return
}
if adv == nil || adv.Type == model.AdvTypeDeny {
err = ecode.DMAdvNoFound
return
}
if adv.Type == model.AdvTypeAccept {
return
}
if _, err = s.dao.UpdateAdvType(c, id, model.AdvTypeAccept); err != nil {
log.Error("dao.UpdateAdvType(%d,%d,%s) error(%v)", mid, id, model.AdvTypeAccept, err)
return
}
if err = s.dao.DelAdvCache(c, adv.Mid, adv.Cid, adv.Mode); err != nil {
log.Error("dao.DelAdvCache(%+v) error(%v)", adv, err)
}
return
}
// DenyAdvance 拒绝高级弹幕申请
func (s *Service) DenyAdvance(c context.Context, mid, id int64) (err error) {
var (
coin float64
reason string
af int64
)
adv, err := s.dao.Advance(c, mid, id)
if err != nil {
log.Error("dao.Advance(%d,%d) error(%v)", mid, id, err)
return
}
if adv == nil {
return
}
if len(adv.Type) == 0 || adv.Type == model.AdvTypeDeny {
err = ecode.DMAdvNoFound
return
}
if af, err = s.dao.UpdateAdvType(c, id, model.AdvTypeDeny); err != nil {
log.Error("dao.UpdateAdvType(%d) error(%v)", id, err)
return
}
if err = s.dao.DelAdvCache(c, adv.Mid, adv.Cid, adv.Mode); err != nil {
log.Error("dao.DelAdvCache(%+v) error(%v)", adv, err)
return
}
if af < 1 {
err = ecode.DMAdvNoFound
return
}
if adv.Refund == 0 {
return
}
coin = model.AdvSPCoin
reason = model.AdvSPCoinCancelReason
if adv.Mode == model.AdvMode {
coin = model.AdvCoin
reason = model.AdvCoinCancelReason
}
if _, err = s.coinRPC.ModifyCoin(c, &coinmdl.ArgModifyCoin{Mid: adv.Mid, Count: coin, Reason: reason}); err != nil {
log.Error("s.accRPC.AddCoin2(%v,%v,%v) error(%v)", adv.Mid, coin, reason, err)
}
return
}
// CancelAdvance 取消高级弹幕申请
func (s *Service) CancelAdvance(c context.Context, mid, id int64) (err error) {
var (
adv *model.Advance
coin float64
reason string
af int64
)
if adv, err = s.dao.Advance(c, mid, id); err != nil {
log.Error("s.dao.Advance(%d,%d) error(%v)", mid, id, err)
return
}
if adv == nil {
err = ecode.DMAdvNoFound
return
}
if af, err = s.dao.DelAdvance(c, id); err != nil {
log.Error("s.dao.DelAdvance(%d) error(%v)", id, err)
return
}
if err = s.dao.DelAdvCache(c, adv.Mid, adv.Cid, adv.Mode); err != nil {
log.Error("s.dao.DelAdvCache(%+v) error(%v)", adv, err)
return
}
if af < 1 {
err = ecode.DMAdvNoFound
return
}
if adv.Refund == 0 || adv.Type == model.AdvTypeDeny {
return
}
coin = model.AdvSPCoin
reason = model.AdvSPCoinCancelReason
if adv.Mode == model.AdvMode {
coin = model.AdvCoin
reason = model.AdvCoinCancelReason
}
if _, err = s.coinRPC.ModifyCoin(c, &coinmdl.ArgModifyCoin{Mid: adv.Mid, Count: coin, Reason: reason}); err != nil {
log.Error("s.accRPC.AddCoin2(%v,%v,%v) error(%v)", adv.Mid, coin, reason, err)
}
return
}
// UpdateAdvancePermit update advance permit.
func (s *Service) UpdateAdvancePermit(c context.Context, mid int64, advPermit int8) (err error) {
_, err = s.dao.AddUpperConfig(c, mid, advPermit)
return
}
// AdvancePermit get advance permission.
func (s *Service) AdvancePermit(c context.Context, mid int64) (advPermit int8, err error) {
advPermit, err = s.dao.UpperConfig(c, mid)
return
}