contribute.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. package space
  2. import (
  3. "context"
  4. "sort"
  5. "time"
  6. "go-common/app/interface/main/app-interface/model"
  7. "go-common/app/interface/main/app-interface/model/audio"
  8. "go-common/app/interface/main/app-interface/model/bplus"
  9. "go-common/app/interface/main/app-interface/model/space"
  10. article "go-common/app/interface/openplatform/article/model"
  11. "go-common/app/service/main/archive/api"
  12. "go-common/library/log"
  13. "go-common/library/sync/errgroup"
  14. xtime "go-common/library/time"
  15. )
  16. const (
  17. _androidAudio = 516009
  18. _iosAudio = 6160
  19. )
  20. // Contribute func
  21. func (s *Service) Contribute(c context.Context, plat int8, build int, vmid int64, pn, ps int, now time.Time) (res *space.Contributes, err error) {
  22. var (
  23. attrs *space.Attrs
  24. items []*space.Item
  25. )
  26. if pn == 1 {
  27. var (
  28. ctime xtime.Time
  29. cached bool
  30. )
  31. size := ps
  32. if items, err = s.bplusDao.RangeContributeCache(c, vmid, pn, ps); err != nil {
  33. log.Error("%+v", err)
  34. } else if len(items) != 0 {
  35. ctime = items[0].CTime
  36. } else {
  37. size = 100
  38. cached = true
  39. }
  40. if res, err = s.firstContribute(c, vmid, size, now); err != nil {
  41. log.Error("%+v", err)
  42. err = nil
  43. }
  44. if res != nil && len(res.Items) != 0 {
  45. if res.Items[0].CTime > ctime {
  46. if err = s.bplusDao.NotifyContribute(c, vmid, nil, ctime); err != nil {
  47. log.Error("%+v", err)
  48. err = nil
  49. }
  50. }
  51. if cached {
  52. ris := res.Items
  53. s.addCache(func() {
  54. s.bplusDao.AddContributeCache(context.Background(), vmid, nil, ris)
  55. })
  56. }
  57. if len(items) == 0 {
  58. ris := make([]*space.Item, 0, ps)
  59. for _, item := range res.Items {
  60. item.FormatKey()
  61. switch item.Goto {
  62. case model.GotoAudio:
  63. if (plat == model.PlatAndroid && build > _androidAudio) || (plat == model.PlatIPhone && build > _iosAudio) || plat == model.PlatAndroidB {
  64. ris = append(ris, item)
  65. }
  66. default:
  67. ris = append(ris, item)
  68. }
  69. if len(ris) == ps {
  70. break
  71. }
  72. }
  73. res.Items = ris
  74. return
  75. }
  76. }
  77. } else {
  78. if items, err = s.bplusDao.RangeContributeCache(c, vmid, pn, ps); err != nil {
  79. return
  80. }
  81. }
  82. if len(items) != 0 {
  83. if attrs, err = s.bplusDao.AttrCache(c, vmid); err != nil {
  84. log.Error("%+v", err)
  85. }
  86. // merge res
  87. if res, err = s.dealContribute(c, plat, build, vmid, attrs, items, now); err != nil {
  88. log.Error("%+v", err)
  89. }
  90. }
  91. if res == nil {
  92. res = &space.Contributes{Tab: &space.Tab{}, Items: []*space.Item{}, Links: &space.Links{}}
  93. }
  94. return
  95. }
  96. // Contribution func
  97. func (s *Service) Contribution(c context.Context, plat int8, build int, vmid int64, cursor *model.Cursor, now time.Time) (res *space.Contributes, err error) {
  98. var (
  99. attrs *space.Attrs
  100. items []*space.Item
  101. )
  102. if cursor.Latest() {
  103. var (
  104. ctime xtime.Time
  105. cached bool
  106. )
  107. size := cursor.Size
  108. if items, err = s.bplusDao.RangeContributeCache(c, vmid, 1, 1); err != nil {
  109. log.Error("%+v", err)
  110. } else if len(items) != 0 {
  111. ctime = items[0].CTime
  112. } else {
  113. size = 100
  114. cached = true
  115. }
  116. if res, err = s.firstContribute(c, vmid, size, now); err != nil {
  117. log.Error("%+v", err)
  118. }
  119. if res != nil && len(res.Items) != 0 {
  120. if cached {
  121. ris := res.Items
  122. s.addCache(func() {
  123. s.bplusDao.AddContributeCache(context.Background(), vmid, nil, ris)
  124. })
  125. }
  126. if res.Items[0].CTime > ctime {
  127. if len(items) != 0 {
  128. if attrs, err = s.bplusDao.AttrCache(c, vmid); err != nil {
  129. log.Error("%+v", err)
  130. }
  131. }
  132. if err = s.bplusDao.NotifyContribute(c, vmid, attrs, ctime); err != nil {
  133. log.Error("%+v", err)
  134. err = nil
  135. }
  136. }
  137. ris := make([]*space.Item, 0, cursor.Size)
  138. for _, item := range res.Items {
  139. item.FormatKey()
  140. ris = append(ris, item)
  141. if len(ris) == cursor.Size {
  142. break
  143. }
  144. }
  145. if len(ris) != 0 {
  146. res.Items = ris
  147. res.Links.Link(0, int64(ris[len(ris)-1].Member))
  148. }
  149. return
  150. }
  151. }
  152. if items, err = s.bplusDao.RangeContributionCache(c, vmid, cursor); err != nil {
  153. return
  154. }
  155. if len(items) != 0 {
  156. if attrs, err = s.bplusDao.AttrCache(c, vmid); err != nil {
  157. log.Error("%+v", err)
  158. }
  159. // merge res
  160. if res, err = s.dealContribute(c, plat, build, vmid, attrs, items, now); err != nil {
  161. log.Error("%+v", err)
  162. }
  163. }
  164. if res == nil {
  165. res = &space.Contributes{Tab: &space.Tab{}, Items: []*space.Item{}, Links: &space.Links{}}
  166. }
  167. return
  168. }
  169. func (s *Service) firstContribute(c context.Context, vmid int64, size int, now time.Time) (res *space.Contributes, err error) {
  170. res = &space.Contributes{Tab: &space.Tab{}, Items: []*space.Item{}, Links: &space.Links{}}
  171. g, ctx := errgroup.WithContext(c)
  172. var arcItem, artItem, clipItem, albumItem, audioItem, items []*space.Item
  173. g.Go(func() (err error) {
  174. var arcs []*api.Arc
  175. if arcs, err = s.arcDao.UpArcs3(ctx, vmid, 1, size); err != nil {
  176. log.Error("s.arcDao.UpArcs3(%d,%d,%d) error(%v)", vmid, 1, size, err)
  177. err = nil
  178. return
  179. }
  180. if len(arcs) != 0 {
  181. arcItem = make([]*space.Item, 0, len(arcs))
  182. for _, v := range arcs {
  183. if v.IsNormal() {
  184. si := &space.Item{}
  185. si.FromArc3(v)
  186. arcItem = append(arcItem, si)
  187. }
  188. }
  189. }
  190. return
  191. })
  192. g.Go(func() (err error) {
  193. var arts []*article.Meta
  194. if arts, _, err = s.artDao.UpArticles(ctx, vmid, 1, size); err != nil {
  195. log.Error("s.artDao.UpArticles(%d,%d,%d) error(%v)", vmid, 1, size, err)
  196. err = nil
  197. return
  198. }
  199. if len(arts) != 0 {
  200. artItem = make([]*space.Item, 0, len(arts))
  201. for _, v := range arts {
  202. if v.AttrVal(article.AttrBitNoDistribute) {
  203. continue
  204. }
  205. si := &space.Item{}
  206. si.FromArticle(v)
  207. artItem = append(artItem, si)
  208. }
  209. }
  210. return
  211. })
  212. g.Go(func() (err error) {
  213. var clips []*bplus.Clip
  214. if clips, _, err = s.bplusDao.AllClip(c, vmid, size); err != nil {
  215. log.Error("s.bplusDao.AllClip(%d,%d) error(%v)", vmid, size, err)
  216. err = nil
  217. return
  218. }
  219. if len(clips) != 0 {
  220. clipItem = make([]*space.Item, 0, len(clips))
  221. for _, v := range clips {
  222. si := &space.Item{}
  223. si.FromClip(v)
  224. clipItem = append(clipItem, si)
  225. }
  226. }
  227. return
  228. })
  229. g.Go(func() (err error) {
  230. var album []*bplus.Album
  231. if album, _, err = s.bplusDao.AllAlbum(c, vmid, size); err != nil {
  232. log.Error("s.bplusDao.AllAlbum(%d,%d) error(%v)", vmid, size, err)
  233. err = nil
  234. return
  235. }
  236. if len(album) != 0 {
  237. albumItem = make([]*space.Item, 0, len(album))
  238. for _, v := range album {
  239. si := &space.Item{}
  240. si.FromAlbum(v)
  241. albumItem = append(albumItem, si)
  242. }
  243. }
  244. return
  245. })
  246. g.Go(func() (err error) {
  247. var audio []*audio.Audio
  248. if audio, err = s.audioDao.AllAudio(c, vmid); err != nil {
  249. log.Error("s.audioDao.AllAudio(%d) error(%v)", vmid, err)
  250. err = nil
  251. return
  252. }
  253. if len(audio) != 0 {
  254. audioItem = make([]*space.Item, 0, len(audio))
  255. for _, v := range audio {
  256. si := &space.Item{}
  257. si.FromAudio(v)
  258. audioItem = append(audioItem, si)
  259. }
  260. }
  261. return
  262. })
  263. if err = g.Wait(); err != nil {
  264. log.Error("Contribute errgroup.WithContext error(%v)", err)
  265. }
  266. items = make([]*space.Item, 0, len(arcItem)+len(artItem)+len(clipItem)+len(albumItem)+len(audioItem))
  267. if len(arcItem) != 0 {
  268. res.Tab.Archive = true
  269. items = append(items, arcItem...)
  270. }
  271. if len(artItem) != 0 {
  272. res.Tab.Article = true
  273. items = append(items, artItem...)
  274. }
  275. if len(clipItem) != 0 {
  276. res.Tab.Clip = true
  277. items = append(items, clipItem...)
  278. }
  279. if len(albumItem) != 0 {
  280. res.Tab.Album = true
  281. items = append(items, albumItem...)
  282. }
  283. if len(audioItem) != 0 {
  284. res.Tab.Audios = true
  285. items = append(items, audioItem...)
  286. }
  287. sort.Sort(space.Items(items))
  288. res.Items = items
  289. return
  290. }
  291. func (s *Service) dealContribute(c context.Context, plat int8, build int, vmid int64, attrs *space.Attrs, items []*space.Item, now time.Time) (res *space.Contributes, err error) {
  292. res = &space.Contributes{Tab: &space.Tab{}, Items: []*space.Item{}, Links: &space.Links{}}
  293. var aids, cvids, clids, alids, auids []int64
  294. if attrs == nil {
  295. attrs = &space.Attrs{}
  296. } else if !((plat == model.PlatAndroid && build > _androidAudio) || (plat == model.PlatIPhone && build > _iosAudio) || plat == model.PlatAndroidB) {
  297. attrs.Audio = false
  298. }
  299. for _, item := range items {
  300. if item.ID == 0 {
  301. continue
  302. }
  303. switch item.Goto {
  304. case model.GotoAv:
  305. aids = append(aids, item.ID)
  306. case model.GotoArticle:
  307. cvids = append(cvids, item.ID)
  308. case model.GotoClip:
  309. clids = append(clids, item.ID)
  310. case model.GotoAlbum:
  311. alids = append(alids, item.ID)
  312. case model.GotoAudio:
  313. if (plat == model.PlatAndroid && build > _androidAudio) || (plat == model.PlatIPhone && build > _iosAudio) || plat == model.PlatAndroidB {
  314. auids = append(auids, item.ID)
  315. }
  316. }
  317. }
  318. var (
  319. am map[int64]*api.Arc
  320. atm map[int64]*article.Meta
  321. clm map[int64]*bplus.Clip
  322. alm map[int64]*bplus.Album
  323. aum map[int64]*audio.Audio
  324. )
  325. g, ctx := errgroup.WithContext(c)
  326. if len(aids) != 0 {
  327. g.Go(func() (err error) {
  328. if am, err = s.arcDao.Archives2(ctx, aids); err != nil {
  329. log.Error("s.arcDao.Archives(%v) error(%v)", aids, err)
  330. err = nil
  331. }
  332. return
  333. })
  334. }
  335. if len(cvids) != 0 {
  336. g.Go(func() (err error) {
  337. if atm, err = s.artDao.Articles(ctx, cvids); err != nil {
  338. log.Error("s.artDao.Articles(%v) error(%v)", cvids, err)
  339. err = nil
  340. }
  341. return
  342. })
  343. }
  344. if len(clids) != 0 {
  345. g.Go(func() (err error) {
  346. if clm, err = s.bplusDao.ClipDetail(ctx, clids); err != nil {
  347. log.Error("s.bplusDao.ClipDetail(%v) error(%v)", clids, err)
  348. err = nil
  349. }
  350. return
  351. })
  352. }
  353. if len(alids) != 0 {
  354. g.Go(func() (err error) {
  355. if alm, err = s.bplusDao.AlbumDetail(ctx, vmid, alids); err != nil {
  356. log.Error("s.bplusDao.AlbumDetail(%v) error(%v)", alids, err)
  357. err = nil
  358. }
  359. return
  360. })
  361. }
  362. if len(auids) != 0 {
  363. g.Go(func() (err error) {
  364. if aum, err = s.audioDao.AudioDetail(c, auids); err != nil {
  365. log.Error("s.audioDao.AudioDetail(%v) error(%v)", auids, err)
  366. err = nil
  367. }
  368. return
  369. })
  370. }
  371. if err = g.Wait(); err != nil {
  372. log.Error("Contribute errgroup.WithContext error(%v)", err)
  373. return
  374. }
  375. if len(am) != 0 || attrs.Archive {
  376. res.Tab.Archive = true
  377. }
  378. if len(atm) != 0 || attrs.Article {
  379. res.Tab.Article = true
  380. }
  381. if len(clm) != 0 || attrs.Clip {
  382. res.Tab.Clip = true
  383. }
  384. if len(alm) != 0 || attrs.Album {
  385. res.Tab.Album = true
  386. }
  387. if len(aum) != 0 || attrs.Audio {
  388. res.Tab.Audios = true
  389. }
  390. ris := make([]*space.Item, 0, len(items))
  391. for _, item := range items {
  392. ri := &space.Item{}
  393. switch item.Goto {
  394. case model.GotoAv:
  395. if a, ok := am[item.ID]; ok && a.IsNormal() {
  396. ri.FromArc3(a)
  397. }
  398. case model.GotoArticle:
  399. if at, ok := atm[item.ID]; ok {
  400. ri.FromArticle(at)
  401. }
  402. case model.GotoClip:
  403. if cl, ok := clm[item.ID]; ok {
  404. ri.FromClip(cl)
  405. }
  406. case model.GotoAlbum:
  407. if al, ok := alm[item.ID]; ok {
  408. ri.FromAlbum(al)
  409. }
  410. case model.GotoAudio:
  411. if au, ok := aum[item.ID]; ok {
  412. ri.FromAudio(au)
  413. }
  414. }
  415. if ri.Goto != "" {
  416. ri.FormatKey()
  417. ris = append(ris, ri)
  418. }
  419. }
  420. res.Items = ris
  421. res.Links.Link(int64(items[0].Member), int64(items[len(items)-1].Member))
  422. return
  423. }
  424. // Clip func
  425. func (s *Service) Clip(c context.Context, vmid int64, pos, size int) (res *space.ClipList) {
  426. var (
  427. clips []*bplus.Clip
  428. err error
  429. )
  430. res = &space.ClipList{Item: []*space.Item{}}
  431. if clips, res.More, res.Offset, err = s.bplusDao.Clips(c, vmid, pos, size); err != nil {
  432. log.Error("%+v", err)
  433. return
  434. }
  435. if len(clips) > 0 {
  436. res.Item = make([]*space.Item, 0, len(clips))
  437. for _, v := range clips {
  438. si := &space.Item{}
  439. si.FromClip(v)
  440. res.Item = append(res.Item, si)
  441. }
  442. }
  443. return
  444. }
  445. // Album func
  446. func (s *Service) Album(c context.Context, vmid int64, pos, size int) (res *space.AlbumList) {
  447. var (
  448. albums []*bplus.Album
  449. err error
  450. )
  451. res = &space.AlbumList{Item: []*space.Item{}}
  452. if albums, res.More, res.Offset, err = s.bplusDao.Albums(c, vmid, pos, size); err != nil {
  453. log.Error("%+v", err)
  454. return
  455. }
  456. if len(albums) > 0 {
  457. res.Item = make([]*space.Item, 0, len(albums))
  458. for _, v := range albums {
  459. si := &space.Item{}
  460. si.FromAlbum(v)
  461. res.Item = append(res.Item, si)
  462. }
  463. }
  464. return
  465. }
  466. // AddContribute func
  467. func (s *Service) AddContribute(c context.Context, vmid int64, attrs *space.Attrs, items []*space.Item) (err error) {
  468. if err = s.bplusDao.AddContributeCache(c, vmid, attrs, items); err != nil {
  469. log.Error("%+v", err)
  470. }
  471. return
  472. }