archive.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. package service
  2. import (
  3. "context"
  4. "encoding/json"
  5. "strconv"
  6. "time"
  7. dm2mdl "go-common/app/interface/main/dm2/model"
  8. tagmdl "go-common/app/interface/main/tag/model"
  9. "go-common/app/interface/main/web/model"
  10. accmdl "go-common/app/service/main/account/api"
  11. infomdl "go-common/app/service/main/account/model"
  12. arcmdl "go-common/app/service/main/archive/api"
  13. "go-common/app/service/main/archive/model/archive"
  14. coinmdl "go-common/app/service/main/coin/api"
  15. favmdl "go-common/app/service/main/favorite/model"
  16. locmdl "go-common/app/service/main/location/model"
  17. sharemdl "go-common/app/service/main/share/api"
  18. thumbup "go-common/app/service/main/thumbup/model"
  19. ugcmdl "go-common/app/service/main/ugcpay/api/grpc/v1"
  20. "go-common/library/conf/env"
  21. "go-common/library/ecode"
  22. "go-common/library/log"
  23. "go-common/library/log/infoc"
  24. "go-common/library/net/metadata"
  25. "go-common/library/sync/errgroup"
  26. )
  27. var (
  28. _emptyTags = make([]*tagmdl.Tag, 0)
  29. _emptyReplyHot = new(model.ReplyHot)
  30. _emptyArchive3 = make([]*arcmdl.Arc, 0)
  31. _emptyArc = make([]*arcmdl.Arc, 0)
  32. )
  33. const (
  34. _japan = "日本"
  35. _businessAppeal = 1
  36. _notForward = 0
  37. _member = 10000
  38. _viewBakCacheRand = 10
  39. _shareArcType = 3
  40. _hasUGCPay = 1
  41. _ugcOtypeArc = "archive"
  42. _ugcCurrencyBp = "bp"
  43. _ugcAssetPaid = "paid"
  44. _ugcPaidState = 1
  45. )
  46. // View get a view page by aid.
  47. func (s *Service) View(c context.Context, aid, cid, mid int64, cdnIP, ck string) (rs *model.View, err error) {
  48. var (
  49. viewReply *arcmdl.ViewReply
  50. video *arcmdl.Page
  51. longDesc string
  52. pDesc, forward, report bool
  53. remoteIP = metadata.String(c, metadata.RemoteIP)
  54. )
  55. if viewReply, err = s.arcClient.View(c, &arcmdl.ViewRequest{Aid: aid}); err != nil {
  56. log.Error("s.arcClient.View(%d) error %v", aid, err)
  57. return
  58. }
  59. if viewReply != nil && viewReply.Arc != nil {
  60. if _, ok := s.specialMids[viewReply.Arc.Author.Mid]; ok && env.DeployEnv == env.DeployEnvProd {
  61. err = ecode.NothingFound
  62. log.Warn("aid(%d) mid(%d) can not view on prod", viewReply.Arc.Aid, viewReply.Arc.Author.Mid)
  63. return
  64. }
  65. if viewReply.Arc.FirstCid == 0 {
  66. if len(viewReply.Pages) > 0 {
  67. viewReply.Arc.FirstCid = viewReply.Pages[0].Cid
  68. }
  69. }
  70. if viewReply.Arc.State == archive.StateForbidLock && viewReply.Arc.Forward > 0 {
  71. forward = true
  72. } else if viewReply.Arc.State == archive.StateForbidRecicle || viewReply.Arc.State == archive.StateForbidLock {
  73. if viewReply.Arc.ReportResult == "" {
  74. err = ecode.NothingFound
  75. return
  76. }
  77. report = true
  78. }
  79. check := []int32{archive.StateForbidWait, archive.StateForbidFixed, archive.StateForbidLater, archive.StateForbidAdminDelay}
  80. for _, v := range check {
  81. if viewReply.Arc.State == v {
  82. err = ecode.ArchiveChecking
  83. return
  84. }
  85. }
  86. if viewReply.Arc.State == archive.StateForbidUserDelay {
  87. err = ecode.ArchivePass
  88. return
  89. } else if !viewReply.Arc.IsNormal() && !forward && !report {
  90. err = ecode.ArchiveDenied
  91. return
  92. }
  93. rs = &model.View{Arc: viewReply.Arc, Pages: viewReply.Pages}
  94. group, errCtx := errgroup.WithContext(c)
  95. if !forward && !report {
  96. group.Go(func() error {
  97. return s.zlimit(errCtx, rs, mid, remoteIP, cdnIP)
  98. })
  99. group.Go(func() error {
  100. return s.checkAccess(errCtx, mid, rs, ck, remoteIP)
  101. })
  102. }
  103. group.Go(func() error {
  104. dmCid := cid
  105. if dmCid == 0 {
  106. dmCid = viewReply.Arc.FirstCid
  107. }
  108. rs.Subtitle = s.dmSubtitle(errCtx, aid, dmCid)
  109. return nil
  110. })
  111. if rs.Arc.Rights.UGCPay == _hasUGCPay {
  112. rs.Asset = s.ugcPayAsset(errCtx, aid, mid)
  113. }
  114. if err = group.Wait(); err != nil {
  115. return
  116. }
  117. if cid > 0 {
  118. if video, err = s.arc.Video3(c, &archive.ArgVideo2{Aid: aid, Cid: cid, RealIP: remoteIP}); err != nil {
  119. err = nil
  120. log.Error("s.arc.Video3(%d,%d,%s) error %v", aid, cid, remoteIP, err)
  121. }
  122. if video.Desc != "" {
  123. rs.Desc = video.Desc
  124. pDesc = true
  125. }
  126. }
  127. if !pDesc {
  128. if longDesc, err = s.arc.Description2(c, &archive.ArgAid{Aid: aid, RealIP: remoteIP}); err != nil {
  129. err = nil
  130. log.Error("view s.arc.Description2(%d) error(%v)", aid, err)
  131. } else if longDesc != "" {
  132. rs.Desc = longDesc
  133. }
  134. }
  135. if rs.AttrVal(archive.AttrBitIsPGC) == archive.AttrNo {
  136. if err = s.initDownload(c, rs, mid, remoteIP, cdnIP); err != nil {
  137. log.Error("s.initDownload aid(%d) mid(%d) ip(%s) error(%+v)", rs.Aid, mid, remoteIP, err)
  138. err = nil
  139. }
  140. }
  141. if !forward {
  142. rs.Forward = _notForward
  143. }
  144. if !report {
  145. rs.ReportResult = ""
  146. }
  147. if rs.AttrVal(archive.AttrBitJumpUrl) == archive.AttrNo {
  148. rs.RedirectURL = ""
  149. }
  150. if rs.Access >= _member {
  151. rs.Stat.View = -1
  152. }
  153. if rs.AttrVal(archive.AttrBitLimitArea) == archive.AttrYes {
  154. rs.NoCache = true
  155. }
  156. s.cache.Do(c, func(c context.Context) {
  157. if s.r.Intn(_viewBakCacheRand) == 1 {
  158. s.dao.SetViewBakCache(c, aid, rs)
  159. }
  160. })
  161. } else {
  162. rs, err = s.dao.ViewBakCache(c, aid)
  163. }
  164. return
  165. }
  166. func (s *Service) zlimit(c context.Context, view *model.View, mid int64, remoteIP, cdnIP string) (err error) {
  167. var data *int64
  168. if data, err = s.loc.Archive(c, &locmdl.Archive{Aid: view.Aid, Mid: mid, IP: remoteIP, CIP: cdnIP}); err != nil {
  169. log.Error("s.loc.Archive(%d%d%s%s) error(%v)", view.Aid, mid, remoteIP, cdnIP, err)
  170. return
  171. }
  172. if *data == locmdl.Forbidden {
  173. log.Warn("s.loc.Archive aid(%d) zlimit.Forbidden", view.Aid)
  174. err = ecode.NothingFound
  175. } else {
  176. err = s.specialLimit(c, view, remoteIP)
  177. }
  178. return
  179. }
  180. // specialLimit spacialLimit special type id limit in japan
  181. func (s *Service) specialLimit(c context.Context, view *model.View, remoteIP string) (err error) {
  182. var zone *locmdl.Info
  183. for _, typeID := range model.LimitTypeIDs {
  184. if int32(typeID) == view.TypeID {
  185. // TODO all no cache
  186. view.NoCache = true
  187. if zone, err = s.loc.Info(c, &locmdl.ArgIP{IP: remoteIP}); err != nil || zone == nil {
  188. log.Error("s.loc.Info(%s) error(%v) or zone is nil", remoteIP, err)
  189. err = nil
  190. } else if zone.Country == _japan {
  191. err = ecode.NothingFound
  192. }
  193. break
  194. }
  195. }
  196. return
  197. }
  198. // checkAccess check mid aid access
  199. func (s *Service) checkAccess(c context.Context, mid int64, view *model.View, ck, ip string) (err error) {
  200. var (
  201. p *accmdl.CardReply
  202. )
  203. if view.Access == 0 {
  204. return
  205. }
  206. view.NoCache = true
  207. if mid <= 0 {
  208. log.Warn("user not login aid(%d)", view.Aid)
  209. err = ecode.AccessDenied
  210. return
  211. }
  212. if p, err = s.accClient.Card3(c, &accmdl.MidReq{Mid: mid}); err != nil {
  213. log.Error("s.accClient.Card3(%d) error(%v)", mid, err)
  214. return
  215. }
  216. if p == nil {
  217. log.Warn("Info2 result is null aid(%d) state(%d) access(%d)", view.Aid, view.State, view.Access)
  218. err = ecode.AccessDenied
  219. return
  220. }
  221. card := p.Card
  222. isVip := (card.Vip.Type > 0) && (card.Vip.Status == 1)
  223. if view.Access > 0 && card.Rank < view.Access && (!isVip) {
  224. log.Warn("mid(%d) rank(%d) vip(tp:%d,status:%d) have not access(%d) view archive(%d) ", mid, card.Rank, card.Vip.Type, card.Vip.Status, view.Access, view.Aid)
  225. if mid > 0 {
  226. err = ecode.NothingFound
  227. } else {
  228. err = ecode.ArchiveNotLogin
  229. }
  230. }
  231. return
  232. }
  233. func (s *Service) initDownload(c context.Context, v *model.View, mid int64, ip, cdnIP string) (err error) {
  234. var download int64
  235. if v.AttrVal(archive.AttrBitLimitArea) == archive.AttrYes {
  236. if download, err = s.downLimit(c, mid, v.Aid, cdnIP); err != nil {
  237. return
  238. }
  239. } else {
  240. download = locmdl.AllowDown
  241. }
  242. if download == locmdl.ForbiddenDown {
  243. v.Rights.Download = int32(download)
  244. return
  245. }
  246. for _, p := range v.Pages {
  247. if p.From == "qq" {
  248. download = locmdl.ForbiddenDown
  249. break
  250. }
  251. }
  252. v.Rights.Download = int32(download)
  253. return
  254. }
  255. // downLimit ip limit
  256. func (s *Service) downLimit(c context.Context, mid, aid int64, cdnIP string) (down int64, err error) {
  257. var (
  258. auth *locmdl.Auth
  259. ip = metadata.String(c, metadata.RemoteIP)
  260. )
  261. if auth, err = s.loc.Archive2(c, &locmdl.Archive{Aid: aid, Mid: mid, IP: ip, CIP: cdnIP}); err != nil {
  262. log.Error("s.loc.Archive2(%d) error(%v)", mid, err)
  263. return
  264. }
  265. if auth.Play == locmdl.Forbidden {
  266. err = ecode.AccessDenied
  267. } else {
  268. down = auth.Down
  269. }
  270. return
  271. }
  272. func (s *Service) dmSubtitle(c context.Context, aid, cid int64) (subtitle *model.Subtitle) {
  273. var (
  274. dmSub *dm2mdl.VideoSubtitles
  275. err error
  276. mids []int64
  277. infosReply *accmdl.InfosReply
  278. subs []*model.SubtitleItem
  279. )
  280. subtitle = new(model.Subtitle)
  281. if dmSub, err = s.dm2.SubtitleGet(c, &dm2mdl.ArgSubtitleGet{Aid: aid, Oid: cid, Type: dm2mdl.SubTypeVideo}); err != nil {
  282. log.Warn("dmSubtitle s.dm2.SubtitleGet aid(%d) cid(%d) warn(%v)", aid, cid, err)
  283. } else if dmSub != nil {
  284. subtitle.AllowSubmit = dmSub.AllowSubmit
  285. if len(dmSub.Subtitles) > 0 {
  286. for _, v := range dmSub.Subtitles {
  287. if v.AuthorMid > 0 {
  288. mids = append(mids, v.AuthorMid)
  289. }
  290. }
  291. infoData := make(map[int64]*infomdl.Info)
  292. if len(mids) > 0 {
  293. if infosReply, err = s.accClient.Infos3(c, &accmdl.MidsReq{Mids: mids, RealIp: metadata.String(c, metadata.RemoteIP)}); err != nil {
  294. log.Error("dmSubtitle aid(%d) cid(%d) s.acc.Infos3 mids(%v) error(%v)", aid, cid, mids, err)
  295. } else {
  296. infoData = infosReply.Infos
  297. }
  298. }
  299. for _, v := range dmSub.Subtitles {
  300. sub := &model.SubtitleItem{VideoSubtitle: v, Author: &infomdl.Info{Mid: v.AuthorMid}}
  301. if info, ok := infoData[v.AuthorMid]; ok && info != nil {
  302. sub.Author = info
  303. }
  304. subs = append(subs, sub)
  305. }
  306. subtitle.List = subs
  307. }
  308. }
  309. if len(subtitle.List) == 0 {
  310. subtitle.List = make([]*model.SubtitleItem, 0)
  311. }
  312. return
  313. }
  314. // ArchiveStat get archive stat data by aid.
  315. func (s *Service) ArchiveStat(c context.Context, aid int64) (stat *model.Stat, err error) {
  316. var (
  317. arcReply *arcmdl.ArcReply
  318. view interface{}
  319. )
  320. if aid == s.c.Bnj2019.LiveAid && s.bnj2019LiveArc != nil {
  321. arcReply = s.bnj2019LiveArc
  322. } else {
  323. if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
  324. log.Error("s.arcClient.Arc(%d) error(%v)", aid, err)
  325. return
  326. }
  327. }
  328. arc := arcReply.Arc
  329. if !model.CheckAllowState(arc) {
  330. err = ecode.AccessDenied
  331. return
  332. }
  333. view = arc.Stat.View
  334. if arc.Access > 0 {
  335. view = "--"
  336. }
  337. stat = &model.Stat{
  338. Aid: arc.Stat.Aid,
  339. View: view,
  340. Danmaku: arc.Stat.Danmaku,
  341. Reply: arc.Stat.Reply,
  342. Fav: arc.Stat.Fav,
  343. Coin: arc.Stat.Coin,
  344. Share: arc.Stat.Share,
  345. Like: arc.Stat.Like,
  346. NowRank: arc.Stat.NowRank,
  347. HisRank: arc.Stat.HisRank,
  348. NoReprint: arc.Rights.NoReprint,
  349. Copyright: arc.Copyright,
  350. }
  351. return
  352. }
  353. // AddShare share add count
  354. func (s *Service) AddShare(c context.Context, aid, mid int64, ua, refer, path, buvid, sid string) (shares int64, err error) {
  355. var (
  356. shareReply *sharemdl.AddShareReply
  357. remoteIP = metadata.String(c, metadata.RemoteIP)
  358. )
  359. // add Anti cheat
  360. if s.CheatInfoc != nil {
  361. ac := map[string]string{
  362. "itemType": infoc.ItemTypeAv,
  363. "action": infoc.ActionShare,
  364. "ip": remoteIP,
  365. "mid": strconv.FormatInt(mid, 10),
  366. "fid": "",
  367. "aid": strconv.FormatInt(aid, 10),
  368. "sid": sid,
  369. "ua": ua,
  370. "buvid": buvid,
  371. "refer": refer,
  372. "url": path,
  373. }
  374. s.CheatInfoc.ServiceAntiCheat(ac)
  375. }
  376. if shareReply, err = s.shareClient.AddShare(c, &sharemdl.AddShareRequest{Oid: aid, Mid: mid, Type: _shareArcType, Ip: remoteIP}); err != nil {
  377. log.Error("AddShare s.shareClient.AddShare (oid:%d,mid:%d) warn(%v)", aid, mid, err)
  378. return
  379. }
  380. shares = shareReply.Shares
  381. return
  382. }
  383. // Description get archive description by aid.
  384. func (s *Service) Description(c context.Context, aid, page int64) (res string, err error) {
  385. var (
  386. viewReply *arcmdl.ViewReply
  387. video *arcmdl.Page
  388. cid int64
  389. longDesc string
  390. ip = metadata.String(c, metadata.RemoteIP)
  391. )
  392. if viewReply, err = s.arcClient.View(c, &arcmdl.ViewRequest{Aid: aid}); err != nil {
  393. log.Error("s.arcClient.View(%d,%s) error %v", aid, ip, err)
  394. return
  395. }
  396. if viewReply != nil && viewReply.Arc != nil {
  397. if !viewReply.Arc.IsNormal() {
  398. err = ecode.ArchiveDenied
  399. return
  400. }
  401. }
  402. if page > 0 {
  403. if int(page-1) >= len(viewReply.Pages) || viewReply.Pages[page-1] == nil {
  404. err = ecode.NothingFound
  405. return
  406. }
  407. cid = viewReply.Pages[page-1].Cid
  408. if cid > 0 {
  409. if video, err = s.arc.Video3(c, &archive.ArgVideo2{Aid: aid, Cid: cid, RealIP: ip}); err != nil {
  410. log.Error("s.arc.Video2(%d,%d,%s) error %v", aid, cid, ip, err)
  411. }
  412. if video.Desc != "" {
  413. res = video.Desc
  414. return
  415. }
  416. }
  417. } else {
  418. res = viewReply.Arc.Desc
  419. }
  420. if longDesc, err = s.arc.Description2(c, &archive.ArgAid{Aid: aid, RealIP: ip}); err != nil {
  421. log.Error("s.arc.Description2(%d) error(%v)", aid, err)
  422. } else if longDesc != "" {
  423. res = longDesc
  424. }
  425. return
  426. }
  427. // ArcReport add archive report
  428. func (s *Service) ArcReport(c context.Context, mid, aid, tp int64, reason, pics string) (err error) {
  429. if err = s.dao.ArcReport(c, mid, aid, tp, reason, pics); err != nil {
  430. log.Error("s.dao.ArcReport(%d,%d,%d,%s,%s) err (%v)", mid, aid, tp, reason, pics, err)
  431. }
  432. return
  433. }
  434. // AppealTags get appeal tags
  435. func (s *Service) AppealTags(c context.Context) (rs json.RawMessage, err error) {
  436. if rs, err = s.dao.AppealTags(c, _businessAppeal); err != nil {
  437. log.Error("s.dao.AppealTags(1) error(%v)", err)
  438. }
  439. return
  440. }
  441. // ArcAppeal add archive appeal.
  442. func (s *Service) ArcAppeal(c context.Context, mid int64, data map[string]string) (err error) {
  443. aid, _ := strconv.ParseInt(data["oid"], 10, 64)
  444. if err = s.dao.ArcAppealCache(c, mid, aid); err != nil {
  445. if err == ecode.ArcAppealLimit {
  446. log.Warn("s.arcAppealLimit mid(%d) aid(%d)", mid, aid)
  447. return
  448. }
  449. err = nil
  450. }
  451. if err = s.dao.ArcAppeal(c, mid, data, _businessAppeal); err != nil {
  452. log.Error("s.dao.ArcAppeal(%d,%v,1) error(%v)", mid, data, err)
  453. return
  454. }
  455. if err = s.dao.SetArcAppealCache(c, mid, aid); err != nil {
  456. log.Error("s.dao.SetArcAppealCache(%d,%d)", mid, aid)
  457. err = nil
  458. }
  459. return
  460. }
  461. // AuthorRecommend get author recommend data
  462. func (s *Service) AuthorRecommend(c context.Context, aid int64) (res []*arcmdl.Arc, err error) {
  463. var (
  464. arcReply *arcmdl.ArcReply
  465. aids []int64
  466. recArcs, upArcs []*arcmdl.Arc
  467. arcs *arcmdl.ArcsReply
  468. ip = metadata.String(c, metadata.RemoteIP)
  469. )
  470. defer func() {
  471. if len(res) == 0 {
  472. res = _emptyArchive3
  473. }
  474. }()
  475. resAids := make(map[int64]int64)
  476. if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
  477. log.Error("s.arcClient.Arc(%d) error(%v)", aid, err)
  478. return
  479. }
  480. resAids[aid] = aid
  481. if recArcs, err = s.arc.Recommend3(c, &archive.ArgAid2{Aid: aid, RealIP: ip}); err != nil {
  482. log.Error("s.arc.Recommend3(%d) error(%v)", aid, err)
  483. err = nil
  484. } else {
  485. for _, v := range recArcs {
  486. res = append(res, v)
  487. resAids[v.Aid] = v.Aid
  488. }
  489. }
  490. if len(res) < s.c.Rule.AuthorRecCnt {
  491. if upArcs, err = s.arc.UpArcs3(c, &archive.ArgUpArcs2{Mid: arcReply.Arc.Author.Mid, Pn: _firstPn, Ps: s.c.Rule.AuthorRecCnt, RealIP: ip}); err != nil {
  492. log.Error("s.arc.UpArcs3(%d) error(%v)", arcReply.Arc.Author.Mid, err)
  493. err = nil
  494. } else {
  495. for _, v := range upArcs {
  496. if _, ok := resAids[v.Aid]; !ok {
  497. res = append(res, v)
  498. resAids[v.Aid] = v.Aid
  499. if len(res) >= s.c.Rule.AuthorRecCnt {
  500. return
  501. }
  502. }
  503. }
  504. }
  505. }
  506. if len(res) < s.c.Rule.AuthorRecCnt {
  507. if aids, err = s.dao.RelatedAids(c, aid); err != nil {
  508. log.Error("s.dao.RelatedArchives(%d) error(%v)", aid, err)
  509. err = nil
  510. } else if len(aids) > 0 {
  511. ps := s.c.Rule.AuthorRecCnt - len(res)
  512. if len(aids) > ps {
  513. aids = aids[0:ps]
  514. }
  515. archivesArgLog("AuthorRecommend", aids)
  516. if arcs, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
  517. log.Error("s.arcClient.Arcs(%v) error(%v)", aids, err)
  518. err = nil
  519. } else {
  520. for _, aid := range aids {
  521. if _, ok := resAids[aid]; !ok {
  522. if arc, ok := arcs.Arcs[aid]; ok {
  523. res = append(res, model.FmtArc(arc))
  524. if len(res) >= s.c.Rule.AuthorRecCnt {
  525. return
  526. }
  527. }
  528. }
  529. }
  530. }
  531. }
  532. }
  533. return
  534. }
  535. // RelatedArcs get related archives
  536. func (s *Service) RelatedArcs(c context.Context, aid int64) (res []*arcmdl.Arc, err error) {
  537. var (
  538. aids []int64
  539. arcReply *arcmdl.ArcReply
  540. arcsReply *arcmdl.ArcsReply
  541. )
  542. if _, ok := s.noRelAids[aid]; ok {
  543. res = _emptyArc
  544. return
  545. }
  546. if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil {
  547. log.Error("s.arcClient.Arc(%d) error(%v)", aid, err)
  548. return
  549. }
  550. // StateForbidUpDelete can have related arc
  551. if !arcReply.Arc.IsNormal() && arcReply.Arc.GetState() != archive.StateForbidUpDelete {
  552. res = _emptyArc
  553. return
  554. }
  555. if aids, err = s.dao.RelatedAids(c, aid); err != nil {
  556. log.Error("s.dao.RelatedArchives(%d) error(%v)", aid, err)
  557. err = nil
  558. } else if len(aids) > 0 {
  559. if len(aids) > s.c.Rule.RelatedArcCnt {
  560. aids = aids[:s.c.Rule.RelatedArcCnt]
  561. }
  562. archivesArgLog("RelatedArcs", aids)
  563. if arcsReply, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
  564. log.Error("s.arcClient.Arcs(%v) error(%v)", aids, err)
  565. err = nil
  566. } else {
  567. for _, aid := range aids {
  568. if arc, ok := arcsReply.Arcs[aid]; ok && arc.IsNormal() {
  569. res = append(res, arc)
  570. }
  571. }
  572. }
  573. }
  574. if len(res) == 0 {
  575. res = _emptyArc
  576. }
  577. return
  578. }
  579. // Detail get merge view card tag reply related.
  580. func (s *Service) Detail(c context.Context, aid, mid int64, cdnIP, ck string) (rs *model.Detail, err error) {
  581. var (
  582. view *model.View
  583. card *model.Card
  584. tags []*tagmdl.Tag
  585. reply *model.ReplyHot
  586. related []*arcmdl.Arc
  587. group *errgroup.Group
  588. cardErr, relatedErr error
  589. )
  590. if view, err = s.View(c, aid, 0, mid, cdnIP, ck); err != nil {
  591. log.Error("s.View(%d) error %+v", aid, err)
  592. return
  593. }
  594. group, errCtx := errgroup.WithContext(c)
  595. group.Go(func() error {
  596. if card, cardErr = s.Card(c, view.Author.Mid, mid, false, false); cardErr != nil {
  597. log.Error("s.Card(%d) error %+v", aid, cardErr)
  598. }
  599. return nil
  600. })
  601. group.Go(func() error {
  602. tags, _ = s.arcTags(errCtx, aid, mid)
  603. return nil
  604. })
  605. group.Go(func() error {
  606. reply, _ = s.replyHot(errCtx, aid)
  607. return nil
  608. })
  609. group.Go(func() error {
  610. if related, relatedErr = s.RelatedArcs(errCtx, aid); relatedErr != nil {
  611. log.Error("s.RelatedArcs(%d) error %+v", aid, relatedErr)
  612. }
  613. return nil
  614. })
  615. group.Wait()
  616. rs = &model.Detail{
  617. View: view,
  618. Card: card,
  619. Tags: tags,
  620. Reply: reply,
  621. Related: related,
  622. }
  623. return
  624. }
  625. // ArcUGCPay get arc ugc pay relation.
  626. func (s *Service) ArcUGCPay(c context.Context, mid, aid int64) (data *model.AssetRelation, err error) {
  627. var relation *ugcmdl.AssetRelationResp
  628. data = new(model.AssetRelation)
  629. if arcReply, e := s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); e != nil {
  630. log.Error("s.arcClient.Arc(%d) error(%v)", aid, e)
  631. } else if arcReply.Arc.Author.Mid == mid {
  632. data.State = _ugcPaidState
  633. return
  634. }
  635. if relation, err = s.ugcPayClient.AssetRelation(c, &ugcmdl.AssetRelationReq{Mid: mid, Oid: aid, Otype: _ugcOtypeArc}); err != nil {
  636. log.Error("ArcUGCPay s.ugcPayClient.AssetRelation mid:%d aid:%d error(%v)", mid, aid, err)
  637. err = nil
  638. return
  639. }
  640. if relation.State == _ugcAssetPaid {
  641. data.State = _ugcPaidState
  642. }
  643. return
  644. }
  645. // ArcRelation .
  646. func (s *Service) ArcRelation(c context.Context, mid, aid int64) (data *model.ReqUser, err error) {
  647. var arc *arcmdl.ArcReply
  648. data = new(model.ReqUser)
  649. if arc, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: aid}); err != nil || arc.Arc == nil || !arc.Arc.IsNormal() {
  650. log.Error("ArcRelation s.arcClient.Arc(%d) error(%v)", aid, err)
  651. err = nil
  652. return
  653. }
  654. authorMid := arc.Arc.Author.Mid
  655. ip := metadata.String(c, metadata.RemoteIP)
  656. group, errCtx := errgroup.WithContext(c)
  657. // attention
  658. group.Go(func() error {
  659. if resp, e := s.accClient.Relation3(errCtx, &accmdl.RelationReq{Mid: mid, Owner: authorMid, RealIp: ip}); e != nil {
  660. log.Error("ArcRelation s.accClient.Relation3(%d,%d,%s) error(%v)", mid, authorMid, ip, e)
  661. } else if resp != nil {
  662. data.Attention = resp.Following
  663. }
  664. return nil
  665. })
  666. // favorite
  667. group.Go(func() error {
  668. if resp, e := s.fav.IsFav(errCtx, &favmdl.ArgIsFav{Type: favmdl.TypeVideo, Mid: mid, Oid: aid, RealIP: ip}); e != nil {
  669. log.Error("ArcRelation s.fav.IsFav(%d,%d,%s) error(%v)", mid, aid, ip, e)
  670. } else {
  671. data.Favorite = resp
  672. }
  673. return nil
  674. })
  675. // like
  676. group.Go(func() error {
  677. if resp, e := s.thumbup.HasLike(errCtx, &thumbup.ArgHasLike{Business: _businessLike, MessageIDs: []int64{aid}, Mid: mid, RealIP: ip}); e != nil {
  678. log.Error("ArcRelation s.thumbup.HasLike(%d,%d,%s) error %v", aid, mid, ip, e)
  679. } else if resp != nil {
  680. if v, ok := resp[aid]; ok {
  681. switch v {
  682. case thumbup.StateLike:
  683. data.Like = true
  684. case thumbup.StateDislike:
  685. data.Dislike = true
  686. }
  687. }
  688. }
  689. return nil
  690. })
  691. // coin
  692. group.Go(func() error {
  693. if resp, e := s.coinClient.ItemUserCoins(errCtx, &coinmdl.ItemUserCoinsReq{Mid: mid, Aid: aid, Business: model.CoinArcBusiness}); e != nil {
  694. log.Error("ArcRelation s.coinClient.ItemUserCoins(%d,%d,%s) error %v", mid, aid, ip, e)
  695. } else if resp != nil {
  696. data.Coin = resp.Number
  697. }
  698. return nil
  699. })
  700. group.Wait()
  701. return
  702. }
  703. func (s *Service) replyHot(c context.Context, aid int64) (res *model.ReplyHot, err error) {
  704. if res, err = s.dao.Hot(c, aid); err != nil {
  705. log.Error("s.dao.Hot(%d) error %+v", aid, err)
  706. }
  707. if res == nil {
  708. res = _emptyReplyHot
  709. }
  710. return
  711. }
  712. func (s *Service) arcTags(c context.Context, aid, mid int64) (res []*tagmdl.Tag, err error) {
  713. remoteIP := metadata.String(c, metadata.RemoteIP)
  714. var (
  715. arg = &tagmdl.ArgAid{
  716. Aid: aid,
  717. Mid: mid,
  718. RealIP: remoteIP,
  719. }
  720. )
  721. if res, err = s.tag.ArcTags(c, arg); err != nil {
  722. log.Error("s.tag.ArcTags(%v) error(%v)", arg, err)
  723. }
  724. if len(res) == 0 {
  725. res = _emptyTags
  726. }
  727. return
  728. }
  729. func (s *Service) ugcPayAsset(c context.Context, aid, mid int64) (data *ugcmdl.AssetQueryResp) {
  730. asset, err := s.ugcPayClient.AssetQuery(c, &ugcmdl.AssetQueryReq{Oid: aid, Otype: _ugcOtypeArc, Currency: _ugcCurrencyBp})
  731. if err != nil {
  732. log.Error("ugcPayAsset mid(%d) oid(%d) error(%v)", mid, aid, err)
  733. data = new(ugcmdl.AssetQueryResp)
  734. return
  735. }
  736. data = asset
  737. return
  738. }
  739. func (s *Service) loadManager() {
  740. for {
  741. time.Sleep(time.Duration(s.c.WEB.SpecailInterval))
  742. midsM, err := s.dao.Special(context.Background())
  743. if err != nil {
  744. log.Error("loadManager error(%+v)", err)
  745. continue
  746. }
  747. log.Info("load special mids(%+v)", midsM)
  748. s.specialMids = midsM
  749. }
  750. }