364 lines
8.8 KiB
Go
Raw Normal View History

2019-04-22 02:59:20 +00:00
package service
import (
"context"
"fmt"
"time"
"go-common/app/interface/main/dm/model"
dm2Mdl "go-common/app/interface/main/dm2/model"
"go-common/app/interface/main/dm2/model/oplog"
account "go-common/app/service/main/account/api"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_notifyUpTitle = "有新的弹幕保护申请"
_notifyUpContent = `您今天新增了一些未处理弹幕保护申请,前去 #{创作中心 - 哔哩哔哩弹幕视频网 - ( ゜- ゜)つロ 乾杯~}{"http://member.bilibili.com/v/#/danmu/report/save"} 处理吧`
_notifyUsrTitle = "弹幕保护申请情况更新~"
_pa48 = "由于up主日理万机您之前申请的%d条弹幕暂未受理请稍后再次申请"
_paa = `您在视频 #{%s}{"http://www.bilibili.com/video/av%d/"} 已被全部保护`
_pap = `您在视频 #{%s}{"http://www.bilibili.com/video/av%d/"} 已被部分保护`
_protectApplyLevel = 4
_maxProtectApply = 100
_paExpire = 48 * 3600
)
// AddProtectApply 批量申请保护弹幕
func (s *Service) AddProtectApply(c context.Context, uid, cid int64, dmids []int64) (err error) {
if len(dmids) == 0 {
err = ecode.DMNotFound
return
}
count, err := s.dao.PaUsrCnt(c, uid)
if err != nil {
log.Error("s.dao.PaUsrCnt(%d) error(%v)", uid, err)
return
}
if (count + len(dmids)) > _maxProtectApply {
err = ecode.DMPAUserLimit
return
}
cardReply, err := s.accountSvc.Card3(c, &account.MidReq{Mid: uid})
if err != nil {
log.Error("s.actSvc.Card3(%d) error(%v)", uid, err)
return
}
if cardReply.GetCard().GetLevel() < _protectApplyLevel {
err = ecode.DMPAUserLevel
return
}
dms, err := s.dms(c, model.SubTypeVideo, cid, dmids)
if err != nil {
return
}
dc := len(dmids)
if len(dms) < 1 && dc == 1 {
err = ecode.DMNotFound
return
}
sub, err := s.subject(c, 1, cid)
if err != nil {
return
}
aps := make([]*model.Pa, 0, len(dms))
now := time.Now().Unix()
var ctime time.Time
for _, dm := range dms {
if dm.Mid != uid && dc == 1 {
err = ecode.DMPADMNotOwner
return
}
if dm.AttrVal(model.AttrProtect) == model.AttrYes && dc == 1 {
err = ecode.DMPADMProtected
return
}
if !dm.NeedDisplay() && dc == 1 {
err = ecode.DMNotFound
return
}
ctime, err = s.dao.ProtectApplyTime(c, dm.ID)
if err != nil {
log.Error("dao.ProtectApplyTime(%d) error(%v)", uid, err)
continue
}
if now-ctime.Unix() < _paExpire {
if dc == 1 {
err = ecode.DMPADMLimit
return
}
continue
}
ap := &model.Pa{
CID: cid,
UID: sub.Mid,
ApplyUID: dm.Mid,
AID: sub.Pid,
Playtime: float32(dm.Progress) / 1000,
DMID: dm.ID,
Msg: dm.Content.Msg,
Status: -1,
Ctime: time.Now(),
Mtime: time.Now(),
}
aps = append(aps, ap)
}
if len(aps) < 1 {
err = ecode.DMPAFailed
return
}
affect, err := s.dao.AddProtectApply(c, aps)
if err != nil {
log.Error("dao.AddProtectApply(%v) error(%v)", aps, err)
return
}
if err = s.dao.UptUsrPaCnt(c, uid, affect); err != nil {
log.Error("s.dao.UptUsrPaCnt(%d,%d) error(%v)", uid, affect, err)
}
return
}
// UptPaSwitch 保护弹幕申请开关
func (s *Service) UptPaSwitch(c context.Context, uid int64, status int) (err error) {
if status != 1 {
status = 0
}
_, err = s.dao.UptPaNoticeSwitch(c, uid, status)
return
}
// UptPaStatus 审核保护弹幕申请
func (s *Service) UptPaStatus(c context.Context, mid int64, ids []int64, status int) (err error) {
dmids, err := s.dao.ProtectApplyByIDs(c, mid, xstr.JoinInts(ids))
if err != nil {
log.Error("s.dao.ProtectApplyByIDs(%d,%s) error(%v)", mid, xstr.JoinInts(ids), err)
return
}
if status != 1 {
status = 0
}
if _, err = s.dao.UptPaStatus(c, mid, xstr.JoinInts(ids), status); err != nil {
log.Error("s.dao.UptPaStatus(%d,%v,%d) error(%v)", mid, ids, status, err)
return
}
if status == 0 {
return
}
for oid, ids := range dmids {
arg := &dm2Mdl.ArgEditDMAttr{
Type: 1,
Oid: oid,
Mid: mid,
Bit: dm2Mdl.AttrProtect,
Value: dm2Mdl.AttrYes,
Dmids: ids,
Source: oplog.SourceUp,
OperatorType: oplog.OperatorUp,
}
if err = s.dmRPC.EditDMAttr(c, arg); err != nil {
log.Error("s.dmRPC.EditDMAttr(%+v) error(%v)", arg, err)
return
}
}
return
}
// ProtectApplies 保护弹幕申请列表
func (s *Service) ProtectApplies(c context.Context, uid, aid int64, page int, sort string) (res *model.ApplyListResult, err error) {
var (
count int
start int
)
if page < 1 {
page = 1
}
res = &model.ApplyListResult{
Pager: &model.Pager{},
List: make([]*model.Apply, 0, model.ProtectApplyLimit),
}
res.List, err = s.dao.ProtectApplies(c, uid, aid, sort)
if err != nil {
log.Error("s.dao.PaLs(%d) error(%v)", uid, err)
return
}
count = len(res.List)
res.Pager.Current = page
res.Pager.Total = count / model.ProtectApplyLimit
res.Pager.Size = model.ProtectApplyLimit
res.Pager.TotalCount = count
if count%model.ProtectApplyLimit != 0 {
res.Pager.Total++
}
if count == 0 {
res.List = make([]*model.Apply, 0, 1)
return
}
start = (page - 1) * model.ProtectApplyLimit
if start > count {
start = 0
}
end := start + model.ProtectApplyLimit
if end > count {
end = count
}
res.List = res.List[start:end]
aids := make([]int64, 0, len(res.List))
uids := make([]int64, 0, len(res.List))
for _, a := range res.List {
aids = append(aids, a.AID)
uids = append(uids, a.ApplyUID)
}
infosReply, err := s.accountSvc.Infos3(c, &account.MidsReq{
Mids: uids,
})
if err != nil {
log.Error("s.actSvc.Infos2(%v) error(%v)", uids, err)
err = nil
}
archives := s.archiveInfos(c, aids)
for _, a := range res.List {
v, ok := archives[a.AID]
if ok {
a.Pic = v.Pic
a.Title = v.Title
}
u, ok := infosReply.GetInfos()[a.ApplyUID]
if ok {
a.Uname = u.GetName()
}
}
return
}
// PaVideoLs 被申请保护弹幕的视频列表
func (s *Service) PaVideoLs(c context.Context, uid int64) (res []*model.Video, err error) {
aids, err := s.dao.ProtectAids(c, uid)
if err != nil {
log.Error("s.dao.ProtectArchives(%d) error(%v)", uid, err)
return
}
archives := s.archiveInfos(c, aids)
res = make([]*model.Video, 0, len(aids))
for _, aid := range aids {
a := new(model.Video)
v, ok := archives[aid]
a.Aid = aid
if ok {
a.Title = v.Title
} else {
a.Title = ""
}
res = append(res, a)
}
return
}
// sendProtectNotifyToUp 发送申请保护弹幕通知给up主
func (s *Service) sendProtectNotifyToUp(c context.Context) (err error) {
if time.Now().Format("15") != "20" {
return
}
lk, err := s.dao.PaLock(c, "up")
if err != nil {
log.Error("s.dao.PaLock() error(%v)", err)
return
}
if lk != 1 {
return
}
uids, err := s.dao.ProtectApplyStatistics(c)
if err != nil {
log.Error("s.dao.PaStat() error(%v)", err)
return
}
if len(uids) < 1 {
return
}
m, err := s.dao.PaNoticeClose(c, uids)
if err != nil {
log.Error("s.dao.PaNoticeClose(%v) error(%v)", uids, err)
return
}
if len(m) > 0 {
for k, v := range uids {
if _, ok := m[v]; ok {
uids = append(uids[:k], uids[k+1:]...)
}
}
}
s.dao.SendNotify(c, _notifyUpTitle, _notifyUpContent, uids)
return
}
// sendProtectNotifyToUser 发送申请保护弹幕处理结果给申请用户
func (s *Service) sendProtectNotifyToUser(c context.Context) {
if time.Now().Format("15") != "22" {
return
}
incr, err := s.dao.PaLock(c, "user")
if err != nil {
log.Error("s.dao.PaLock() error(%v)", err)
return
}
if incr != 1 {
return
}
stats, err := s.dao.PaUsrStat(c)
if err != nil {
log.Error("s.dao.PaStat() error(%v)", err)
return
}
aids := make([]int64, 0, len(stats))
for _, stat := range stats {
aids = append(aids, stat.Aid)
}
archives := s.archiveInfos(c, aids)
userStats := make(map[int64]map[int64]*model.ApplyUserNotify)
now := time.Now().Unix()
untreated := make(map[int64]int)
for _, stat := range stats {
m, ok := userStats[stat.Aid]
if !ok {
m = make(map[int64]*model.ApplyUserNotify)
userStats[stat.Aid] = m
}
n, ok := m[stat.UID]
if !ok {
n = &model.ApplyUserNotify{}
m[stat.UID] = n
}
if stat.Status == 1 {
n.Protect++
} else {
n.Unprotect++
if stat.Status == -1 && (now-stat.Ctime.Unix()) > 2*24*3600 {
untreated[stat.UID]++
}
}
}
for k, v := range untreated {
s.dao.SendNotify(c, _notifyUsrTitle, fmt.Sprintf(_pa48, v), []int64{k})
}
for aid, m := range userStats {
archive, ok := archives[aid]
if !ok {
continue
}
for uid, stat := range m {
var content string
if stat.Protect > 0 && stat.Unprotect == 0 {
content = fmt.Sprintf(_paa, archive.Title, archive.Aid)
}
if stat.Protect > 0 && stat.Unprotect > 0 {
content = fmt.Sprintf(_pap, archive.Title, archive.Aid)
}
if content == "" {
continue
}
s.dao.SendNotify(c, _notifyUsrTitle, content, []int64{uid})
}
}
}