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.
894 lines
29 KiB
894 lines
29 KiB
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 |
|
}
|
|
|