From a2377d15ee09301cf4cc5434ad865a21918da15f Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 14 Sep 2018 16:51:35 +0200 Subject: [PATCH] Refractor activities sending --- server/controllers/api/videos/index.ts | 4 +- server/lib/activitypub/audience.ts | 10 +- .../lib/activitypub/process/process-delete.ts | 2 + server/lib/activitypub/send/send-announce.ts | 4 +- server/lib/activitypub/send/send-create.ts | 95 +++++++++---------- server/lib/activitypub/send/send-delete.ts | 13 +-- server/lib/activitypub/send/send-like.ts | 23 ++--- server/lib/activitypub/send/send-undo.ts | 85 +++++++---------- server/lib/activitypub/send/send-update.ts | 16 ++-- server/lib/activitypub/send/utils.ts | 30 +++++- server/tests/api/server/stats.ts | 3 - 11 files changed, 135 insertions(+), 150 deletions(-) diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 0c9e6c2d1..8353a649a 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts @@ -393,9 +393,9 @@ async function viewVideo (req: express.Request, res: express.Response) { Redis.Instance.setIPVideoView(ip, videoInstance.uuid) ]) - const serverAccount = await getServerActor() + const serverActor = await getServerActor() - await sendCreateView(serverAccount, videoInstance, undefined) + await sendCreateView(serverActor, videoInstance, undefined) return res.status(204).end() } diff --git a/server/lib/activitypub/audience.ts b/server/lib/activitypub/audience.ts index 7b4067c11..a86428461 100644 --- a/server/lib/activitypub/audience.ts +++ b/server/lib/activitypub/audience.ts @@ -6,7 +6,7 @@ import { VideoModel } from '../../models/video/video' import { VideoCommentModel } from '../../models/video/video-comment' import { VideoShareModel } from '../../models/video/video-share' -function getVideoAudience (video: VideoModel, actorsInvolvedInVideo: ActorModel[]) { +function getRemoteVideoAudience (video: VideoModel, actorsInvolvedInVideo: ActorModel[]): ActivityAudience { return { to: [ video.VideoChannel.Account.Actor.url ], cc: actorsInvolvedInVideo.map(a => a.followersUrl) @@ -18,7 +18,7 @@ function getVideoCommentAudience ( threadParentComments: VideoCommentModel[], actorsInvolvedInVideo: ActorModel[], isOrigin = false -) { +): ActivityAudience { const to = [ ACTIVITY_PUB.PUBLIC ] const cc: string[] = [] @@ -41,7 +41,7 @@ function getVideoCommentAudience ( } } -function getObjectFollowersAudience (actorsInvolvedInObject: ActorModel[]) { +function getAudienceFromFollowersOf (actorsInvolvedInObject: ActorModel[]): ActivityAudience { return { to: [ ACTIVITY_PUB.PUBLIC ].concat(actorsInvolvedInObject.map(a => a.followersUrl)), cc: [] @@ -83,9 +83,9 @@ function audiencify (object: T, audience: ActivityAudience) { export { buildAudience, getAudience, - getVideoAudience, + getRemoteVideoAudience, getActorsInvolvedInVideo, - getObjectFollowersAudience, + getAudienceFromFollowersOf, audiencify, getVideoCommentAudience } diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts index 3c830abea..4c034a81c 100644 --- a/server/lib/activitypub/process/process-delete.ts +++ b/server/lib/activitypub/process/process-delete.ts @@ -41,6 +41,8 @@ async function processDeleteActivity (activity: ActivityDelete) { { const videoInstance = await VideoModel.loadByUrlAndPopulateAccount(objectUrl) if (videoInstance) { + if (videoInstance.isOwned()) throw new Error(`Remote instance cannot delete owned video ${videoInstance.url}.`) + return retryTransactionWrapper(processDeleteVideo, actor, videoInstance) } } diff --git a/server/lib/activitypub/send/send-announce.ts b/server/lib/activitypub/send/send-announce.ts index f137217f8..cd0cab7ee 100644 --- a/server/lib/activitypub/send/send-announce.ts +++ b/server/lib/activitypub/send/send-announce.ts @@ -4,14 +4,14 @@ import { ActorModel } from '../../../models/activitypub/actor' import { VideoModel } from '../../../models/video/video' import { VideoShareModel } from '../../../models/video/video-share' import { broadcastToFollowers } from './utils' -import { audiencify, getActorsInvolvedInVideo, getAudience, getObjectFollowersAudience } from '../audience' +import { audiencify, getActorsInvolvedInVideo, getAudience, getAudienceFromFollowersOf } from '../audience' import { logger } from '../../../helpers/logger' async function buildAnnounceWithVideoAudience (byActor: ActorModel, videoShare: VideoShareModel, video: VideoModel, t: Transaction) { const announcedObject = video.url const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, t) - const audience = getObjectFollowersAudience(actorsInvolvedInVideo) + const audience = getAudienceFromFollowersOf(actorsInvolvedInVideo) const activity = buildAnnounceActivity(videoShare.url, byActor, announcedObject, audience) diff --git a/server/lib/activitypub/send/send-create.ts b/server/lib/activitypub/send/send-create.ts index 6f89b1a22..285edba3b 100644 --- a/server/lib/activitypub/send/send-create.ts +++ b/server/lib/activitypub/send/send-create.ts @@ -1,21 +1,13 @@ import { Transaction } from 'sequelize' import { ActivityAudience, ActivityCreate } from '../../../../shared/models/activitypub' import { VideoPrivacy } from '../../../../shared/models/videos' -import { getServerActor } from '../../../helpers/utils' import { ActorModel } from '../../../models/activitypub/actor' import { VideoModel } from '../../../models/video/video' import { VideoAbuseModel } from '../../../models/video/video-abuse' import { VideoCommentModel } from '../../../models/video/video-comment' import { getVideoAbuseActivityPubUrl, getVideoDislikeActivityPubUrl, getVideoViewActivityPubUrl } from '../url' -import { broadcastToActors, broadcastToFollowers, unicastTo } from './utils' -import { - audiencify, - getActorsInvolvedInVideo, - getAudience, - getObjectFollowersAudience, - getVideoAudience, - getVideoCommentAudience -} from '../audience' +import { broadcastToActors, broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils' +import { audiencify, getActorsInvolvedInVideo, getAudience, getAudienceFromFollowersOf, getVideoCommentAudience } from '../audience' import { logger } from '../../../helpers/logger' import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy' @@ -40,6 +32,7 @@ async function sendVideoAbuse (byActor: ActorModel, videoAbuse: VideoAbuseModel, logger.info('Creating job to send video abuse %s.', url) + // Custom audience, we only send the abuse to the origin instance const audience = { to: [ video.VideoChannel.Account.Actor.url ], cc: [] } const createActivity = buildCreateActivity(url, byActor, videoAbuse.toActivityPubObject(), audience) @@ -49,15 +42,15 @@ async function sendVideoAbuse (byActor: ActorModel, videoAbuse: VideoAbuseModel, async function sendCreateCacheFile (byActor: ActorModel, fileRedundancy: VideoRedundancyModel) { logger.info('Creating job to send file cache of %s.', fileRedundancy.url) - const redundancyObject = fileRedundancy.toActivityPubObject() - const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(fileRedundancy.VideoFile.Video.id) - const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, undefined) - - const audience = getVideoAudience(video, actorsInvolvedInVideo) - const createActivity = buildCreateActivity(fileRedundancy.url, byActor, redundancyObject, audience) + const redundancyObject = fileRedundancy.toActivityPubObject() - return unicastTo(createActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) + return sendVideoRelatedCreateActivity({ + byActor, + video, + url: fileRedundancy.url, + object: redundancyObject + }) } async function sendCreateVideoComment (comment: VideoCommentModel, t: Transaction) { @@ -70,6 +63,7 @@ async function sendCreateVideoComment (comment: VideoCommentModel, t: Transactio const commentObject = comment.toActivityPubObject(threadParentComments) const actorsInvolvedInComment = await getActorsInvolvedInVideo(comment.Video, t) + // Add the actor that commented too actorsInvolvedInComment.push(byActor) const parentsCommentActors = threadParentComments.map(c => c.Account.Actor) @@ -78,7 +72,7 @@ async function sendCreateVideoComment (comment: VideoCommentModel, t: Transactio if (isOrigin) { audience = getVideoCommentAudience(comment, threadParentComments, actorsInvolvedInComment, isOrigin) } else { - audience = getObjectFollowersAudience(actorsInvolvedInComment.concat(parentsCommentActors)) + audience = getAudienceFromFollowersOf(actorsInvolvedInComment.concat(parentsCommentActors)) } const createActivity = buildCreateActivity(comment.url, byActor, commentObject, audience) @@ -103,24 +97,14 @@ async function sendCreateView (byActor: ActorModel, video: VideoModel, t: Transa const url = getVideoViewActivityPubUrl(byActor, video) const viewActivity = buildViewActivity(byActor, video) - const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, t) - - // Send to origin - if (video.isOwned() === false) { - const audience = getVideoAudience(video, actorsInvolvedInVideo) - const createActivity = buildCreateActivity(url, byActor, viewActivity, audience) - - return unicastTo(createActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) - } - - // Send to followers - const audience = getObjectFollowersAudience(actorsInvolvedInVideo) - const createActivity = buildCreateActivity(url, byActor, viewActivity, audience) - - // Use the server actor to send the view - const serverActor = await getServerActor() - const actorsException = [ byActor ] - return broadcastToFollowers(createActivity, serverActor, actorsInvolvedInVideo, t, actorsException) + return sendVideoRelatedCreateActivity({ + // Use the server actor to send the view + byActor, + video, + url, + object: viewActivity, + transaction: t + }) } async function sendCreateDislike (byActor: ActorModel, video: VideoModel, t: Transaction) { @@ -129,22 +113,13 @@ async function sendCreateDislike (byActor: ActorModel, video: VideoModel, t: Tra const url = getVideoDislikeActivityPubUrl(byActor, video) const dislikeActivity = buildDislikeActivity(byActor, video) - const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, t) - - // Send to origin - if (video.isOwned() === false) { - const audience = getVideoAudience(video, actorsInvolvedInVideo) - const createActivity = buildCreateActivity(url, byActor, dislikeActivity, audience) - - return unicastTo(createActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) - } - - // Send to followers - const audience = getObjectFollowersAudience(actorsInvolvedInVideo) - const createActivity = buildCreateActivity(url, byActor, dislikeActivity, audience) - - const actorsException = [ byActor ] - return broadcastToFollowers(createActivity, byActor, actorsInvolvedInVideo, t, actorsException) + return sendVideoRelatedCreateActivity({ + byActor, + video, + url, + object: dislikeActivity, + transaction: t + }) } function buildCreateActivity (url: string, byActor: ActorModel, object: any, audience?: ActivityAudience): ActivityCreate { @@ -189,3 +164,19 @@ export { sendCreateVideoComment, sendCreateCacheFile } + +// --------------------------------------------------------------------------- + +async function sendVideoRelatedCreateActivity (options: { + byActor: ActorModel, + video: VideoModel, + url: string, + object: any, + transaction?: Transaction +}) { + const activityBuilder = (audience: ActivityAudience) => { + return buildCreateActivity(options.url, options.byActor, options.object, audience) + } + + return sendVideoRelatedActivity(activityBuilder, options) +} diff --git a/server/lib/activitypub/send/send-delete.ts b/server/lib/activitypub/send/send-delete.ts index 479182543..18969433a 100644 --- a/server/lib/activitypub/send/send-delete.ts +++ b/server/lib/activitypub/send/send-delete.ts @@ -5,21 +5,22 @@ import { VideoModel } from '../../../models/video/video' import { VideoCommentModel } from '../../../models/video/video-comment' import { VideoShareModel } from '../../../models/video/video-share' import { getDeleteActivityPubUrl } from '../url' -import { broadcastToActors, broadcastToFollowers, unicastTo } from './utils' +import { broadcastToActors, broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils' import { audiencify, getActorsInvolvedInVideo, getVideoCommentAudience } from '../audience' import { logger } from '../../../helpers/logger' -async function sendDeleteVideo (video: VideoModel, t: Transaction) { +async function sendDeleteVideo (video: VideoModel, transaction: Transaction) { logger.info('Creating job to broadcast delete of video %s.', video.url) - const url = getDeleteActivityPubUrl(video.url) const byActor = video.VideoChannel.Account.Actor - const activity = buildDeleteActivity(url, video.url, byActor) + const activityBuilder = (audience: ActivityAudience) => { + const url = getDeleteActivityPubUrl(video.url) - const actorsInvolved = await getActorsInvolvedInVideo(video, t) + return buildDeleteActivity(url, video.url, byActor, audience) + } - return broadcastToFollowers(activity, byActor, actorsInvolved, t) + return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction }) } async function sendDeleteActor (byActor: ActorModel, t: Transaction) { diff --git a/server/lib/activitypub/send/send-like.ts b/server/lib/activitypub/send/send-like.ts index a5408ac6a..89307acc6 100644 --- a/server/lib/activitypub/send/send-like.ts +++ b/server/lib/activitypub/send/send-like.ts @@ -3,31 +3,20 @@ import { ActivityAudience, ActivityLike } from '../../../../shared/models/activi import { ActorModel } from '../../../models/activitypub/actor' import { VideoModel } from '../../../models/video/video' import { getVideoLikeActivityPubUrl } from '../url' -import { broadcastToFollowers, unicastTo } from './utils' -import { audiencify, getActorsInvolvedInVideo, getAudience, getObjectFollowersAudience, getVideoAudience } from '../audience' +import { sendVideoRelatedActivity } from './utils' +import { audiencify, getAudience } from '../audience' import { logger } from '../../../helpers/logger' async function sendLike (byActor: ActorModel, video: VideoModel, t: Transaction) { logger.info('Creating job to like %s.', video.url) - const url = getVideoLikeActivityPubUrl(byActor, video) + const activityBuilder = (audience: ActivityAudience) => { + const url = getVideoLikeActivityPubUrl(byActor, video) - const accountsInvolvedInVideo = await getActorsInvolvedInVideo(video, t) - - // Send to origin - if (video.isOwned() === false) { - const audience = getVideoAudience(video, accountsInvolvedInVideo) - const data = buildLikeActivity(url, byActor, video, audience) - - return unicastTo(data, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) + return buildLikeActivity(url, byActor, video, audience) } - // Send to followers - const audience = getObjectFollowersAudience(accountsInvolvedInVideo) - const activity = buildLikeActivity(url, byActor, video, audience) - - const followersException = [ byActor ] - return broadcastToFollowers(activity, byActor, accountsInvolvedInVideo, t, followersException) + return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction: t }) } function buildLikeActivity (url: string, byActor: ActorModel, video: VideoModel, audience?: ActivityAudience): ActivityLike { diff --git a/server/lib/activitypub/send/send-undo.ts b/server/lib/activitypub/send/send-undo.ts index a50673c79..5236d2cb3 100644 --- a/server/lib/activitypub/send/send-undo.ts +++ b/server/lib/activitypub/send/send-undo.ts @@ -11,8 +11,8 @@ import { ActorModel } from '../../../models/activitypub/actor' import { ActorFollowModel } from '../../../models/activitypub/actor-follow' import { VideoModel } from '../../../models/video/video' import { getActorFollowActivityPubUrl, getUndoActivityPubUrl, getVideoDislikeActivityPubUrl, getVideoLikeActivityPubUrl } from '../url' -import { broadcastToFollowers, unicastTo } from './utils' -import { audiencify, getActorsInvolvedInVideo, getAudience, getObjectFollowersAudience, getVideoAudience } from '../audience' +import { broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils' +import { audiencify, getAudience } from '../audience' import { buildCreateActivity, buildDislikeActivity } from './send-create' import { buildFollowActivity } from './send-follow' import { buildLikeActivity } from './send-like' @@ -39,79 +39,44 @@ async function sendUndoFollow (actorFollow: ActorFollowModel, t: Transaction) { return unicastTo(undoActivity, me, following.inboxUrl) } -async function sendUndoLike (byActor: ActorModel, video: VideoModel, t: Transaction) { - logger.info('Creating job to undo a like of video %s.', video.url) +async function sendUndoAnnounce (byActor: ActorModel, videoShare: VideoShareModel, video: VideoModel, t: Transaction) { + logger.info('Creating job to undo announce %s.', videoShare.url) - const likeUrl = getVideoLikeActivityPubUrl(byActor, video) - const undoUrl = getUndoActivityPubUrl(likeUrl) + const undoUrl = getUndoActivityPubUrl(videoShare.url) - const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, t) - const likeActivity = buildLikeActivity(likeUrl, byActor, video) + const { activity: announceActivity, actorsInvolvedInVideo } = await buildAnnounceWithVideoAudience(byActor, videoShare, video, t) + const undoActivity = undoActivityData(undoUrl, byActor, announceActivity) - // Send to origin - if (video.isOwned() === false) { - const audience = getVideoAudience(video, actorsInvolvedInVideo) - const undoActivity = undoActivityData(undoUrl, byActor, likeActivity, audience) + const followersException = [ byActor ] + return broadcastToFollowers(undoActivity, byActor, actorsInvolvedInVideo, t, followersException) +} - return unicastTo(undoActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) - } +async function sendUndoLike (byActor: ActorModel, video: VideoModel, t: Transaction) { + logger.info('Creating job to undo a like of video %s.', video.url) - const audience = getObjectFollowersAudience(actorsInvolvedInVideo) - const undoActivity = undoActivityData(undoUrl, byActor, likeActivity, audience) + const likeUrl = getVideoLikeActivityPubUrl(byActor, video) + const likeActivity = buildLikeActivity(likeUrl, byActor, video) - const followersException = [ byActor ] - return broadcastToFollowers(undoActivity, byActor, actorsInvolvedInVideo, t, followersException) + return sendUndoVideoRelatedActivity({ byActor, video, url: likeUrl, activity: likeActivity, transaction: t }) } async function sendUndoDislike (byActor: ActorModel, video: VideoModel, t: Transaction) { logger.info('Creating job to undo a dislike of video %s.', video.url) const dislikeUrl = getVideoDislikeActivityPubUrl(byActor, video) - const undoUrl = getUndoActivityPubUrl(dislikeUrl) - - const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, t) const dislikeActivity = buildDislikeActivity(byActor, video) const createDislikeActivity = buildCreateActivity(dislikeUrl, byActor, dislikeActivity) - if (video.isOwned() === false) { - const audience = getVideoAudience(video, actorsInvolvedInVideo) - const undoActivity = undoActivityData(undoUrl, byActor, createDislikeActivity, audience) - - return unicastTo(undoActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) - } - - const undoActivity = undoActivityData(undoUrl, byActor, createDislikeActivity) - - const followersException = [ byActor ] - return broadcastToFollowers(undoActivity, byActor, actorsInvolvedInVideo, t, followersException) -} - -async function sendUndoAnnounce (byActor: ActorModel, videoShare: VideoShareModel, video: VideoModel, t: Transaction) { - logger.info('Creating job to undo announce %s.', videoShare.url) - - const undoUrl = getUndoActivityPubUrl(videoShare.url) - - const { activity: announceActivity, actorsInvolvedInVideo } = await buildAnnounceWithVideoAudience(byActor, videoShare, video, t) - const undoActivity = undoActivityData(undoUrl, byActor, announceActivity) - - const followersException = [ byActor ] - return broadcastToFollowers(undoActivity, byActor, actorsInvolvedInVideo, t, followersException) + return sendUndoVideoRelatedActivity({ byActor, video, url: dislikeUrl, activity: createDislikeActivity, transaction: t }) } async function sendUndoCacheFile (byActor: ActorModel, redundancyModel: VideoRedundancyModel, t: Transaction) { logger.info('Creating job to undo cache file %s.', redundancyModel.url) - const undoUrl = getUndoActivityPubUrl(redundancyModel.url) - const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(redundancyModel.VideoFile.Video.id) - const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, t) - - const audience = getVideoAudience(video, actorsInvolvedInVideo) const createActivity = buildCreateActivity(redundancyModel.url, byActor, redundancyModel.toActivityPubObject()) - const undoActivity = undoActivityData(undoUrl, byActor, createActivity, audience) - - return unicastTo(undoActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) + return sendUndoVideoRelatedActivity({ byActor, video, url: redundancyModel.url, activity: createActivity, transaction: t }) } // --------------------------------------------------------------------------- @@ -144,3 +109,19 @@ function undoActivityData ( audience ) } + +async function sendUndoVideoRelatedActivity (options: { + byActor: ActorModel, + video: VideoModel, + url: string, + activity: ActivityFollow | ActivityLike | ActivityCreate | ActivityAnnounce, + transaction: Transaction +}) { + const activityBuilder = (audience: ActivityAudience) => { + const undoUrl = getUndoActivityPubUrl(options.url) + + return undoActivityData(undoUrl, options.byActor, options.activity, audience) + } + + return sendVideoRelatedActivity(activityBuilder, options) +} diff --git a/server/lib/activitypub/send/send-update.ts b/server/lib/activitypub/send/send-update.ts index 605473338..ec46789b7 100644 --- a/server/lib/activitypub/send/send-update.ts +++ b/server/lib/activitypub/send/send-update.ts @@ -7,8 +7,8 @@ import { VideoModel } from '../../../models/video/video' import { VideoChannelModel } from '../../../models/video/video-channel' import { VideoShareModel } from '../../../models/video/video-share' import { getUpdateActivityPubUrl } from '../url' -import { broadcastToFollowers, unicastTo } from './utils' -import { audiencify, getActorsInvolvedInVideo, getAudience, getObjectFollowersAudience } from '../audience' +import { broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils' +import { audiencify, getActorsInvolvedInVideo, getAudience, getAudienceFromFollowersOf } from '../audience' import { logger } from '../../../helpers/logger' import { VideoCaptionModel } from '../../../models/video/video-caption' import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy' @@ -61,16 +61,16 @@ async function sendUpdateActor (accountOrChannel: AccountModel | VideoChannelMod async function sendUpdateCacheFile (byActor: ActorModel, redundancyModel: VideoRedundancyModel) { logger.info('Creating job to update cache file %s.', redundancyModel.url) - const url = getUpdateActivityPubUrl(redundancyModel.url, redundancyModel.updatedAt.toISOString()) const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(redundancyModel.VideoFile.Video.id) - const redundancyObject = redundancyModel.toActivityPubObject() + const activityBuilder = (audience: ActivityAudience) => { + const redundancyObject = redundancyModel.toActivityPubObject() + const url = getUpdateActivityPubUrl(redundancyModel.url, redundancyModel.updatedAt.toISOString()) - const accountsInvolvedInVideo = await getActorsInvolvedInVideo(video, undefined) - const audience = getObjectFollowersAudience(accountsInvolvedInVideo) + return buildUpdateActivity(url, byActor, redundancyObject, audience) + } - const updateActivity = buildUpdateActivity(url, byActor, redundancyObject, audience) - return unicastTo(updateActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) + return sendVideoRelatedActivity(activityBuilder, { byActor, video }) } // --------------------------------------------------------------------------- diff --git a/server/lib/activitypub/send/utils.ts b/server/lib/activitypub/send/utils.ts index c20c15633..69706e620 100644 --- a/server/lib/activitypub/send/utils.ts +++ b/server/lib/activitypub/send/utils.ts @@ -1,13 +1,36 @@ import { Transaction } from 'sequelize' -import { Activity } from '../../../../shared/models/activitypub' +import { Activity, ActivityAudience } from '../../../../shared/models/activitypub' import { logger } from '../../../helpers/logger' import { ActorModel } from '../../../models/activitypub/actor' import { ActorFollowModel } from '../../../models/activitypub/actor-follow' import { JobQueue } from '../../job-queue' import { VideoModel } from '../../../models/video/video' -import { getActorsInvolvedInVideo } from '../audience' +import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience' import { getServerActor } from '../../../helpers/utils' +async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { + byActor: ActorModel, + video: VideoModel, + transaction?: Transaction +}) { + const actorsInvolvedInVideo = await getActorsInvolvedInVideo(options.video, options.transaction) + + // Send to origin + if (options.video.isOwned() === false) { + const audience = getRemoteVideoAudience(options.video, actorsInvolvedInVideo) + const activity = activityBuilder(audience) + + return unicastTo(activity, options.byActor, options.video.VideoChannel.Account.Actor.sharedInboxUrl) + } + + // Send to followers + const audience = getAudienceFromFollowersOf(actorsInvolvedInVideo) + const activity = activityBuilder(audience) + + const actorsException = [ options.byActor ] + return broadcastToFollowers(activity, options.byActor, actorsInvolvedInVideo, options.transaction, actorsException) +} + async function forwardVideoRelatedActivity ( activity: Activity, t: Transaction, @@ -110,7 +133,8 @@ export { unicastTo, forwardActivity, broadcastToActors, - forwardVideoRelatedActivity + forwardVideoRelatedActivity, + sendVideoRelatedActivity } // --------------------------------------------------------------------------- diff --git a/server/tests/api/server/stats.ts b/server/tests/api/server/stats.ts index d8a3268bb..cb229e876 100644 --- a/server/tests/api/server/stats.ts +++ b/server/tests/api/server/stats.ts @@ -65,7 +65,6 @@ describe('Test stats (excluding redundancy)', function () { expect(data.totalVideos).to.equal(1) expect(data.totalInstanceFollowers).to.equal(2) expect(data.totalInstanceFollowing).to.equal(1) - expect(data.videosRedundancy).to.have.lengthOf(0) }) it('Should have the correct stats on instance 2', async function () { @@ -80,7 +79,6 @@ describe('Test stats (excluding redundancy)', function () { expect(data.totalVideos).to.equal(1) expect(data.totalInstanceFollowers).to.equal(1) expect(data.totalInstanceFollowing).to.equal(1) - expect(data.videosRedundancy).to.have.lengthOf(0) }) it('Should have the correct stats on instance 3', async function () { @@ -95,7 +93,6 @@ describe('Test stats (excluding redundancy)', function () { expect(data.totalVideos).to.equal(1) expect(data.totalInstanceFollowing).to.equal(1) expect(data.totalInstanceFollowers).to.equal(0) - expect(data.videosRedundancy).to.have.lengthOf(0) }) after(async function () { -- 2.41.0