extra.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. package dao
  2. import (
  3. "context"
  4. "fmt"
  5. "net/url"
  6. "strconv"
  7. "sync"
  8. "time"
  9. "go-common/app/admin/main/workflow/model"
  10. "go-common/app/admin/main/workflow/model/param"
  11. credit "go-common/app/interface/main/credit/model"
  12. "go-common/app/job/main/member/model/block"
  13. acc "go-common/app/service/main/account/api"
  14. arc "go-common/app/service/main/archive/api"
  15. member "go-common/app/service/main/member/model/block"
  16. "go-common/library/ecode"
  17. "go-common/library/log"
  18. "go-common/library/sync/errgroup"
  19. "go-common/library/xstr"
  20. "github.com/pkg/errors"
  21. )
  22. const (
  23. _upergroupURI = "http://api.bilibili.co/x/internal/uper/special/get"
  24. _tagListURI = "http://manager.bilibili.co/x/admin/manager/internal/tag/list"
  25. _blockURI = "http://api.bilibili.co/x/internal/block/batch/block"
  26. _creditBlockedURI = "http://api.bilibili.co/x/internal/credit/blocked/info/add"
  27. _blockInfoURI = "http://api.bilibili.co/x/internal/block/info"
  28. _blockNumURI = "http://api.bilibili.co/x/internal/credit/blocked/user/num"
  29. _blockCaseAddURI = "http://api.bilibili.co/x/internal/credit/blocked/case/add"
  30. )
  31. // BatchUperSpecial .
  32. // http://info.bilibili.co/pages/viewpage.action?pageId=8479274
  33. func (d *Dao) BatchUperSpecial(c context.Context, mids []int64) (UperTagMap map[int64][]*model.SpecialTag, err error) {
  34. uri := _upergroupURI
  35. uperSpecialResp := new(model.UperSpecial)
  36. UperTagMap = make(map[int64][]*model.SpecialTag)
  37. uv := url.Values{}
  38. uv.Set("group_id", "0")
  39. uv.Set("mids", xstr.JoinInts(mids))
  40. uv.Set("pn", "1")
  41. uv.Set("ps", "1000")
  42. if err = d.httpRead.Get(c, uri, "", uv, uperSpecialResp); err != nil {
  43. err = errors.Wrap(err, fmt.Sprintf("search uper special tag failed mids(%v)", uv.Get("mids")))
  44. return
  45. }
  46. if uperSpecialResp.Code != ecode.OK.Code() {
  47. log.Error("call %s result error code(%d), message(%s)", uri, uperSpecialResp.Code, uperSpecialResp.Message)
  48. err = ecode.Int(uperSpecialResp.Code)
  49. return
  50. }
  51. for _, special := range uperSpecialResp.Data.Items {
  52. UperTagMap[special.MID] = append(UperTagMap[special.MID], special)
  53. }
  54. return
  55. }
  56. // ArchiveRPC .
  57. func (d *Dao) ArchiveRPC(c context.Context, oids []int64) (archives map[int64]*model.Archive, err error) {
  58. if len(oids) == 0 {
  59. return
  60. }
  61. archives = make(map[int64]*model.Archive, len(oids))
  62. var res *arc.ArcsReply
  63. arg := &arc.ArcsRequest{
  64. Aids: oids,
  65. }
  66. if res, err = d.arcRPC.Arcs(c, arg); err != nil {
  67. log.Error("d.arcRPC.Archives3(%+v) error(%v)", arg, err)
  68. return
  69. }
  70. for oid, arc := range res.Arcs {
  71. tmplArc := &model.Archive{
  72. Author: arc.Author.Name,
  73. State: arc.State,
  74. Mid: arc.Author.Mid,
  75. TypeID: arc.TypeID,
  76. Type: arc.TypeName,
  77. Title: arc.Title,
  78. }
  79. archives[oid] = tmplArc
  80. }
  81. return
  82. }
  83. // TagList .
  84. // http://info.bilibili.co/pages/viewpage.action?pageId=9831467
  85. // tags map[bid][tagid]
  86. func (d *Dao) TagList(c context.Context) (tags map[int8]map[int64]*model.TagMeta, err error) {
  87. uri := _tagListURI
  88. uv := url.Values{}
  89. uv.Set("ps", "1000")
  90. uv.Set("pn", "1")
  91. result := new(model.TagListResult)
  92. tags = make(map[int8]map[int64]*model.TagMeta)
  93. if err = d.httpRead.Get(c, uri, "", uv, result); err != nil {
  94. return
  95. }
  96. if result.Code != ecode.OK.Code() {
  97. log.Error("tag list failed: %s?%s, error code(%d), message(%s)", uri, uv.Encode(), result.Code, result.Message)
  98. err = ecode.Int(result.Code)
  99. return
  100. }
  101. for _, tm := range result.Data.Tags {
  102. if _, ok := tags[tm.Bid]; !ok {
  103. tags[tm.Bid] = make(map[int64]*model.TagMeta)
  104. }
  105. tags[tm.Bid][tm.TagID] = tm
  106. }
  107. return
  108. }
  109. // CommonExtraInfo return common external info
  110. func (d *Dao) CommonExtraInfo(c context.Context, bid int8, uri string, ids, oids, eids []int64) (data map[string]interface{}, err error) {
  111. log.Info("start call common extra info bid(%d) gids(%v) oids(%v) eids(%v)", bid, ids, oids, eids)
  112. data = make(map[string]interface{})
  113. uv := url.Values{}
  114. uv.Set("bid", strconv.FormatInt(int64(bid), 10))
  115. uv.Set("ids", xstr.JoinInts(ids))
  116. uv.Set("oids", xstr.JoinInts(oids))
  117. uv.Set("eids", xstr.JoinInts(eids))
  118. res := &model.CommonExtraDataResponse{}
  119. if err = d.httpRead.Get(c, uri, "", uv, &res); err != nil {
  120. return data, err
  121. }
  122. if res.Code != ecode.OK.Code() {
  123. log.Error("get extra info failed: url(%s), code(%d), message(%s), bid(%d)", uri+"?"+uv.Encode(), res.Code, res.Message, bid)
  124. err = ecode.Int(res.Code)
  125. return
  126. }
  127. log.Info("success extra info (%+v) req url(%s)", res, uri+"?"+uv.Encode())
  128. data = res.Data
  129. return
  130. }
  131. // AccountInfoRPC .
  132. func (d *Dao) AccountInfoRPC(c context.Context, mids []int64) (authors map[int64]*model.Account) {
  133. g := &errgroup.Group{}
  134. mutex := sync.RWMutex{}
  135. authors = make(map[int64]*model.Account)
  136. if len(mids) == 0 {
  137. return
  138. }
  139. // distinct mid
  140. mMap := make(map[int64]bool)
  141. dMids := make([]int64, 0)
  142. for _, m := range mids {
  143. if _, ok := mMap[m]; !ok {
  144. mMap[m] = false
  145. dMids = append(dMids, m)
  146. continue
  147. }
  148. }
  149. for _, mid := range dMids {
  150. gMid := mid
  151. g.Go(func() (err error) {
  152. var res *acc.ProfileStatReply
  153. start := time.Now()
  154. arg := &acc.MidReq{Mid: gMid}
  155. if res, err = d.accRPC.ProfileWithStat3(c, arg); err != nil {
  156. log.Error("d.accRPC.ProfileWithStat3(%v) error(%v)", arg, err)
  157. err = nil
  158. return
  159. }
  160. mutex.Lock()
  161. acc := &model.Account{
  162. Mid: res.Profile.Mid,
  163. Name: res.Profile.Name,
  164. Rank: res.Profile.Rank,
  165. Follower: res.Follower,
  166. Official: &model.Official{Role: res.Profile.Official.Role},
  167. }
  168. authors[res.Profile.Mid] = acc
  169. log.Info("mid(%d) data(%+v) wrap success", res.Profile.Mid, acc)
  170. mutex.Unlock()
  171. log.Info("account rpc request gmid(%d) time %s", gMid, time.Since(start).String())
  172. return
  173. })
  174. }
  175. g.Wait()
  176. return
  177. }
  178. // AddMoral 扣节操
  179. func (d *Dao) AddMoral(c context.Context, mids []int64, gssp *param.GroupStateSetParam) (err error) {
  180. var errFlag bool
  181. for _, mid := range mids {
  182. arg := &acc.MoralReq{
  183. Mid: mid,
  184. Moral: float64(gssp.DecreaseMoral),
  185. Oper: gssp.AdminName,
  186. Reason: gssp.Reason,
  187. Remark: "workflow",
  188. }
  189. if _, err = d.accRPC.AddMoral3(c, arg); err != nil {
  190. log.Error("failed decrease moral arg(%+v) error(%v)", arg, err)
  191. errFlag = true
  192. }
  193. }
  194. if !errFlag {
  195. log.Info("add moral success mids(%v) param(%+v)", mids, gssp)
  196. }
  197. return
  198. }
  199. // AddBlock 发起账号封禁
  200. // http://info.bilibili.co/pages/viewpage.action?pageId=7559616
  201. func (d *Dao) AddBlock(c context.Context, mids []int64, gssp *param.GroupStateSetParam) (err error) {
  202. uri := _blockURI
  203. uv := url.Values{}
  204. uv.Set("mids", xstr.JoinInts(mids))
  205. source := strconv.Itoa(int(member.BlockSourceBlackHouse))
  206. uv.Set("source", source) //来源: 后台相关
  207. if gssp.Business == model.CommentComplain {
  208. area := strconv.Itoa(int(member.BlockAreaReply))
  209. uv.Set("area", area) //违规业务
  210. }
  211. if gssp.BlockDay > 0 { //限时封禁
  212. action := strconv.Itoa(int(block.BlockActionLimit))
  213. uv.Set("action", action)
  214. uv.Set("duration", strconv.FormatInt(gssp.BlockDay*86400, 10))
  215. } else { //永久封禁
  216. action := strconv.Itoa(int(block.BlockActionForever))
  217. uv.Set("action", action)
  218. }
  219. uv.Set("start_time", strconv.FormatInt(time.Now().Unix(), 10))
  220. uv.Set("op_id", strconv.FormatInt(gssp.AdminID, 10))
  221. uv.Set("operator", gssp.AdminName)
  222. reason := model.BlockReason[gssp.BlockReason]
  223. uv.Set("reason", reason)
  224. uv.Set("notify", "1")
  225. resp := &model.CommonResponse{}
  226. if err = d.httpWrite.Post(c, uri, "", uv, resp); err != nil {
  227. log.Error("add block url(%s) param(%s) error(%v)", uri, uv.Encode(), err)
  228. return
  229. }
  230. if resp.Code != ecode.OK.Code() {
  231. err = ecode.Int(resp.Code)
  232. log.Error("call add block url(%s) param(%s) error res code(%d)", uri, uv.Encode(), resp.Code)
  233. return
  234. }
  235. log.Info("add block success mids(%v) param(%+v)", mids, gssp)
  236. return
  237. }
  238. // AddCreditBlockInfo 上报封禁信息到小黑屋
  239. // http://info.bilibili.co/pages/viewpage.action?pageId=5417571
  240. func (d *Dao) AddCreditBlockInfo(c context.Context, bus map[int64]*model.Business, gssp *param.GroupStateSetParam) (err error) {
  241. // 请求小黑屋
  242. uri := _creditBlockedURI
  243. for _, b := range bus {
  244. uv := url.Values{}
  245. uv.Set("mid", strconv.FormatInt(b.Mid, 10))
  246. uv.Set("oper_id", strconv.FormatInt(gssp.AdminID, 10))
  247. uv.Set("origin_content", b.Title)
  248. if gssp.Business == model.CommentComplain {
  249. uv.Set("origin_type", strconv.Itoa(int(member.BlockAreaReply))) //违规业务
  250. }
  251. if gssp.BlockDay > 0 { //限时封禁
  252. uv.Set("blocked_days", strconv.FormatInt(gssp.BlockDay, 10))
  253. uv.Set("blocked_forever", strconv.Itoa(int(credit.NotInBlockedForever)))
  254. uv.Set("punish_type", strconv.Itoa(int(credit.PunishTypeBlock)))
  255. } else { //永久封禁
  256. uv.Set("blocked_forever", strconv.Itoa(int(credit.InBlockedForever)))
  257. uv.Set("punish_type", strconv.Itoa(int(credit.PunishTypeForever)))
  258. }
  259. uv.Set("punish_time", strconv.FormatInt(time.Now().Unix(), 10))
  260. uv.Set("reason_type", strconv.Itoa(int(gssp.BlockReason)))
  261. uv.Set("operator_name", gssp.AdminName)
  262. resp := &model.CommonResponse{}
  263. if err = d.httpWrite.Post(c, uri, "", uv, resp); err != nil {
  264. log.Error("add credit block info url(%s) param(%s) error(%v)", uri, uv.Encode(), err)
  265. continue
  266. }
  267. if resp.Code != ecode.OK.Code() {
  268. err = ecode.Int(resp.Code)
  269. log.Error("call add credit block info url(%s) param(%s) error res code(%d)", uri, uv.Encode(), resp.Code)
  270. continue
  271. }
  272. log.Info("add credit block info success mid(%v) param(%+v)", b.Mid, gssp)
  273. }
  274. return
  275. }
  276. // AddCreditCase 请求风纪委众裁
  277. func (d *Dao) AddCreditCase(c context.Context, uv url.Values) (err error) {
  278. uri := _blockCaseAddURI
  279. var res model.CommonResponse
  280. if err = d.httpWrite.Post(c, uri, "", uv, &res); err != nil {
  281. log.Error("d.httpWrite.Post(%s) body(%s) error(%v)", uri, uv.Encode(), err)
  282. err = ecode.WkfSetPublicRefereeFailed
  283. return
  284. }
  285. if res.Code != ecode.OK.Code() {
  286. log.Error("call url(%s) body(%s) error code(%d)", uri, uv.Encode(), res.Code)
  287. err = ecode.WkfSetPublicRefereeFailed
  288. return
  289. }
  290. log.Info("call block add case success url(%s) body(%s)", uri, uv.Encode())
  291. return
  292. }
  293. // BlockNum 查询封禁次数
  294. func (d *Dao) BlockNum(c context.Context, mid int64) (sum int64, err error) {
  295. uri := _blockNumURI
  296. uv := url.Values{}
  297. uv.Set("mid", strconv.FormatInt(mid, 10))
  298. var numResp model.BlockNumResp
  299. if err = d.httpRead.Get(c, uri, "", uv, &numResp); err != nil {
  300. log.Error("d.httpRead.Get() error(%v) url(%s?%s)", err, uri, uv.Encode())
  301. err = ecode.WkfGetBlockInfoFailed
  302. return
  303. }
  304. if numResp.Code != ecode.OK.Code() {
  305. log.Error("call url(%s?%s) response code (%d) error", uri, uv.Encode(), numResp.Code)
  306. err = ecode.WkfGetBlockInfoFailed
  307. return
  308. }
  309. sum = numResp.Data.BlockedSum
  310. log.Info("url(%s) mid(%d) block num (%d)", uri, mid, sum)
  311. return
  312. }
  313. // BlockInfo 查询封禁信息
  314. func (d *Dao) BlockInfo(c context.Context, mid int64) (resp model.BlockInfoResp, err error) {
  315. uri := _blockInfoURI
  316. uv := url.Values{}
  317. uv.Set("mid", strconv.FormatInt(mid, 10))
  318. if err = d.httpRead.Get(c, uri, "", uv, &resp); err != nil {
  319. log.Error("d.httpRead.Get() error(%v) url(%s?%s)", err, uri, uv.Encode())
  320. err = ecode.WkfGetBlockInfoFailed
  321. return
  322. }
  323. if resp.Code != ecode.OK.Code() {
  324. log.Error("call url(%s?%s) response code (%d) error", uri, uv.Encode(), resp.Code)
  325. err = ecode.WkfGetBlockInfoFailed
  326. return
  327. }
  328. log.Info("url(%s) mid(%d) block info resp(%+v)", uri, mid, resp)
  329. return
  330. }
  331. // SourceInfo 返回业务来源
  332. func (d *Dao) SourceInfo(c context.Context, uri string) (data map[string]interface{}, err error) {
  333. log.Info("start call SourceInfo uri(%s)", uri)
  334. res := &model.SourceQueryResponse{}
  335. if err = d.httpRead.Get(c, uri, "", nil, &res); err != nil {
  336. return
  337. }
  338. if res.Code != ecode.OK.Code() {
  339. log.Error("get SourceInfo failed: url(%s), code(%d), message(%s)", uri, res.Code, res.Message)
  340. err = ecode.Int(res.Code)
  341. return
  342. }
  343. log.Info("success SourceInfo (%+v)", res.Data)
  344. return res.Data, nil
  345. }