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.
546 lines
15 KiB
546 lines
15 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"encoding/json" |
|
"fmt" |
|
"reflect" |
|
"sort" |
|
"strconv" |
|
"time" |
|
|
|
creditMDL "go-common/app/admin/main/credit/model" |
|
"go-common/app/admin/main/credit/model/blocked" |
|
account "go-common/app/service/main/account/api" |
|
relationmdl "go-common/app/service/main/relation/model" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
"go-common/library/net/metadata" |
|
"go-common/library/sync/errgroup" |
|
xtime "go-common/library/time" |
|
"go-common/library/xstr" |
|
) |
|
|
|
// AddJury add jury to admin |
|
func (s *Service) AddJury(c context.Context, arg *blocked.ArgAddJurys) (err error) { |
|
arg.MIDs = creditMDL.ArrayUnique(arg.MIDs) |
|
if len(arg.MIDs) == 0 { |
|
return |
|
} |
|
items := []*blocked.Jury{} |
|
if err = s.blockedDao.ReadDB.Where("mid IN (?)", arg.MIDs).Find(&items).Error; err != nil { |
|
log.Error("s.blockedDao.juryByMIDs(%s) error(%v)", xstr.JoinInts(arg.MIDs), err) |
|
err = nil |
|
} |
|
mids := make(map[int64]*blocked.Jury, len(arg.MIDs)) |
|
for _, v := range items { |
|
mids[v.UID] = v |
|
} |
|
day, _ := time.ParseDuration("24h") |
|
users := make([]*blocked.Jury, 0, len(arg.MIDs)) |
|
tx := s.DB.Begin() |
|
defer func() { |
|
if err != nil { |
|
tx.Rollback() |
|
} else { |
|
tx.Commit() |
|
} |
|
}() |
|
now := time.Now() |
|
var multiple []interface{} |
|
for _, mid := range arg.MIDs { |
|
user := &blocked.Jury{ |
|
UID: mid, |
|
Status: blocked.JuryStatusOn, |
|
OPID: arg.OPID, |
|
Remark: blocked.AddJuryRemark, |
|
Expired: xtime.Time(now.Add(day * time.Duration(arg.Day)).Unix()), |
|
} |
|
if jury, ok := mids[mid]; ok { |
|
user.ID = jury.ID |
|
switch { |
|
case jury.Black == blocked.JuryBlack: |
|
continue |
|
case jury.Black == blocked.JuryWhite: |
|
user.Black = blocked.JuryWhite |
|
} |
|
user.CTime = jury.CTime |
|
user.VoteTotal = jury.VoteTotal |
|
user.VoteRight = jury.VoteRight |
|
user.Total = jury.Total |
|
single := map[string]interface{}{ |
|
"id": jury.ID, |
|
"oper_id": arg.OPID, |
|
"status": blocked.JuryStatusOn, |
|
"black": user.Black, |
|
"expired": now.Add(day * time.Duration(arg.Day)).Format(creditMDL.TimeFormatSec), |
|
} |
|
multiple = append(multiple, single) |
|
} |
|
if err = tx.Save(&user).Error; err != nil { |
|
log.Error("s.DB.Create error(%v)", err) |
|
return |
|
} |
|
s.AddNotify(func() { |
|
s.Search.SearchUpdate(context.TODO(), blocked.BusinessBlockedJury, blocked.TableBlockedJury, multiple) |
|
}) |
|
users = append(users, user) |
|
} |
|
if arg.Send == blocked.NeedSendMsg { |
|
for _, u := range users { |
|
msg := &blocked.SysMsg{ |
|
Type: blocked.MsgTypeGetJuryer, |
|
MID: u.UID, |
|
Day: arg.Day, |
|
RemoteIP: metadata.String(c, metadata.RemoteIP), |
|
} |
|
s.MsgCh <- msg |
|
} |
|
} |
|
return |
|
} |
|
|
|
// Cases deal case data. |
|
func (s *Service) Cases(c context.Context, arg *blocked.ArgCaseSearch) (list []*blocked.Case, pager *blocked.Pager, err error) { |
|
var ids []int64 |
|
ids, pager, err = s.searchDao.Case(c, arg) |
|
if err != nil { |
|
log.Error(" s.searchDao.Case error(%v)", err) |
|
return |
|
} |
|
if len(ids) == 0 { |
|
return |
|
} |
|
var ( |
|
accInfoMap map[int64]*account.Info |
|
relationsMap map[int64]*relationmdl.Stat |
|
uids = make([]int64, 0) |
|
) |
|
ids = creditMDL.ArrayUnique(ids) |
|
if err = s.blockedDao.ReadDB.Where("id IN (?)", ids).Order(fmt.Sprintf("%s %s", arg.Order, arg.Sort)).Find(&list).Error; err != nil { |
|
if err != ecode.NothingFound { |
|
log.Error("s.blockedDao(%s) error(%v)", xstr.JoinInts(ids), err) |
|
return |
|
} |
|
log.Warn("search ids(%s) not in db", xstr.JoinInts(ids)) |
|
err = nil |
|
} |
|
for _, v := range list { |
|
if v.MID > 0 { |
|
uids = append(uids, v.MID) |
|
} |
|
} |
|
if accInfoMap, err = s.accDao.RPCInfos(c, uids); err != nil { |
|
log.Error("s.accDao.RPCInfos(%s) error(%v)", xstr.JoinInts(uids), err) |
|
err = nil |
|
} |
|
if relationsMap, err = s.RelationDao.RPCStats(c, uids); err != nil { |
|
log.Error("s.RelationDao.RPCStats(%s) error(%v)", xstr.JoinInts(uids), err) |
|
err = nil |
|
} |
|
for _, v := range list { |
|
if accInfo, ok := accInfoMap[v.MID]; ok { |
|
v.Uname = accInfo.Name |
|
} |
|
if relationInfo, ok := relationsMap[v.MID]; ok { |
|
v.Fans = relationInfo.Follower |
|
} |
|
v.OPName = s.Managers[v.OPID] |
|
v.StatusDesc = blocked.StatusDesc[v.Status] |
|
v.OriginTypeDesc = blocked.OriginTypeDesc[v.OriginType] |
|
v.ReasonTypeDesc = blocked.ReasonTypeDesc(v.ReasonType) |
|
v.PunishDesc = blocked.PunishDesc[v.PunishResult] |
|
v.CaseTypeDesc = blocked.CaseTypeDesc[v.CaseType] |
|
v.VoteTotal = blocked.VoteTotal(v.VoteRule, v.VoteBreak, v.VoteDelete) |
|
if v.VoteRule > 0 || v.VoteBreak > 0 || v.VoteDelete > 0 { |
|
v.BlockedPercent = blocked.BreakPercent(v.VoteRule, v.VoteBreak, v.VoteDelete) |
|
v.DeletePercent = blocked.DeletePercent(v.VoteRule, v.VoteBreak, v.VoteDelete) |
|
v.RulePercent = blocked.RulePercent(v.VoteRule, v.VoteBreak, v.VoteDelete) |
|
} |
|
} |
|
return |
|
} |
|
|
|
// Opinions is block opinions |
|
func (s *Service) Opinions(c context.Context, arg *blocked.ArgOpinionSearch) (list []*blocked.Opinion, pager *blocked.Pager, err error) { |
|
var ids []int64 |
|
ids, pager, err = s.searchDao.Opinion(c, arg) |
|
if err != nil { |
|
log.Error("s.blockedDao.Search appid(%s) error(%v)", "", err) |
|
return |
|
} |
|
if len(ids) == 0 { |
|
return |
|
} |
|
var ( |
|
accInfoMap map[int64]*account.Info |
|
relationsMap map[int64]*relationmdl.Stat |
|
uids = make([]int64, 0) |
|
) |
|
ids = creditMDL.ArrayUnique(ids) |
|
if err = s.blockedDao.ReadDB.Where("id IN (?)", ids).Order(fmt.Sprintf("%s %s", arg.Order, arg.Sort)).Find(&list).Error; err != nil { |
|
if err != ecode.NothingFound { |
|
log.Error("s.blockedDao(%s) error(%v)", xstr.JoinInts(ids), err) |
|
return |
|
} |
|
log.Warn("search ids(%s) not in db", xstr.JoinInts(ids)) |
|
err = nil |
|
} |
|
for _, v := range list { |
|
if v.MID > 0 { |
|
uids = append(uids, v.MID) |
|
|
|
} |
|
} |
|
accInfoMap, err = s.accDao.RPCInfos(c, uids) |
|
if err != nil { |
|
log.Error("s.accDao.RPCInfos error(%v)", err) |
|
err = nil |
|
} |
|
if relationsMap, err = s.RelationDao.RPCStats(c, uids); err != nil { |
|
log.Error("s.RelationDao.RPCStats(%s) error(%v)", xstr.JoinInts(uids), err) |
|
err = nil |
|
} |
|
for _, v := range list { |
|
if opinion, ok := accInfoMap[v.MID]; ok { |
|
v.UName = opinion.Name |
|
} |
|
if relationInfo, ok := relationsMap[v.MID]; ok { |
|
v.Fans = relationInfo.Follower |
|
} |
|
v.OPName = s.Managers[v.OperID] |
|
v.AttrDesc = blocked.AttrDesc[v.Attr] |
|
v.VoteDesc = blocked.VoteDesc[v.Vote] |
|
v.VoteStateDesc = blocked.VoteStateDesc[v.State] |
|
} |
|
return |
|
} |
|
|
|
// Jurys select jury lists. |
|
func (s *Service) Jurys(c context.Context, arg *blocked.ArgJurySearch) (list []*blocked.Jury, pager *blocked.Pager, err error) { |
|
var ids []int64 |
|
ids, pager, err = s.searchDao.Jury(c, arg) |
|
if err != nil { |
|
log.Error("s.searchDao.Jury error(%v)", err) |
|
return |
|
} |
|
if len(ids) == 0 { |
|
return |
|
} |
|
var ( |
|
accInfoMap map[int64]*account.Info |
|
uids = make([]int64, len(ids)) |
|
) |
|
ids = creditMDL.ArrayUnique(ids) |
|
if err = s.blockedDao.ReadDB.Where("id IN (?)", ids).Order(fmt.Sprintf("%s %s", arg.Order, arg.Sort)).Find(&list).Error; err != nil { |
|
if err != ecode.NothingFound { |
|
log.Error("s.blockedDao(%s) error(%v)", xstr.JoinInts(ids), err) |
|
return |
|
} |
|
log.Warn("search ids(%s) not in db", xstr.JoinInts(ids)) |
|
err = nil |
|
} |
|
for _, v := range list { |
|
uids = append(uids, v.UID) |
|
} |
|
accInfoMap, err = s.accDao.RPCInfos(c, uids) |
|
if err != nil { |
|
log.Error("s.accDao.RPCInfos error(%v)", err) |
|
err = nil |
|
} |
|
for _, v := range list { |
|
if jury, ok := accInfoMap[v.UID]; ok { |
|
v.UName = jury.Name |
|
} |
|
v.OPName = s.Managers[v.OPID] |
|
v.EffectDay = xtime.Time(v.Expired.Time().AddDate(0, 0, -blocked.JuryDay).Unix()) |
|
if v.EffectDay < v.CTime { |
|
v.EffectDay = v.CTime |
|
} |
|
if v.VoteTotal > 0 { |
|
v.VoteRadio = strconv.FormatFloat(float64(v.VoteRight)/float64(v.VoteTotal)*100, 'f', 2, 64) |
|
} else { |
|
v.VoteRadio = "-1" |
|
} |
|
v.StatusDesc = blocked.JuryerStatus[v.Status] |
|
v.BlackDesc = blocked.JuryerStyle[v.Black] |
|
} |
|
return |
|
} |
|
|
|
// JurysEx export jury list. |
|
func (s *Service) JurysEx(c context.Context, arg *blocked.ArgJurySearch) (list []*blocked.Jury, err error) { |
|
var ( |
|
ps = 500 |
|
count int |
|
pager *blocked.Pager |
|
g errgroup.Group |
|
) |
|
if list, pager, err = s.Jurys(c, arg); err != nil { |
|
log.Error("s.Infos(%+v) error(%v)", arg, err) |
|
return |
|
} |
|
if pager == nil { |
|
log.Warn("arg(%+v) jury search data empty!", arg) |
|
return |
|
} |
|
count = pager.Total / ps |
|
if pager.Total%ps != 0 { |
|
count++ |
|
} |
|
lCh := make(chan []*blocked.Jury, count) |
|
for pn := 1; pn <= count; pn++ { |
|
tmpPn := pn |
|
g.Go(func() (err error) { |
|
var gJury []*blocked.Jury |
|
gArg := &blocked.ArgJurySearch{ |
|
UID: arg.UID, |
|
Status: arg.Status, |
|
Black: arg.Black, |
|
ExpiredFrom: arg.ExpiredFrom, |
|
ExpiredTo: arg.ExpiredTo, |
|
Order: arg.Order, |
|
Sort: arg.Sort, |
|
PN: tmpPn, |
|
PS: ps, |
|
} |
|
gJury, _, err = s.Jurys(c, gArg) |
|
if err != nil { |
|
log.Error("s.Jurys(%+v) error(%v)", gJury, err) |
|
err = nil |
|
return |
|
} |
|
lCh <- gJury |
|
return |
|
}) |
|
} |
|
g.Wait() |
|
close(lCh) |
|
for jInfo := range lCh { |
|
list = append(list, jInfo...) |
|
} |
|
sort.Slice(list, func(i int, j int) bool { |
|
return list[i].ID < list[j].ID |
|
}) |
|
return |
|
} |
|
|
|
// UpCaseStatus update case status. |
|
func (s *Service) UpCaseStatus(c context.Context, arg *blocked.ArgUpStatus) (err error) { |
|
items := []blocked.Case{} |
|
if err = s.blockedDao.ReadDB.Where("id IN(?)", arg.IDS).Find(&items).Error; err != nil { |
|
log.Error("s.blockedDao.caseByIDs(%s) error(%v)", xstr.JoinInts(arg.IDS), err) |
|
return |
|
} |
|
var multiple []interface{} |
|
if arg.Status == blocked.CaseStatusGranting { |
|
hour := s.CaseConfig(blocked.ConfigCaseGiveHours) |
|
now := time.Now() |
|
if err = s.DB.Model(blocked.Case{}).Where("id IN(?)", arg.IDS).Updates( |
|
&blocked.Case{ |
|
Status: arg.Status, |
|
OPID: arg.OID, |
|
StartTime: xtime.Time(now.Unix()), |
|
EndTime: xtime.Time(now.Add(time.Duration(hour) * time.Hour).Unix()), |
|
}).Error; err != nil { |
|
return |
|
} |
|
for _, item := range items { |
|
single := map[string]interface{}{ |
|
"id": item.ID, |
|
"oper_id": arg.OID, |
|
"start_time": now.Format(creditMDL.TimeFormatSec), |
|
"status": arg.Status, |
|
"case_type": item.CaseType, |
|
} |
|
multiple = append(multiple, single) |
|
} |
|
} else { |
|
if err = s.DB.Model(blocked.Case{}).Where("id IN(?)", arg.IDS).Updates( |
|
&blocked.Case{ |
|
Status: arg.Status, |
|
OPID: arg.OID, |
|
}).Error; err != nil { |
|
return |
|
} |
|
for _, item := range items { |
|
single := map[string]interface{}{ |
|
"id": item.ID, |
|
"oper_id": arg.OID, |
|
"status": arg.Status, |
|
"case_type": item.CaseType, |
|
} |
|
multiple = append(multiple, single) |
|
} |
|
} |
|
s.AddNotify(func() { |
|
s.Search.SearchUpdate(context.TODO(), blocked.BusinessBlockedCase, blocked.TableBlockedCase, multiple) |
|
}) |
|
return |
|
} |
|
|
|
// CaseReason reason info. |
|
func (s *Service) CaseReason(c context.Context) (cr map[int]string, err error) { |
|
var reason []*blocked.Reason |
|
cr = make(map[int]string) |
|
if err = s.ReadDB.Select([]string{"id", "reason"}).Where("status = 0").Find(&reason).Error; err != nil { |
|
if err == ecode.NothingFound { |
|
err = nil |
|
return |
|
} |
|
return |
|
} |
|
for _, v := range reason { |
|
cr[v.ID] = v.Reason |
|
} |
|
return |
|
} |
|
|
|
// CaseConf caseconfig list. |
|
func (s *Service) CaseConf(c context.Context) (cc map[string]string, err error) { |
|
var configs []*blocked.Config |
|
cc = make(map[string]string) |
|
err = s.ReadDB.Select([]string{"config_key", "content"}).Find(&configs).Error |
|
if err != nil || configs == nil { |
|
return |
|
} |
|
for _, v := range configs { |
|
cc[v.ConfigKey] = v.Content |
|
} |
|
return |
|
} |
|
|
|
// SetCaseConf update case config. |
|
func (s *Service) SetCaseConf(c context.Context, cc *blocked.ArgCaseConf) (err error) { |
|
v := reflect.ValueOf(cc).Elem() |
|
tx := s.DB.Begin() |
|
defer func() { |
|
if err != nil { |
|
tx.Rollback() |
|
} else { |
|
tx.Commit() |
|
} |
|
}() |
|
for i := 0; i < v.NumField(); i++ { |
|
fieldValue := strconv.Itoa(v.Field(i).Interface().(int)) |
|
tag := v.Type().Field(i).Tag.Get("form") |
|
if err = tx.Model(&blocked.Config{}).Where("config_key = ?", tag).Updates(map[string]interface{}{"content": fieldValue, "oper_id": cc.OID}).Error; err != nil { |
|
log.Error("caseConfig(%s,%d) update error(%v)", v.Field(i).Type().Name(), v.Field(i).Interface().(int64), err) |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
// CaseConfig get config by key. |
|
func (s *Service) CaseConfig(ck string) (cv int64) { |
|
if v, ok := s.caseConfCache[ck]; ok { |
|
cv, _ = strconv.ParseInt(v, 10, 64) |
|
} |
|
return |
|
} |
|
|
|
// KPIPoint get kpi_point data |
|
func (s *Service) KPIPoint(c context.Context, arg *blocked.ArgKpiPointSearch) (list []*blocked.KPIPoint, pager *blocked.Pager, err error) { |
|
var ids []int64 |
|
ids, pager, err = s.searchDao.KPIPoint(c, arg) |
|
if err != nil { |
|
log.Error("s.searchDao.KPIPoint error (%v)", err) |
|
return |
|
} |
|
if len(ids) == 0 { |
|
return |
|
} |
|
ids = creditMDL.ArrayUnique(ids) |
|
if err = s.blockedDao.ReadDB.Where("id IN (?)", ids).Order(fmt.Sprintf("%s %s", arg.Order, arg.Sort)).Find(&list).Error; err != nil { |
|
if err != ecode.NothingFound { |
|
log.Error("s.blockedDao(%s) error(%v)", xstr.JoinInts(ids), err) |
|
return |
|
} |
|
log.Warn("search ids(%s) not in db", xstr.JoinInts(ids)) |
|
err = nil |
|
} |
|
return |
|
} |
|
|
|
// VotenumConf votenumConf list. |
|
func (s *Service) VotenumConf(c context.Context) (cc string, err error) { |
|
var bc = &blocked.Config{} |
|
err = s.ReadDB.Select("content").Where("config_key = 'vote_num'").Find(&bc).Error |
|
if err != nil || bc.Content == "" { |
|
log.Error("s.VotenumConf(%s) error(%v)", cc, err) |
|
return |
|
} |
|
cc = bc.Content |
|
return |
|
} |
|
|
|
// SetVotenumConf . |
|
func (s *Service) SetVotenumConf(c context.Context, vn *blocked.ArgVoteNum) (err error) { |
|
v := blocked.VoteNum{} |
|
v.RateS = vn.RateS |
|
v.RateA = vn.RateA |
|
v.RateB = vn.RateB |
|
v.RateC = vn.RateC |
|
v.RateD = vn.RateD |
|
vnb, err := json.Marshal(v) |
|
if err != nil { |
|
log.Error("json.Marshal(%+v) error(%v)", v, err) |
|
} |
|
config := &blocked.Config{} |
|
s.ReadDB.Where("config_key = 'vote_num'").Find(config) |
|
var vconfig *blocked.Config |
|
if config != nil && config.ID != 0 { |
|
vconfig = &blocked.Config{ |
|
ID: config.ID, |
|
ConfigKey: "vote_num", |
|
Content: string(vnb), |
|
OperID: vn.OID, |
|
} |
|
} else { |
|
vconfig = &blocked.Config{ |
|
ConfigKey: "vote_num", |
|
Content: string(vnb), |
|
OperID: vn.OID, |
|
} |
|
} |
|
if err = s.DB.Save(&vconfig).Error; err != nil { |
|
log.Error("http.setAutoCaseConfig error(%v)", err) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// WebHook a webhook from work flow. |
|
func (s *Service) WebHook(c context.Context, data []byte) (err error) { |
|
wh := &blocked.WebHook{} |
|
if err = json.Unmarshal(data, &wh); err != nil { |
|
err = ecode.RequestErr |
|
log.Error("webhook json rawmessage(%s) error(%v)", string(data), err) |
|
return |
|
} |
|
if wh.Verb == "chall.SetResult" || wh.Verb == "chall.BatchSetResult" { |
|
if wh.Target == nil || wh.Object == nil { |
|
log.Warn("wh.Target or wh.Object is nil %v,%v", wh.Target, wh.Object) |
|
return |
|
} |
|
// appeal state not changed . |
|
if wh.Target.State == wh.Object.State { |
|
log.Warn("appeal state not changed target=%d object=%d", wh.Target.State, wh.Object.State) |
|
return |
|
} |
|
switch wh.Object.State { |
|
case blocked.AppealStateSucc: |
|
if err = s.blockedDao.DB.Model(&blocked.Info{}).Where("case_id =?", wh.Target.OID).Update("status", blocked.BlockStateClose).Error; err != nil { |
|
log.Error("s.blockedDao.DB error(%v)", err) |
|
return |
|
} |
|
s.MsgCh <- &blocked.SysMsg{Type: blocked.MsgTypeAppealSucc, MID: wh.Target.Mid, CID: wh.Target.OID, RemoteIP: metadata.String(c, metadata.RemoteIP)} |
|
case blocked.AppealStateFail: |
|
s.MsgCh <- &blocked.SysMsg{Type: blocked.MsgTypeAppealFail, MID: wh.Target.Mid, CID: wh.Target.OID, RemoteIP: metadata.String(c, metadata.RemoteIP)} |
|
default: |
|
log.Warn("unknown webhook state(%d) ", wh.Object.State) |
|
} |
|
} |
|
return |
|
}
|
|
|