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'
+import { afterCommitIfTransaction } from '../../../helpers/database-utils'
+import { MActorFollowerException, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models'
+
+async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: {
+ byActor: MActorLight,
+ video: MVideoAccountLight,
+ transaction?: Transaction
+}) {
+ const { byActor, video, transaction } = options
+
+ const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, transaction)
+
+ // Send to origin
+ if (video.isOwned() === false) {
+ const audience = getRemoteVideoAudience(video, actorsInvolvedInVideo)
+ const activity = activityBuilder(audience)
+
+ return afterCommitIfTransaction(transaction, () => {
+ return unicastTo(activity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl)
+ })
+ }
+
+ // Send to followers
+ const audience = getAudienceFromFollowersOf(actorsInvolvedInVideo)
+ const activity = activityBuilder(audience)
+
+ const actorsException = [ byActor ]
+
+ return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, transaction, actorsException)
+}
async function forwardVideoRelatedActivity (
activity: Activity,
t: Transaction,
- followersException: ActorModel[] = [],
- video: VideoModel
+ followersException: MActorFollowerException[] = [],
+ video: MVideo
) {
// Mastodon does not add our announces in audience, so we forward to them manually
const additionalActors = await getActorsInvolvedInVideo(video, t)
async function forwardActivity (
activity: Activity,
t: Transaction,
- followersException: ActorModel[] = [],
+ followersException: MActorFollowerException[] = [],
additionalFollowerUrls: string[] = []
) {
logger.info('Forwarding activity %s.', activity.id)
uris,
body: activity
}
- return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload })
+ return afterCommitIfTransaction(t, () => JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload }))
}
async function broadcastToFollowers (
data: any,
- byActor: ActorModel,
- toActorFollowers: ActorModel[],
+ byActor: MActorId,
+ toFollowersOf: MActorId[],
t: Transaction,
- actorsException: ActorModel[] = []
+ actorsException: MActorFollowerException[] = []
) {
- const uris = await computeFollowerUris(toActorFollowers, actorsException, t)
- return broadcastTo(uris, data, byActor)
+ const uris = await computeFollowerUris(toFollowersOf, actorsException, t)
+
+ return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor))
}
async function broadcastToActors (
data: any,
- byActor: ActorModel,
- toActors: ActorModel[],
- actorsException: ActorModel[] = []
+ byActor: MActorId,
+ toActors: MActor[],
+ t?: Transaction,
+ actorsException: MActorFollowerException[] = []
) {
const uris = await computeUris(toActors, actorsException)
- return broadcastTo(uris, data, byActor)
+ return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor))
}
-async function broadcastTo (uris: string[], data: any, byActor: ActorModel) {
+function broadcastTo (uris: string[], data: any, byActor: MActorId) {
if (uris.length === 0) return undefined
logger.debug('Creating broadcast job.', { uris })
return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload })
}
-async function unicastTo (data: any, byActor: ActorModel, toActorUrl: string) {
+function unicastTo (data: any, byActor: MActorId, toActorUrl: string) {
logger.debug('Creating unicast job.', { uri: toActorUrl })
const payload = {
body: data
}
- return JobQueue.Instance.createJob({ type: 'activitypub-http-unicast', payload })
+ JobQueue.Instance.createJob({ type: 'activitypub-http-unicast', payload })
}
// ---------------------------------------------------------------------------
unicastTo,
forwardActivity,
broadcastToActors,
- forwardVideoRelatedActivity
+ forwardVideoRelatedActivity,
+ sendVideoRelatedActivity
}
// ---------------------------------------------------------------------------
-async function computeFollowerUris (toActorFollower: ActorModel[], actorsException: ActorModel[], t: Transaction) {
- const toActorFollowerIds = toActorFollower.map(a => a.id)
+async function computeFollowerUris (toFollowersOf: MActorId[], actorsException: MActorFollowerException[], t: Transaction) {
+ const toActorFollowerIds = toFollowersOf.map(a => a.id)
const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t)
- const sharedInboxesException = actorsException.map(f => f.sharedInboxUrl || f.inboxUrl)
+ const sharedInboxesException = await buildSharedInboxesException(actorsException)
+
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))
+async function computeUris (toActors: MActor[], actorsException: MActorFollowerException[] = []) {
+ const serverActor = await getServerActor()
+ const targetUrls = toActors
+ .filter(a => a.id !== serverActor.id) // Don't send to ourselves
+ .map(a => a.sharedInboxUrl || a.inboxUrl)
+
+ const toActorSharedInboxesSet = new Set(targetUrls)
- const sharedInboxesException = actorsException.map(f => f.sharedInboxUrl || f.inboxUrl)
+ const sharedInboxesException = await buildSharedInboxesException(actorsException)
return Array.from(toActorSharedInboxesSet)
.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1)
}
+
+async function buildSharedInboxesException (actorsException: MActorFollowerException[]) {
+ const serverActor = await getServerActor()
+
+ return actorsException
+ .map(f => f.sharedInboxUrl || f.inboxUrl)
+ .concat([ serverActor.sharedInboxUrl ])
+}