share.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { getServerActor } from '@server/models/application/application.js'
  2. import Bluebird from 'bluebird'
  3. import { Transaction } from 'sequelize'
  4. import { logger, loggerTagsFactory } from '../../helpers/logger.js'
  5. import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants.js'
  6. import { VideoShareModel } from '../../models/video/video-share.js'
  7. import { MChannelActorLight, MVideo, MVideoAccountLight, MVideoId } from '../../types/models/video/index.js'
  8. import { fetchAP, getAPId } from './activity.js'
  9. import { getOrCreateAPActor } from './actors/index.js'
  10. import { sendUndoAnnounce, sendVideoAnnounce } from './send/index.js'
  11. import { checkUrlsSameHost, getLocalVideoAnnounceActivityPubUrl } from './url.js'
  12. const lTags = loggerTagsFactory('share')
  13. export async function changeVideoChannelShare (
  14. video: MVideoAccountLight,
  15. oldVideoChannel: MChannelActorLight,
  16. t: Transaction
  17. ) {
  18. logger.info(
  19. 'Updating video channel of video %s: %s -> %s.', video.uuid, oldVideoChannel.name, video.VideoChannel.name,
  20. lTags(video.uuid)
  21. )
  22. await undoShareByVideoChannel(video, oldVideoChannel, t)
  23. await shareByVideoChannel(video, t)
  24. }
  25. export async function addVideoShares (shareUrls: string[], video: MVideoId) {
  26. await Bluebird.map(shareUrls, async shareUrl => {
  27. try {
  28. await addVideoShare(shareUrl, video)
  29. } catch (err) {
  30. logger.warn('Cannot add share %s.', shareUrl, { err })
  31. }
  32. }, { concurrency: CRAWL_REQUEST_CONCURRENCY })
  33. }
  34. export async function shareByServer (video: MVideo, t: Transaction) {
  35. const serverActor = await getServerActor()
  36. const serverShareUrl = getLocalVideoAnnounceActivityPubUrl(serverActor, video)
  37. const [ serverShare ] = await VideoShareModel.findOrCreate({
  38. defaults: {
  39. actorId: serverActor.id,
  40. videoId: video.id,
  41. url: serverShareUrl
  42. },
  43. where: {
  44. url: serverShareUrl
  45. },
  46. transaction: t
  47. })
  48. return sendVideoAnnounce(serverActor, serverShare, video, t)
  49. }
  50. export async function shareByVideoChannel (video: MVideoAccountLight, t: Transaction) {
  51. const videoChannelShareUrl = getLocalVideoAnnounceActivityPubUrl(video.VideoChannel.Actor, video)
  52. const [ videoChannelShare ] = await VideoShareModel.findOrCreate({
  53. defaults: {
  54. actorId: video.VideoChannel.actorId,
  55. videoId: video.id,
  56. url: videoChannelShareUrl
  57. },
  58. where: {
  59. url: videoChannelShareUrl
  60. },
  61. transaction: t
  62. })
  63. return sendVideoAnnounce(video.VideoChannel.Actor, videoChannelShare, video, t)
  64. }
  65. // ---------------------------------------------------------------------------
  66. // Private
  67. // ---------------------------------------------------------------------------
  68. async function addVideoShare (shareUrl: string, video: MVideoId) {
  69. const { body } = await fetchAP<any>(shareUrl)
  70. if (!body?.actor) throw new Error('Body or body actor is invalid')
  71. const actorUrl = getAPId(body.actor)
  72. if (checkUrlsSameHost(shareUrl, actorUrl) !== true) {
  73. throw new Error(`Actor url ${actorUrl} has not the same host than the share url ${shareUrl}`)
  74. }
  75. const actor = await getOrCreateAPActor(actorUrl)
  76. const entry = {
  77. actorId: actor.id,
  78. videoId: video.id,
  79. url: shareUrl
  80. }
  81. await VideoShareModel.upsert(entry)
  82. }
  83. async function undoShareByVideoChannel (video: MVideo, oldVideoChannel: MChannelActorLight, t: Transaction) {
  84. // Load old share
  85. const oldShare = await VideoShareModel.load(oldVideoChannel.actorId, video.id, t)
  86. if (!oldShare) return new Error('Cannot find old video channel share ' + oldVideoChannel.actorId + ' for video ' + video.id)
  87. await sendUndoAnnounce(oldVideoChannel.Actor, oldShare, video, t)
  88. await oldShare.destroy({ transaction: t })
  89. }