share.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { Transaction } from 'sequelize'
  2. import { VideoPrivacy } from '../../../shared/models/videos'
  3. import { getServerActor } from '../../helpers/utils'
  4. import { VideoModel } from '../../models/video/video'
  5. import { VideoShareModel } from '../../models/video/video-share'
  6. import { sendUndoAnnounce, sendVideoAnnounce } from './send'
  7. import { getVideoAnnounceActivityPubUrl } from './url'
  8. import { VideoChannelModel } from '../../models/video/video-channel'
  9. import * as Bluebird from 'bluebird'
  10. import { doRequest } from '../../helpers/requests'
  11. import { getOrCreateActorAndServerAndModel } from './actor'
  12. import { logger } from '../../helpers/logger'
  13. import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants'
  14. import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub'
  15. async function shareVideoByServerAndChannel (video: VideoModel, t: Transaction) {
  16. if (video.privacy === VideoPrivacy.PRIVATE) return undefined
  17. return Promise.all([
  18. shareByServer(video, t),
  19. shareByVideoChannel(video, t)
  20. ])
  21. }
  22. async function changeVideoChannelShare (video: VideoModel, oldVideoChannel: VideoChannelModel, t: Transaction) {
  23. logger.info('Updating video channel of video %s: %s -> %s.', video.uuid, oldVideoChannel.name, video.VideoChannel.name)
  24. await undoShareByVideoChannel(video, oldVideoChannel, t)
  25. await shareByVideoChannel(video, t)
  26. }
  27. async function addVideoShares (shareUrls: string[], instance: VideoModel) {
  28. await Bluebird.map(shareUrls, async shareUrl => {
  29. try {
  30. // Fetch url
  31. const { body } = await doRequest({
  32. uri: shareUrl,
  33. json: true,
  34. activityPub: true
  35. })
  36. if (!body || !body.actor) throw new Error('Body or body actor is invalid')
  37. const actorUrl = getAPId(body.actor)
  38. if (checkUrlsSameHost(shareUrl, actorUrl) !== true) {
  39. throw new Error(`Actor url ${actorUrl} has not the same host than the share url ${shareUrl}`)
  40. }
  41. const actor = await getOrCreateActorAndServerAndModel(actorUrl)
  42. const entry = {
  43. actorId: actor.id,
  44. videoId: instance.id,
  45. url: shareUrl
  46. }
  47. await VideoShareModel.upsert(entry)
  48. } catch (err) {
  49. logger.warn('Cannot add share %s.', shareUrl, { err })
  50. }
  51. }, { concurrency: CRAWL_REQUEST_CONCURRENCY })
  52. }
  53. export {
  54. changeVideoChannelShare,
  55. addVideoShares,
  56. shareVideoByServerAndChannel
  57. }
  58. // ---------------------------------------------------------------------------
  59. async function shareByServer (video: VideoModel, t: Transaction) {
  60. const serverActor = await getServerActor()
  61. const serverShareUrl = getVideoAnnounceActivityPubUrl(serverActor, video)
  62. const [ serverShare ] = await VideoShareModel.findOrCreate({
  63. defaults: {
  64. actorId: serverActor.id,
  65. videoId: video.id,
  66. url: serverShareUrl
  67. },
  68. where: {
  69. url: serverShareUrl
  70. },
  71. transaction: t
  72. })
  73. return sendVideoAnnounce(serverActor, serverShare, video, t)
  74. }
  75. async function shareByVideoChannel (video: VideoModel, t: Transaction) {
  76. const videoChannelShareUrl = getVideoAnnounceActivityPubUrl(video.VideoChannel.Actor, video)
  77. const [ videoChannelShare ] = await VideoShareModel.findOrCreate({
  78. defaults: {
  79. actorId: video.VideoChannel.actorId,
  80. videoId: video.id,
  81. url: videoChannelShareUrl
  82. },
  83. where: {
  84. url: videoChannelShareUrl
  85. },
  86. transaction: t
  87. })
  88. return sendVideoAnnounce(video.VideoChannel.Actor, videoChannelShare, video, t)
  89. }
  90. async function undoShareByVideoChannel (video: VideoModel, oldVideoChannel: VideoChannelModel, t: Transaction) {
  91. // Load old share
  92. const oldShare = await VideoShareModel.load(oldVideoChannel.actorId, video.id, t)
  93. if (!oldShare) return new Error('Cannot find old video channel share ' + oldVideoChannel.actorId + ' for video ' + video.id)
  94. await sendUndoAnnounce(oldVideoChannel.Actor, oldShare, video, t)
  95. await oldShare.destroy({ transaction: t })
  96. }