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})
|
||
}
|
||
}
|
||
}
|