video-rates.ts 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import { Transaction } from 'sequelize'
  2. import { AccountModel } from '../../models/account/account'
  3. import { VideoModel } from '../../models/video/video'
  4. import { sendLike, sendUndoDislike, sendUndoLike } from './send'
  5. import { VideoRateType } from '../../../shared/models/videos'
  6. import * as Bluebird from 'bluebird'
  7. import { getOrCreateActorAndServerAndModel } from './actor'
  8. import { AccountVideoRateModel } from '../../models/account/account-video-rate'
  9. import { logger } from '../../helpers/logger'
  10. import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants'
  11. import { doRequest } from '../../helpers/requests'
  12. import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub'
  13. import { ActorModel } from '../../models/activitypub/actor'
  14. import { getVideoDislikeActivityPubUrl, getVideoLikeActivityPubUrl } from './url'
  15. import { sendDislike } from './send/send-dislike'
  16. async function createRates (ratesUrl: string[], video: VideoModel, rate: VideoRateType) {
  17. let rateCounts = 0
  18. await Bluebird.map(ratesUrl, async rateUrl => {
  19. try {
  20. // Fetch url
  21. const { body } = await doRequest({
  22. uri: rateUrl,
  23. json: true,
  24. activityPub: true
  25. })
  26. if (!body || !body.actor) throw new Error('Body or body actor is invalid')
  27. const actorUrl = getAPId(body.actor)
  28. if (checkUrlsSameHost(actorUrl, rateUrl) !== true) {
  29. throw new Error(`Rate url ${rateUrl} has not the same host than actor url ${actorUrl}`)
  30. }
  31. if (checkUrlsSameHost(body.id, rateUrl) !== true) {
  32. throw new Error(`Rate url ${rateUrl} host is different from the AP object id ${body.id}`)
  33. }
  34. const actor = await getOrCreateActorAndServerAndModel(actorUrl)
  35. const entry = {
  36. videoId: video.id,
  37. accountId: actor.Account.id,
  38. type: rate,
  39. url: body.id
  40. }
  41. const created = await AccountVideoRateModel.upsert(entry)
  42. if (created) rateCounts += 1
  43. } catch (err) {
  44. logger.warn('Cannot add rate %s.', rateUrl, { err })
  45. }
  46. }, { concurrency: CRAWL_REQUEST_CONCURRENCY })
  47. logger.info('Adding %d %s to video %s.', rateCounts, rate, video.uuid)
  48. // This is "likes" and "dislikes"
  49. if (rateCounts !== 0) {
  50. const field = rate === 'like' ? 'likes' : 'dislikes'
  51. await video.increment(field, { by: rateCounts })
  52. }
  53. return
  54. }
  55. async function sendVideoRateChange (account: AccountModel,
  56. video: VideoModel,
  57. likes: number,
  58. dislikes: number,
  59. t: Transaction) {
  60. const actor = account.Actor
  61. // Keep the order: first we undo and then we create
  62. // Undo Like
  63. if (likes < 0) await sendUndoLike(actor, video, t)
  64. // Undo Dislike
  65. if (dislikes < 0) await sendUndoDislike(actor, video, t)
  66. // Like
  67. if (likes > 0) await sendLike(actor, video, t)
  68. // Dislike
  69. if (dislikes > 0) await sendDislike(actor, video, t)
  70. }
  71. function getRateUrl (rateType: VideoRateType, actor: ActorModel, video: VideoModel) {
  72. return rateType === 'like' ? getVideoLikeActivityPubUrl(actor, video) : getVideoDislikeActivityPubUrl(actor, video)
  73. }
  74. export {
  75. getRateUrl,
  76. createRates,
  77. sendVideoRateChange
  78. }