]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/lib/activitypub/send/misc.ts
Put activity pub sends inside transactions
[github/Chocobozzz/PeerTube.git] / server / lib / activitypub / send / misc.ts
index f3dc5c148e59dc94fffe76f554b006d0ed215711..999def70168a4fef7866169d9ce348c42f7c4a1e 100644 (file)
@@ -1,8 +1,47 @@
 import { Transaction } from 'sequelize'
+import { Activity } from '../../../../shared/models/activitypub/activity'
 import { logger } from '../../../helpers/logger'
 import { ACTIVITY_PUB, database as db } from '../../../initializers'
 import { AccountInstance } from '../../../models/account/account-interface'
-import { activitypubHttpJobScheduler } from '../../jobs/activitypub-http-job-scheduler/activitypub-http-job-scheduler'
+import { VideoChannelInstance } from '../../../models/index'
+import { VideoInstance } from '../../../models/video/video-interface'
+import {
+  activitypubHttpJobScheduler,
+  ActivityPubHttpPayload
+} from '../../jobs/activitypub-http-job-scheduler/activitypub-http-job-scheduler'
+
+async function forwardActivity (
+  activity: Activity,
+  t: Transaction,
+  followersException: AccountInstance[] = []
+) {
+  const to = activity.to || []
+  const cc = activity.cc || []
+
+  const followersUrls: string[] = []
+  for (const dest of to.concat(cc)) {
+    if (dest.endsWith('/followers')) {
+      followersUrls.push(dest)
+    }
+  }
+
+  const toAccountFollowers = await db.Account.listByFollowersUrls(followersUrls, t)
+  const uris = await computeFollowerUris(toAccountFollowers, followersException, t)
+
+  if (uris.length === 0) {
+    logger.info('0 followers for %s, no forwarding.', toAccountFollowers.map(a => a.id).join(', '))
+    return undefined
+  }
+
+  logger.debug('Creating forwarding job.', { uris })
+
+  const jobPayload: ActivityPubHttpPayload = {
+    uris,
+    body: activity
+  }
+
+  return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpBroadcastHandler', jobPayload)
+}
 
 async function broadcastToFollowers (
   data: any,
@@ -11,18 +50,15 @@ async function broadcastToFollowers (
   t: Transaction,
   followersException: AccountInstance[] = []
 ) {
-  const toAccountFollowerIds = toAccountFollowers.map(a => a.id)
-
-  const result = await db.AccountFollow.listAcceptedFollowerSharedInboxUrls(toAccountFollowerIds)
-  if (result.data.length === 0) {
-    logger.info('Not broadcast because of 0 followers for %s.', toAccountFollowerIds.join(', '))
+  const uris = await computeFollowerUris(toAccountFollowers, followersException, t)
+  if (uris.length === 0) {
+    logger.info('0 followers for %s, no broadcasting.', toAccountFollowers.map(a => a.id).join(', '))
     return undefined
   }
 
-  const followersSharedInboxException = followersException.map(f => f.sharedInboxUrl)
-  const uris = result.data.filter(sharedInbox => followersSharedInboxException.indexOf(sharedInbox) === -1)
+  logger.debug('Creating broadcast job.', { uris })
 
-  const jobPayload = {
+  const jobPayload: ActivityPubHttpPayload = {
     uris,
     signatureAccountId: byAccount.id,
     body: data
@@ -32,7 +68,9 @@ async function broadcastToFollowers (
 }
 
 async function unicastTo (data: any, byAccount: AccountInstance, toAccountUrl: string, t: Transaction) {
-  const jobPayload = {
+  logger.debug('Creating unicast job.', { uri: toAccountUrl })
+
+  const jobPayload: ActivityPubHttpPayload = {
     uris: [ toAccountUrl ],
     signatureAccountId: byAccount.id,
     body: data
@@ -41,8 +79,43 @@ async function unicastTo (data: any, byAccount: AccountInstance, toAccountUrl: s
   return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpUnicastHandler', jobPayload)
 }
 
-async function getAudience (accountSender: AccountInstance, isPublic = true) {
-  const followerInboxUrls = await accountSender.getFollowerSharedInboxUrls()
+function getOriginVideoAudience (video: VideoInstance, accountsInvolvedInVideo: AccountInstance[]) {
+  return {
+    to: [ video.VideoChannel.Account.url ],
+    cc: accountsInvolvedInVideo.map(a => a.followersUrl)
+  }
+}
+
+function getOriginVideoChannelAudience (videoChannel: VideoChannelInstance, accountsInvolved: AccountInstance[]) {
+  return {
+    to: [ videoChannel.Account.url ],
+    cc: accountsInvolved.map(a => a.followersUrl)
+  }
+}
+
+function getObjectFollowersAudience (accountsInvolvedInObject: AccountInstance[]) {
+  return {
+    to: accountsInvolvedInObject.map(a => a.followersUrl),
+    cc: []
+  }
+}
+
+async function getAccountsInvolvedInVideo (video: VideoInstance, t: Transaction) {
+  const accountsToForwardView = await db.VideoShare.loadAccountsByShare(video.id, t)
+  accountsToForwardView.push(video.VideoChannel.Account)
+
+  return accountsToForwardView
+}
+
+async function getAccountsInvolvedInVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) {
+  const accountsToForwardView = await db.VideoChannelShare.loadAccountsByShare(videoChannel.id, t)
+  accountsToForwardView.push(videoChannel.Account)
+
+  return accountsToForwardView
+}
+
+async function getAudience (accountSender: AccountInstance, t: Transaction, isPublic = true) {
+  const followerInboxUrls = await accountSender.getFollowerSharedInboxUrls(t)
 
   // Thanks Mastodon: https://github.com/tootsuite/mastodon/blob/master/app/lib/activitypub/tag_manager.rb#L47
   let to = []
@@ -59,10 +132,26 @@ async function getAudience (accountSender: AccountInstance, isPublic = true) {
   return { to, cc }
 }
 
+async function computeFollowerUris (toAccountFollower: AccountInstance[], followersException: AccountInstance[], t: Transaction) {
+  const toAccountFollowerIds = toAccountFollower.map(a => a.id)
+
+  const result = await db.AccountFollow.listAcceptedFollowerSharedInboxUrls(toAccountFollowerIds, t)
+  const followersSharedInboxException = followersException.map(f => f.sharedInboxUrl)
+  const uris = result.data.filter(sharedInbox => followersSharedInboxException.indexOf(sharedInbox) === -1)
+
+  return uris
+}
+
 // ---------------------------------------------------------------------------
 
 export {
   broadcastToFollowers,
+  getOriginVideoChannelAudience,
   unicastTo,
-  getAudience
+  getAudience,
+  getOriginVideoAudience,
+  getAccountsInvolvedInVideo,
+  getAccountsInvolvedInVideoChannel,
+  getObjectFollowersAudience,
+  forwardActivity
 }