364 lines
8.8 KiB
Go
364 lines
8.8 KiB
Go
|
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})
|
|||
|
}
|
|||
|
}
|
|||
|
}
|