package service import ( "context" "sync" "time" "go-common/app/admin/main/block/model" xsql "go-common/library/database/sql" "go-common/library/log" "go-common/library/sync/errgroup" "github.com/pkg/errors" ) // Search . func (s *Service) Search(c context.Context, mids []int64) (infos []*model.BlockInfo, err error) { var ( users []*model.DBUser userDetails []*model.DBUserDetail eg errgroup.Group mapMu sync.Mutex userMap = make(map[int64]*model.BlockInfo) ) if users, err = s.dao.Users(c, mids); err != nil { return } if userDetails, err = s.dao.UserDetails(c, mids); err != nil { return } infos = make([]*model.BlockInfo, 0, len(mids)) for _, m := range mids { mid := m eg.Go(func() (err error) { info := &model.BlockInfo{ MID: mid, } // 1. account 数据 if info.Nickname, info.TelStatus, info.Level, info.RegTime, err = s.dao.AccountInfo(context.TODO(), mid); err != nil { log.Error("%+v", err) err = nil } if info.Nickname == "" { log.Info("user mid(%d) not found", info.MID) return } // 2. 封禁状态 for i := range users { if users[i].MID == mid { info.ParseStatus(users[i]) break } } // 3. 封禁次数 for i := range userDetails { if userDetails[i].MID == mid { info.BlockCount = userDetails[i].BlockCount break } } // 4. spy 分值 if info.SpyScore, err = s.dao.SpyScore(context.TODO(), mid); err != nil { log.Error("%+v", err) err = nil info.SpyScore = -1 } // 5. figure 排名 if info.FigureRank, err = s.dao.FigureRank(context.TODO(), mid); err != nil { log.Error("%+v", err) err = nil info.FigureRank = -1 } // 6. extra 额外账号信息 if info.Tel, err = s.telInfo(context.TODO(), mid); err != nil { log.Error("%+v", err) err = nil info.Tel = "N/A" } if info.Mail, err = s.mailInfo(context.TODO(), mid); err != nil { log.Error("%+v", err) err = nil info.Mail = "N/A" } if info.Username, err = s.userID(context.TODO(), mid); err != nil { log.Error("%+v", err) err = nil info.Username = "N/A" } mapMu.Lock() userMap[info.MID] = info mapMu.Unlock() return }) } eg.Wait() for _, mid := range mids { if info, ok := userMap[mid]; ok { infos = append(infos, info) } } return } // History . func (s *Service) History(c context.Context, mid int64, ps, pn int) (status model.BlockStatus, total int, history []*model.BlockHistory, err error) { var ( start = (pn - 1) * ps limit = ps dbHistory []*model.DBHistory dbUser *model.DBUser ) if dbUser, err = s.dao.User(c, mid); err != nil { return } if dbUser != nil { status = dbUser.Status } if total, err = s.dao.HistoryCount(c, mid); err != nil { return } if dbHistory, err = s.dao.History(c, mid, start, limit); err != nil { return } for i := range dbHistory { his := &model.BlockHistory{} his.ParseDB(dbHistory[i]) history = append(history, his) } return } // BatchBlock . func (s *Service) BatchBlock(c context.Context, p *model.ParamBatchBlock) (err error) { var ( tx *xsql.Tx duration = time.Duration(p.Duration) * time.Hour * 24 source model.BlockSource mids []int64 stime = time.Now() ) if tx, err = s.dao.BeginTX(c); err != nil { return } if p.Source == 1 { // 系统封禁 source = model.BlockSourceSys } else if p.Source == 2 { // 小黑屋封禁 source = model.BlockSourceBlackHouse if err = s.dao.BlackhouseBlock(context.TODO(), p); err != nil { return } } for _, mid := range p.MIDs { mids = append(mids, mid) theMID := mid s.cache.Save(func() { if cacheErr := s.dao.DeleteUserCache(context.TODO(), theMID); cacheErr != nil { log.Error("%+v", cacheErr) } if databusErr := s.accountNotify(context.TODO(), theMID); databusErr != nil { log.Error("%+v", databusErr) } }) if err = s.action(c, tx, mid, p.AdminID, p.AdminName, source, p.Area, p.Reason, p.Comment, p.Action, duration, p.Notify, stime); err != nil { tx.Rollback() return } } // 发送站内信 if p.Notify { s.mission(func() { if notifyErr := s.notifyMSG(context.TODO(), p.MIDs, source, p.Action, p.Area, p.Reason, p.Duration); notifyErr != nil { log.Error("%+v", notifyErr) return } }) } s.mission(func() { s.AddAuditLog(context.TODO(), p.Action, p.AdminID, p.AdminName, mids, duration, source, p.Area, p.Reason, p.Comment, p.Notify, stime) }) err = tx.Commit() return } // BatchRemove . func (s *Service) BatchRemove(c context.Context, p *model.ParamBatchRemove) (err error) { var ( tx *xsql.Tx mids []int64 stime = time.Now() ) if tx, err = s.dao.BeginTX(c); err != nil { return } for _, mid := range p.MIDs { mids = append(mids, mid) theMID := mid s.cache.Save(func() { if cacheErr := s.dao.DeleteUserCache(context.TODO(), theMID); cacheErr != nil { log.Error("%+v", cacheErr) } if databusErr := s.accountNotify(context.TODO(), theMID); databusErr != nil { log.Error("%+v", databusErr) } }) if err = s.action(c, tx, mid, p.AdminID, p.AdminName, model.BlockSourceRemove, model.BlockAreaNone, "", p.Comment, model.BlockActionAdminRemove, 0, p.Notify, stime); err != nil { tx.Rollback() return } } // 发送站内信 if p.Notify { s.mission(func() { if notifyErr := s.notifyMSG(context.TODO(), p.MIDs, model.BlockSourceRemove, model.BlockActionAdminRemove, model.BlockAreaNone, "", 0); notifyErr != nil { log.Error("%+v", notifyErr) return } }) } s.mission(func() { s.AddAuditLog(context.TODO(), model.BlockActionAdminRemove, p.AdminID, p.AdminName, mids, 0, model.BlockSourceRemove, model.BlockAreaNone, "", p.Comment, p.Notify, stime) }) err = tx.Commit() return } // notifyMSG . func (s *Service) notifyMSG(c context.Context, mids []int64, source model.BlockSource, action model.BlockAction, area model.BlockArea, reason string, days int64) (err error) { code, title, content := s.MSGInfo(source, action, area, reason, days) log.Info("block admin title : %s , content : %s , mids : %+v", title, content, mids) if err = s.dao.SendSysMsg(context.TODO(), code, mids, title, content, ""); err != nil { return } return } func (s *Service) action(c context.Context, tx *xsql.Tx, mid int64, adminID int64, adminName string, source model.BlockSource, area model.BlockArea, reason, comment string, action model.BlockAction, duration time.Duration, notify bool, stime time.Time) (err error) { var ( db = &model.DBHistory{ MID: mid, AdminID: adminID, AdminName: adminName, Source: source, Area: area, Reason: reason, Comment: comment, Action: action, StartTime: stime, Duration: int64(duration / time.Second), Notify: notify, } blockStatus model.BlockStatus ) if err = s.dao.TxInsertHistory(c, tx, db); err != nil { return } switch action { case model.BlockActionAdminRemove, model.BlockActionSelfRemove: blockStatus = model.BlockStatusFalse case model.BlockActionLimit: switch source { case model.BlockSourceBlackHouse: blockStatus = model.BlockStatusCredit default: blockStatus = model.BlockStatusLimit } s.mission(func() { if err = s.dao.UpdateAddBlockCount(context.TODO(), mid); err != nil { log.Error("%+v", err) } }) case model.BlockActionForever: blockStatus = model.BlockStatusForever s.mission(func() { if err = s.dao.UpdateAddBlockCount(context.TODO(), mid); err != nil { log.Error("%+v", err) } }) default: err = errors.Errorf("unknown block action [%d]", action) return } if err = s.dao.TxUpdateUser(c, tx, mid, blockStatus); err != nil { return } return } func (s *Service) userID(c context.Context, mid int64) (id string, err error) { return "N/A", nil } func (s *Service) mailInfo(c context.Context, mid int64) (mail string, err error) { if mail, err = s.dao.MailInfo(c, mid); mail == "" { mail = "N/A" } return } // TelInfo . func (s *Service) telInfo(c context.Context, mid int64) (tel string, err error) { if tel, err = s.dao.TelInfo(c, mid); err != nil { return } if len(tel) == 0 { tel = "N/A" return } if len(tel) < 4 { tel = tel[:1] + "****" return } tel = tel[:3] + "****" + tel[len(tel)-4:] return }