895 lines
29 KiB
Go
895 lines
29 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"go-common/app/job/main/reply/model/reply"
|
|
model "go-common/app/job/main/reply/model/reply"
|
|
xsql "go-common/library/database/sql"
|
|
"go-common/library/log"
|
|
xtime "go-common/library/time"
|
|
)
|
|
|
|
const (
|
|
_eventReportAdd = "report_add"
|
|
_eventReportDel = "report_del"
|
|
_eventReportIgnore = "report_ignore"
|
|
_eventReportRecover = "report_recover"
|
|
)
|
|
|
|
func (s *Service) actionAdmin(c context.Context, msg *consumerMsg) {
|
|
var d struct {
|
|
Op string `json:"op"`
|
|
Adid int64 `json:"adid"`
|
|
AdName string `json:"adname"`
|
|
Oid int64 `json:"oid"`
|
|
RpID int64 `json:"rpid"`
|
|
Mid int64 `json:"mid"`
|
|
Tp int8 `json:"tp"`
|
|
Action uint32 `json:"action"`
|
|
Moral int `json:"moral"`
|
|
Notify bool `json:"notify"`
|
|
Remark string `json:"remark"`
|
|
MTime xtime.Time `json:"mtime"`
|
|
Ftime int64 `json:"ftime"`
|
|
Audit int8 `json:"audit"`
|
|
Reason int8 `json:"reason"`
|
|
Content string `json:"content"`
|
|
FReason int8 `json:"freason"`
|
|
Assist bool `json:"assist"`
|
|
State int8 `json:"state"`
|
|
}
|
|
if err := json.Unmarshal([]byte(msg.Data), &d); err != nil {
|
|
log.Error("json.Unmarshal() error(%v)", err)
|
|
return
|
|
}
|
|
if d.Oid <= 0 || d.RpID <= 0 {
|
|
log.Error("The structure of msg.Data(%s) was wrong", msg.Data)
|
|
return
|
|
}
|
|
rp, err := s.getReply(c, d.Oid, d.RpID)
|
|
if err != nil {
|
|
log.Error("s.getReply failed , oid(%d), RpID(%d) err(%v)", d.Oid, d.RpID, err)
|
|
return
|
|
}
|
|
if rp == nil {
|
|
log.Error("getReply nil oid(%d) RpID(%d)", d.Oid, d.RpID)
|
|
return
|
|
}
|
|
switch {
|
|
case d.Op == "del":
|
|
s.adminDel(c, rp, d.Adid, d.Mid, d.Ftime, d.Moral, d.AdName, d.Remark, d.MTime, d.Notify, d.Reason, d.FReason)
|
|
case d.Op == "del_rpt":
|
|
s.reportDel(c, rp, d.Adid, d.Mid, d.Ftime, d.Moral, d.AdName, d.Remark, d.MTime, d.Notify, d.Audit, d.Reason, d.Content, d.FReason)
|
|
case d.Op == "del_up":
|
|
s.userDel(c, rp, d.Mid, d.MTime, d.Remark, d.Assist)
|
|
case d.Op == "re", d.Op == "pass":
|
|
s.passReply(c, rp, d.MTime, d.Adid, d.Remark, d.Op)
|
|
case d.Op == "edit":
|
|
s.addSearchUp(c, rp.State, rp, nil)
|
|
case d.Op == "ignore":
|
|
s.reportIgnore(c, rp, d.Audit, d.MTime, d.Adid, d.Remark)
|
|
case d.Op == "transfer":
|
|
s.reportTransfer(c, rp, d.Audit, d.MTime, d.Adid, d.Remark)
|
|
case d.Op == "stateset":
|
|
s.reportStateSet(c, rp, d.State, d.MTime, d.Adid, d.Remark)
|
|
case d.Op == "top_add":
|
|
err := s.topAdd(c, rp, d.MTime, d.Action, model.SubAttrAdminTop)
|
|
if err != nil {
|
|
log.Error("s.topAdd(oid:%d,tp:%d err(%v))", rp.Oid, rp.Type, err)
|
|
return
|
|
}
|
|
// s.dao.Redis.AddTopOid(c, rp.Oid, rp.Type)
|
|
s.adminLog(c, rp, d.Adid, model.AdminIsReport, model.AdminOperSubTop, "管理员置顶评论", d.Remark)
|
|
s.addSearchUp(c, rp.State, rp, nil)
|
|
case d.Op == "rpt_re":
|
|
s.reportRecover(c, rp, d.Audit, d.MTime, d.Adid, d.Remark)
|
|
}
|
|
}
|
|
|
|
func (s *Service) reportStateSet(c context.Context, rp *model.Reply, state int8, mtime xtime.Time, adid int64, remark string) (err error) {
|
|
var (
|
|
op int8
|
|
result string
|
|
oldState = rp.State
|
|
)
|
|
rpt, err := s.dao.Report.Get(c, rp.Oid, rp.RpID)
|
|
if err != nil || rpt == nil {
|
|
log.Error("dao.Report.GetReport(%d, %d) met error (%v)", rp.Oid, rp.RpID, err)
|
|
return
|
|
}
|
|
|
|
rpt.State = state
|
|
rpt.MTime = mtime
|
|
|
|
op = model.AdminOperRptTransferArbitration
|
|
if adid == 0 {
|
|
result = "系统自动移交至风纪委"
|
|
} else {
|
|
result = "管理员移交至风纪委"
|
|
}
|
|
if _, err = s.dao.Report.Update(c, rpt); err != nil {
|
|
log.Error("dao.Report.Update(%v) error(%v)", rpt, err)
|
|
return
|
|
}
|
|
// admin log
|
|
s.adminLog(c, rp, adid, model.AdminIsReport, op, result, remark)
|
|
s.addSearchUp(c, oldState, rp, rpt)
|
|
return
|
|
}
|
|
|
|
func (s *Service) reportTransfer(c context.Context, rp *model.Reply, audit int8, mtime xtime.Time, adid int64, remark string) (err error) {
|
|
var (
|
|
op int8
|
|
result string
|
|
oldState = rp.State
|
|
)
|
|
rpt, err := s.dao.Report.Get(c, rp.Oid, rp.RpID)
|
|
if err != nil || rpt == nil {
|
|
log.Error("dao.Report.GetReport(%d, %d) met error (%v)", rp.Oid, rp.RpID, err)
|
|
return
|
|
}
|
|
if rpt.IsTransferred() {
|
|
log.Error("report(%v) has been transfferd before!", *rpt)
|
|
return
|
|
}
|
|
if audit == model.AuditTypeOne {
|
|
rpt.State = model.ReportStateNew
|
|
op = model.AdminOperRptTransfer1
|
|
result = "二审转一审"
|
|
} else if audit == model.AuditTypeTwo {
|
|
rpt.State = model.ReportStateNewTwo
|
|
op = model.AdminOperRptTransfer2
|
|
result = "一审转二审"
|
|
}
|
|
rpt.MTime = mtime
|
|
rpt.SetTransferred()
|
|
if _, err = s.dao.Report.Update(c, rpt); err != nil {
|
|
log.Error("dao.Report.Update(%v) error(%v)", rpt, err)
|
|
return
|
|
}
|
|
// admin log
|
|
s.adminLog(c, rp, adid, model.AdminIsReport, op, result, remark)
|
|
s.addSearchUp(c, oldState, rp, rpt)
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Service) reportIgnore(c context.Context, rp *model.Reply, audit int8, mtime xtime.Time, adid int64, remark string) (err error) {
|
|
var (
|
|
op int8
|
|
result string
|
|
oldState = rp.State
|
|
)
|
|
rpt, err := s.dao.Report.Get(c, rp.Oid, rp.RpID)
|
|
if err != nil || rpt == nil {
|
|
log.Error("dao.Report.GetReport(%d, %d) met error (%v)", rp.Oid, rp.RpID, err)
|
|
return
|
|
}
|
|
if audit == model.AuditTypeOne {
|
|
rpt.State = model.ReportStateIgnoreOne
|
|
op = model.AdminOperRptIgnore1
|
|
result = "一审忽略"
|
|
} else if audit == model.AuditTypeTwo {
|
|
rpt.State = model.ReportStateIgnoreTwo
|
|
op = model.AdminOperRptIgnore2
|
|
result = "二审忽略"
|
|
} else {
|
|
if rpt.State == model.ReportStateNew {
|
|
rpt.State = model.ReportStateIgnoreOne
|
|
} else {
|
|
rpt.State = model.ReportStateIgnoreTwo
|
|
}
|
|
op = model.AdminOperIgnoreReport
|
|
result = "已忽略举报"
|
|
}
|
|
rpt.MTime = mtime
|
|
if _, err = s.dao.Report.Update(c, rpt); err != nil {
|
|
log.Error("dao.Report.Update(%v) error(%v)", rpt, err)
|
|
return
|
|
}
|
|
// admin log
|
|
s.adminLog(c, rp, adid, model.AdminIsReport, op, result, remark)
|
|
s.addSearchUp(c, oldState, rp, rpt)
|
|
|
|
sub, err := s.getSubject(c, rp.Oid, rp.Type)
|
|
if err != nil || sub == nil {
|
|
log.Error("s.getSubject(%v,%v) err(%v) or sub nil", sub.Oid, sub.Type, err)
|
|
return
|
|
}
|
|
if err = s.dao.PubEvent(c, _eventReportIgnore, rpt.Mid, sub, rp, rpt); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) reportRecover(c context.Context, rp *model.Reply, audit int8, mtime xtime.Time, adid int64, remark string) (err error) {
|
|
var (
|
|
ok bool
|
|
op int8
|
|
result string
|
|
rootRp *model.Reply
|
|
oldState = rp.State
|
|
)
|
|
isRoot := rp.Root == 0 && rp.Parent == 0
|
|
rpt, _ := s.dao.Report.Get(c, rp.Oid, rp.RpID)
|
|
if err != nil || rpt == nil {
|
|
log.Error("dao.Report.GetReport(%d, %d) met error (%v)", rp.Oid, rp.RpID, err)
|
|
return
|
|
}
|
|
sub, err := s.getSubject(c, rp.Oid, rp.Type)
|
|
if err != nil || sub == nil {
|
|
log.Error("s.getSubject(%v,%v) err(%v) or sub nil", sub.Oid, sub.Type, err)
|
|
return
|
|
}
|
|
if audit == model.AuditTypeOne {
|
|
// 一审移除,恢复到待一审忽略,评论正常
|
|
rpt.State = model.ReportStateIgnoreOne
|
|
op = model.AdminOperRptRecover1
|
|
result = "一审恢复评论"
|
|
} else if audit == model.AuditTypeTwo {
|
|
// 二审移除,恢复到二审忽略,评论正常
|
|
rpt.State = model.ReportStateIgnoreTwo
|
|
op = model.AdminOperRptRecover2
|
|
result = "二审恢复评论"
|
|
} else {
|
|
log.Error("reportRecover unsupport audit: %d", audit)
|
|
return
|
|
}
|
|
rpt.MTime = mtime
|
|
if _, err = s.dao.Report.Update(c, rpt); err != nil {
|
|
log.Error("dao.Report.Update(%v) error(%v) or row==0", rpt, err)
|
|
return
|
|
}
|
|
// 只恢复管理员删除的评论,不恢复用户删除的
|
|
if rp.State == model.ReplyStateAdminDel {
|
|
rp.MTime = mtime
|
|
rp.State = model.ReplyStateNormal
|
|
if err = s.tranRecover(c, rp, model.ReplyStateNormal, isRoot); err != nil {
|
|
log.Error("Transaction recover reply failed err(%v)", err)
|
|
return
|
|
}
|
|
}
|
|
// add cache
|
|
if isRoot {
|
|
if err = s.dao.Mc.AddReply(c, rp); err != nil {
|
|
log.Error("s.dao.Mc.AddReply failed , RpID(%d), err(%v)", rp.RpID, err)
|
|
}
|
|
if err = s.dao.Redis.AddIndex(c, rp.Oid, rp.Type, rpt, rp, true); err != nil {
|
|
log.Error("s.dao.Redis.AddIndex(%d, %d) error(%v)", rp.Oid, rp.Type, err)
|
|
}
|
|
} else {
|
|
if ok, err = s.dao.Redis.ExpireNewChildIndex(c, rp.Root); err == nil && ok {
|
|
if err = s.dao.Redis.AddNewChildIndex(c, rp.Root, rp); err != nil {
|
|
log.Error("s.dao.Redis.AddFloorIndexByRoot failed , rproot(%d), err(%v)", rp.Root, err)
|
|
}
|
|
}
|
|
if rootRp, err = s.getReplyCache(c, rp.Oid, rp.Root); err != nil {
|
|
log.Error("s.getReply failed , oid(%d), root(%d) err(%v)", rp.Oid, rp.Root, err)
|
|
} else if rootRp != nil {
|
|
rootRp.RCount++
|
|
if err = s.dao.Mc.AddReply(c, rootRp); err != nil {
|
|
log.Error("s.dao.Mc.AddReply failed , RpID(%d) err(%v)", rootRp.RpID, err)
|
|
}
|
|
}
|
|
}
|
|
// log
|
|
s.adminLog(c, rp, adid, model.AdminIsReport, op, result, remark)
|
|
// notify
|
|
s.addSearchUp(c, oldState, rp, rpt)
|
|
s.upAcount(c, sub.Oid, sub.Type, sub.ACount, rp.CTime.Time())
|
|
|
|
if err = s.dao.PubEvent(c, _eventReportRecover, rpt.Mid, sub, rp, rpt); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// topAdd add top reply
|
|
func (s *Service) topAdd(c context.Context, rp *model.Reply, ts xtime.Time, act uint32, tp uint32) (err error) {
|
|
sub, err := s.getSubject(c, rp.Oid, rp.Type)
|
|
if err != nil || sub == nil {
|
|
log.Error("s.getsubject(%v,%v) err(%v) or sub nil", rp.Oid, rp.Type, err)
|
|
return
|
|
}
|
|
if act == 1 && sub.AttrVal(tp) == 1 {
|
|
log.Error("Repeat to add top reply(%d,%d,%d,%d) ", rp.RpID, rp.Oid, tp, sub.Attr)
|
|
return
|
|
}
|
|
err = sub.TopSet(rp.RpID, tp, act)
|
|
if err != nil {
|
|
log.Error("sub.TopSet(%d,%d,%d) failed!err:=%v ", rp.RpID, rp.Oid, tp, err)
|
|
return
|
|
}
|
|
sub.AttrSet(act, tp)
|
|
rp.AttrSet(act, tp)
|
|
tx, err := s.beginTran(c)
|
|
if err != nil {
|
|
log.Error("s.beginTran() err(%v)", err)
|
|
return
|
|
}
|
|
var rows int64
|
|
//rp.State = model.ReplyStateTop
|
|
if rows, err = s.dao.Reply.TxUpAttr(tx, rp.Oid, rp.RpID, rp.Attr, ts.Time()); err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
log.Error("dao.Reply.UpState(%v, %d) error(%v) or row==0", rp, rp.State, err)
|
|
return
|
|
}
|
|
if rows, err = s.dao.Subject.TxUpMeta(tx, sub.Oid, sub.Type, sub.Meta, ts.Time()); err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
log.Error("dao.TxUpMeta(oid:%d,tp:%d) err(%v) rows(%d)", sub.Oid, sub.Type, err, rows)
|
|
return
|
|
}
|
|
if rows, err = s.dao.Subject.TxUpAttr(tx, sub.Oid, sub.Type, sub.Attr, ts.Time()); err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
log.Error("dao.Upattr(oid:%d,tp:%d) err(%v) rows(%d)", sub.Oid, sub.Type, err, rows)
|
|
return
|
|
}
|
|
tx.Commit()
|
|
s.dao.Mc.AddSubject(c, sub)
|
|
if act == 1 {
|
|
s.dao.Redis.DelIndexBySortType(c, rp, reply.SortByCount)
|
|
s.dao.Redis.DelIndexBySortType(c, rp, reply.SortByLike)
|
|
} else if rp.IsNormal() {
|
|
if ok, err := s.dao.Redis.ExpireIndex(c, sub.Oid, sub.Type, model.SortByCount); err == nil && ok {
|
|
if err = s.dao.Redis.AddCountIndex(c, sub.Oid, sub.Type, rp); err != nil {
|
|
log.Error("s.dao.Redis.AddCountIndex failed , oid(%d) type(%d) err(%v)", sub.Oid, sub.Type, err)
|
|
}
|
|
}
|
|
if ok, err := s.dao.Redis.ExpireIndex(c, sub.Oid, sub.Type, model.SortByLike); err == nil && ok {
|
|
rpts := make(map[int64]*reply.Report, 1)
|
|
if rpt, _ := s.dao.Report.Get(c, rp.Oid, rp.RpID); rpt != nil {
|
|
rpts[rp.RpID] = rpt
|
|
}
|
|
if err = s.dao.Redis.AddLikeIndex(c, sub.Oid, sub.Type, rpts, rp); err != nil {
|
|
log.Error("s.dao.Redis.AddLikeIndex failed , oid(%d) type(%d) err(%v)", sub.Oid, sub.Type, err)
|
|
}
|
|
}
|
|
}
|
|
s.dao.Mc.AddReply(c, rp)
|
|
s.dao.Mc.AddTop(c, rp)
|
|
if act == 1 {
|
|
s.dao.PubEvent(c, "top", 0, sub, rp, nil)
|
|
} else if act == 0 {
|
|
s.dao.PubEvent(c, "untop", 0, sub, rp, nil)
|
|
}
|
|
// 折叠评论被置顶自动取消折叠
|
|
if rp.IsFolded() && act == 1 {
|
|
rp.State = model.ReplyStateNormal
|
|
s.marker.Do(c, func(ctx context.Context) {
|
|
if _, err := s.dao.Reply.UpState(ctx, rp.Oid, rp.RpID, rp.State, time.Now()); err == nil {
|
|
if ok, err := s.dao.Redis.ExpireIndex(c, rp.Oid, rp.Type, model.SortByFloor); err == nil && ok {
|
|
s.dao.Redis.AddFloorIndex(c, rp.Oid, rp.Type, rp)
|
|
}
|
|
s.handleFolded(ctx, rp)
|
|
}
|
|
})
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) userDel(c context.Context, rp *model.Reply, mid int64, mtime xtime.Time, remark string, assist bool) (err error) {
|
|
var (
|
|
state int8
|
|
sub *model.Subject
|
|
oldState = rp.State
|
|
isRoot = rp.Root == 0 && rp.Parent == 0
|
|
isFolded = rp.IsFolded()
|
|
)
|
|
if rp.IsDeleted() {
|
|
s.addSearchUp(c, oldState, rp, nil)
|
|
return
|
|
}
|
|
if sub, err = s.dao.Subject.Get(c, rp.Oid, rp.Type); err != nil || sub == nil {
|
|
log.Error("s.dao.Subject.Get(%d,%d) error(%v)", rp.Oid, rp.Type, err)
|
|
return
|
|
}
|
|
if rp.Mid == mid {
|
|
state = model.ReplyStateUserDel
|
|
} else if assist {
|
|
state = model.ReplyStateAssistDel
|
|
} else if mid > 0 {
|
|
state = model.ReplyStateUpDel
|
|
} else {
|
|
state = model.ReplyStateAdminDel
|
|
}
|
|
rp.MTime = mtime
|
|
if err = s.tranDel(c, rp, state, sub, isRoot); err != nil {
|
|
log.Error("reportDel tranDel(%d, %d) error(%v)", rp.Oid, rp.RpID, err)
|
|
return
|
|
}
|
|
if isFolded {
|
|
s.marker.Do(c, func(ctx context.Context) {
|
|
s.handleFolded(ctx, rp)
|
|
})
|
|
}
|
|
if err = s.clearReplyCache(c, rp); err != nil {
|
|
log.Error("reportDel clearReplyCache(%d, %d) error(%v)", rp.Oid, rp.RpID, err)
|
|
}
|
|
rp.State = state
|
|
if rp.Mid == mid {
|
|
s.adminLog(c, rp, mid, model.AdminIsNotReport, model.AdminOperDeleteUser, "由本人删除", remark)
|
|
s.searchDao.DelReply(c, rp.RpID, sub.Oid, mid, state)
|
|
} else if assist {
|
|
s.adminLog(c, rp, mid, model.AdminIsNotReport, model.AdminOperDeleteAssist, "由UP主协管员删除", remark)
|
|
s.addAssistLog(c, sub.Mid, mid, sub.Oid, 1, 1, strconv.FormatInt(rp.RpID, 10), rp.Content.Message)
|
|
} else if mid > 0 {
|
|
s.adminLog(c, rp, mid, model.AdminIsNotReport, model.AdminOperDeleteUp, "由up主删除", remark)
|
|
} else {
|
|
s.adminLog(c, rp, 0, model.AdminIsNotReport, model.AdminOperDelete, "由系统删除", remark)
|
|
}
|
|
s.dao.PubEvent(c, "reply_del", rp.Mid, sub, rp, nil)
|
|
return
|
|
}
|
|
|
|
func (s *Service) adminDel(c context.Context, rp *model.Reply, adid, mid, ftime int64, moral int, adName, remark string, mtime xtime.Time, notify bool, reason, freason int8) (err error) {
|
|
var (
|
|
sub *model.Subject
|
|
report *model.Report
|
|
oldState = rp.State
|
|
isRoot = rp.Root == 0 && rp.Parent == 0
|
|
isFolded = rp.IsFolded()
|
|
)
|
|
if rp.IsDeleted() {
|
|
s.addSearchUp(c, oldState, rp, nil)
|
|
return
|
|
}
|
|
if sub, err = s.dao.Subject.Get(c, rp.Oid, rp.Type); err != nil || sub == nil {
|
|
log.Error("s.dao.Subject.Get(%d,%d) error(%v)", rp.Oid, rp.Type, err)
|
|
return
|
|
}
|
|
rp.MTime = mtime
|
|
if err = s.tranDel(c, rp, model.ReplyStateAdminDel, sub, isRoot); err != nil {
|
|
log.Error("reportDel tranDel(%d, %d) error(%v)", rp.Oid, rp.RpID, err)
|
|
return
|
|
}
|
|
if isFolded {
|
|
s.marker.Do(c, func(ctx context.Context) {
|
|
s.handleFolded(ctx, rp)
|
|
})
|
|
}
|
|
if err = s.clearReplyCache(c, rp); err != nil {
|
|
log.Error("reportDel clearReplyCache(%d, %d) error(%v)", rp.Oid, rp.RpID, err)
|
|
}
|
|
if report, err = s.dao.Report.Get(c, rp.Oid, rp.RpID); err != nil {
|
|
log.Error("reportDel getReport(%d,%d) error(%v)", rp.Oid, rp.RpID, err)
|
|
return
|
|
}
|
|
if report != nil {
|
|
if report.State == model.ReportStateNew || report.State == model.ReportStateNewTwo {
|
|
if report.State == model.ReportStateNew {
|
|
report.State = model.ReportStateDeleteOne
|
|
} else if report.State == model.ReportStateNewTwo {
|
|
report.State = model.ReportStateDeleteTwo
|
|
}
|
|
report.MTime = mtime
|
|
if _, err = s.dao.Report.Update(c, report); err != nil {
|
|
log.Error("reportDel updateReport(%d, %d) error(%v)", report.Oid, report.ID, err)
|
|
return
|
|
}
|
|
s.addSearchUp(c, oldState, rp, report)
|
|
s.dao.PubEvent(c, _eventReportDel, 0, sub, rp, report)
|
|
}
|
|
}
|
|
rp.State = model.ReplyStateAdminDel
|
|
// add moral and notify
|
|
s.moralAndNotify(c, rp, moral, notify, mid, adid, adName, remark, reason, freason, ftime, false)
|
|
// forbidden tip
|
|
forbidDay := strconv.FormatInt(ftime, 10) + "天"
|
|
if ftime == -1 {
|
|
forbidDay = "永久"
|
|
}
|
|
s.adminLog(c, rp, adid, model.AdminIsNotReport, model.AdminOperDelete, fmt.Sprintf("已删除并封禁%s/扣除%d节操", forbidDay, moral), remark)
|
|
s.addSearchUp(c, oldState, rp, nil)
|
|
if report == nil {
|
|
s.dao.PubEvent(c, "reply_del", 0, sub, rp, nil)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) reportDel(c context.Context, rp *model.Reply, adid, mid, ftime int64, moral int, adName, remark string, mtime xtime.Time, notify bool, audit int8, reason int8, content string, freason int8) (err error) {
|
|
var (
|
|
op int8
|
|
isPunish bool
|
|
sub *model.Subject
|
|
report *model.Report
|
|
oldState = rp.State
|
|
)
|
|
if sub, err = s.dao.Subject.Get(c, rp.Oid, rp.Type); err != nil || sub == nil {
|
|
log.Error("s.dao.Subject.Get(%d,%d) error(%v)", rp.Oid, rp.Type, err)
|
|
return
|
|
}
|
|
if report, err = s.dao.Report.Get(c, rp.Oid, rp.RpID); err != nil || report == nil {
|
|
log.Error("reportDel getReport(%d,%d) error(%v)", rp.Oid, rp.RpID, err)
|
|
return
|
|
}
|
|
report.MTime = mtime
|
|
// 一审、二审操作
|
|
switch audit {
|
|
case model.AuditTypeOne:
|
|
report.State = model.ReportStateDeleteOne
|
|
op = model.AdminOperRptDel1
|
|
case model.AuditTypeTwo:
|
|
report.State = model.ReportStateDeleteTwo
|
|
op = model.AdminOperRptDel2
|
|
default:
|
|
report.State = model.ReportStateDelete
|
|
op = model.AdminOperDeleteByReport
|
|
}
|
|
report.Reason = reason
|
|
report.Content = content
|
|
if _, err = s.dao.Report.Update(c, report); err != nil {
|
|
log.Error("reportDel updateReport(%d, %d) error(%v)", report.Oid, report.ID, err)
|
|
return
|
|
}
|
|
if !rp.IsDeleted() {
|
|
isRoot := rp.Root == 0 && rp.Parent == 0
|
|
rp.MTime = mtime
|
|
if err = s.tranDel(c, rp, model.ReplyStateAdminDel, sub, isRoot); err != nil {
|
|
log.Error("reportDel tranDel(%d, %d) error(%v)", rp.Oid, rp.RpID, err)
|
|
return
|
|
}
|
|
if err = s.clearReplyCache(c, rp); err != nil {
|
|
log.Error("reportDel clearReplyCache(%d, %d) error(%v)", rp.Oid, rp.RpID, err)
|
|
}
|
|
rp.State = model.ReplyStateAdminDel
|
|
} else {
|
|
isPunish = true
|
|
}
|
|
// add moral and notify
|
|
s.moralAndNotify(c, rp, moral, notify, mid, adid, adName, remark, reason, freason, ftime, isPunish)
|
|
// forbidden tip
|
|
forbidDay := strconv.FormatInt(ftime, 10) + "天"
|
|
if ftime == -1 {
|
|
forbidDay = "永久"
|
|
}
|
|
s.adminLog(c, rp, adid, model.AdminIsReport, op, fmt.Sprintf("已通过举报删除并封禁%s/扣除%d节操", forbidDay, moral), remark)
|
|
s.addSearchUp(c, oldState, rp, report)
|
|
|
|
if err = s.dao.PubEvent(c, _eventReportDel, report.Mid, sub, rp, report); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) clearReplyCache(c context.Context, rp *model.Reply) (err error) {
|
|
var (
|
|
sub *model.Subject
|
|
rootRp *model.Reply
|
|
isRoot = rp.Root == 0 && rp.Parent == 0
|
|
)
|
|
if !isRoot && rp.IsNormal() {
|
|
// update root cache for count.
|
|
if rootRp, err = s.getReplyCache(c, rp.Oid, rp.Root); err != nil {
|
|
return
|
|
}
|
|
if rootRp != nil {
|
|
rootRp.RCount--
|
|
if err = s.addReplyCache(c, rootRp); err != nil {
|
|
log.Error("s.dao.Mc.addReplyCache(%d,%d,%d) error(%v)", rp.Oid, rp.Type, rp.RpID, err)
|
|
}
|
|
}
|
|
}
|
|
if rp.IsAdminTop() {
|
|
s.dao.Mc.DeleteTop(c, rp, model.ReplyAttrAdminTop)
|
|
}
|
|
if rp.IsUpTop() {
|
|
s.dao.Mc.DeleteTop(c, rp, model.ReplyAttrUpperTop)
|
|
}
|
|
if err = s.dao.Mc.DeleteReply(c, rp.RpID); err != nil {
|
|
log.Error("s.dao.Mc.DeleteReply failed , RpID(%d), err(%v)", rp.RpID, err)
|
|
}
|
|
if err = s.dao.Redis.DelIndex(c, rp); err != nil {
|
|
log.Error("s.dao.Redis.DelIndex failed , RpID(%d), err(%v)", rp.RpID, err)
|
|
}
|
|
if rp.State == model.ReplyStateAudit {
|
|
s.eraseAuditIndex(c, rp)
|
|
}
|
|
// update reply count
|
|
sub, err = s.dao.Subject.Get(c, rp.Oid, rp.Type)
|
|
if err != nil || sub == nil {
|
|
log.Error("s.dao.Subject.Get(%d,%d) error(%v)", rp.Oid, rp.Type, err)
|
|
return
|
|
}
|
|
if err = s.dao.Mc.AddSubject(c, sub); err != nil {
|
|
log.Error("s.dao.Mc.AddSubject failed , oid(%d), err(%v)", sub.Oid, err)
|
|
}
|
|
s.upAcount(c, sub.Oid, sub.Type, sub.ACount, rp.CTime.Time())
|
|
return
|
|
}
|
|
|
|
func (s *Service) passReply(c context.Context, rp *model.Reply, mtime xtime.Time, adid int64, remark, op string) {
|
|
var (
|
|
err error
|
|
ok bool
|
|
rootRp *model.Reply
|
|
oldState = rp.State
|
|
isRoot = rp.Root == 0 && rp.Parent == 0
|
|
)
|
|
sub, err := s.dao.Subject.Get(c, rp.Oid, rp.Type)
|
|
if err != nil || sub == nil {
|
|
log.Error("s.dao.Subject.Get(%d,%d) error(%v)", rp.Oid, rp.Type, err)
|
|
return
|
|
}
|
|
if rp.State <= model.ReplyStateHidden {
|
|
s.addSearchUp(c, oldState, rp, nil)
|
|
return
|
|
}
|
|
rp.MTime = mtime
|
|
rp.State = model.ReplyStateNormal
|
|
if op == "re" || oldState == model.ReplyStateAudit {
|
|
if err = s.tranRecover(c, rp, model.ReplyStateNormal, isRoot); err != nil {
|
|
log.Error("Transaction recover reply failed err(%v)", err)
|
|
return
|
|
}
|
|
} else if op == "pass" {
|
|
var row int64
|
|
var tx *xsql.Tx
|
|
tx, err = s.dao.BeginTran(c)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if row, err = s.dao.Reply.TxUpState(tx, rp.Oid, rp.RpID, model.ReplyStateNormal, mtime.Time()); err != nil || row == 0 {
|
|
tx.Rollback()
|
|
log.Error("dao.Reply.TxUpState(%v, %d) error(%v) or row==0", rp, model.ReplyStateNormal, err)
|
|
return
|
|
}
|
|
if rp.State == model.ReplyStateAudit || rp.State == model.ReplyStateMonitor {
|
|
if _, err = s.dao.Subject.TxDecrMCount(tx, rp.Oid, rp.Type, mtime.Time()); err != nil {
|
|
tx.Rollback()
|
|
log.Error("dao.Reply.TxDecrMCount(%v) error(%v)", rp, err)
|
|
return
|
|
}
|
|
}
|
|
if err = tx.Commit(); err != nil {
|
|
log.Error("tx.Commit error(%v)", err)
|
|
return
|
|
}
|
|
}
|
|
if isRoot {
|
|
if ok, err = s.dao.Redis.ExpireIndex(c, rp.Oid, rp.Type, model.SortByFloor); err == nil && ok {
|
|
var min int
|
|
min, err = s.dao.Redis.MinScore(c, rp.Oid, rp.Type, reply.SortByFloor)
|
|
if err != nil {
|
|
log.Error("s.dao.Redis.AddFloorIndex failed , oid(%d) type(%d) err(%v)", rp.Oid, rp.Type, err)
|
|
} else if rp.Floor > min {
|
|
if err = s.dao.Redis.AddFloorIndex(c, rp.Oid, rp.Type, rp); err != nil {
|
|
log.Error("s.dao.Redis.AddFloorIndex failed , RpID(%d), err(%v)", rp.RpID, err)
|
|
}
|
|
}
|
|
}
|
|
if ok, err = s.dao.Redis.ExpireIndex(c, rp.Oid, rp.Type, model.SortByCount); err == nil && ok {
|
|
if err = s.dao.Redis.AddCountIndex(c, rp.Oid, rp.Type, rp); err != nil {
|
|
log.Error("s.dao.Redis.AddCountIndex failed , RpID(%d), err(%v)", rp.RpID, err)
|
|
}
|
|
}
|
|
if ok, err = s.dao.Redis.ExpireIndex(c, rp.Oid, rp.Type, model.SortByLike); err == nil && ok {
|
|
rpts := make(map[int64]*reply.Report, 1)
|
|
if rpt, _ := s.dao.Report.Get(c, rp.Oid, rp.RpID); rpt != nil {
|
|
rpts[rp.RpID] = rpt
|
|
}
|
|
if err = s.dao.Redis.AddLikeIndex(c, rp.Oid, rp.Type, rpts, rp); err != nil {
|
|
log.Error("s.dao.Redis.AddLikeIndex failed , RpID(%d), err(%v)", rp.RpID, err)
|
|
}
|
|
}
|
|
} else {
|
|
if ok, err = s.dao.Redis.ExpireDialogIndex(c, rp.Dialog); err == nil && ok {
|
|
if err = s.dao.Redis.AddDialogIndex(c, rp.Dialog, []*model.Reply{rp}); err != nil {
|
|
log.Error("s.dao.Redis.AddDialogINdex Error (%v)", err)
|
|
}
|
|
}
|
|
if ok, err = s.dao.Redis.ExpireNewChildIndex(c, rp.Root); err == nil && ok {
|
|
if err = s.dao.Redis.AddNewChildIndex(c, rp.Root, rp); err != nil {
|
|
log.Error("s.dao.Redis.AddFloorIndexByRoot failed , rproot(%d), err(%v)", rp.Root, err)
|
|
}
|
|
}
|
|
if op == "re" || oldState == model.ReplyStateAudit {
|
|
if rootRp, err = s.getReplyCache(c, rp.Oid, rp.Root); err != nil {
|
|
log.Error("s.getReply failed , oid(%d), root(%d) err(%v)", rp.Oid, rp.Root, err)
|
|
} else if rootRp != nil {
|
|
rootRp.RCount++
|
|
if err = s.addReplyCache(c, rootRp); err != nil {
|
|
log.Error("s.addReplyCache oid(%d), rpid(%d) err(%v)", rootRp.Oid, rootRp.RpID, err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if err = s.addReplyCache(c, rp); err != nil {
|
|
log.Error("s.addReplyCache oid(%d), rpid(%d) err(%v)", rp.Oid, rp.RpID, err)
|
|
}
|
|
if oldState == model.ReplyStateAudit {
|
|
s.dao.Redis.DelAuditIndexs(c, rp)
|
|
}
|
|
// update reply count
|
|
s.upAcount(c, sub.Oid, sub.Type, sub.ACount, rp.CTime.Time())
|
|
if err = s.dao.Mc.AddSubject(c, sub); err != nil {
|
|
log.Error("s.dao.Mc.AddSubject failed , oid(%d) err(%v)", sub.Oid, err)
|
|
}
|
|
// admin log
|
|
if op == "re" {
|
|
s.adminLog(c, rp, adid, model.AdminIsNotReport, model.AdminOperRecover, "已恢复评论", remark)
|
|
|
|
} else if op == "pass" {
|
|
s.adminLog(c, rp, adid, model.AdminIsNotReport, model.AdminOperPass, "已通过评论", remark)
|
|
}
|
|
s.addSearchUp(c, oldState, rp, nil)
|
|
}
|
|
|
|
func (s *Service) tranRecover(c context.Context, rp *model.Reply, state int8, isRoot bool) error {
|
|
var (
|
|
err error
|
|
rootReply *model.Reply
|
|
count int
|
|
rows int64
|
|
tx *xsql.Tx
|
|
)
|
|
if tx, err = s.beginTran(c); err != nil {
|
|
return err
|
|
}
|
|
mtime := rp.MTime
|
|
if rp, err = s.dao.Reply.GetForUpdate(tx, rp.Oid, rp.RpID); err != nil || rp == nil {
|
|
tx.Rollback()
|
|
return fmt.Errorf("s.dao.Reply.GetForUpdate(%d,%d) error(%v) or is nil)", rp.Oid, rp.RpID, err)
|
|
}
|
|
if mtime != 0 {
|
|
rp.MTime = mtime
|
|
}
|
|
if rp.IsNormal() {
|
|
tx.Rollback()
|
|
return fmt.Errorf("reply(%d,%d) already is normal", rp.Oid, rp.RpID)
|
|
}
|
|
rows, err = s.dao.Reply.TxUpState(tx, rp.Oid, rp.RpID, state, rp.MTime.Time())
|
|
if err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("TxUpState error(%v) or rows(%d)", err, rows)
|
|
}
|
|
if isRoot {
|
|
count = rp.RCount + 1
|
|
} else {
|
|
rootReply, err = s.dao.Reply.Get(c, rp.Oid, rp.Root)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
count = 1
|
|
}
|
|
if isRoot {
|
|
rows, err = s.dao.Subject.TxIncrRCount(tx, rp.Oid, rp.Type, rp.MTime.Time())
|
|
} else {
|
|
rows, err = s.dao.Reply.TxIncrRCount(tx, rp.Oid, rp.Root, rp.MTime.Time())
|
|
}
|
|
if err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("TxIncrRCount error(%v) or rows(%d)", err, rows)
|
|
}
|
|
if isRoot || rootReply != nil && rootReply.IsNormal() {
|
|
rows, err = s.dao.Subject.TxIncrACount(tx, rp.Oid, rp.Type, count, rp.MTime.Time())
|
|
if err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("TxIncrACount error(%v) or rows(%d)", err, rows)
|
|
}
|
|
}
|
|
return tx.Commit()
|
|
}
|
|
|
|
func (s *Service) tranDel(c context.Context, rp *model.Reply, state int8, sub *model.Subject, isRoot bool) error {
|
|
var (
|
|
count int
|
|
rows int64
|
|
rootReply *model.Reply
|
|
err error
|
|
tx *xsql.Tx
|
|
)
|
|
if tx, err = s.beginTran(c); err != nil {
|
|
return err
|
|
}
|
|
mtime := rp.MTime
|
|
if rp, err = s.dao.Reply.GetForUpdate(tx, rp.Oid, rp.RpID); err != nil || rp == nil {
|
|
tx.Rollback()
|
|
return fmt.Errorf("s.dao.Reply.GetForUpdate(%d,%d) error(%v) or is nil)", rp.Oid, rp.RpID, err)
|
|
}
|
|
if mtime != 0 {
|
|
rp.MTime = mtime
|
|
}
|
|
if rp.IsDeleted() || rp.AttrVal(reply.ReplyAttrAdminTop) == 1 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("reply(%d,%d) already deleted", rp.Oid, rp.RpID)
|
|
}
|
|
rows, err = s.dao.Reply.TxUpState(tx, rp.Oid, rp.RpID, state, rp.MTime.Time())
|
|
if err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("error(%v) or rows(%d)", err, rows)
|
|
}
|
|
if rp.IsNormal() {
|
|
if isRoot {
|
|
count = rp.RCount + 1
|
|
rows, err = s.dao.Subject.TxDecrACount(tx, rp.Oid, rp.Type, count, rp.MTime.Time())
|
|
if err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("error(%v) or rows(%d)", err, rows)
|
|
}
|
|
rows, err = s.dao.Subject.TxDecrCount(tx, rp.Oid, rp.Type, rp.MTime.Time())
|
|
if err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("SubjectTxDecrCount error(%v) or rows(%d)", err, rows)
|
|
}
|
|
} else {
|
|
if rootReply, err = s.dao.Reply.GetForUpdate(tx, rp.Oid, rp.Root); err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
if rootReply != nil {
|
|
if rootReply.IsNormal() {
|
|
rows, err = s.dao.Subject.TxDecrACount(tx, rp.Oid, rp.Type, 1, rp.MTime.Time())
|
|
if err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("error(%v) or rows(%d)", err, rows)
|
|
}
|
|
}
|
|
rows, err = s.dao.Reply.TxDecrCount(tx, rp.Oid, rp.Root, rp.MTime.Time())
|
|
if err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("ReplyTxDecrCount error(%v) or rows(%d)", err, rows)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if rp.AttrVal(model.ReplyAttrUpperTop) == 1 {
|
|
rp.AttrSet(0, model.ReplyAttrUpperTop)
|
|
sub.AttrSet(0, model.SubAttrUpperTop)
|
|
sub.TopSet(0, model.SubAttrUpperTop, 0)
|
|
if rows, err = s.dao.Subject.TxUpMeta(tx, sub.Oid, sub.Type, sub.Meta, rp.MTime.Time()); err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
log.Error("dao.TxUpMeta(oid:%d,tp:%d) err(%v) rows(%d)", sub.Oid, sub.Type, err, rows)
|
|
return fmt.Errorf("dao.TxUpMeta(oid:%d,tp:%d) err(%v) rows(%d)", sub.Oid, sub.Type, err, rows)
|
|
}
|
|
if rows, err = s.dao.Subject.TxUpAttr(tx, sub.Oid, sub.Type, sub.Attr, rp.MTime.Time()); err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("dao.Upattr(oid:%d,tp:%d) err(%v) rows(%d)", sub.Oid, sub.Type, err, rows)
|
|
}
|
|
//rp.State = model.ReplyStateTop
|
|
if rows, err = s.dao.Reply.TxUpAttr(tx, rp.Oid, rp.RpID, rp.Attr, rp.MTime.Time()); err != nil || rows == 0 {
|
|
tx.Rollback()
|
|
return fmt.Errorf("dao.Reply.UpState(%v, %d) error(%v) or rows(%d)", rp, rp.State, err, rows)
|
|
}
|
|
}
|
|
if rp.State == model.ReplyStateMonitor || rp.State == model.ReplyStateAudit {
|
|
if _, err = s.dao.Subject.TxDecrMCount(tx, rp.Oid, rp.Type, rp.MTime.Time()); err != nil {
|
|
tx.Rollback()
|
|
log.Error("dao.Reply.TxDecrMCount(%v) error(%v)", rp, err)
|
|
return fmt.Errorf("dao.Reply.TxDecrMCount error(%v)", err)
|
|
}
|
|
}
|
|
return tx.Commit()
|
|
}
|
|
|
|
func (s *Service) eraseAuditIndex(c context.Context, rp *model.Reply) (err error) {
|
|
var rs []*model.Reply
|
|
if rp.Root == 0 && rp.Parent == 0 {
|
|
if rs, err = s.dao.Reply.GetsByRoot(c, rp.Oid, rp.RpID, rp.Type, model.ReplyStateAudit); err != nil {
|
|
return
|
|
}
|
|
}
|
|
if err = s.dao.Redis.DelAuditIndexs(c, append(rs, rp)...); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) addReplyCache(c context.Context, rp *model.Reply) (err error) {
|
|
var isRoot = rp.Root == 0 && rp.Parent == 0
|
|
if err = s.dao.Mc.AddReply(c, rp); err != nil {
|
|
log.Error("s.dao.Mc.AddReply(%d,%d,%d) error(%v)", rp.Oid, rp.RpID, rp.Type, err)
|
|
}
|
|
if isRoot && rp.IsTop() {
|
|
if err = s.dao.Mc.AddTop(c, rp); err != nil {
|
|
log.Error("s.dao.Mc.AddTop(%d,%d,%d) error(%v)", rp.Oid, rp.RpID, rp.Type, err)
|
|
}
|
|
}
|
|
return
|
|
}
|