channel.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. package service
  2. import (
  3. "context"
  4. "sync"
  5. "time"
  6. "go-common/app/interface/main/space/conf"
  7. "go-common/app/interface/main/space/model"
  8. arcmdl "go-common/app/service/main/archive/api"
  9. filmdl "go-common/app/service/main/filter/model/rpc"
  10. "go-common/library/ecode"
  11. "go-common/library/log"
  12. "go-common/library/sync/errgroup"
  13. xtime "go-common/library/time"
  14. )
  15. var (
  16. _emptyChArc = make([]*arcmdl.Arc, 0)
  17. _emptyChList = make([]*model.Channel, 0)
  18. _emptyChDetailList = make([]*model.ChannelDetail, 0)
  19. _nameErrorLevel = int8(20)
  20. _introWarnLevel = int8(20)
  21. _introErrorLevel = int8(30)
  22. )
  23. // ChannelList get channel list.
  24. func (s *Service) ChannelList(c context.Context, mid int64, isGuest bool) (channels []*model.Channel, err error) {
  25. var (
  26. channelExtra map[int64]*model.ChannelExtra
  27. cids []int64
  28. addCache = true
  29. )
  30. if channels, err = s.dao.ChannelListCache(c, mid); err != nil {
  31. addCache = false
  32. } else if len(channels) > 0 {
  33. return
  34. }
  35. if channels, err = s.dao.ChannelList(c, mid); err != nil {
  36. log.Error("s.dao.ChannelList(%d) error(%v)", mid, err)
  37. return
  38. }
  39. if len(channels) == 0 {
  40. channels = _emptyChList
  41. return
  42. }
  43. for _, channel := range channels {
  44. cids = append(cids, channel.Cid)
  45. }
  46. if channelExtra, err = s.channelExtra(c, mid, cids); err != nil {
  47. err = nil
  48. return
  49. }
  50. for _, channel := range channels {
  51. if _, ok := channelExtra[channel.Cid]; ok {
  52. channel.Count = channelExtra[channel.Cid].Count
  53. channel.Cover = channelExtra[channel.Cid].Cover
  54. }
  55. }
  56. if addCache {
  57. s.cache.Do(c, func(c context.Context) {
  58. s.dao.SetChannelListCache(c, mid, channels)
  59. })
  60. }
  61. return
  62. }
  63. // Channel get channel info.
  64. func (s *Service) Channel(c context.Context, mid, cid int64) (channel *model.Channel, err error) {
  65. var (
  66. extra *model.ChannelExtra
  67. arcReply *arcmdl.ArcReply
  68. addCache bool
  69. )
  70. if channel, addCache, err = s.channel(c, mid, cid); err != nil {
  71. log.Error("s.channel(%d,%d) error(%v)", mid, cid, err)
  72. return
  73. }
  74. if extra, err = s.dao.ChannelExtra(c, mid, cid); err != nil {
  75. log.Error("s.dao.ChannelExtra(%d,%d) error(%v)", mid, cid, err)
  76. err = nil
  77. } else if extra != nil {
  78. channel.Count = extra.Count
  79. if extra.Aid > 0 {
  80. if arcReply, err = s.arcClient.Arc(c, &arcmdl.ArcRequest{Aid: extra.Aid}); err != nil {
  81. log.Error("s.arcClient.Arc(%d) error(%v)", extra.Aid, err)
  82. err = nil
  83. } else {
  84. channel.Cover = arcReply.Arc.Pic
  85. }
  86. }
  87. }
  88. if addCache {
  89. s.cache.Do(c, func(c context.Context) {
  90. s.dao.SetChannelCache(c, mid, cid, channel)
  91. })
  92. }
  93. return
  94. }
  95. func (s *Service) channel(c context.Context, mid, cid int64) (res *model.Channel, addCache bool, err error) {
  96. addCache = true
  97. if res, err = s.dao.ChannelCache(c, mid, cid); err != nil {
  98. addCache = false
  99. } else if res != nil {
  100. return
  101. }
  102. if res, err = s.dao.Channel(c, mid, cid); err != nil {
  103. log.Error("s.dao.Channel(%d,%d) error(%v)", mid, cid, err)
  104. } else if res == nil {
  105. err = ecode.NothingFound
  106. }
  107. return
  108. }
  109. // ChannelIndex get channel index info.
  110. func (s *Service) ChannelIndex(c context.Context, mid int64, isGuest bool) (channelDetails []*model.ChannelDetail, err error) {
  111. var (
  112. channels []*model.Channel
  113. detail *model.ChannelDetail
  114. )
  115. if channels, err = s.ChannelList(c, mid, isGuest); err != nil {
  116. log.Error("s.Channel(%d) error(%v)", mid, err)
  117. return
  118. } else if len(channels) == 0 {
  119. channelDetails = _emptyChDetailList
  120. return
  121. }
  122. group, errCtx := errgroup.WithContext(c)
  123. mutex := sync.Mutex{}
  124. for _, channel := range channels {
  125. cid := channel.Cid
  126. group.Go(func() (err error) {
  127. if detail, err = s.ChannelVideos(errCtx, mid, cid, 1, conf.Conf.Rule.ChIndexCnt, isGuest, false); err != nil {
  128. log.Error("s.ChannelVideos(%d,%d) error(%v)", mid, cid, err)
  129. err = nil
  130. } else if detail != nil {
  131. mutex.Lock()
  132. channelDetails = append(channelDetails, detail)
  133. mutex.Unlock()
  134. }
  135. return
  136. })
  137. }
  138. group.Wait()
  139. if len(channelDetails) == 0 {
  140. channelDetails = _emptyChDetailList
  141. }
  142. return
  143. }
  144. // AddChannel add channel.
  145. func (s *Service) AddChannel(c context.Context, mid int64, name, intro string) (cid int64, err error) {
  146. var (
  147. afIntro string
  148. ts = time.Now()
  149. )
  150. if _, err = s.realName(c, mid); err != nil {
  151. return
  152. }
  153. if err = s.channelCheck(c, mid, 0, name, true, true); err != nil {
  154. log.Error("s.channelCheck(%d,%s) error(%v)", mid, name, err)
  155. return
  156. }
  157. if afIntro, err = s.channelFilter(c, name, intro); err != nil {
  158. log.Error("s.channelFilter(%s,%s) error(%v)", name, intro, err)
  159. return
  160. }
  161. if cid, err = s.dao.AddChannel(c, mid, name, afIntro, ts); err != nil {
  162. log.Error("s.dao.AddChannel(%d,%s,%s) error(%v)", mid, name, intro, err)
  163. return
  164. } else if cid > 0 {
  165. s.cache.Do(c, func(c context.Context) {
  166. ch := &model.Channel{Cid: cid, Mid: mid, Name: name, Intro: intro, Mtime: xtime.Time(ts.Unix())}
  167. s.dao.SetChannelCache(c, mid, cid, ch)
  168. })
  169. }
  170. return
  171. }
  172. // EditChannel edit channel.
  173. func (s *Service) EditChannel(c context.Context, mid, cid int64, name, intro string) (err error) {
  174. var (
  175. affected int64
  176. afIntro string
  177. ts = time.Now()
  178. )
  179. if _, err = s.realName(c, mid); err != nil {
  180. return
  181. }
  182. if err = s.channelCheck(c, mid, cid, name, true, false); err != nil {
  183. log.Error("s.channelCheck(%d,%d,%s) error(%v)", mid, cid, name, err)
  184. return
  185. }
  186. if afIntro, err = s.channelFilter(c, name, intro); err != nil {
  187. log.Error("s.channelFilter(%s,%s) error(%v)", name, intro, err)
  188. return
  189. }
  190. //if channel,err := s.Channel(c,mid,cid,ip)
  191. if affected, err = s.dao.EditChannel(c, mid, cid, name, afIntro, ts); err != nil {
  192. log.Error("s.dao.EditChannel(%d,%s,%s) error(%v)", mid, name, intro, err)
  193. return
  194. } else if affected > 0 {
  195. s.cache.Do(c, func(c context.Context) {
  196. ch := &model.Channel{Cid: cid, Mid: mid, Name: name, Intro: intro, Mtime: xtime.Time(ts.Unix())}
  197. s.dao.SetChannelCache(c, mid, cid, ch)
  198. })
  199. }
  200. return
  201. }
  202. // DelChannel del channel.
  203. func (s *Service) DelChannel(c context.Context, mid, cid int64) (err error) {
  204. var affected int64
  205. if affected, err = s.dao.DelChannel(c, mid, cid); err != nil {
  206. log.Error("s.dao.DelChannel(%d,%d) error(%v)", mid, cid, err)
  207. return
  208. } else if affected > 0 {
  209. s.dao.DelChannelCache(c, mid, cid)
  210. s.dao.DelChannelArcsCache(c, mid, cid)
  211. }
  212. return
  213. }
  214. func (s *Service) channelExtra(c context.Context, mid int64, cids []int64) (extra map[int64]*model.ChannelExtra, err error) {
  215. if len(cids) == 0 {
  216. return
  217. }
  218. var (
  219. arcsReply *arcmdl.ArcsReply
  220. aids = make([]int64, 0, len(cids))
  221. )
  222. extra = make(map[int64]*model.ChannelExtra, len(cids))
  223. for _, cid := range cids {
  224. var data *model.ChannelExtra
  225. if data, err = s.dao.ChannelExtra(c, mid, cid); err != nil {
  226. log.Error("s.dao.ChannelExtra(%d,%d) error(%v)", mid, cid, err)
  227. continue
  228. } else if data != nil {
  229. extra[cid] = &model.ChannelExtra{Aid: data.Aid, Cid: data.Cid, Count: data.Count}
  230. if data.Aid > 0 {
  231. aids = append(aids, data.Aid)
  232. }
  233. }
  234. }
  235. if arcsReply, err = s.arcClient.Arcs(c, &arcmdl.ArcsRequest{Aids: aids}); err != nil {
  236. log.Error("s.arcClient.Arcs(%v) error (%v)", aids, err)
  237. return
  238. }
  239. for _, cid := range cids {
  240. if _, ok := extra[cid]; ok {
  241. if arc, ok := arcsReply.Arcs[extra[cid].Aid]; ok {
  242. extra[cid].Cover = arc.Pic
  243. }
  244. }
  245. }
  246. return
  247. }
  248. func (s *Service) channelCheck(c context.Context, mid, cid int64, name string, nameCheck, countCheck bool) (err error) {
  249. var (
  250. channels []*model.Channel
  251. dbCheck = false
  252. )
  253. if channels, err = s.dao.ChannelListCache(c, mid); err != nil {
  254. err = nil
  255. dbCheck = true
  256. } else if len(channels) == 0 {
  257. dbCheck = true
  258. }
  259. if dbCheck {
  260. if channels, err = s.dao.ChannelList(c, mid); err != nil {
  261. log.Error("s.dao.ChannelList(%d) error(%v)", mid, err)
  262. return
  263. }
  264. }
  265. if cnt := len(channels); cnt > 0 {
  266. if countCheck && cnt > conf.Conf.Rule.MaxChLimit {
  267. err = ecode.ChMaxCount
  268. return
  269. }
  270. if nameCheck {
  271. for _, channel := range channels {
  272. if name == channel.Name && cid != channel.Cid {
  273. err = ecode.ChNameExist
  274. return
  275. }
  276. }
  277. }
  278. }
  279. return
  280. }
  281. func (s *Service) channelFilter(c context.Context, name, intro string) (afterIntro string, err error) {
  282. var (
  283. filterRes map[string]*filmdl.FilterRes
  284. arg = &filmdl.ArgMfilter{Area: "common", Message: map[string]string{"name": name, "intro": intro}}
  285. )
  286. afterIntro = intro
  287. if filterRes, err = s.filter.MFilter(c, arg); err != nil {
  288. log.Error("s.filter.MFilter(%v) error(%v)", arg, err)
  289. return
  290. }
  291. for k, v := range filterRes {
  292. if k == "name" && v.Level >= _nameErrorLevel {
  293. err = ecode.ChNameBanned
  294. return
  295. }
  296. if k == "intro" {
  297. if v.Level == _introWarnLevel {
  298. afterIntro = v.Result
  299. } else if v.Level >= _introErrorLevel {
  300. err = ecode.ChIntroBanned
  301. return
  302. }
  303. }
  304. }
  305. return
  306. }