pre.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. package service
  2. import (
  3. "context"
  4. "go-common/app/interface/main/videoup/model/archive"
  5. accapi "go-common/app/service/main/account/api"
  6. "go-common/library/ecode"
  7. "go-common/library/log"
  8. xtime "go-common/library/time"
  9. "html"
  10. "strings"
  11. "time"
  12. )
  13. func (s *Service) preMust(c context.Context, mid int64, ap *archive.ArcParam, ip string, upFrom int8) (err error) {
  14. // title xss filter
  15. originTitleLen := len(ap.Title)
  16. ap.Title = html.UnescapeString(xssFilter(ap.Title))
  17. if len(ap.Title) != originTitleLen {
  18. log.Warn("ap.Title inject by xss:mid(%d)|ip(%d)", mid, ip)
  19. }
  20. // check videos
  21. if upFrom != archive.UpFromAPP {
  22. if err = s.checkVideos(c, ap); err != nil {
  23. log.Error("s.checkVideos mid(%d) ap.TypeID(%d) err(%+v)", mid, ap.TypeID, err)
  24. return
  25. }
  26. }
  27. // check archive
  28. if !s.allowType(ap.TypeID) {
  29. log.Error("s.allowType mid(%d) ap.TypeID(%d) typeid not exists", mid, ap.TypeID)
  30. err = ecode.VideoupTypeidErr
  31. return
  32. }
  33. if !s.allowCopyright(ap.Copyright) {
  34. log.Error("s.allowCopyright mid(%d) ap.Copyright(%d) no legal copyright", mid, ap.Copyright)
  35. err = ecode.VideoupCopyrightErr
  36. return
  37. }
  38. ap.Tag = s.removeDupTag(ap.Tag)
  39. if !s.allowTag(ap.Tag) {
  40. log.Error("s.allowTag mid(%d) ap.Tag(%s) tag name or number too large or Empty", mid, ap.Tag)
  41. err = ecode.VideoupTagErr
  42. return
  43. }
  44. if err = s.checkVideo(ap); err != nil {
  45. log.Error("s.checkVideo mid(%d) ap(%+v) error(%v)", mid, ap, err)
  46. return
  47. }
  48. var ok bool
  49. if ap.Cover, ok = s.checkCover(ap.Cover); !ok {
  50. log.Error("s.checkCover mid(%d) ap.Cover(%s) cover no legal", mid, ap.Cover)
  51. err = ecode.VideoupCoverErr
  52. return
  53. }
  54. if ap.Title, ok = s.checkTitle(ap.Title); !ok || ap.Title == "" {
  55. log.Error("s.checkTitle mid(%d) ap.Title(%s) title contains legal char or is empty", err, mid, ap.Title)
  56. err = ecode.VideoupTitleErr
  57. return
  58. }
  59. if ap.Dynamic, ok = s.checkDynamicLen233(ap.Dynamic); !ok {
  60. log.Error("s.checkDynamic err(%+v) mid(%d) ap.Dynamic(%s) contains length larger 233", err, mid, ap.Dynamic)
  61. err = ecode.VideoupDynamicErr
  62. return
  63. }
  64. if ap.Desc, ok = s.checkDesc(ap.Desc); !ok {
  65. log.Error("s.checkDesc mid(%d) ap.Desc(%s) desc contains legal char or is empty", mid, ap.Desc)
  66. err = ecode.VideoupDescErr
  67. return
  68. }
  69. var p *accapi.Profile
  70. if p, err = s.checkAccount(c, mid, ip); err != nil {
  71. log.Error("s.checkAccount mid(%d) error(%v)", mid, err)
  72. return
  73. }
  74. ap.Author = p.Name
  75. if ap.Copyright == archive.CopyrightCopy {
  76. ap.NoReprint = 0
  77. }
  78. // DisableVideoDesc except UpFromWindows, step 1 for all
  79. if upFrom != archive.UpFromWindows {
  80. for _, v := range ap.Videos {
  81. v.Desc = ""
  82. }
  83. }
  84. // 防止脏数据
  85. if ap.Vote != nil && ap.Vote.VoteID == 0 {
  86. ap.Vote = nil
  87. }
  88. return
  89. }
  90. func (s *Service) preOrder(c context.Context, ap *archive.ArcParam, a *archive.Archive, ip string) (err error) {
  91. if ap.Porder != nil && ap.Porder.FlowID > 0 && ap.OrderID > 0 {
  92. err = ecode.VideoupPvodForbidOrderAlready
  93. return
  94. }
  95. if ap.OrderID < 0 {
  96. err = ecode.VideoupOrderIDNotAllow
  97. return
  98. }
  99. if ap.Aid == 0 && ap.OrderID == 0 { // NOTE: add no orderid
  100. return
  101. }
  102. if ap.Aid > 0 && ap.OrderID == 0 && a.OrderID == 0 { // NOTE: edit always no orderid
  103. return
  104. }
  105. if ap.Aid > 0 { // NOTE: edit had order id, not allow change
  106. ap.OrderID = a.OrderID
  107. ap.DTime = a.DTime
  108. return
  109. }
  110. if !s.allowOrderUps(ap.Mid) {
  111. log.Error("s.allowOrderUps mid(%d) error(%v)", ap.Mid, err)
  112. err = ecode.VideoupUperIDNotAllow
  113. return
  114. }
  115. if err = s.checkOrderID(c, ap.Mid, ap.OrderID, ip); err != nil {
  116. return
  117. }
  118. var ptime xtime.Time
  119. if ptime, err = s.order.PubTime(c, ap.Mid, ap.OrderID, ip); err != nil {
  120. err = ecode.VideoupOrderAPIErr
  121. return
  122. }
  123. if ap.Aid == 0 && int64(ptime) < time.Now().Add(2*time.Hour).Unix() {
  124. err = ecode.VideoupLaunchTimeIllegal
  125. return
  126. }
  127. ap.DTime = ptime
  128. return
  129. }
  130. func (s *Service) preAdd(c context.Context, mid int64, ap *archive.ArcParam, ip string, upFrom int8) (err error) {
  131. if ap.ForbidAddVideoType() {
  132. err = ecode.VideoupTypeidErr
  133. log.Error("ap.ForbidAddVideoType VideoupTypeidErr mid(%d),type(%d),err(%v) ", mid, ap.TypeID, err)
  134. return
  135. }
  136. if ap.ForbidCopyrightAndTypes() {
  137. err = ecode.VideoupCopyrightErr
  138. log.Error("ap.ForbidCopyrightAndTypes VideoupCopyrightErr mid(%d),copyright(%d),type(%d),err(%v) ", mid, ap.Copyright, ap.TypeID, err)
  139. return
  140. }
  141. if len(ap.Videos) > s.c.MaxAddVsCnt {
  142. err = ecode.VideoupVideosMaxLimit
  143. log.Error("ap.VideoupVideosMaxLimit current(%d), max(%d),err(%v) ", len(ap.Videos), s.c.MaxAddVsCnt, err)
  144. return
  145. }
  146. if !s.allowSource(ap.Copyright, ap.Source) {
  147. err = ecode.VideoupSourceErr
  148. return
  149. }
  150. originDesc := ap.Desc
  151. //join source and desc for CopyrightCopy with \n
  152. if ap.Copyright == archive.CopyrightCopy && len(strings.TrimSpace(ap.Source)) > 0 {
  153. ap.Desc = ap.Source + "\n" + ap.Desc
  154. }
  155. // App端允许在添加和编辑稿件的时候简介为空,但是需要区分是操作系统平台
  156. ap.Desc = s.switchDesc(upFrom, ap.Desc)
  157. // preMust method must be first
  158. if err = s.preMust(c, mid, ap, ip, upFrom); err != nil {
  159. log.Error("s.preMust mid(%d), err(%v) ", mid, err)
  160. return
  161. }
  162. if !s.allowRepeat(c, mid, ap.Title) {
  163. err = ecode.VideoupCanotRepeat
  164. return
  165. }
  166. if !s.allowDelayTime(ap.DTime) {
  167. err = ecode.VideoupDelayTimeErr
  168. return
  169. }
  170. if err = s.checkMission(c, ap); err != nil {
  171. log.Error("s.checkMission mid(%d) ap.MissionID(%d)|TypeID(%d) missionId not exists", mid, ap.MissionID, ap.TypeID)
  172. return
  173. }
  174. if ap.Tag, err = s.checkMissionTag(ap.Tag, ap.MissionID); err != nil {
  175. log.Error("s.checkMissionTag mid(%d) ap.tag(%s) ap.MissionID(%d) missionId not exists", mid, ap.Tag, ap.MissionID)
  176. return
  177. }
  178. if err = s.checkDescForLength(originDesc, ap.DescFormatID, ap.TypeID, ap.Copyright); err != nil {
  179. log.Error("s.checkDescForLength mid(%d) ap.Source(%s), apDesc(%s),ap.DescFormatID(%d) ap.Lang(%d) err(%v)", mid, ap.Source, originDesc, ap.DescFormatID, ap.Lang, err)
  180. return
  181. }
  182. if err = s.preOrder(c, ap, nil, ip); err != nil {
  183. log.Error("s.preOrder mid(%d) ap(%v), err(%v) ", mid, ap, err)
  184. return
  185. }
  186. //checkPorderForAdd
  187. if ap.Porder != nil && ap.Porder.IndustryID > 0 {
  188. if err = s.checkPorderForAdd(c, ap, mid); err != nil {
  189. log.Error("s.checkPorderForAdd mid(%d) ap(%v) |err(%+v)", mid, ap, err)
  190. return
  191. }
  192. }
  193. ap.NilPoiObj()
  194. return
  195. }
  196. func (s *Service) switchDesc(upFrom int8, originDesc string) (resDesc string) {
  197. resDesc = originDesc
  198. if (upFrom == archive.UpFromAPP ||
  199. upFrom == archive.UpFromAPPAndroid ||
  200. upFrom == archive.UpFromIpad ||
  201. upFrom == archive.UpFromAPPiOS) &&
  202. len(originDesc) == 0 {
  203. resDesc = "-"
  204. }
  205. return
  206. }
  207. func (s *Service) preEdit(c context.Context, mid int64, a *archive.Archive, vs []*archive.Video, ap *archive.ArcParam, ip string, upFrom int8) (err error) {
  208. //检查联合投稿移区和修改转载类型
  209. if err = s.checkStaffMoveType(c, ap, a, ip); err != nil {
  210. return
  211. }
  212. if len(ap.Videos) > s.c.MaxAllVsCnt {
  213. newErr := ecode.VideoupMaxAllVsCntLimit
  214. err = ecode.Errorf(newErr, newErr.Message(), s.c.MaxAllVsCnt)
  215. log.Error("MaxAllVsCnt err(%+v)|MaxAllVsCnt(%d)|mid(%d)|aid(%d)", err, s.c.MaxAllVsCnt, mid, a.Aid)
  216. return
  217. }
  218. // App端允许在添加和编辑稿件的时候简介为空,但是需要区分是操作系统平台
  219. if ap.ForbidCopyrightAndTypes() {
  220. err = ecode.VideoupCopyrightErr
  221. log.Error("ap.ForbidCopyrightAndTypes VideoupCopyrightErr mid(%d),copyright(%d),type(%d),err(%v) ", mid, ap.Copyright, ap.TypeID, err)
  222. return
  223. }
  224. ap.Desc = s.switchDesc(upFrom, ap.Desc)
  225. if err = s.preMust(c, mid, ap, ip, upFrom); err != nil {
  226. log.Error("s.preMust mid(%d), err(%v) ", mid, err)
  227. return
  228. }
  229. // DisableVideoDesc, except UpFromWindows step 2 for edit
  230. if upFrom != archive.UpFromWindows {
  231. ap.DisableVideoDesc(vs)
  232. }
  233. ap.TypeID, ap.Copyright, ap.Tag, ap.MissionID, ap.DescFormatID = s.protectFieldForEdit(ap, a)
  234. //not in cache or not StateForbidRecicle
  235. _, ok := s.missCache[ap.MissionID]
  236. if (!ok && ap.MissionID > 0) || (a.State != archive.StateForbidRecicle) {
  237. ap.MissionID = a.MissionID
  238. }
  239. if a.State == archive.StateForbidRecicle {
  240. if err = s.checkMission(c, ap); err != nil {
  241. log.Error("s.checkMission mid(%d) ap.MissionID(%d)|TypeID(%d) missionId not exists", mid, ap.MissionID, ap.TypeID)
  242. return
  243. }
  244. }
  245. if ap.Tag, err = s.checkMissionTag(ap.Tag, ap.MissionID); err != nil {
  246. log.Error("s.checkMissionTag mid(%d) ap.tag(%s) ap.MissionID(%d) missionId not exists", mid, ap.Tag, ap.MissionID)
  247. return
  248. }
  249. // mid check
  250. if a.Mid != mid {
  251. log.Error("mid(%d) is not author(%d)", mid, a.Mid)
  252. err = ecode.ArchiveOwnerErr
  253. return
  254. }
  255. // state check
  256. if a.NotAllowUp() {
  257. err = ecode.ArchiveBlocked
  258. return
  259. }
  260. // web和新发粉版允许修改创作类型,其他的都不允许
  261. if upFrom != archive.UpFromWeb &&
  262. upFrom != archive.UpFromAPPiOS &&
  263. upFrom != archive.UpFromIpad &&
  264. upFrom != archive.UpFromAPPAndroid {
  265. ap.NoReprint = a.NoReprint
  266. log.Info("upfrom forbid change np, np(%d)|upfrom(%+v)", a.NoReprint, upFrom)
  267. }
  268. // NoReprint check
  269. if a.NoReprint == 0 && ap.NoReprint == 1 {
  270. log.Error("notAllow set NoReprint = 1 after now's Noreprint is 0 mid(%d) ap.NoReprint(%d) a.NoReprint(%d)", mid, ap.NoReprint, a.NoReprint)
  271. err = ecode.VideoupForbidNoreprint
  272. return
  273. }
  274. // allowDelayTime check for archive which state nq -40
  275. if a.State == archive.StateForbidUserDelay {
  276. ap.DTime = a.DTime
  277. } else if a.State != archive.StateOpen {
  278. if a.DTime != ap.DTime && !s.allowDelayTime(ap.DTime) {
  279. log.Error("s.allowDelayTime err(%+v) mid(%d) ap.Dtime(%d) must between 4h 15d", err, mid, ap.DTime)
  280. err = ecode.VideoupDelayTimeErr
  281. return
  282. }
  283. }
  284. if err = s.preOrder(c, ap, a, ip); err != nil {
  285. log.Error("s.preOrder mid(%d) ap(%v), err(%v) ", mid, ap, err)
  286. return
  287. }
  288. // checkDescForLength
  289. if err = s.checkDescForLength(ap.Desc, ap.DescFormatID, ap.TypeID, ap.Copyright); err != nil {
  290. log.Error("s.checkDescForLength mid(%d) ap.Desc(%s) ap.DescFormatID(%d) err(%v)", mid, ap.Desc, ap.DescFormatID, err)
  291. return
  292. }
  293. // 手动暴力禁止编辑的时候进行修改poi地理位置信息
  294. ap.PoiObj = nil
  295. // checkEditPay
  296. if err = s.checkEditPay(c, ap, a, ip); err != nil {
  297. log.Error("s.checkEditPay mid(%d) ap(%+v) a(%+v) err(%v)", mid, ap, a, err)
  298. return
  299. }
  300. return
  301. }
  302. // protectFieldForEdit only StateForbidRecicle allow change typeID and Copyright
  303. // 简介模板的ID暂时近期内不允许修改
  304. func (s *Service) protectFieldForEdit(ap *archive.ArcParam, a *archive.Archive) (typeID int16, copyright int8, tag string, missionID, descFormatID int) {
  305. if a.State == archive.StateForbidRecicle ||
  306. a.State == archive.StateForbidSubmit ||
  307. a.State == archive.StateForbidFixed ||
  308. a.State == archive.StateOrange ||
  309. a.State == archive.StateOpen {
  310. return ap.TypeID, ap.Copyright, ap.Tag, ap.MissionID, ap.DescFormatID
  311. }
  312. return a.TypeID, a.Copyright, a.Tag, a.MissionID, a.DescFormatID
  313. }
  314. func (s *Service) removeDupTag(tagStr string) string {
  315. result := []string{}
  316. elements := strings.Split(tagStr, ",")
  317. for i := 0; i < len(elements); i++ {
  318. exists := false
  319. for v := 0; v < i; v++ {
  320. if elements[v] == elements[i] {
  321. exists = true
  322. break
  323. }
  324. }
  325. if !exists {
  326. result = append(result, elements[i])
  327. }
  328. }
  329. return strings.Join(result, ",")
  330. }