From e251f170b00b2014ac4e823113c6ff40e3fb1471 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 25 May 2018 11:32:36 +0200 Subject: Split files in activitypub server --- server/controllers/activitypub/client.ts | 2 +- server/controllers/activitypub/outbox.ts | 2 +- server/lib/activitypub/audience.ts | 92 ++++++++++ server/lib/activitypub/index.ts | 1 - server/lib/activitypub/process/process-announce.ts | 2 +- server/lib/activitypub/process/process-create.ts | 3 +- server/lib/activitypub/process/process-delete.ts | 2 +- server/lib/activitypub/process/process-like.ts | 2 +- server/lib/activitypub/process/process-undo.ts | 2 +- server/lib/activitypub/process/process-update.ts | 3 +- server/lib/activitypub/send/misc.ts | 196 --------------------- server/lib/activitypub/send/send-accept.ts | 2 +- server/lib/activitypub/send/send-announce.ts | 3 +- server/lib/activitypub/send/send-create.ts | 14 +- server/lib/activitypub/send/send-delete.ts | 3 +- server/lib/activitypub/send/send-follow.ts | 2 +- server/lib/activitypub/send/send-like.ts | 13 +- server/lib/activitypub/send/send-undo.ts | 15 +- server/lib/activitypub/send/send-update.ts | 3 +- server/lib/activitypub/send/utils.ts | 113 ++++++++++++ 20 files changed, 236 insertions(+), 239 deletions(-) create mode 100644 server/lib/activitypub/audience.ts delete mode 100644 server/lib/activitypub/send/misc.ts create mode 100644 server/lib/activitypub/send/utils.ts diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts index 5199b3f81..767fde5d9 100644 --- a/server/controllers/activitypub/client.ts +++ b/server/controllers/activitypub/client.ts @@ -5,7 +5,7 @@ import { activityPubCollectionPagination, activityPubContextify } from '../../he import { pageToStartAndCount } from '../../helpers/core-utils' import { ACTIVITY_PUB, CONFIG, ROUTE_CACHE_LIFETIME } from '../../initializers' import { buildVideoAnnounce } from '../../lib/activitypub/send' -import { audiencify, getAudience } from '../../lib/activitypub/send/misc' +import { audiencify, getAudience } from '../../lib/activitypub/audience' import { createActivityData } from '../../lib/activitypub/send/send-create' import { asyncMiddleware, executeIfActivityPub, localAccountValidator } from '../../middlewares' import { videoChannelsGetValidator, videosGetValidator, videosShareValidator } from '../../middlewares/validators' diff --git a/server/controllers/activitypub/outbox.ts b/server/controllers/activitypub/outbox.ts index 0077e1d0b..c9e087a13 100644 --- a/server/controllers/activitypub/outbox.ts +++ b/server/controllers/activitypub/outbox.ts @@ -6,7 +6,7 @@ import { pageToStartAndCount } from '../../helpers/core-utils' import { logger } from '../../helpers/logger' import { ACTIVITY_PUB } from '../../initializers/constants' import { announceActivityData, createActivityData } from '../../lib/activitypub/send' -import { buildAudience } from '../../lib/activitypub/send/misc' +import { buildAudience } from '../../lib/activitypub/audience' import { asyncMiddleware, localAccountValidator } from '../../middlewares' import { AccountModel } from '../../models/account/account' import { ActorModel } from '../../models/activitypub/actor' diff --git a/server/lib/activitypub/audience.ts b/server/lib/activitypub/audience.ts new file mode 100644 index 000000000..916358fe2 --- /dev/null +++ b/server/lib/activitypub/audience.ts @@ -0,0 +1,92 @@ +import { Transaction } from 'sequelize' +import { ActivityAudience } from '../../../shared/models/activitypub' +import { ACTIVITY_PUB } from '../../initializers' +import { ActorModel } from '../../models/activitypub/actor' +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[]) { + return { + to: [ video.VideoChannel.Account.Actor.url ], + cc: actorsInvolvedInVideo.map(a => a.followersUrl) + } +} + +function getVideoCommentAudience ( + videoComment: VideoCommentModel, + threadParentComments: VideoCommentModel[], + actorsInvolvedInVideo: ActorModel[], + isOrigin = false +) { + const to = [ ACTIVITY_PUB.PUBLIC ] + const cc = [ ] + + // Owner of the video we comment + if (isOrigin === false) { + cc.push(videoComment.Video.VideoChannel.Account.Actor.url) + } + + // Followers of the poster + cc.push(videoComment.Account.Actor.followersUrl) + + // Send to actors we reply to + for (const parentComment of threadParentComments) { + cc.push(parentComment.Account.Actor.url) + } + + return { + to, + cc: cc.concat(actorsInvolvedInVideo.map(a => a.followersUrl)) + } +} + +function getObjectFollowersAudience (actorsInvolvedInObject: ActorModel[]) { + return { + to: [ ACTIVITY_PUB.PUBLIC ].concat(actorsInvolvedInObject.map(a => a.followersUrl)), + cc: [] + } +} + +async function getActorsInvolvedInVideo (video: VideoModel, t: Transaction) { + const actors = await VideoShareModel.loadActorsByShare(video.id, t) + actors.push(video.VideoChannel.Account.Actor) + + return actors +} + +async function getAudience (actorSender: ActorModel, t: Transaction, isPublic = true) { + return buildAudience([ actorSender.followersUrl ], isPublic) +} + +function buildAudience (followerInboxUrls: string[], isPublic = true) { + // Thanks Mastodon: https://github.com/tootsuite/mastodon/blob/master/app/lib/activitypub/tag_manager.rb#L47 + let to = [] + let cc = [] + + if (isPublic) { + to = [ ACTIVITY_PUB.PUBLIC ] + cc = followerInboxUrls + } else { // Unlisted + to = [ ] + cc = [ ] + } + + return { to, cc } +} + +function audiencify (object: T, audience: ActivityAudience) { + return Object.assign(object, audience) +} + +// --------------------------------------------------------------------------- + +export { + buildAudience, + getAudience, + getVideoAudience, + getActorsInvolvedInVideo, + getObjectFollowersAudience, + audiencify, + getVideoCommentAudience +} diff --git a/server/lib/activitypub/index.ts b/server/lib/activitypub/index.ts index 88064c6b6..6906bf9d3 100644 --- a/server/lib/activitypub/index.ts +++ b/server/lib/activitypub/index.ts @@ -1,7 +1,6 @@ export * from './process' export * from './send' export * from './actor' -export * from './fetch' export * from './share' export * from './videos' export * from './video-comments' diff --git a/server/lib/activitypub/process/process-announce.ts b/server/lib/activitypub/process/process-announce.ts index 09f2e80f3..a6e1e2d47 100644 --- a/server/lib/activitypub/process/process-announce.ts +++ b/server/lib/activitypub/process/process-announce.ts @@ -5,7 +5,7 @@ import { ActorModel } from '../../../models/activitypub/actor' import { VideoModel } from '../../../models/video/video' import { VideoShareModel } from '../../../models/video/video-share' import { getOrCreateActorAndServerAndModel } from '../actor' -import { forwardActivity } from '../send/misc' +import { forwardActivity } from '../send/utils' import { getOrCreateAccountAndVideoAndChannel } from '../videos' async function processAnnounceActivity (activity: ActivityAnnounce) { diff --git a/server/lib/activitypub/process/process-create.ts b/server/lib/activitypub/process/process-create.ts index ee180b765..99a5f6f9c 100644 --- a/server/lib/activitypub/process/process-create.ts +++ b/server/lib/activitypub/process/process-create.ts @@ -9,9 +9,10 @@ import { ActorModel } from '../../../models/activitypub/actor' import { VideoAbuseModel } from '../../../models/video/video-abuse' import { VideoCommentModel } from '../../../models/video/video-comment' import { getOrCreateActorAndServerAndModel } from '../actor' -import { forwardActivity, getActorsInvolvedInVideo } from '../send/misc' +import { getActorsInvolvedInVideo } from '../audience' import { resolveThread } from '../video-comments' import { getOrCreateAccountAndVideoAndChannel } from '../videos' +import { forwardActivity } from '../send/utils' async function processCreateActivity (activity: ActivityCreate) { const activityObject = activity.object diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts index b58f6c04a..8310b70f0 100644 --- a/server/lib/activitypub/process/process-delete.ts +++ b/server/lib/activitypub/process/process-delete.ts @@ -8,7 +8,7 @@ import { VideoModel } from '../../../models/video/video' import { VideoChannelModel } from '../../../models/video/video-channel' import { VideoCommentModel } from '../../../models/video/video-comment' import { getOrCreateActorAndServerAndModel } from '../actor' -import { forwardActivity } from '../send/misc' +import { forwardActivity } from '../send/utils' async function processDeleteActivity (activity: ActivityDelete) { const objectUrl = typeof activity.object === 'string' ? activity.object : activity.object.id diff --git a/server/lib/activitypub/process/process-like.ts b/server/lib/activitypub/process/process-like.ts index 0d161b126..d219e76eb 100644 --- a/server/lib/activitypub/process/process-like.ts +++ b/server/lib/activitypub/process/process-like.ts @@ -4,7 +4,7 @@ import { sequelizeTypescript } from '../../../initializers' import { AccountVideoRateModel } from '../../../models/account/account-video-rate' import { ActorModel } from '../../../models/activitypub/actor' import { getOrCreateActorAndServerAndModel } from '../actor' -import { forwardActivity } from '../send/misc' +import { forwardActivity } from '../send/utils' import { getOrCreateAccountAndVideoAndChannel } from '../videos' async function processLikeActivity (activity: ActivityLike) { diff --git a/server/lib/activitypub/process/process-undo.ts b/server/lib/activitypub/process/process-undo.ts index 9b024d15f..d023f7029 100644 --- a/server/lib/activitypub/process/process-undo.ts +++ b/server/lib/activitypub/process/process-undo.ts @@ -8,7 +8,7 @@ import { AccountModel } from '../../../models/account/account' import { AccountVideoRateModel } from '../../../models/account/account-video-rate' import { ActorModel } from '../../../models/activitypub/actor' import { ActorFollowModel } from '../../../models/activitypub/actor-follow' -import { forwardActivity } from '../send/misc' +import { forwardActivity } from '../send/utils' import { getOrCreateAccountAndVideoAndChannel } from '../videos' import { VideoShareModel } from '../../../models/video/video-share' diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts index 0dd657c2b..2750f48c3 100644 --- a/server/lib/activitypub/process/process-update.ts +++ b/server/lib/activitypub/process/process-update.ts @@ -14,7 +14,8 @@ import { VideoFileModel } from '../../../models/video/video-file' import { fetchAvatarIfExists, getOrCreateActorAndServerAndModel, updateActorAvatarInstance, updateActorInstance } from '../actor' import { generateThumbnailFromUrl, - getOrCreateAccountAndVideoAndChannel, getOrCreateVideoChannel, + getOrCreateAccountAndVideoAndChannel, + getOrCreateVideoChannel, videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from '../videos' diff --git a/server/lib/activitypub/send/misc.ts b/server/lib/activitypub/send/misc.ts deleted file mode 100644 index 646aa9f0a..000000000 --- a/server/lib/activitypub/send/misc.ts +++ /dev/null @@ -1,196 +0,0 @@ -import { Transaction } from 'sequelize' -import { Activity, ActivityAudience } from '../../../../shared/models/activitypub' -import { logger } from '../../../helpers/logger' -import { ACTIVITY_PUB } from '../../../initializers' -import { ActorModel } from '../../../models/activitypub/actor' -import { ActorFollowModel } from '../../../models/activitypub/actor-follow' -import { VideoModel } from '../../../models/video/video' -import { VideoCommentModel } from '../../../models/video/video-comment' -import { VideoShareModel } from '../../../models/video/video-share' -import { JobQueue } from '../../job-queue' - -async function forwardActivity ( - activity: Activity, - t: Transaction, - followersException: ActorModel[] = [], - additionalFollowerUrls: string[] = [] -) { - const to = activity.to || [] - const cc = activity.cc || [] - - const followersUrls = additionalFollowerUrls - for (const dest of to.concat(cc)) { - if (dest.endsWith('/followers')) { - followersUrls.push(dest) - } - } - - const toActorFollowers = await ActorModel.listByFollowersUrls(followersUrls, t) - const uris = await computeFollowerUris(toActorFollowers, followersException, t) - - if (uris.length === 0) { - logger.info('0 followers for %s, no forwarding.', toActorFollowers.map(a => a.id).join(', ')) - return undefined - } - - logger.debug('Creating forwarding job.', { uris }) - - const payload = { - uris, - body: activity - } - return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload }) -} - -async function broadcastToFollowers ( - data: any, - byActor: ActorModel, - toActorFollowers: ActorModel[], - t: Transaction, - actorsException: ActorModel[] = [] -) { - const uris = await computeFollowerUris(toActorFollowers, actorsException, t) - return broadcastTo(uris, data, byActor) -} - -async function broadcastToActors ( - data: any, - byActor: ActorModel, - toActors: ActorModel[], - actorsException: ActorModel[] = [] -) { - const uris = await computeUris(toActors, actorsException) - return broadcastTo(uris, data, byActor) -} - -async function broadcastTo (uris: string[], data: any, byActor: ActorModel) { - if (uris.length === 0) return undefined - - logger.debug('Creating broadcast job.', { uris }) - - const payload = { - uris, - signatureActorId: byActor.id, - body: data - } - - return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload }) -} - -async function unicastTo (data: any, byActor: ActorModel, toActorUrl: string) { - logger.debug('Creating unicast job.', { uri: toActorUrl }) - - const payload = { - uri: toActorUrl, - signatureActorId: byActor.id, - body: data - } - - return JobQueue.Instance.createJob({ type: 'activitypub-http-unicast', payload }) -} - -function getOriginVideoAudience (video: VideoModel, actorsInvolvedInVideo: ActorModel[]) { - return { - to: [ video.VideoChannel.Account.Actor.url ], - cc: actorsInvolvedInVideo.map(a => a.followersUrl) - } -} - -function getVideoCommentAudience ( - videoComment: VideoCommentModel, - threadParentComments: VideoCommentModel[], - actorsInvolvedInVideo: ActorModel[], - isOrigin = false -) { - const to = [ ACTIVITY_PUB.PUBLIC ] - const cc = [ ] - - // Owner of the video we comment - if (isOrigin === false) { - cc.push(videoComment.Video.VideoChannel.Account.Actor.url) - } - - // Followers of the poster - cc.push(videoComment.Account.Actor.followersUrl) - - // Send to actors we reply to - for (const parentComment of threadParentComments) { - cc.push(parentComment.Account.Actor.url) - } - - return { - to, - cc: cc.concat(actorsInvolvedInVideo.map(a => a.followersUrl)) - } -} - -function getObjectFollowersAudience (actorsInvolvedInObject: ActorModel[]) { - return { - to: [ ACTIVITY_PUB.PUBLIC ].concat(actorsInvolvedInObject.map(a => a.followersUrl)), - cc: [] - } -} - -async function getActorsInvolvedInVideo (video: VideoModel, t: Transaction) { - const actors = await VideoShareModel.loadActorsByShare(video.id, t) - actors.push(video.VideoChannel.Account.Actor) - - return actors -} - -async function getAudience (actorSender: ActorModel, t: Transaction, isPublic = true) { - return buildAudience([ actorSender.followersUrl ], isPublic) -} - -function buildAudience (followerInboxUrls: string[], isPublic = true) { - // Thanks Mastodon: https://github.com/tootsuite/mastodon/blob/master/app/lib/activitypub/tag_manager.rb#L47 - let to = [] - let cc = [] - - if (isPublic) { - to = [ ACTIVITY_PUB.PUBLIC ] - cc = followerInboxUrls - } else { // Unlisted - to = [ ] - cc = [ ] - } - - return { to, cc } -} - -function audiencify (object: T, audience: ActivityAudience) { - return Object.assign(object, audience) -} - -async function computeFollowerUris (toActorFollower: ActorModel[], actorsException: ActorModel[], t: Transaction) { - const toActorFollowerIds = toActorFollower.map(a => a.id) - - const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t) - const sharedInboxesException = actorsException.map(f => f.sharedInboxUrl || f.inboxUrl) - return result.data.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) -} - -async function computeUris (toActors: ActorModel[], actorsException: ActorModel[] = []) { - const toActorSharedInboxesSet = new Set(toActors.map(a => a.sharedInboxUrl || a.inboxUrl)) - - const sharedInboxesException = actorsException.map(f => f.sharedInboxUrl || f.inboxUrl) - return Array.from(toActorSharedInboxesSet) - .filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) -} - -// --------------------------------------------------------------------------- - -export { - broadcastToFollowers, - unicastTo, - buildAudience, - getAudience, - getOriginVideoAudience, - getActorsInvolvedInVideo, - getObjectFollowersAudience, - forwardActivity, - audiencify, - getVideoCommentAudience, - computeUris, - broadcastToActors -} diff --git a/server/lib/activitypub/send/send-accept.ts b/server/lib/activitypub/send/send-accept.ts index 064fd88d2..44644a22f 100644 --- a/server/lib/activitypub/send/send-accept.ts +++ b/server/lib/activitypub/send/send-accept.ts @@ -2,7 +2,7 @@ import { ActivityAccept, ActivityFollow } from '../../../../shared/models/activi import { ActorModel } from '../../../models/activitypub/actor' import { ActorFollowModel } from '../../../models/activitypub/actor-follow' import { getActorFollowAcceptActivityPubUrl, getActorFollowActivityPubUrl } from '../url' -import { unicastTo } from './misc' +import { unicastTo } from './utils' import { followActivityData } from './send-follow' async function sendAccept (actorFollow: ActorFollowModel) { diff --git a/server/lib/activitypub/send/send-announce.ts b/server/lib/activitypub/send/send-announce.ts index 4179c9d43..fa1d47259 100644 --- a/server/lib/activitypub/send/send-announce.ts +++ b/server/lib/activitypub/send/send-announce.ts @@ -3,7 +3,8 @@ import { ActivityAnnounce, ActivityAudience } from '../../../../shared/models/ac import { ActorModel } from '../../../models/activitypub/actor' import { VideoModel } from '../../../models/video/video' import { VideoShareModel } from '../../../models/video/video-share' -import { broadcastToFollowers, getActorsInvolvedInVideo, getAudience, getObjectFollowersAudience } from './misc' +import { broadcastToFollowers } from './utils' +import { getActorsInvolvedInVideo, getAudience, getObjectFollowersAudience } from '../audience' async function buildVideoAnnounce (byActor: ActorModel, videoShare: VideoShareModel, video: VideoModel, t: Transaction) { const announcedObject = video.url diff --git a/server/lib/activitypub/send/send-create.ts b/server/lib/activitypub/send/send-create.ts index 4ff20b033..3ef4fcd3b 100644 --- a/server/lib/activitypub/send/send-create.ts +++ b/server/lib/activitypub/send/send-create.ts @@ -7,17 +7,15 @@ 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, - broadcastToActors, - broadcastToFollowers, getActorsInvolvedInVideo, getAudience, getObjectFollowersAudience, - getOriginVideoAudience, - getVideoCommentAudience, - unicastTo -} from './misc' + getVideoAudience, + getVideoCommentAudience +} from '../audience' async function sendCreateVideo (video: VideoModel, t: Transaction) { if (video.privacy === VideoPrivacy.PRIVATE) return undefined @@ -83,7 +81,7 @@ async function sendCreateView (byActor: ActorModel, video: VideoModel, t: Transa // Send to origin if (video.isOwned() === false) { - const audience = getOriginVideoAudience(video, actorsInvolvedInVideo) + const audience = getVideoAudience(video, actorsInvolvedInVideo) const data = await createActivityData(url, byActor, viewActivityData, t, audience) return unicastTo(data, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) @@ -107,7 +105,7 @@ async function sendCreateDislike (byActor: ActorModel, video: VideoModel, t: Tra // Send to origin if (video.isOwned() === false) { - const audience = getOriginVideoAudience(video, actorsInvolvedInVideo) + const audience = getVideoAudience(video, actorsInvolvedInVideo) const data = await createActivityData(url, byActor, dislikeActivityData, t, audience) return unicastTo(data, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) diff --git a/server/lib/activitypub/send/send-delete.ts b/server/lib/activitypub/send/send-delete.ts index bb5d6913c..e9a8951b5 100644 --- a/server/lib/activitypub/send/send-delete.ts +++ b/server/lib/activitypub/send/send-delete.ts @@ -5,7 +5,8 @@ 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 { audiencify, broadcastToActors, broadcastToFollowers, getActorsInvolvedInVideo, getVideoCommentAudience, unicastTo } from './misc' +import { broadcastToActors, broadcastToFollowers, unicastTo } from './utils' +import { audiencify, getActorsInvolvedInVideo, getVideoCommentAudience } from '../audience' async function sendDeleteVideo (video: VideoModel, t: Transaction) { const url = getDeleteActivityPubUrl(video.url) diff --git a/server/lib/activitypub/send/send-follow.ts b/server/lib/activitypub/send/send-follow.ts index 4e9865af4..f81d9a194 100644 --- a/server/lib/activitypub/send/send-follow.ts +++ b/server/lib/activitypub/send/send-follow.ts @@ -2,7 +2,7 @@ import { ActivityFollow } from '../../../../shared/models/activitypub' import { ActorModel } from '../../../models/activitypub/actor' import { ActorFollowModel } from '../../../models/activitypub/actor-follow' import { getActorFollowActivityPubUrl } from '../url' -import { unicastTo } from './misc' +import { unicastTo } from './utils' function sendFollow (actorFollow: ActorFollowModel) { const me = actorFollow.ActorFollower diff --git a/server/lib/activitypub/send/send-like.ts b/server/lib/activitypub/send/send-like.ts index fb2b4aaf8..ddeb1fcd2 100644 --- a/server/lib/activitypub/send/send-like.ts +++ b/server/lib/activitypub/send/send-like.ts @@ -3,15 +3,8 @@ import { ActivityAudience, ActivityLike } from '../../../../shared/models/activi import { ActorModel } from '../../../models/activitypub/actor' import { VideoModel } from '../../../models/video/video' import { getVideoLikeActivityPubUrl } from '../url' -import { - audiencify, - broadcastToFollowers, - getActorsInvolvedInVideo, - getAudience, - getObjectFollowersAudience, - getOriginVideoAudience, - unicastTo -} from './misc' +import { broadcastToFollowers, unicastTo } from './utils' +import { audiencify, getActorsInvolvedInVideo, getAudience, getObjectFollowersAudience, getVideoAudience } from '../audience' async function sendLike (byActor: ActorModel, video: VideoModel, t: Transaction) { const url = getVideoLikeActivityPubUrl(byActor, video) @@ -20,7 +13,7 @@ async function sendLike (byActor: ActorModel, video: VideoModel, t: Transaction) // Send to origin if (video.isOwned() === false) { - const audience = getOriginVideoAudience(video, accountsInvolvedInVideo) + const audience = getVideoAudience(video, accountsInvolvedInVideo) const data = await likeActivityData(url, byActor, video, t, audience) return unicastTo(data, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) diff --git a/server/lib/activitypub/send/send-undo.ts b/server/lib/activitypub/send/send-undo.ts index adee2192f..9733e66dc 100644 --- a/server/lib/activitypub/send/send-undo.ts +++ b/server/lib/activitypub/send/send-undo.ts @@ -11,15 +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 { - audiencify, - broadcastToFollowers, - getActorsInvolvedInVideo, - getAudience, - getObjectFollowersAudience, - getOriginVideoAudience, - unicastTo -} from './misc' +import { broadcastToFollowers, unicastTo } from './utils' +import { audiencify, getActorsInvolvedInVideo, getAudience, getObjectFollowersAudience, getVideoAudience } from '../audience' import { createActivityData, createDislikeActivityData } from './send-create' import { followActivityData } from './send-follow' import { likeActivityData } from './send-like' @@ -48,7 +41,7 @@ async function sendUndoLike (byActor: ActorModel, video: VideoModel, t: Transact // Send to origin if (video.isOwned() === false) { - const audience = getOriginVideoAudience(video, actorsInvolvedInVideo) + const audience = getVideoAudience(video, actorsInvolvedInVideo) const data = await undoActivityData(undoUrl, byActor, object, t, audience) return unicastTo(data, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) @@ -70,7 +63,7 @@ async function sendUndoDislike (byActor: ActorModel, video: VideoModel, t: Trans const object = await createActivityData(dislikeUrl, byActor, dislikeActivity, t) if (video.isOwned() === false) { - const audience = getOriginVideoAudience(video, actorsInvolvedInVideo) + const audience = getVideoAudience(video, actorsInvolvedInVideo) const data = await undoActivityData(undoUrl, byActor, object, t, audience) return unicastTo(data, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) diff --git a/server/lib/activitypub/send/send-update.ts b/server/lib/activitypub/send/send-update.ts index e15fecff6..d64b88343 100644 --- a/server/lib/activitypub/send/send-update.ts +++ b/server/lib/activitypub/send/send-update.ts @@ -7,7 +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 { audiencify, broadcastToFollowers, getAudience } from './misc' +import { broadcastToFollowers } from './utils' +import { audiencify, getAudience } from '../audience' async function sendUpdateVideo (video: VideoModel, t: Transaction) { const byActor = video.VideoChannel.Account.Actor diff --git a/server/lib/activitypub/send/utils.ts b/server/lib/activitypub/send/utils.ts new file mode 100644 index 000000000..80d4463ff --- /dev/null +++ b/server/lib/activitypub/send/utils.ts @@ -0,0 +1,113 @@ +import { Transaction } from 'sequelize' +import { Activity } 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' + +async function forwardActivity ( + activity: Activity, + t: Transaction, + followersException: ActorModel[] = [], + additionalFollowerUrls: string[] = [] +) { + const to = activity.to || [] + const cc = activity.cc || [] + + const followersUrls = additionalFollowerUrls + for (const dest of to.concat(cc)) { + if (dest.endsWith('/followers')) { + followersUrls.push(dest) + } + } + + const toActorFollowers = await ActorModel.listByFollowersUrls(followersUrls, t) + const uris = await computeFollowerUris(toActorFollowers, followersException, t) + + if (uris.length === 0) { + logger.info('0 followers for %s, no forwarding.', toActorFollowers.map(a => a.id).join(', ')) + return undefined + } + + logger.debug('Creating forwarding job.', { uris }) + + const payload = { + uris, + body: activity + } + return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload }) +} + +async function broadcastToFollowers ( + data: any, + byActor: ActorModel, + toActorFollowers: ActorModel[], + t: Transaction, + actorsException: ActorModel[] = [] +) { + const uris = await computeFollowerUris(toActorFollowers, actorsException, t) + return broadcastTo(uris, data, byActor) +} + +async function broadcastToActors ( + data: any, + byActor: ActorModel, + toActors: ActorModel[], + actorsException: ActorModel[] = [] +) { + const uris = await computeUris(toActors, actorsException) + return broadcastTo(uris, data, byActor) +} + +async function broadcastTo (uris: string[], data: any, byActor: ActorModel) { + if (uris.length === 0) return undefined + + logger.debug('Creating broadcast job.', { uris }) + + const payload = { + uris, + signatureActorId: byActor.id, + body: data + } + + return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload }) +} + +async function unicastTo (data: any, byActor: ActorModel, toActorUrl: string) { + logger.debug('Creating unicast job.', { uri: toActorUrl }) + + const payload = { + uri: toActorUrl, + signatureActorId: byActor.id, + body: data + } + + return JobQueue.Instance.createJob({ type: 'activitypub-http-unicast', payload }) +} + +// --------------------------------------------------------------------------- + +export { + broadcastToFollowers, + unicastTo, + forwardActivity, + broadcastToActors +} + +// --------------------------------------------------------------------------- + +async function computeFollowerUris (toActorFollower: ActorModel[], actorsException: ActorModel[], t: Transaction) { + const toActorFollowerIds = toActorFollower.map(a => a.id) + + const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t) + const sharedInboxesException = actorsException.map(f => f.sharedInboxUrl || f.inboxUrl) + return result.data.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) +} + +async function computeUris (toActors: ActorModel[], actorsException: ActorModel[] = []) { + const toActorSharedInboxesSet = new Set(toActors.map(a => a.sharedInboxUrl || a.inboxUrl)) + + const sharedInboxesException = actorsException.map(f => f.sharedInboxUrl || f.inboxUrl) + return Array.from(toActorSharedInboxesSet) + .filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) +} -- cgit v1.2.3