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