process-dislike.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { ActivityDislike } from '@peertube/peertube-models'
  2. import { logger } from '@server/helpers/logger.js'
  3. import { VideoModel } from '@server/models/video/video.js'
  4. import { retryTransactionWrapper } from '../../../helpers/database-utils.js'
  5. import { sequelizeTypescript } from '../../../initializers/database.js'
  6. import { AccountVideoRateModel } from '../../../models/account/account-video-rate.js'
  7. import { APProcessorOptions } from '../../../types/activitypub-processor.model.js'
  8. import { MActorSignature } from '../../../types/models/index.js'
  9. import { canVideoBeFederated, federateVideoIfNeeded, maybeGetOrCreateAPVideo } from '../videos/index.js'
  10. async function processDislikeActivity (options: APProcessorOptions<ActivityDislike>) {
  11. const { activity, byActor } = options
  12. return retryTransactionWrapper(processDislike, activity, byActor)
  13. }
  14. // ---------------------------------------------------------------------------
  15. export {
  16. processDislikeActivity
  17. }
  18. // ---------------------------------------------------------------------------
  19. async function processDislike (activity: ActivityDislike, byActor: MActorSignature) {
  20. const videoUrl = activity.object
  21. const byAccount = byActor.Account
  22. if (!byAccount) throw new Error('Cannot create dislike with the non account actor ' + byActor.url)
  23. const { video: onlyVideo } = await maybeGetOrCreateAPVideo({ videoObject: videoUrl, fetchType: 'only-video-and-blacklist' })
  24. if (!onlyVideo?.isOwned()) return
  25. if (!canVideoBeFederated(onlyVideo)) {
  26. logger.warn(`Do not process dislike on video ${videoUrl} that cannot be federated`)
  27. return
  28. }
  29. return sequelizeTypescript.transaction(async t => {
  30. const video = await VideoModel.loadFull(onlyVideo.id, t)
  31. const existingRate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byAccount.id, video.id, activity.id, t)
  32. if (existingRate && existingRate.type === 'dislike') return
  33. await video.increment('dislikes', { transaction: t })
  34. video.dislikes++
  35. if (existingRate && existingRate.type === 'like') {
  36. await video.decrement('likes', { transaction: t })
  37. video.likes--
  38. }
  39. const rate = existingRate || new AccountVideoRateModel()
  40. rate.type = 'dislike'
  41. rate.videoId = video.id
  42. rate.accountId = byAccount.id
  43. rate.url = activity.id
  44. await rate.save({ transaction: t })
  45. await federateVideoIfNeeded(video, false, t)
  46. })
  47. }