contain.go 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. package view
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "hash/crc32"
  7. "sort"
  8. "time"
  9. "go-common/app/interface/main/app-view/model"
  10. "go-common/app/interface/main/app-view/model/ad"
  11. "go-common/app/interface/main/app-view/model/bangumi"
  12. "go-common/app/interface/main/app-view/model/game"
  13. "go-common/app/interface/main/app-view/model/manager"
  14. "go-common/app/interface/main/app-view/model/tag"
  15. "go-common/app/interface/main/app-view/model/view"
  16. account "go-common/app/service/main/account/model"
  17. "go-common/app/service/main/archive/api"
  18. "go-common/app/service/main/archive/model/archive"
  19. location "go-common/app/service/main/location/model"
  20. thumbup "go-common/app/service/main/thumbup/model"
  21. "go-common/app/service/openplatform/pgc-season/api/grpc/season/v1"
  22. "go-common/library/ecode"
  23. "go-common/library/log"
  24. "go-common/library/sync/errgroup"
  25. )
  26. var (
  27. _rate = map[int]int64{15: 464, 16: 464, 32: 1028, 48: 1328, 64: 2192, 74: 3192, 80: 3192, 112: 6192, 116: 6192, 66: 1820}
  28. )
  29. const (
  30. _dmformat = "http://comment.bilibili.com/%d.xml"
  31. _qn480 = 32
  32. _qnAndroidBuildGt = 5325000
  33. _qnIosBuildGt = 8170
  34. _qnAndroidBuildLt = 5335000
  35. _qnIosBuildLt = 8190
  36. )
  37. // initReqUser init Req User
  38. func (s *Service) initReqUser(c context.Context, v *view.View, mid int64, plat int8, build int) {
  39. const (
  40. _androidOld = 427000
  41. _iosOld = 4000
  42. _ipadOld = 4300
  43. _ipadHD = 10410
  44. )
  45. // owner ext
  46. var (
  47. owners []int64
  48. cards map[int64]*account.Card
  49. fls map[int64]int8
  50. )
  51. g, ctx := errgroup.WithContext(c)
  52. if v.Author.Mid > 0 {
  53. owners = append(owners, v.Author.Mid)
  54. for _, staffInfo := range v.StaffInfo {
  55. owners = append(owners, staffInfo.Mid)
  56. }
  57. g.Go(func() (err error) {
  58. v.OwnerExt.OfficialVerify.Type = -1
  59. cards, err = s.accDao.Cards3(ctx, owners)
  60. if err != nil {
  61. log.Error("%+v", err)
  62. err = nil
  63. return
  64. }
  65. if card, ok := cards[v.Author.Mid]; ok && card != nil {
  66. otp := -1
  67. odesc := ""
  68. if card.Official.Role != 0 {
  69. if card.Official.Role <= 2 {
  70. otp = 0
  71. } else {
  72. otp = 1
  73. }
  74. odesc = card.Official.Title
  75. }
  76. v.OwnerExt.OfficialVerify.Type = otp
  77. v.OwnerExt.OfficialVerify.Desc = odesc
  78. v.OwnerExt.Vip.Type = int(card.Vip.Type)
  79. v.OwnerExt.Vip.VipStatus = int(card.Vip.Status)
  80. v.OwnerExt.Vip.DueDate = card.Vip.DueDate
  81. v.Author.Name = card.Name
  82. v.Author.Face = card.Face
  83. }
  84. if l, ok := s.liveCache[v.Author.Mid]; ok {
  85. v.OwnerExt.Live = l
  86. }
  87. return
  88. })
  89. g.Go(func() (err error) {
  90. stat, err := s.relDao.Stat(c, v.Author.Mid)
  91. if err != nil {
  92. log.Error("%+v", err)
  93. err = nil
  94. return
  95. }
  96. if stat != nil {
  97. v.OwnerExt.Fans = int(stat.Follower)
  98. }
  99. return
  100. })
  101. g.Go(func() error {
  102. if ass, err := s.assDao.Assist(ctx, v.Author.Mid); err != nil {
  103. log.Error("%+v", err)
  104. } else {
  105. v.OwnerExt.Assists = ass
  106. }
  107. return nil
  108. })
  109. }
  110. // req user
  111. v.ReqUser = &view.ReqUser{Favorite: 0, Attention: -999, Like: 0, Dislike: 0}
  112. // check req user
  113. if mid > 0 {
  114. g.Go(func() error {
  115. var is bool
  116. if (model.IsAndroid(plat) && build < _androidOld) || (model.IsIPhone(plat) && build < _iosOld) || ((plat == model.PlatIPad && build < _ipadOld) || (plat == model.PlatIpadHD && build < _ipadHD) || (plat == model.PlatIPadI)) {
  117. is, _ = s.favDao.IsFavDefault(ctx, mid, v.Aid)
  118. } else {
  119. is, _ = s.favDao.IsFav(ctx, mid, v.Aid)
  120. }
  121. if is {
  122. v.ReqUser.Favorite = 1
  123. }
  124. return nil
  125. })
  126. g.Go(func() error {
  127. res, err := s.thumbupDao.HasLike(ctx, mid, _businessLike, []int64{v.Aid})
  128. if err != nil {
  129. log.Error("s.thumbupDao.HasLike err(%+v)", err)
  130. return nil
  131. }
  132. if res.States == nil {
  133. return nil
  134. }
  135. if typ, ok := res.States[v.Aid]; ok {
  136. if typ.State == thumbup.StateLike {
  137. v.ReqUser.Like = 1
  138. } else if typ.State == thumbup.StateDislike {
  139. v.ReqUser.Dislike = 1
  140. }
  141. }
  142. return nil
  143. })
  144. g.Go(func() (err error) {
  145. res, err := s.coinDao.ArchiveUserCoins(ctx, v.Aid, mid, _avTypeAv)
  146. if err != nil {
  147. log.Error("%+v", err)
  148. err = nil
  149. }
  150. if res != nil && res.Multiply > 0 {
  151. v.ReqUser.Coin = 1
  152. }
  153. return
  154. })
  155. if v.Author.Mid > 0 {
  156. g.Go(func() error {
  157. fls = s.accDao.IsAttention(ctx, owners, mid)
  158. if _, ok := fls[v.Author.Mid]; ok {
  159. v.ReqUser.Attention = 1
  160. }
  161. return nil
  162. })
  163. }
  164. }
  165. if err := g.Wait(); err != nil {
  166. log.Error("%+v", err)
  167. }
  168. // fill staff
  169. for _, owner := range owners {
  170. if card, ok := cards[owner]; ok && card != nil {
  171. staff := &view.Staff{Mid: owner}
  172. if owner == v.Author.Mid {
  173. staff.Title = "UP主"
  174. } else {
  175. for _, s := range v.StaffInfo {
  176. if s.Mid == owner {
  177. staff.Title = s.Title
  178. }
  179. }
  180. }
  181. staff.Name = card.Name
  182. staff.Face = card.Face
  183. staff.OfficialVerify.Type = -1
  184. otp := -1
  185. odesc := ""
  186. if card.Official.Role != 0 {
  187. if card.Official.Role <= 2 {
  188. otp = 0
  189. } else {
  190. otp = 1
  191. }
  192. odesc = card.Official.Title
  193. }
  194. staff.OfficialVerify.Type = otp
  195. staff.OfficialVerify.Desc = odesc
  196. staff.Vip.Type = int(card.Vip.Type)
  197. staff.Vip.VipStatus = int(card.Vip.Status)
  198. staff.Vip.DueDate = card.Vip.DueDate
  199. if _, ok := fls[owner]; ok {
  200. staff.Attention = 1
  201. }
  202. v.Staff = append(v.Staff, staff)
  203. }
  204. }
  205. }
  206. func (s *Service) initRelateCMTag(c context.Context, v *view.View, plat int8, build, qn, fnver, fnval, forceHost, parentMode int, mid int64, buvid, mobiApp, device, network, adExtra, from string, now time.Time) {
  207. const (
  208. _iPhoneRelateGame = 6500
  209. _androidRelateGame = 5210000
  210. )
  211. var (
  212. rls []*view.Relate
  213. aidm map[int64]struct{}
  214. mr *manager.Relate
  215. rGameID, cGameID int64
  216. advert *ad.Ad
  217. adm map[int]*ad.AdInfo
  218. relateRsc int64
  219. cmRsc int64
  220. err error
  221. adminfo json.RawMessage
  222. hasDalao int
  223. dalaoExp int
  224. )
  225. tids := s.initTag(c, v, mid, plat)
  226. g, ctx := errgroup.WithContext(c)
  227. g.Go(func() (err error) {
  228. if mid > 0 || buvid != "" {
  229. if rls, v.UserFeature, v.ReturnCode, hasDalao, dalaoExp, err = s.newRcmdRelate(ctx, plat, v.Aid, mid, buvid, mobiApp, from, build, qn, fnver, fnval, forceHost, parentMode); err != nil {
  230. log.Error("s.newRcmdRelate(%d) error(%+v)", v.Aid, err)
  231. }
  232. }
  233. if len(rls) == 0 {
  234. rls, _, err = s.dealRcmdRelate(ctx, plat, v.Aid, build)
  235. log.Warn("s.dealRcmdRelate aid(%d) mid(%d) buvid(%s)", v.Aid, mid, buvid)
  236. } else {
  237. v.IsRec = 1
  238. log.Warn("s.newRcmdRelate returncode(%s) aid(%d) mid(%d) buvid(%s) hasDalao(%d) dalaoExp(%d)", v.ReturnCode, v.Aid, mid, buvid, hasDalao, dalaoExp)
  239. }
  240. err = nil
  241. return
  242. })
  243. if !model.IsIPad(plat) {
  244. g.Go(func() (err error) {
  245. const (
  246. _iphoneRelateRsc = 2029
  247. _androidRelateRsc = 2028
  248. _iphoneCMRsc = 2335
  249. _androidCMRsc = 2337
  250. )
  251. if model.IsIPhone(plat) {
  252. relateRsc = _iphoneRelateRsc
  253. cmRsc = _iphoneCMRsc
  254. } else {
  255. relateRsc = _androidRelateRsc
  256. cmRsc = _androidCMRsc
  257. }
  258. if advert, err = s.adDao.Ad(ctx, mobiApp, device, buvid, build, mid, v.Author.Mid, v.Aid, v.TypeID, tids, []int64{relateRsc, cmRsc}, network, adExtra); err != nil {
  259. log.Error("%+v", err)
  260. err = nil
  261. }
  262. return
  263. })
  264. if v.OrderID > 0 {
  265. g.Go(func() (err error) {
  266. if adminfo, err = s.adDao.MonitorInfo(ctx, v.Aid); err != nil {
  267. log.Error("%+v", err)
  268. err = nil
  269. }
  270. return
  271. })
  272. }
  273. }
  274. if dalaoExp != 1 {
  275. g.Go(func() (err error) {
  276. mr = s.relateCache(ctx, plat, build, now, v.Aid, tids, v.TypeID)
  277. return
  278. })
  279. }
  280. if (plat == model.PlatAndroid && build >= _androidRelateGame) || (plat == model.PlatIPhone && build >= _iPhoneRelateGame) || plat == model.PlatIPhoneB {
  281. if buvid != "" && crc32.ChecksumIEEE([]byte(buvid))%10 == 1 {
  282. g.Go(func() (err error) {
  283. rGameID = s.relateGame(ctx, v.Aid)
  284. return
  285. })
  286. }
  287. if v.AttrVal(archive.AttrBitIsPorder) == archive.AttrYes || v.OrderID > 0 {
  288. g.Go(func() (err error) {
  289. if cGameID, err = s.arcDao.Commercial(ctx, v.Aid); err != nil {
  290. log.Error("%+v", err)
  291. err = nil
  292. }
  293. return
  294. })
  295. }
  296. }
  297. if err = g.Wait(); err != nil {
  298. log.Error("%+v", err)
  299. return
  300. }
  301. //ad config
  302. if advert != nil {
  303. if advert.AdsControl != nil {
  304. v.CMConfig = &view.CMConfig{
  305. AdsControl: advert.AdsControl,
  306. }
  307. }
  308. }
  309. if adminfo != nil {
  310. if v.CMConfig == nil {
  311. v.CMConfig = &view.CMConfig{
  312. MonitorInfo: adminfo,
  313. }
  314. } else {
  315. v.CMConfig.MonitorInfo = adminfo
  316. }
  317. }
  318. //ad
  319. if len(rls) == 0 {
  320. s.prom.Incr("zero_relates")
  321. return
  322. }
  323. var (
  324. r *view.Relate
  325. rm map[int]*view.Relate
  326. )
  327. if advert != nil {
  328. if adm, err = s.dealCM(c, advert, relateRsc); err != nil {
  329. log.Error("%+v", err)
  330. }
  331. initCM(c, v, advert, cmRsc)
  332. }
  333. //ai已经有dalao卡则直接返回,没有则看要不要第一位拼接其他卡
  334. if hasDalao == 1 {
  335. v.Relates = rls
  336. return
  337. }
  338. if dalaoExp != 1 {
  339. if r, err = s.dealManagerRelate(c, plat, mr, build); err != nil {
  340. log.Error("%+v", err)
  341. }
  342. }
  343. if r == nil {
  344. if r, err = s.dealGame(c, plat, cGameID, model.FromOrder); err != nil {
  345. log.Error("%+v", err)
  346. }
  347. }
  348. if r == nil {
  349. if r, err = s.dealGame(c, plat, rGameID, model.FromRcmd); err != nil {
  350. log.Error("%+v", err)
  351. }
  352. }
  353. if r != nil {
  354. rm = map[int]*view.Relate{0: r}
  355. aidm = map[int64]struct{}{r.Aid: struct{}{}}
  356. } else if len(adm) != 0 {
  357. rm = make(map[int]*view.Relate, len(adm))
  358. for idx, ad := range adm {
  359. r = &view.Relate{}
  360. r.FromCM(ad)
  361. rm[idx] = r
  362. }
  363. }
  364. if len(rm) != 0 {
  365. var tmp []*view.Relate
  366. for _, rl := range rls {
  367. if _, ok := aidm[rl.Aid]; ok {
  368. continue
  369. }
  370. tmp = append(tmp, rl)
  371. }
  372. v.Relates = make([]*view.Relate, 0, len(tmp)+len(rm))
  373. for _, rl := range tmp {
  374. LABEL:
  375. if r, ok := rm[len(v.Relates)]; ok {
  376. if r.IsAdLoc && r.AdCb == "" {
  377. rel := &view.Relate{}
  378. *rel = *rl
  379. rel.IsAdLoc = r.IsAdLoc
  380. rel.RequestID = r.RequestID
  381. rel.SrcID = r.SrcID
  382. rel.ClientIP = r.ClientIP
  383. rel.AdIndex = r.AdIndex
  384. rel.Extra = r.Extra
  385. rel.CardIndex = r.CardIndex
  386. v.Relates = append(v.Relates, rel)
  387. } else if r.Aid != v.Aid {
  388. v.Relates = append(v.Relates, r)
  389. goto LABEL
  390. } else {
  391. v.Relates = append(v.Relates, rl)
  392. }
  393. } else {
  394. v.Relates = append(v.Relates, rl)
  395. }
  396. }
  397. } else {
  398. v.Relates = rls
  399. }
  400. }
  401. func initCM(c context.Context, v *view.View, advert *ad.Ad, resource int64) {
  402. ads, _ := advert.Convert(resource)
  403. sort.Sort(ad.AdInfos(ads))
  404. if len(ads) == 0 {
  405. return
  406. }
  407. v.CMs = make([]*view.CM, 0, len(ads))
  408. for _, ad := range ads {
  409. cm := &view.CM{}
  410. cm.FromCM(ad)
  411. v.CMs = append(v.CMs, cm)
  412. }
  413. }
  414. func (s *Service) initMovie(c context.Context, v *view.View, mid int64, build int, mobiApp, device string, nMovie bool) (err error) {
  415. s.pHit.Incr("is_movie")
  416. var m *bangumi.Movie
  417. if m, err = s.banDao.Movie(c, v.Aid, mid, build, mobiApp, device); err != nil || m == nil {
  418. log.Error("%+v", err)
  419. err = ecode.NothingFound
  420. s.pMiss.Incr("err_is_PGC")
  421. return
  422. }
  423. if v.Rights.HD5 == 1 && m.PayUser.Status == 0 && !s.checkVIP(c, mid) {
  424. v.Rights.HD5 = 0
  425. }
  426. if len(m.List) == 0 {
  427. err = ecode.NothingFound
  428. return
  429. }
  430. vps := make([]*view.Page, 0, len(m.List))
  431. for _, l := range m.List {
  432. vp := &view.Page{
  433. Page3: &archive.Page3{Cid: l.Cid, Page: int32(l.Page), From: l.Type, Part: l.Part, Vid: l.Vid},
  434. }
  435. vps = append(vps, vp)
  436. }
  437. m.List = nil
  438. // view
  439. v.Pages = vps
  440. v.Rights.Download = int32(m.AllowDownload)
  441. m.AllowDownload = 0
  442. v.Rights.Bp = 0
  443. if nMovie {
  444. v.Movie = m
  445. v.Desc = m.Season.Evaluate
  446. }
  447. return
  448. }
  449. func (s *Service) initPGC(c context.Context, v *view.View, mid int64, build int, mobiApp, device string) (err error) {
  450. s.pHit.Incr("is_PGC")
  451. var season *bangumi.Season
  452. if season, err = s.banDao.PGC(c, v.Aid, mid, build, mobiApp, device); err != nil {
  453. log.Error("%+v", err)
  454. err = ecode.NothingFound
  455. s.pMiss.Incr("err_is_PGC")
  456. return
  457. }
  458. if season != nil {
  459. if season.Player != nil {
  460. if len(v.Pages) != 0 {
  461. if season.Player.Cid != 0 {
  462. v.Pages[0].Cid = season.Player.Cid
  463. }
  464. if season.Player.From != "" {
  465. v.Pages[0].From = season.Player.From
  466. }
  467. if season.Player.Vid != "" {
  468. v.Pages[0].Vid = season.Player.Vid
  469. }
  470. }
  471. season.Player = nil
  472. }
  473. if season.AllowDownload == "1" {
  474. v.Rights.Download = 1
  475. } else {
  476. v.Rights.Download = 0
  477. }
  478. if season.SeasonID != "" {
  479. season.AllowDownload = ""
  480. v.Season = season
  481. }
  482. }
  483. if v.Rights.HD5 == 1 && !s.checkVIP(c, mid) {
  484. v.Rights.HD5 = 0
  485. }
  486. v.Rights.Bp = 0
  487. return
  488. }
  489. func (s *Service) initPages(c context.Context, vs *view.ViewStatic, ap []*archive.Page3) {
  490. pages := make([]*view.Page, 0, len(ap))
  491. for _, v := range ap {
  492. page := &view.Page{}
  493. metas := make([]*view.Meta, 0, 4)
  494. for q, r := range _rate {
  495. meta := &view.Meta{
  496. Quality: q,
  497. Size: int64(float64(r*v.Duration) * 1.1 / 8.0),
  498. }
  499. metas = append(metas, meta)
  500. }
  501. if vs.AttrVal(archive.AttrBitIsBangumi) == archive.AttrYes {
  502. v.From = "bangumi"
  503. }
  504. page.Page3 = v
  505. page.Metas = metas
  506. page.DMLink = fmt.Sprintf(_dmformat, v.Cid)
  507. pages = append(pages, page)
  508. }
  509. vs.Pages = pages
  510. }
  511. func (s *Service) initDownload(c context.Context, v *view.View, mid int64, cdnIP string) (err error) {
  512. var download int64
  513. if v.AttrVal(archive.AttrBitLimitArea) == archive.AttrYes {
  514. if download, err = s.ipLimit(c, mid, v.Aid, cdnIP); err != nil {
  515. return
  516. }
  517. } else {
  518. download = location.AllowDown
  519. }
  520. if download == location.ForbiddenDown {
  521. v.Rights.Download = int32(download)
  522. return
  523. }
  524. for _, p := range v.Pages {
  525. if p.From == "qq" {
  526. download = location.ForbiddenDown
  527. break
  528. }
  529. }
  530. v.Rights.Download = int32(download)
  531. return
  532. }
  533. func (s *Service) initUGCPay(c context.Context, v *view.View, plat int8, mid int64) (err error) {
  534. var (
  535. asset *view.Asset
  536. platform = model.Platform(plat)
  537. )
  538. if asset, err = s.ugcpayDao.AssetRelationDetail(c, mid, v.Aid, platform); err != nil {
  539. log.Error("%+v", err)
  540. return
  541. }
  542. if asset != nil {
  543. v.Asset = asset
  544. }
  545. return
  546. }
  547. func (s *Service) initContributions(c context.Context, v *view.View) {
  548. const _count = 5
  549. if v.ReqUser != nil && v.ReqUser.Attention == 1 {
  550. return
  551. }
  552. var hasAudio bool
  553. for _, page := range v.Pages {
  554. if page.Audio != nil {
  555. hasAudio = true
  556. break
  557. }
  558. }
  559. if hasAudio || v.OwnerExt.Archives < 20 {
  560. return
  561. }
  562. aids, err := s.arcDao.ViewContributeCache(c, v.Author.Mid)
  563. if err != nil {
  564. log.Error("%+v", err)
  565. return
  566. }
  567. if len(aids) < _count+1 {
  568. return
  569. }
  570. as, err := s.arcDao.Archives(c, aids)
  571. if err != nil {
  572. log.Error("%+v", err)
  573. return
  574. }
  575. if len(as) == 0 {
  576. return
  577. }
  578. ctbt := make([]*view.Contribution, 0, len(as))
  579. for _, aid := range aids {
  580. if a, ok := as[aid]; ok && a.IsNormal() {
  581. if a.Aid != v.Aid {
  582. vc := &view.Contribution{Aid: a.Aid, Title: a.Title, Pic: a.Pic, Author: a.Author, Stat: a.Stat, CTime: a.PubDate}
  583. ctbt = append(ctbt, vc)
  584. }
  585. }
  586. }
  587. if len(ctbt) > _count {
  588. ctbt = ctbt[:_count]
  589. }
  590. if len(ctbt) == _count {
  591. v.Contributions = ctbt
  592. }
  593. }
  594. func (s *Service) initAudios(c context.Context, v *view.View) {
  595. pLen := len(v.Pages)
  596. if pLen == 0 || pLen > 100 {
  597. return
  598. }
  599. if pLen > 50 {
  600. pLen = 50
  601. }
  602. cids := make([]int64, 0, len(v.Pages[:pLen]))
  603. for _, p := range v.Pages[:pLen] {
  604. cids = append(cids, p.Cid)
  605. }
  606. vam, err := s.audioDao.AudioByCids(c, cids)
  607. if err != nil {
  608. log.Error("%+v", err)
  609. return
  610. }
  611. if len(vam) != 0 {
  612. for _, p := range v.Pages[:pLen] {
  613. if va, ok := vam[p.Cid]; ok {
  614. p.Audio = va
  615. }
  616. }
  617. if len(v.Pages) == 1 {
  618. if va, ok := vam[v.Pages[0].Cid]; ok {
  619. v.Audio = va
  620. }
  621. }
  622. }
  623. }
  624. func (s *Service) initElec(c context.Context, v *view.View, mid int64) {
  625. if _, ok := s.allowTypeIds[int16(v.TypeID)]; !ok || int8(v.Copyright) != archive.CopyrightOriginal {
  626. return
  627. }
  628. info, err := s.elcDao.Info(c, v.Author.Mid, mid)
  629. if err != nil {
  630. log.Error("%+v", err)
  631. return
  632. }
  633. if info != nil {
  634. v.Rights.Elec = 1
  635. info.Show = true
  636. v.Elec = info
  637. }
  638. }
  639. func (s *Service) initTag(c context.Context, v *view.View, mid int64, plat int8) (tids []int64) {
  640. var (
  641. actTag []*tag.Tag
  642. arcTag []*tag.Tag
  643. actTagName string
  644. )
  645. if v.MissionID > 0 {
  646. protocol, err := s.actDao.ActProtocol(c, v.MissionID)
  647. if err != nil {
  648. log.Error("s.actDao.ActProtocol err(%+v)", err)
  649. err = nil
  650. } else {
  651. if protocol.SubjectItem != nil {
  652. v.ActivityURL = protocol.SubjectItem.AndroidURL
  653. if model.IsIOS(plat) {
  654. v.ActivityURL = protocol.SubjectItem.IosURL
  655. }
  656. }
  657. if protocol.ActSubjectProtocol != nil {
  658. actTagName = protocol.ActSubjectProtocol.Tags
  659. }
  660. }
  661. }
  662. tags, err := s.tagDao.ArcTags(c, v.Aid, mid)
  663. if err != nil {
  664. log.Error("s.tagDao.ArcTags err(%+v)", err)
  665. return
  666. }
  667. tids = make([]int64, 0, len(tags))
  668. for _, t := range tags {
  669. if actTagName == t.Name {
  670. t.IsActivity = 1
  671. actTag = append(actTag, t)
  672. } else {
  673. arcTag = append(arcTag, t)
  674. }
  675. tids = append(tids, t.TagID)
  676. }
  677. //活动稿件tag放在第一位
  678. v.Tag = append(actTag, arcTag...)
  679. return
  680. }
  681. func (s *Service) initDM(c context.Context, v *view.View) {
  682. const (
  683. _dmTypeAv = 1
  684. _dmPlatMobie = 1
  685. )
  686. pLen := len(v.Pages)
  687. if pLen == 0 || pLen > 100 {
  688. return
  689. }
  690. if pLen > 50 {
  691. pLen = 50
  692. }
  693. cids := make([]int64, 0, len(v.Pages[:pLen]))
  694. for _, p := range v.Pages[:pLen] {
  695. cids = append(cids, p.Cid)
  696. }
  697. res, err := s.dmDao.SubjectInfos(c, _dmTypeAv, _dmPlatMobie, cids...)
  698. if err != nil {
  699. log.Error("%+v", err)
  700. return
  701. }
  702. if len(res) == 0 {
  703. return
  704. }
  705. for _, p := range v.Pages[:pLen] {
  706. if r, ok := res[p.Cid]; ok {
  707. p.DM = r
  708. }
  709. }
  710. }
  711. func (s *Service) dealCM(c context.Context, advert *ad.Ad, resource int64) (adm map[int]*ad.AdInfo, err error) {
  712. ads, aids := advert.Convert(resource)
  713. if len(ads) == 0 {
  714. return
  715. }
  716. adm = make(map[int]*ad.AdInfo, len(ads))
  717. for _, ad := range ads {
  718. adm[ad.CardIndex-1] = ad
  719. }
  720. if len(aids) == 0 {
  721. return
  722. }
  723. as, err := s.arcDao.Archives(c, aids)
  724. if err != nil {
  725. log.Error("%+v", err)
  726. err = nil
  727. return
  728. }
  729. for _, ad := range adm {
  730. if ad.Goto == model.GotoAv && ad.CreativeContent != nil {
  731. if a, ok := as[ad.CreativeContent.VideoID]; ok {
  732. ad.View = int(a.Stat.View)
  733. ad.Danmaku = int(a.Stat.Danmaku)
  734. if ad.CreativeContent.Desc == "" {
  735. ad.CreativeContent.Desc = a.Desc
  736. }
  737. ad.URI = model.FillURI(ad.Goto, ad.Param, model.AvHandler(a, "", nil))
  738. }
  739. }
  740. }
  741. return
  742. }
  743. func (s *Service) dealRcmdRelate(c context.Context, plat int8, aid int64, build int) (rls []*view.Relate, aidm map[int64]struct{}, err error) {
  744. if rls, err = s.arcDao.RelatesCache(c, aid); err != nil {
  745. return
  746. }
  747. if len(rls) != 0 {
  748. aidm = make(map[int64]struct{}, len(rls))
  749. for _, rl := range rls {
  750. if rl.Aid != 0 {
  751. aidm[rl.Aid] = struct{}{}
  752. }
  753. }
  754. return
  755. }
  756. s.prom.Incr("need_relates")
  757. var aids []int64
  758. if aids, err = s.arcDao.RelateAids(c, aid); err != nil {
  759. return
  760. }
  761. if len(aids) == 0 {
  762. return
  763. }
  764. var as map[int64]*api.Arc
  765. if as, err = s.arcDao.Archives(c, aids); err != nil {
  766. return
  767. }
  768. aidm = make(map[int64]struct{}, len(as))
  769. for _, aid := range aids {
  770. if a, ok := as[aid]; ok {
  771. if s.overseaCheck(archive.BuildArchive3(a), plat) || !a.IsNormal() {
  772. continue
  773. }
  774. r := &view.Relate{}
  775. var cooperation bool
  776. if (model.IsAndroid(plat) && build > s.c.BuildLimit.CooperationAndroid) || (model.IsIPhone(plat) && build > s.c.BuildLimit.CooperationIOS) {
  777. cooperation = true
  778. }
  779. r.FromAv(a, "", "", nil, cooperation)
  780. rls = append(rls, r)
  781. aidm[aid] = struct{}{}
  782. }
  783. }
  784. if len(rls) != 0 {
  785. s.arcDao.AddRelatesCache(aid, rls)
  786. }
  787. return
  788. }
  789. func (s *Service) dealManagerRelate(c context.Context, plat int8, mr *manager.Relate, build int) (r *view.Relate, err error) {
  790. if mr == nil || mr.Param < 1 {
  791. return
  792. }
  793. var cooperation bool
  794. if (model.IsAndroid(plat) && build > s.c.BuildLimit.CooperationAndroid) || (model.IsIPhone(plat) && build > s.c.BuildLimit.CooperationIOS) {
  795. cooperation = true
  796. }
  797. switch mr.Goto {
  798. case model.GotoAv:
  799. var a *api.Arc
  800. if a, err = s.arcDao.Archive3(c, mr.Param); err != nil {
  801. return
  802. }
  803. if a != nil {
  804. r = &view.Relate{}
  805. r.FromOperateOld(mr, a, nil, nil, model.FromOperation, cooperation)
  806. }
  807. case model.GotoGame:
  808. var info *game.Info
  809. if info, err = s.gameDao.Info(c, mr.Param, plat); err != nil {
  810. return
  811. }
  812. if info != nil && info.IsOnline {
  813. r = &view.Relate{}
  814. r.FromOperateOld(mr, nil, info, nil, model.FromOperation, cooperation)
  815. }
  816. case model.GotoSpecial:
  817. if sp, ok := s.specialCache[mr.Param]; ok {
  818. r = &view.Relate{}
  819. r.FromOperateOld(mr, nil, nil, sp, model.FromOperation, cooperation)
  820. }
  821. }
  822. return
  823. }
  824. func (s *Service) dealGame(c context.Context, plat int8, id int64, from string) (r *view.Relate, err error) {
  825. if id < 1 {
  826. return
  827. }
  828. var info *game.Info
  829. if info, err = s.gameDao.Info(c, id, plat); err != nil {
  830. return
  831. }
  832. if info != nil && info.IsOnline {
  833. r = &view.Relate{}
  834. r.FromGame(info, from)
  835. }
  836. return
  837. }
  838. func (s *Service) newRcmdRelate(c context.Context, plat int8, aid, mid int64, buvid, mobiApp, from string, build, qn, fnver, fnval, forceHost, parentMode int) (rls []*view.Relate, userFeature, returnCode string, hasDalao, dalaoExp int, err error) {
  839. recData, userFeature, returnCode, dalaoExp, err := s.arcDao.NewRelateAids(c, aid, mid, build, parentMode, buvid, from, plat)
  840. if err != nil || len(recData) == 0 {
  841. return
  842. }
  843. var (
  844. aids []int64
  845. ssIDs []int32
  846. gameID int64
  847. specialID int64
  848. arcm map[int64]*api.Arc
  849. banm map[int32]*v1.CardInfoProto
  850. gameInfo *game.Info
  851. )
  852. for _, rec := range recData {
  853. switch rec.Goto {
  854. case model.GotoAv:
  855. aids = append(aids, rec.Oid)
  856. case model.GotoBangumi:
  857. ssIDs = append(ssIDs, int32(rec.Oid))
  858. case model.GotoGame:
  859. gameID = rec.Oid
  860. case model.GotoSpecial:
  861. specialID = rec.Oid
  862. }
  863. }
  864. eg := errgroup.Group{}
  865. if len(aids) > 0 {
  866. eg.Go(func() (err error) {
  867. if arcm, err = s.arcDao.Archives(context.Background(), aids); err != nil {
  868. log.Error("s.arcDao.Archives err(%+v)", err)
  869. }
  870. return
  871. })
  872. }
  873. if len(ssIDs) > 0 {
  874. eg.Go(func() (err error) {
  875. if banm, err = s.banDao.CardsInfoReply(context.Background(), ssIDs); err != nil {
  876. log.Error("s.banDao.CardsInfoReply err(%+v)", err)
  877. }
  878. return
  879. })
  880. }
  881. if gameID > 0 {
  882. eg.Go(func() (err error) {
  883. if gameInfo, err = s.gameDao.Info(c, gameID, plat); err != nil {
  884. log.Error("s.gameDao.Info err(%+v)", err)
  885. }
  886. return
  887. })
  888. }
  889. eg.Wait()
  890. players := make(map[int64]*archive.PlayerInfo)
  891. if (model.IsAndroid(plat) && build > _qnAndroidBuildGt) || (model.IsIOSNormal(plat) && build > _qnIosBuildGt) || model.IsIPhoneB(plat) {
  892. var cids []int64
  893. if aid%100 < s.c.RelateGray {
  894. for k, v := range aids {
  895. if k == s.c.RelateCnt {
  896. break
  897. }
  898. if arcm[v].Rights.Autoplay == 1 {
  899. cids = append(cids, arcm[v].FirstCid)
  900. }
  901. }
  902. }
  903. if len(cids) > 0 {
  904. playerInfo := make(map[uint32]*archive.BvcVideoItem)
  905. if (model.IsAndroid(plat) && build < _qnAndroidBuildLt) || (model.IsIOSNormal(plat) && build <= _qnIosBuildLt) || qn <= 0 {
  906. qn = _qn480
  907. }
  908. if playerInfo, err = s.arcDao.PlayerInfos(c, cids, qn, fnver, fnval, forceHost, mobiApp); err != nil {
  909. log.Error("%+v", err)
  910. err = nil
  911. } else if len(playerInfo) > 0 {
  912. for k, pi := range playerInfo {
  913. cid := int64(k)
  914. players[cid] = new(archive.PlayerInfo)
  915. players[cid].Cid = pi.Cid
  916. players[cid].ExpireTime = pi.ExpireTime
  917. players[cid].FileInfo = make(map[int][]*archive.PlayerFileInfo)
  918. for qn, files := range pi.FileInfo {
  919. for _, f := range files.Infos {
  920. players[cid].FileInfo[int(qn)] = append(players[cid].FileInfo[int(qn)], &archive.PlayerFileInfo{
  921. FileSize: f.Filesize,
  922. TimeLength: f.Timelength,
  923. })
  924. }
  925. }
  926. players[cid].SupportQuality = pi.SupportQuality
  927. players[cid].SupportFormats = pi.SupportFormats
  928. players[cid].SupportDescription = pi.SupportDescription
  929. players[cid].Quality = pi.Quality
  930. players[cid].URL = pi.Url
  931. players[cid].VideoCodecid = pi.VideoCodecid
  932. players[cid].VideoProject = pi.VideoProject
  933. players[cid].Fnver = pi.Fnver
  934. players[cid].Fnval = pi.Fnval
  935. players[cid].Dash = pi.Dash
  936. }
  937. }
  938. }
  939. }
  940. var cooperation bool
  941. if (model.IsAndroid(plat) && build > s.c.BuildLimit.CooperationAndroid) || (model.IsIPhone(plat) && build > s.c.BuildLimit.CooperationIOS) {
  942. cooperation = true
  943. }
  944. for _, rec := range recData {
  945. r := &view.Relate{AvFeature: rec.AvFeature, Source: rec.Source, TrackID: rec.TrackID}
  946. switch rec.Goto {
  947. case model.GotoAv:
  948. arc, ok := arcm[rec.Oid]
  949. if !ok || s.overseaCheck(archive.BuildArchive3(arc), plat) || !arc.IsNormal() {
  950. continue
  951. }
  952. if rec.IsDalao == 1 {
  953. r.FromOperate(rec, arc, nil, nil, model.FromOperation, cooperation)
  954. } else {
  955. r.FromAv(arc, "", rec.TrackID, players[arc.FirstCid], cooperation)
  956. }
  957. case model.GotoBangumi:
  958. ban, ok := banm[int32(rec.Oid)]
  959. if !ok {
  960. continue
  961. }
  962. r.FromBangumi(ban)
  963. case model.GotoGame:
  964. if gameInfo == nil || !gameInfo.IsOnline {
  965. continue
  966. }
  967. r.FromOperate(rec, nil, gameInfo, nil, model.FromOperation, cooperation)
  968. case model.GotoSpecial:
  969. sp, ok := s.specialCache[specialID]
  970. if !ok {
  971. continue
  972. }
  973. r.FromOperate(rec, nil, nil, sp, model.FromOperation, cooperation)
  974. }
  975. if rec.IsDalao == 1 {
  976. hasDalao = 1
  977. }
  978. rls = append(rls, r)
  979. }
  980. return
  981. }