member.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. package service
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/csv"
  6. "encoding/json"
  7. "fmt"
  8. "io"
  9. "sort"
  10. "strconv"
  11. "time"
  12. "go-common/app/admin/main/member/model"
  13. "go-common/app/admin/main/member/model/bom"
  14. coin "go-common/app/service/main/coin/model"
  15. member "go-common/app/service/main/member/model"
  16. "go-common/library/ecode"
  17. "go-common/library/log"
  18. "go-common/library/net/metadata"
  19. "go-common/library/queue/databus/report"
  20. "github.com/pkg/errors"
  21. )
  22. const (
  23. _logActionBaseAudit = "base_audit"
  24. _logActionDeleteSign = "delete_sign"
  25. _logActionRankUpdate = "rank_set"
  26. _logActionCoinUpdate = "coin_set"
  27. _logActionExpUpdate = "exp_set"
  28. _logActionMoralUpdate = "moral_set"
  29. )
  30. func (s *Service) batchBase(ctx context.Context, mids []int64) (map[int64]*model.Base, error) {
  31. bs := make(map[int64]*model.Base, len(mids))
  32. for _, mid := range mids {
  33. b, err := s.dao.Base(ctx, mid)
  34. if err != nil {
  35. log.Error("Failed to retrive user base by mid: %d: %+v", mid, err)
  36. continue
  37. }
  38. bs[b.Mid] = b
  39. }
  40. return bs, nil
  41. }
  42. // BaseReview is.
  43. func (s *Service) BaseReview(ctx context.Context, arg *model.ArgBaseReview) ([]*model.BaseReview, error) {
  44. mids := arg.Mids()
  45. if len(mids) == 0 {
  46. return nil, ecode.RequestErr
  47. }
  48. if len(mids) > 200 {
  49. //mids = mids[:200]
  50. return nil, ecode.SearchMidOverLimit
  51. }
  52. var mrs []*model.BaseReview
  53. for _, mid := range mids {
  54. base, err := s.dao.Base(ctx, mid)
  55. if err != nil {
  56. log.Error("Failed to retrive user base by mid: %d: %+v", mid, err)
  57. continue
  58. }
  59. logs, err := s.dao.SearchUserAuditLog(ctx, mid)
  60. if err != nil {
  61. log.Error("Failed to search user audit log, mid: %d error: %v", mid, err)
  62. continue
  63. }
  64. fixFaceLogs(logs.Result)
  65. mr := &model.BaseReview{
  66. Base: *base,
  67. Logs: logs.Result,
  68. }
  69. mrs = append(mrs, mr)
  70. }
  71. if err := s.reviewAddit(ctx, mids, mrs); err != nil {
  72. log.Error("Failed to fetch review violation count with mids: %+v: %+v", mids, err)
  73. }
  74. return mrs, nil
  75. }
  76. func fixFaceLogs(auditLogs []model.AuditLog) {
  77. for i, v := range auditLogs {
  78. if v.Type != model.BaseAuditTypeFace {
  79. continue
  80. }
  81. // 对头像进行重新签名
  82. ext := new(struct {
  83. Old string `json:"old"`
  84. New string `json:"new"`
  85. })
  86. if err := json.Unmarshal([]byte(v.Extra), &ext); err != nil {
  87. log.Error("Failed to unmarshal extra, additLog: %+v error: %v", v, err)
  88. continue
  89. }
  90. ext.New = model.BuildFaceURL(ext.New)
  91. extraDataBytes, err := json.Marshal(ext)
  92. if err != nil {
  93. log.Error("FaceExtra (%+v) json marshal err(%v)", ext, err)
  94. continue
  95. }
  96. auditLogs[i].Extra = string(extraDataBytes)
  97. }
  98. }
  99. // ClearFace is
  100. func (s *Service) ClearFace(ctx context.Context, arg *model.ArgMids) error {
  101. for _, mid := range arg.Mid {
  102. b, err := s.dao.Base(ctx, mid)
  103. if err != nil {
  104. log.Error("Failed to retrive user base by mid: %d: %+v", mid, err)
  105. continue
  106. }
  107. if err = s.dao.UpFace(ctx, mid, ""); err != nil {
  108. log.Error("Failed to clear face mid %d error: %+v", mid, err)
  109. continue
  110. }
  111. privFace, err := s.mvToPrivate(ctx, urlPath(b.Face))
  112. if err != nil {
  113. log.Error("Failed to mv face To private bucket, mid: %d error: %+v", mid, err)
  114. err = nil
  115. }
  116. if err = s.dao.Message(ctx, "违规头像处理通知", "抱歉,由于你的头像涉嫌违规,已被修改。如有疑问请联系客服。", []int64{mid}); err != nil {
  117. log.Error("Failed to send message, mid: %d error: %+v", mid, err)
  118. err = nil
  119. }
  120. if err = s.dao.IncrViolationCount(ctx, mid); err != nil {
  121. log.Error("Failed to increase violation count mid: %d error: %+v", mid, err)
  122. err = nil
  123. }
  124. report.Manager(&report.ManagerInfo{
  125. Uname: arg.Operator,
  126. UID: arg.OperatorID,
  127. Business: model.ManagerLogID,
  128. Type: model.BaseAuditTypeFace,
  129. Oid: mid,
  130. Action: _logActionBaseAudit,
  131. Ctime: time.Now(),
  132. // extra
  133. Index: []interface{}{0, 0, 0, "", "", ""},
  134. Content: map[string]interface{}{
  135. "old": b.Face,
  136. "new": model.BuildFaceURL(privFace),
  137. },
  138. })
  139. }
  140. return nil
  141. }
  142. // ClearSign is
  143. func (s *Service) ClearSign(ctx context.Context, arg *model.ArgMids) error {
  144. for _, mid := range arg.Mid {
  145. b, err := s.dao.Base(ctx, mid)
  146. if err != nil {
  147. log.Error("Failed to retrive user base by mid: %d: %+v", mid, err)
  148. continue
  149. }
  150. if err = s.dao.UpSign(ctx, mid, ""); err != nil {
  151. log.Error("Failed to clear sign mid %d error: %+v", mid, err)
  152. continue
  153. }
  154. if err = s.dao.Message(ctx, "违规签名处理通知", "抱歉,由于你的签名涉嫌违规,已被修改。如有疑问请联系客服。", []int64{mid}); err != nil {
  155. log.Error("Failed to send message, mid: %d error: %+v", mid, err)
  156. err = nil
  157. }
  158. if err = s.dao.IncrViolationCount(ctx, mid); err != nil {
  159. log.Error("Failed to increase violation count mid: %d error: %+v", mid, err)
  160. err = nil
  161. }
  162. report.Manager(&report.ManagerInfo{
  163. Uname: arg.Operator,
  164. UID: arg.OperatorID,
  165. Business: model.ManagerLogID,
  166. Type: model.BaseAuditTypeSign,
  167. Oid: mid,
  168. Action: _logActionBaseAudit,
  169. Ctime: time.Now(),
  170. // extra
  171. Index: []interface{}{0, 0, 0, "", "", ""},
  172. Content: map[string]interface{}{
  173. "old": b.Sign,
  174. "new": "",
  175. },
  176. })
  177. }
  178. return nil
  179. }
  180. // ClearName is
  181. func (s *Service) ClearName(ctx context.Context, arg *model.ArgMids) error {
  182. for _, mid := range arg.Mid {
  183. b, err := s.dao.Base(ctx, mid)
  184. if err != nil {
  185. log.Error("Failed to retrive user base by mid: %d: %+v", mid, err)
  186. continue
  187. }
  188. defaultName := fmt.Sprintf("bili_%d", mid)
  189. if err = s.dao.UpdateUname(ctx, mid, defaultName); err != nil {
  190. log.Error("Failed to clear name mid %d error: %+v", mid, err)
  191. continue
  192. }
  193. if err = s.dao.Message(ctx, "违规昵称处理通知", "抱歉,由于你的昵称涉嫌违规,已被修改。如有疑问请联系客服。", []int64{mid}); err != nil {
  194. log.Error("Failed to send message, mid: %d error: %+v", mid, err)
  195. err = nil
  196. }
  197. if err = s.dao.IncrViolationCount(ctx, mid); err != nil {
  198. log.Error("Failed to increase violation count mid: %d error: %+v", mid, err)
  199. err = nil
  200. }
  201. report.Manager(&report.ManagerInfo{
  202. Uname: arg.Operator,
  203. UID: arg.OperatorID,
  204. Business: model.ManagerLogID,
  205. Type: model.BaseAuditTypeName,
  206. Oid: mid,
  207. Action: _logActionBaseAudit,
  208. Ctime: time.Now(),
  209. // extra
  210. Index: []interface{}{0, 0, 0, "", "", ""},
  211. Content: map[string]interface{}{
  212. "old": b.Name,
  213. "new": defaultName,
  214. },
  215. })
  216. }
  217. return nil
  218. }
  219. // Members is.
  220. func (s *Service) Members(ctx context.Context, arg *model.ArgList) (*model.MemberPagination, error) {
  221. searched, err := s.dao.SearchMember(ctx, arg)
  222. if err != nil {
  223. return nil, err
  224. }
  225. mids := searched.Mids()
  226. bs, err := s.batchBase(ctx, mids)
  227. if err != nil {
  228. return nil, err
  229. }
  230. result := make([]*model.Base, 0, len(mids))
  231. for _, mid := range mids {
  232. if b, ok := bs[mid]; ok {
  233. result = append(result, b)
  234. }
  235. }
  236. page := &model.MemberPagination{
  237. CommonPagination: searched.Pagination(),
  238. Members: result,
  239. }
  240. return page, nil
  241. }
  242. // MemberProfile is.
  243. func (s *Service) MemberProfile(ctx context.Context, mid int64) (*model.Profile, error) {
  244. p := model.NewProfile()
  245. // base
  246. b, err := s.dao.Base(ctx, mid)
  247. if err != nil {
  248. log.Error("Failed to retrive user base with mid: %d: %+v", mid, err)
  249. return nil, err
  250. }
  251. p.Base = *b
  252. // detail
  253. // remove later
  254. p.Detail = model.Detail{
  255. Mid: b.Mid,
  256. Birthday: b.Birthday,
  257. }
  258. // exp
  259. e, err := s.dao.Exp(ctx, mid)
  260. if err != nil {
  261. log.Error("Failed to retrive user exp with mid: %d: %+v", mid, err)
  262. }
  263. if e != nil {
  264. p.Exp = *e
  265. p.Level.FromExp(e)
  266. }
  267. // moral
  268. mo, err := s.dao.Moral(ctx, mid)
  269. if err != nil {
  270. log.Error("Failed to retrive user moral with mid: %d: %+v", mid, err)
  271. }
  272. if mo != nil {
  273. p.Moral = *mo
  274. }
  275. // official
  276. of, err := s.dao.Official(ctx, mid)
  277. if err != nil {
  278. log.Error("Failed to retrive user official with mid: %d: %+v", mid, err)
  279. }
  280. if of != nil {
  281. p.Official = *of
  282. }
  283. // coin
  284. co, err := s.coinRPC.UserCoins(ctx, &coin.ArgCoinInfo{Mid: mid})
  285. if err != nil {
  286. log.Error("Failed to retrive user coins with mid: %d: %+v", mid, err)
  287. }
  288. p.Coin = model.Coin{Coins: co}
  289. // addit
  290. ad, err := s.dao.UserAddit(ctx, mid)
  291. if err != nil {
  292. log.Error("Failed to retrive user addit with mid: %d: %+v", mid, err)
  293. }
  294. if ad != nil {
  295. p.Addit = *ad
  296. }
  297. // realname
  298. dr, err := s.dao.RealnameInfo(ctx, mid)
  299. if err != nil {
  300. log.Error("Failed to retrive user realname with mid: %d: %+v", mid, err)
  301. }
  302. if dr != nil {
  303. p.Realanme.ParseInfo(dr)
  304. } else {
  305. p.Realanme.State = model.RealnameApplyStateNone
  306. }
  307. return p, nil
  308. }
  309. // DelSign is.
  310. func (s *Service) DelSign(ctx context.Context, arg *model.ArgMids) error {
  311. for _, mid := range arg.Mid {
  312. err := s.dao.UpSign(ctx, mid, "")
  313. if err != nil {
  314. log.Error("Failed to delete sign mid: %d: %+v", mid, err)
  315. continue
  316. }
  317. if err := s.dao.Message(ctx, "违规签名处理通知", "抱歉,由于你的个性签名内容涉嫌违规,我们已将你的个性签名清空,如有问题请联系客服。", []int64{mid}); err != nil {
  318. log.Error("Failed to send message: mid: %d: %+v", mid, err)
  319. }
  320. report.Manager(&report.ManagerInfo{
  321. Uname: arg.Operator,
  322. UID: arg.OperatorID,
  323. Business: model.ManagerLogID,
  324. Type: 0,
  325. Oid: mid,
  326. Action: _logActionDeleteSign,
  327. Ctime: time.Now(),
  328. })
  329. }
  330. return nil
  331. }
  332. // SetMoral is.
  333. func (s *Service) SetMoral(ctx context.Context, arg *model.ArgMoralSet) error {
  334. moral, err := s.dao.Moral(ctx, arg.Mid)
  335. if err != nil {
  336. return errors.WithStack(err)
  337. }
  338. newMoral := int64(arg.Moral * 100)
  339. delta := newMoral - moral.Moral
  340. if err = s.memberRPC.AddMoral(ctx,
  341. &member.ArgUpdateMoral{
  342. Mid: arg.Mid,
  343. Delta: delta,
  344. Operator: arg.Operator,
  345. Reason: arg.Reason,
  346. Remark: "管理后台",
  347. Origin: member.ManualChangeType,
  348. IP: arg.IP}); err != nil {
  349. return errors.WithStack(err)
  350. }
  351. report.Manager(&report.ManagerInfo{
  352. Uname: arg.Operator,
  353. UID: arg.OperatorID,
  354. Business: model.ManagerLogID,
  355. Type: 0,
  356. Oid: arg.Mid,
  357. Action: _logActionMoralUpdate,
  358. Ctime: time.Now(),
  359. // extra
  360. Index: []interface{}{0, 0, 0, "", "", ""},
  361. Content: map[string]interface{}{
  362. "new_moral": newMoral,
  363. "delta": delta,
  364. },
  365. })
  366. return nil
  367. }
  368. // SetExp is.
  369. func (s *Service) SetExp(ctx context.Context, arg *model.ArgExpSet) error {
  370. exp, err := func() (*model.Exp, error) {
  371. exp, err := s.dao.Exp(ctx, arg.Mid)
  372. if err != nil {
  373. if err == ecode.NothingFound {
  374. return &model.Exp{Mid: arg.Mid}, nil
  375. }
  376. return nil, errors.WithStack(err)
  377. }
  378. return exp, nil
  379. }()
  380. if err != nil {
  381. return err
  382. }
  383. delta := arg.Exp - float64(exp.Exp/100)
  384. if err = s.memberRPC.UpdateExp(ctx,
  385. &member.ArgAddExp{
  386. Mid: arg.Mid,
  387. Count: delta,
  388. Operate: arg.Operator,
  389. Reason: arg.Reason,
  390. IP: arg.IP}); err != nil {
  391. return errors.WithStack(err)
  392. }
  393. report.Manager(&report.ManagerInfo{
  394. Uname: arg.Operator,
  395. UID: arg.OperatorID,
  396. Business: model.ManagerLogID,
  397. Type: 0,
  398. Oid: arg.Mid,
  399. Action: _logActionExpUpdate,
  400. Ctime: time.Now(),
  401. // extra
  402. Index: []interface{}{0, 0, 0, "", "", ""},
  403. Content: map[string]interface{}{
  404. "new_exp": arg.Exp,
  405. "delta": delta,
  406. },
  407. })
  408. return nil
  409. }
  410. // SetRank is.
  411. func (s *Service) SetRank(ctx context.Context, arg *model.ArgRankSet) error {
  412. if err := s.memberRPC.SetRank(ctx,
  413. &member.ArgUpdateRank{
  414. Mid: arg.Mid,
  415. Rank: arg.Rank,
  416. RemoteIP: arg.IP}); err != nil {
  417. return errors.WithStack(err)
  418. }
  419. report.Manager(&report.ManagerInfo{
  420. Uname: arg.Operator,
  421. UID: arg.OperatorID,
  422. Business: model.ManagerLogID,
  423. Type: 0,
  424. Oid: arg.Mid,
  425. Action: _logActionRankUpdate,
  426. Ctime: time.Now(),
  427. // extra
  428. Index: []interface{}{0, 0, 0, "", "", ""},
  429. Content: map[string]interface{}{
  430. "new_rank": arg.Rank,
  431. "reason": arg.Reason,
  432. },
  433. })
  434. return nil
  435. }
  436. // SetCoin is.
  437. func (s *Service) SetCoin(ctx context.Context, arg *model.ArgCoinSet) error {
  438. coins, err := s.coinRPC.UserCoins(ctx, &coin.ArgCoinInfo{Mid: arg.Mid, RealIP: arg.IP})
  439. if err != nil {
  440. return errors.WithStack(err)
  441. }
  442. reason := "系统操作"
  443. if arg.Reason != "" {
  444. reason = fmt.Sprintf("系统操作:%s", arg.Reason)
  445. }
  446. delta := arg.Coins - coins
  447. if _, err = s.coinRPC.ModifyCoin(ctx,
  448. &coin.ArgModifyCoin{
  449. Mid: arg.Mid,
  450. Operator: arg.Operator,
  451. Reason: reason,
  452. Count: delta,
  453. IP: arg.IP}); err != nil {
  454. return errors.WithStack(err)
  455. }
  456. report.Manager(&report.ManagerInfo{
  457. Uname: arg.Operator,
  458. UID: arg.OperatorID,
  459. Business: model.ManagerLogID,
  460. Type: 0,
  461. Oid: arg.Mid,
  462. Action: _logActionCoinUpdate,
  463. Ctime: time.Now(),
  464. // extra
  465. Index: []interface{}{0, 0, 0, "", "", ""},
  466. Content: map[string]interface{}{
  467. "new_coins": arg.Coins,
  468. "delta": delta,
  469. "reason": reason,
  470. },
  471. })
  472. return nil
  473. }
  474. // SetAdditRemark is.
  475. func (s *Service) SetAdditRemark(ctx context.Context, arg *model.ArgAdditRemarkSet) error {
  476. return s.dao.UpAdditRemark(ctx, arg.Mid, arg.Remark)
  477. }
  478. // PubExpMsg is.
  479. func (s *Service) PubExpMsg(ctx context.Context, arg *model.ArgPubExpMsg) (err error) {
  480. msg := &model.AddExpMsg{
  481. Event: arg.Event,
  482. Mid: arg.Mid,
  483. IP: arg.IP,
  484. Ts: arg.Ts,
  485. }
  486. return s.dao.PubExpMsg(ctx, msg)
  487. }
  488. // ExpLog is.
  489. func (s *Service) ExpLog(ctx context.Context, mid int64) ([]*model.UserLog, error) {
  490. return nil, ecode.MethodNotAllowed
  491. }
  492. func filterByStatus(status ...int8) func(*model.FaceRecord) bool {
  493. ss := make(map[int8]struct{}, len(status))
  494. for _, s := range status {
  495. ss[s] = struct{}{}
  496. }
  497. return func(fr *model.FaceRecord) bool {
  498. _, ok := ss[fr.Status]
  499. return ok
  500. }
  501. }
  502. func filterByMid(mid int64) func(*model.FaceRecord) bool {
  503. return func(fr *model.FaceRecord) bool {
  504. return fr.Mid == mid
  505. }
  506. }
  507. func filterByOP(operator string) func(*model.FaceRecord) bool {
  508. return func(fr *model.FaceRecord) bool {
  509. return fr.Operator == operator
  510. }
  511. }
  512. // FaceHistory is.
  513. func (s *Service) FaceHistory(ctx context.Context, arg *model.ArgFaceHistory) (*model.FaceRecordPagination, error) {
  514. list, err := s.faceHistory(ctx, arg)
  515. if err != nil {
  516. return nil, err
  517. }
  518. plist := list.Paginate(arg.PS*(arg.PN-1), arg.PS)
  519. page := &model.FaceRecordPagination{
  520. Records: plist,
  521. CommonPagination: &model.CommonPagination{
  522. Page: model.Page{
  523. Num: arg.PN,
  524. Size: arg.PS,
  525. Total: len(list),
  526. },
  527. },
  528. }
  529. return page, nil
  530. }
  531. func (s *Service) faceHistory(ctx context.Context, arg *model.ArgFaceHistory) (res model.FaceRecordList, err error) {
  532. switch arg.Mode() {
  533. case "op":
  534. res, err = s.dao.FaceHistoryByOP(ctx, arg)
  535. if err != nil {
  536. return nil, err
  537. }
  538. if arg.Mid > 0 {
  539. res = res.Filter(filterByMid(arg.Mid))
  540. }
  541. case "mid":
  542. res, err = s.dao.FaceHistoryByMid(ctx, arg)
  543. if err != nil {
  544. return nil, err
  545. }
  546. if arg.Operator != "" {
  547. res = res.Filter(filterByOP(arg.Operator))
  548. }
  549. }
  550. res = res.Filter(filterByStatus(arg.Status...))
  551. sort.Slice(res, func(i, j int) bool {
  552. return res[i].ModifyTime > res[j].ModifyTime
  553. })
  554. for _, r := range res {
  555. r.BuildFaceURL()
  556. }
  557. return
  558. }
  559. // MoralLog is.
  560. func (s *Service) MoralLog(ctx context.Context, mid int64) ([]*model.UserLog, error) {
  561. return nil, ecode.MethodNotAllowed
  562. }
  563. func (s *Service) reviewAddit(ctx context.Context, mids []int64, mrs []*model.BaseReview) error {
  564. uas, err := s.dao.BatchUserAddit(ctx, mids)
  565. if err != nil {
  566. return err
  567. }
  568. for _, mr := range mrs {
  569. if ua, ok := uas[mr.Mid]; ok {
  570. mr.Addit = *ua
  571. }
  572. }
  573. return nil
  574. }
  575. // BatchFormal is
  576. func (s *Service) BatchFormal(ctx context.Context, arg *model.ArgBatchFormal) error {
  577. fp := bom.NewReader(bytes.NewReader(arg.FileData))
  578. reader := csv.NewReader(fp)
  579. ip := metadata.String(ctx, metadata.RemoteIP)
  580. columns, err := reader.Read()
  581. if err != nil {
  582. log.Error("Failed to read columns from csv: %+v", err)
  583. return ecode.RequestErr
  584. }
  585. findMidPositon := func() (int, error) {
  586. for i, col := range columns {
  587. if col == "mid" {
  588. return i, nil
  589. }
  590. }
  591. return 0, errors.New("No mid column")
  592. }
  593. midPosition, err := findMidPositon()
  594. if err != nil {
  595. log.Error("Failed to find mid column: %+v", err)
  596. return ecode.RequestErr
  597. }
  598. mids := make([]int64, 0)
  599. for {
  600. record, rerr := reader.Read()
  601. if rerr == io.EOF {
  602. break
  603. }
  604. if rerr != nil {
  605. log.Error("Failed to parse csv: %+v", errors.WithStack(rerr))
  606. return ecode.RequestErr
  607. }
  608. if len(record) < midPosition {
  609. log.Warn("Skip record due to no suitable position: %+v", record)
  610. continue
  611. }
  612. mid, perr := strconv.ParseInt(record[midPosition], 10, 64)
  613. if perr != nil {
  614. log.Warn("Failed to parse mid on data: %+v: %+v", record[midPosition], perr)
  615. continue
  616. }
  617. mids = append(mids, mid)
  618. }
  619. bases, err := s.batchBase(ctx, mids)
  620. if err != nil {
  621. log.Error("Failed to query bases with mids: %+v: %+v", mids, err)
  622. return ecode.RequestErr
  623. }
  624. for _, mid := range mids {
  625. base, ok := bases[mid]
  626. if !ok {
  627. log.Warn("No such user with mid: %d", mid)
  628. continue
  629. }
  630. if base.Rank >= 10000 {
  631. log.Warn("Rank already exceeded 10000 on mid: %d: %+v", mid, base)
  632. continue
  633. }
  634. rankArg := &model.ArgRankSet{
  635. Mid: mid,
  636. Rank: 10000,
  637. Operator: arg.Operator,
  638. OperatorID: arg.OperatorID,
  639. IP: ip,
  640. }
  641. if err := s.SetRank(ctx, rankArg); err != nil {
  642. log.Warn("Failed to set rank with mid: %d: %+v", mid, err)
  643. continue
  644. }
  645. // 通过发放一次每日登录的经验奖励消息来使用户等级直升 lv1
  646. expArg := &model.ArgPubExpMsg{
  647. Mid: mid,
  648. IP: ip,
  649. Ts: time.Now().Unix(),
  650. Event: "login",
  651. }
  652. if err := s.PubExpMsg(ctx, expArg); err != nil {
  653. log.Warn("Failed to pub exp message with mid: %d: %+v", mid, err)
  654. continue
  655. }
  656. }
  657. return nil
  658. }