toview.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. package service
  2. import (
  3. "context"
  4. "sort"
  5. "time"
  6. "go-common/app/interface/main/history/model"
  7. arcmdl "go-common/app/service/main/archive/model/archive"
  8. "go-common/library/ecode"
  9. "go-common/library/log"
  10. )
  11. const maxToView = 100
  12. var (
  13. _empToView = []*model.ToView{}
  14. _empArcToView = []*model.ArcToView{}
  15. _empWebArcToView = []*model.WebArcToView{}
  16. )
  17. // AddToView add the user a toview item.
  18. // +wd:ignore
  19. func (s *Service) AddToView(c context.Context, mid, aid int64, ip string) (err error) {
  20. var (
  21. ok bool
  22. count int
  23. arc *arcmdl.View3
  24. now = time.Now().Unix()
  25. )
  26. arcAid := &arcmdl.ArgAid2{Aid: aid}
  27. if arc, err = s.arcRPC.View3(c, arcAid); err != nil {
  28. return
  29. }
  30. if arc == nil {
  31. return
  32. }
  33. if arc.Rights.UGCPay == 1 {
  34. return ecode.ToViewPayUGC
  35. }
  36. if ok, err = s.toviewDao.Expire(c, mid); err != nil {
  37. return
  38. }
  39. if ok {
  40. if count, err = s.toviewDao.CntCache(c, mid); err != nil {
  41. return
  42. }
  43. } else {
  44. if _, count, err = s.toView(c, mid, 1, maxToView, ip); err != nil {
  45. return
  46. }
  47. }
  48. if count >= maxToView {
  49. err = ecode.ToViewOverMax
  50. return
  51. }
  52. if err = s.toviewDao.Add(c, mid, aid, now); err != nil {
  53. return
  54. }
  55. s.toviewCache.Do(c, func(ctx context.Context) {
  56. if errCache := s.toviewDao.AddCache(ctx, mid, aid, now); errCache != nil {
  57. log.Warn("s.toviewDao.AddCache(%d,%d,%d) err:%v", mid, aid, now, errCache)
  58. }
  59. })
  60. return
  61. }
  62. // AddMultiToView add toview items to user.
  63. // +wd:ignore
  64. func (s *Service) AddMultiToView(c context.Context, mid int64, aids []int64, ip string) (err error) {
  65. var (
  66. ok bool
  67. count int
  68. expectedAids []int64
  69. arcs map[int64]*arcmdl.View3
  70. viewMap map[int64]*model.ToView
  71. views []*model.ToView
  72. now = time.Now().Unix()
  73. )
  74. arcAids := &arcmdl.ArgAids2{Aids: aids}
  75. if arcs, err = s.arcRPC.Views3(c, arcAids); err != nil {
  76. return
  77. } else if len(arcs) == 0 {
  78. return
  79. }
  80. for _, v := range arcs {
  81. if v.Rights.UGCPay == 1 {
  82. return ecode.ToViewPayUGC
  83. }
  84. }
  85. if ok, err = s.toviewDao.Expire(c, mid); err != nil {
  86. return
  87. }
  88. if ok {
  89. if viewMap, err = s.toviewDao.CacheMap(c, mid); err != nil {
  90. return
  91. }
  92. } else {
  93. var list []*model.ToView
  94. list, _, err = s.toView(c, mid, 1, maxToView, ip)
  95. if err != nil {
  96. return
  97. }
  98. viewMap = make(map[int64]*model.ToView)
  99. for _, v := range list {
  100. if v == nil {
  101. continue
  102. }
  103. viewMap[v.Aid] = v
  104. }
  105. }
  106. count = len(viewMap)
  107. if count >= maxToView {
  108. err = ecode.ToViewOverMax
  109. return
  110. }
  111. expectedLen := maxToView - count
  112. for _, aid := range aids {
  113. if _, exist := viewMap[aid]; !exist {
  114. expectedAids = append(expectedAids, aid)
  115. expectedLen--
  116. if expectedLen == 0 {
  117. break
  118. }
  119. }
  120. }
  121. if err = s.toviewDao.Adds(c, mid, expectedAids, now); err != nil {
  122. return
  123. }
  124. if ok {
  125. s.toviewCache.Do(c, func(ctx context.Context) {
  126. for _, aid := range expectedAids {
  127. views = append(views, &model.ToView{Aid: aid, Unix: now})
  128. }
  129. if errCache := s.toviewDao.AddCacheList(ctx, mid, views); errCache != nil {
  130. log.Warn("s.toviewDao.AddCacheList(%d,%v) err:%v", mid, views, errCache)
  131. }
  132. })
  133. }
  134. return
  135. }
  136. // RemainingToView add toview items to user.
  137. // +wd:ignore
  138. func (s *Service) RemainingToView(c context.Context, mid int64, ip string) (remaining int, err error) {
  139. var (
  140. count int
  141. )
  142. if _, count, err = s.toView(c, mid, 1, maxToView, ip); err != nil {
  143. return
  144. }
  145. remaining = maxToView - count
  146. return
  147. }
  148. // ClearToView clear the user toview items.
  149. // +wd:ignore
  150. func (s *Service) ClearToView(c context.Context, mid int64) (err error) {
  151. if err = s.toviewDao.ClearCache(c, mid); err != nil {
  152. return
  153. }
  154. s.userActionLog(mid, model.ToviewClear)
  155. return s.toviewDao.Clear(c, mid)
  156. }
  157. // DelToView delete the user to videos.
  158. // +wd:ignore
  159. func (s *Service) DelToView(c context.Context, mid int64, aids []int64, viewed bool, ip string) (err error) {
  160. var (
  161. delAids []int64
  162. list []*model.ToView
  163. rhs, hs map[int64]*model.History
  164. rs *model.History
  165. )
  166. // viewed del all viewed
  167. if viewed {
  168. if list, _, err = s.toView(c, mid, 1, maxToView, ip); err != nil {
  169. return
  170. }
  171. for _, l := range list {
  172. aids = append(aids, l.Aid)
  173. }
  174. if len(aids) == 0 {
  175. return
  176. }
  177. if hs, err = s.historyDao.AidsMap(c, mid, aids); err != nil {
  178. return
  179. }
  180. rhs, _ = s.historyDao.CacheMap(c, mid)
  181. for _, rs = range rhs {
  182. hs[rs.Aid] = rs
  183. }
  184. for k, v := range hs {
  185. if v.Pro >= 30 || v.Pro == -1 {
  186. delAids = append(delAids, k)
  187. }
  188. }
  189. if len(delAids) == 0 {
  190. return
  191. }
  192. if err = s.toviewDao.Del(c, mid, delAids); err != nil {
  193. return
  194. }
  195. s.toviewCache.Do(c, func(ctx context.Context) {
  196. s.toviewDao.DelCaches(ctx, mid, delAids)
  197. })
  198. return
  199. }
  200. if err = s.toviewDao.Del(c, mid, aids); err != nil {
  201. return
  202. }
  203. s.toviewCache.Do(c, func(ctx context.Context) {
  204. s.toviewDao.DelCaches(ctx, mid, aids)
  205. })
  206. return
  207. }
  208. // WebToView get videos of user view history.
  209. // +wd:ignore
  210. func (s *Service) WebToView(c context.Context, mid int64, pn, ps int, ip string) (res []*model.WebArcToView, count int, err error) {
  211. var (
  212. ok bool
  213. aids, epids []int64
  214. avs map[int64]*arcmdl.View3
  215. views []*model.ToView
  216. v *model.ToView
  217. hm map[int64]*model.History
  218. av *arcmdl.View3
  219. epban = make(map[int64]*model.Bangumi)
  220. seasonMap = make(map[int64]*model.BangumiSeason)
  221. )
  222. if views, count, err = s.toView(c, mid, pn, ps, ip); err != nil {
  223. return
  224. }
  225. if len(views) == 0 {
  226. return
  227. }
  228. for _, v = range views {
  229. if v != nil {
  230. aids = append(aids, v.Aid)
  231. }
  232. }
  233. argAids := &arcmdl.ArgAids2{Aids: aids}
  234. if avs, err = s.arcRPC.Views3(c, argAids); err != nil {
  235. log.Error("s.arcRPC.Views3(arcAids:(%v), arcs) error(%v)", aids, err)
  236. return
  237. }
  238. if len(avs) == 0 {
  239. return
  240. }
  241. seasonMap, epids = s.season(c, mid, aids, ip)
  242. // bangumi info
  243. if len(epids) > 0 {
  244. epban = s.bangumi(c, mid, epids)
  245. }
  246. if hm, err = s.toViewPro(c, mid, aids); err != nil {
  247. err = nil
  248. }
  249. res = make([]*model.WebArcToView, 0, len(aids))
  250. for _, v = range views {
  251. if v == nil {
  252. count--
  253. continue
  254. }
  255. // NOTE compat android
  256. if av, ok = avs[v.Aid]; !ok || av == nil {
  257. count--
  258. continue
  259. }
  260. // NOTE all no pay
  261. av.Rights.Movie = 0
  262. at := &model.WebArcToView{View3: av}
  263. at.AddTime = v.Unix
  264. if hm[v.Aid] != nil {
  265. at.Cid = hm[v.Aid].Cid
  266. at.Progress = hm[v.Aid].Pro
  267. }
  268. if season, ok := seasonMap[v.Aid]; ok && season != nil {
  269. if bangumi, ok := epban[season.Epid]; ok && bangumi != nil {
  270. at.BangumiInfo = bangumi
  271. }
  272. }
  273. res = append(res, at)
  274. }
  275. if len(res) == 0 {
  276. res = _empWebArcToView
  277. }
  278. return
  279. }
  280. // ToView get videos of user view history.
  281. // +wd:ignore
  282. func (s *Service) ToView(c context.Context, mid int64, pn, ps int, ip string) (res []*model.ArcToView, count int, err error) {
  283. var (
  284. ok bool
  285. aids []int64
  286. avs map[int64]*arcmdl.View3
  287. views []*model.ToView
  288. v *model.ToView
  289. hm map[int64]*model.History
  290. av *arcmdl.View3
  291. )
  292. res = _empArcToView
  293. if views, count, err = s.toView(c, mid, pn, ps, ip); err != nil {
  294. return
  295. }
  296. if len(views) == 0 {
  297. return
  298. }
  299. for _, v = range views {
  300. if v != nil {
  301. aids = append(aids, v.Aid)
  302. }
  303. }
  304. argAids := &arcmdl.ArgAids2{Aids: aids}
  305. if avs, err = s.arcRPC.Views3(c, argAids); err != nil {
  306. log.Error("s.arcRPC.Views3(%v) error(%v)", aids, err)
  307. return
  308. }
  309. if len(avs) == 0 {
  310. return
  311. }
  312. if hm, err = s.toViewPro(c, mid, aids); err != nil {
  313. err = nil
  314. }
  315. res = make([]*model.ArcToView, 0, len(aids))
  316. for _, v = range views {
  317. if v == nil {
  318. count--
  319. continue
  320. }
  321. // NOTE compat android
  322. if av, ok = avs[v.Aid]; !ok || av.Archive3 == nil {
  323. count--
  324. continue
  325. }
  326. // NOTE all no pay
  327. av.Rights.Movie = 0
  328. at := &model.ArcToView{
  329. Archive3: av.Archive3,
  330. Count: len(av.Pages),
  331. }
  332. at.AddTime = v.Unix
  333. // get cid and progress
  334. if hm[v.Aid] != nil {
  335. at.Cid = hm[v.Aid].Cid
  336. at.Progress = hm[v.Aid].Pro
  337. }
  338. for n, p := range av.Pages {
  339. if p.Cid == at.Cid {
  340. p.Page = int32(n + 1)
  341. at.Page = p
  342. break
  343. }
  344. }
  345. res = append(res, at)
  346. }
  347. return
  348. }
  349. // toView return ToSee of After the paging data.
  350. func (s *Service) toView(c context.Context, mid int64, pn, ps int, ip string) (res []*model.ToView, count int, err error) {
  351. var (
  352. ok bool
  353. start = (pn - 1) * ps
  354. end = start + ps - 1
  355. )
  356. if ok, err = s.toviewDao.Expire(c, mid); err != nil {
  357. return
  358. }
  359. if ok {
  360. if end > maxToView {
  361. end = maxToView
  362. }
  363. if res, err = s.toviewDao.Cache(c, mid, start, end); err != nil {
  364. return
  365. }
  366. count, err = s.toviewDao.CntCache(c, mid)
  367. if count > maxToView {
  368. count = maxToView
  369. }
  370. return
  371. }
  372. var views []*model.ToView
  373. var viewMap = make(map[int64]*model.ToView)
  374. if viewMap, err = s.toviewDao.MapInfo(c, mid, nil); err != nil {
  375. return
  376. }
  377. if len(viewMap) == 0 {
  378. res = _empToView
  379. return
  380. }
  381. for _, v := range viewMap {
  382. views = append(views, v)
  383. }
  384. sort.Sort(model.ToViews(views))
  385. if count = len(views); count > maxToView {
  386. count = maxToView
  387. views = views[:count]
  388. }
  389. switch {
  390. case count > start && count > end:
  391. res = views[start : end+1]
  392. case count > start && count <= end:
  393. res = views[start:]
  394. default:
  395. res = _empToView
  396. }
  397. s.toviewCache.Do(c, func(ctx context.Context) {
  398. if errCache := s.toviewDao.AddCacheList(ctx, mid, views); errCache != nil {
  399. log.Warn("s.toviewDao.AddCacheList(%d,%v) err:%v", mid, views, errCache)
  400. }
  401. })
  402. return
  403. }
  404. func (s *Service) toViewPro(c context.Context, mid int64, aids []int64) (res map[int64]*model.History, err error) {
  405. var (
  406. miss []int64
  407. hm map[int64]*model.History
  408. )
  409. if res, miss, err = s.historyDao.Cache(c, mid, aids); err != nil {
  410. err = nil
  411. } else if len(res) == len(aids) {
  412. return
  413. }
  414. if len(res) == 0 {
  415. res = make(map[int64]*model.History)
  416. miss = aids
  417. }
  418. if hm, err = s.historyDao.AidsMap(c, mid, miss); err != nil {
  419. err = nil
  420. }
  421. for k, v := range hm {
  422. res[k] = v
  423. }
  424. return
  425. }
  426. func (s *Service) season(c context.Context, mid int64, aids []int64, ip string) (seasonMap map[int64]*model.BangumiSeason, epids []int64) {
  427. var (
  428. n = 50
  429. seasonM = make(map[int64]*model.BangumiSeason, n)
  430. )
  431. seasonMap = make(map[int64]*model.BangumiSeason, n)
  432. for len(aids) > 0 {
  433. if n > len(aids) {
  434. n = len(aids)
  435. }
  436. seasonM, _ = s.historyDao.BangumisByAids(c, mid, aids[:n], ip)
  437. aids = aids[n:]
  438. for k, v := range seasonM {
  439. epids = append(epids, v.Epid)
  440. seasonMap[k] = v
  441. }
  442. }
  443. return
  444. }
  445. // ManagerToView manager get mid toview list.
  446. // +wd:ignore
  447. func (s *Service) ManagerToView(c context.Context, mid int64, ip string) ([]*model.ToView, error) {
  448. return s.toviewDao.ListInfo(c, mid, nil)
  449. }