You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
8.8 KiB
363 lines
8.8 KiB
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}) |
|
} |
|
} |
|
}
|
|
|