favorite.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. package service
  2. import (
  3. "context"
  4. "sort"
  5. "strconv"
  6. "time"
  7. "go-common/app/interface/main/playlist/dao"
  8. "go-common/app/interface/main/playlist/model"
  9. accwarden "go-common/app/service/main/account/api"
  10. arcmdl "go-common/app/service/main/archive/api"
  11. favmdl "go-common/app/service/main/favorite/model"
  12. "go-common/library/ecode"
  13. "go-common/library/log"
  14. "go-common/library/net/metadata"
  15. xtime "go-common/library/time"
  16. )
  17. const (
  18. _first = 1
  19. _sortDefault = 0
  20. _sortByMTime = 1
  21. _sortByView = 2
  22. )
  23. var _empPlaylists = make([]*model.Playlist, 0)
  24. // White playlist white list.
  25. func (s *Service) White(c context.Context, mid int64) (res map[string]bool, err error) {
  26. _, power := s.allowMids[mid]
  27. res = make(map[string]bool, 1)
  28. res["power"] = power
  29. return
  30. }
  31. // Add add playlist.
  32. func (s *Service) Add(c context.Context, mid int64, public int8, name, description, cover, cookie, accessKey string) (pid int64, err error) {
  33. var (
  34. fid int64
  35. ts = time.Now()
  36. ip = metadata.String(c, metadata.RemoteIP)
  37. )
  38. if _, ok := s.allowMids[mid]; !ok {
  39. err = ecode.PlDenied
  40. return
  41. }
  42. arg := &favmdl.ArgAddFolder{Type: favmdl.TypePlayVideo, Mid: mid, Name: name, Description: description, Cover: cover, Public: public, Cookie: cookie, AccessKey: accessKey, RealIP: ip}
  43. if fid, err = s.fav.AddFolder(c, arg); err != nil {
  44. dao.PromError("添加播单rpc错误", "s.fav.AddFolder(%v) error(%v)", arg, err)
  45. return
  46. }
  47. if pid, err = s.dao.Add(c, mid, fid); err != nil {
  48. log.Error("s.dao.Add(%d,%d) error(%v)", mid, fid, err)
  49. } else if pid > 0 {
  50. s.cache.Save(func() {
  51. stat := &model.PlStat{ID: pid, Mid: mid, Fid: fid, MTime: xtime.Time(ts.Unix())}
  52. s.dao.SetPlStatCache(context.Background(), mid, pid, stat)
  53. })
  54. if err = s.dao.RegReply(c, pid, mid); err != nil {
  55. err = nil
  56. }
  57. }
  58. return
  59. }
  60. // Del delete playlist.
  61. func (s *Service) Del(c context.Context, mid, pid int64) (err error) {
  62. var (
  63. affected int64
  64. stat *model.PlStat
  65. ip = metadata.String(c, metadata.RemoteIP)
  66. )
  67. if stat, err = s.plByPid(c, pid); err != nil {
  68. log.Error("s.plByPid(%d,%d) error(%v)", mid, pid, err)
  69. return
  70. }
  71. arg := &favmdl.ArgDelFolder{Type: favmdl.TypePlayVideo, Mid: mid, Fid: stat.Fid, RealIP: ip}
  72. if err = s.fav.DelFolder(c, arg); err != nil {
  73. dao.PromError("删除播单rpc错误", "s.fav.DelFolder(%+v) error(%v)", arg, err)
  74. return
  75. }
  76. if affected, err = s.dao.Del(c, pid); err != nil {
  77. log.Error("s.dao.Del(%d) error(%v)", pid, err)
  78. return
  79. } else if affected > 0 {
  80. s.dao.DelPlCache(c, mid, pid)
  81. }
  82. return
  83. }
  84. // Update update playlist.
  85. func (s *Service) Update(c context.Context, mid, pid int64, public int8, name, description, cover, cookie, accessKey string) (err error) {
  86. var (
  87. stat *model.PlStat
  88. ip = metadata.String(c, metadata.RemoteIP)
  89. )
  90. if stat, err = s.plByPid(c, pid); err != nil {
  91. log.Error("s.plByPid(%d) error(%v)", pid, err)
  92. return
  93. }
  94. arg := &favmdl.ArgUpdateFolder{Type: favmdl.TypePlayVideo, Fid: stat.Fid, Mid: mid, Name: name, Description: description, Cover: cover, Public: public, Cookie: cookie, AccessKey: accessKey, RealIP: ip}
  95. if err = s.fav.UpdateFolder(c, arg); err != nil {
  96. dao.PromError("更新播单rpc错误", "s.fav.UpdateFolder(%+v) error(%v)", arg, err)
  97. return
  98. }
  99. s.updatePlTime(c, mid, pid)
  100. return
  101. }
  102. func (s *Service) updatePlTime(c context.Context, mid, pid int64) (err error) {
  103. var (
  104. affected int64
  105. ts = time.Now()
  106. stat *model.PlStat
  107. )
  108. if affected, err = s.dao.Update(c, pid); err != nil {
  109. err = nil
  110. log.Error("s.dao.Update(%d) error(%v)", pid, err)
  111. return
  112. } else if affected > 0 {
  113. s.cache.Save(func() {
  114. if stat, err = s.plByPid(context.Background(), pid); err != nil {
  115. err = nil
  116. } else {
  117. stat.MTime = xtime.Time(ts.Unix())
  118. s.dao.SetPlStatCache(context.Background(), mid, pid, stat)
  119. }
  120. })
  121. }
  122. return
  123. }
  124. // Info playlist stat info.
  125. func (s *Service) Info(c context.Context, mid, pid int64) (res *model.Playlist, err error) {
  126. var (
  127. fav *favmdl.Folder
  128. stat *model.PlStat
  129. infoReply *accwarden.InfoReply
  130. isFav bool
  131. ip = metadata.String(c, metadata.RemoteIP)
  132. )
  133. if stat, err = s.plByPid(c, pid); err != nil {
  134. return
  135. }
  136. if stat == nil || stat.ID == 0 {
  137. err = ecode.PlNotExist
  138. dao.PromError("Info:播单不存在", "s.plByPid(%d) error(%v)", pid, stat)
  139. return
  140. }
  141. arg := &favmdl.ArgFolder{Type: favmdl.TypePlayVideo, Fid: stat.Fid, Mid: stat.Mid, RealIP: ip}
  142. if fav, err = s.fav.Folder(c, arg); err != nil || fav == nil {
  143. dao.PromError("Info Forder:rpc错误", "s.fav.Folder(%+v) error(%v)", arg, err)
  144. return
  145. }
  146. if fav.State == favmdl.StateIsDel {
  147. err = ecode.PlNotExist
  148. dao.PromError("InfoFav:播单不存在", "s.fav.Folder(%d) error(%v)", pid, err)
  149. return
  150. }
  151. // author
  152. if infoReply, err = s.accClient.Info3(c, &accwarden.MidReq{Mid: fav.Mid, RealIp: ip}); err != nil {
  153. dao.PromError("账号Info:grpc错误", "s.accClient.Info3 error(%v)", err)
  154. return
  155. }
  156. if mid > 0 {
  157. if isFav, err = s.fav.IsFav(c, &favmdl.ArgIsFav{Type: favmdl.TypePlayList, Mid: mid, Oid: pid, RealIP: ip}); err != nil {
  158. log.Error("s.fav.IsFav(%d,%d) error(%d)", mid, pid, err)
  159. err = nil
  160. }
  161. }
  162. owner := &arcmdl.Author{Mid: fav.Mid, Name: infoReply.Info.Name, Face: infoReply.Info.Face}
  163. fav.MTime = stat.MTime
  164. res = &model.Playlist{Pid: pid, Folder: fav, Stat: &model.Stat{Pid: stat.ID, View: stat.View, Reply: stat.Reply, Fav: stat.Fav, Share: stat.Share}, Author: owner, IsFavorite: isFav}
  165. return
  166. }
  167. func (s *Service) plInfo(c context.Context, mid, pid int64, ip string) (res *model.PlStat, err error) {
  168. var fav *favmdl.Folder
  169. if res, err = s.plByPid(c, pid); err != nil {
  170. return
  171. }
  172. if res == nil || res.ID == 0 {
  173. err = ecode.PlNotExist
  174. log.Error("s.plByPid(%d) res(%v)", pid, res)
  175. return
  176. }
  177. arg := &favmdl.ArgFolder{Type: favmdl.TypePlayVideo, Fid: res.Fid, Mid: res.Mid, RealIP: ip}
  178. if fav, err = s.fav.Folder(c, arg); err != nil || fav == nil {
  179. log.Error("s.fav.Folder(%+v) error(%v)", arg, err)
  180. return
  181. }
  182. if fav.State == favmdl.StateIsDel {
  183. err = ecode.PlNotExist
  184. log.Error("s.fav.Folder(%d) state(%d)", pid, fav.State)
  185. return
  186. }
  187. if mid > 0 && mid != res.Mid {
  188. err = ecode.PlNotUser
  189. }
  190. return
  191. }
  192. // List playlist.
  193. func (s *Service) List(c context.Context, mid int64, pn, ps, sortType int) (res []*model.Playlist, count int, err error) {
  194. var (
  195. start = (pn - 1) * ps
  196. end = start + ps - 1
  197. plStats []*model.PlStat
  198. ip = metadata.String(c, metadata.RemoteIP)
  199. )
  200. if plStats, err = s.plsByMid(c, mid); err != nil {
  201. return
  202. }
  203. count = len(plStats)
  204. if count == 0 || count < start {
  205. res = _empPlaylists
  206. return
  207. }
  208. switch sortType {
  209. case _sortDefault, _sortByMTime:
  210. sort.Slice(plStats, func(i, j int) bool { return plStats[i].MTime > plStats[j].MTime })
  211. case _sortByView:
  212. sort.Slice(plStats, func(i, j int) bool { return plStats[i].View > plStats[j].View })
  213. }
  214. if count > end {
  215. plStats = plStats[start : end+1]
  216. } else {
  217. plStats = plStats[start:]
  218. }
  219. res, err = s.batchFav(c, mid, plStats, ip)
  220. return
  221. }
  222. //AddFavorite add playlist to favorite.
  223. func (s *Service) AddFavorite(c context.Context, mid, pid int64) (err error) {
  224. ip := metadata.String(c, metadata.RemoteIP)
  225. if _, err = s.Info(c, 0, pid); err != nil {
  226. return
  227. }
  228. arg := &favmdl.ArgAdd{Type: favmdl.TypePlayList, Mid: mid, Oid: pid, Fid: 0, RealIP: ip}
  229. if err = s.fav.Add(c, arg); err != nil {
  230. dao.PromError("rpc:添加播单收藏", "s.fav.Add(%+v) error(%v)", arg, err)
  231. }
  232. return
  233. }
  234. // DelFavorite del playlist from favorite.
  235. func (s *Service) DelFavorite(c context.Context, mid, pid int64) (err error) {
  236. ip := metadata.String(c, metadata.RemoteIP)
  237. arg := &favmdl.ArgDel{Type: favmdl.TypePlayList, Mid: mid, Oid: pid, Fid: 0, RealIP: ip}
  238. if err = s.fav.Del(c, arg); err != nil {
  239. dao.PromError("rpc:删除播单收藏", "s.fav.Del(%+v) error(%v)", arg, err)
  240. }
  241. return
  242. }
  243. //ListFavorite playlist list.
  244. func (s *Service) ListFavorite(c context.Context, mid, vmid int64, pn, ps, sortType int) (res []*model.Playlist, count int, err error) {
  245. var (
  246. plStats []*model.PlStat
  247. favRes *favmdl.Favorites
  248. pids []int64
  249. tmpFavs map[int64]*favmdl.Favorite
  250. tmpRs []*model.Playlist
  251. ip = metadata.String(c, metadata.RemoteIP)
  252. )
  253. arg := &favmdl.ArgFavs{Type: favmdl.TypePlayList, Mid: mid, Vmid: vmid, Fid: 0, Pn: pn, Ps: ps, RealIP: ip}
  254. if favRes, err = s.fav.Favorites(c, arg); err != nil {
  255. dao.PromError("rpc:播单收藏列表", "s.fav.Favorites(%+v) error(%v)", arg, err)
  256. return
  257. }
  258. if favRes == nil || len(favRes.List) == 0 {
  259. res = _empPlaylists
  260. return
  261. }
  262. tmpFavs = make(map[int64]*favmdl.Favorite)
  263. for _, fav := range favRes.List {
  264. pids = append(pids, fav.Oid)
  265. tmpFavs[fav.Oid] = fav
  266. }
  267. if plStats, err = s.plsByPid(c, pids); err != nil {
  268. return
  269. }
  270. count = favRes.Page.Count
  271. tmpRs, err = s.batchFav(c, mid, plStats, ip)
  272. for _, v := range tmpRs {
  273. v.FavoriteTime = tmpFavs[v.Pid].MTime
  274. res = append(res, v)
  275. }
  276. return
  277. }
  278. func (s *Service) batchFav(c context.Context, uid int64, plStats []*model.PlStat, ip string) (res []*model.Playlist, err error) {
  279. var (
  280. fVMids []*favmdl.ArgFVmid
  281. tmpStats map[string]*model.PlStat
  282. favRes []*favmdl.Folder
  283. stat *model.Stat
  284. )
  285. tmpStats = make(map[string]*model.PlStat)
  286. for _, v := range plStats {
  287. statKey := strconv.FormatInt(v.Mid, 10) + "_" + strconv.FormatInt(v.Fid, 10)
  288. tmpStats[statKey] = &model.PlStat{ID: v.ID, Mid: v.Mid, Fid: v.Fid, View: v.View, Reply: v.Reply, Fav: v.Fav, Share: v.Share, MTime: v.MTime}
  289. fVMids = append(fVMids, &favmdl.ArgFVmid{Fid: v.Fid, Vmid: v.Mid})
  290. }
  291. arg := &favmdl.ArgFolders{Type: favmdl.TypePlayVideo, Mid: uid, FVmids: fVMids, RealIP: ip}
  292. if favRes, err = s.fav.Folders(c, arg); err != nil {
  293. dao.PromError("rpc:批量获取播单列表", "s.fav.Folders(%+v) error(%v)", arg, err)
  294. return
  295. }
  296. for _, fav := range favRes {
  297. statKey := strconv.FormatInt(fav.Mid, 10) + "_" + strconv.FormatInt(fav.ID, 10)
  298. plStat := tmpStats[statKey]
  299. stat = &model.Stat{Pid: plStat.ID, View: plStat.View, Fav: plStat.Fav, Reply: plStat.Reply, Share: plStat.Share}
  300. fav.MTime = plStat.MTime
  301. res = append(res, &model.Playlist{Pid: plStat.ID, Folder: fav, Stat: stat})
  302. }
  303. return
  304. }