import { activityPubValidator } from '../../middlewares/validators/activitypub/activity'
import { queue } from 'async'
import { ActorModel } from '../../models/activitypub/actor'
+import { SignatureActorModel } from '../../typings/models'
const inboxRouter = express.Router()
// ---------------------------------------------------------------------------
-const inboxQueue = queue<{ activities: Activity[], signatureActor?: ActorModel, inboxActor?: ActorModel }, Error>((task, cb) => {
+const inboxQueue = queue<{ activities: Activity[], signatureActor?: SignatureActorModel, inboxActor?: ActorModel }, Error>((task, cb) => {
const options = { signatureActor: task.signatureActor, inboxActor: task.inboxActor }
processActivities(task.activities, options)
return undefined
}
-async function addFetchOutboxJob (actor: ActorModel) {
+async function addFetchOutboxJob (actor: Pick<ActorModel, 'id' | 'outboxUrl'>) {
// Don't fetch ourselves
const serverActor = await getServerActor()
if (serverActor.id === actor.id) {
import { VideoModel } from '../../models/video/video'
import { VideoCommentModel } from '../../models/video/video-comment'
import { VideoShareModel } from '../../models/video/video-share'
+import { ActorModelOnly } from '../../typings/models'
function getRemoteVideoAudience (video: VideoModel, actorsInvolvedInVideo: ActorModel[]): ActivityAudience {
return {
return actors
}
-function getAudience (actorSender: ActorModel, isPublic = true) {
+function getAudience (actorSender: ActorModelOnly, isPublic = true) {
return buildAudience([ actorSender.followersUrl ], isPublic)
}
import { sequelizeTypescript } from '../../initializers/database'
import { createPlaylistMiniatureFromUrl } from '../thumbnail'
import { FilteredModelAttributes } from '../../typings/sequelize'
+import { AccountModelId } from '../../typings/models'
-function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: AccountModel, to: string[]) {
+function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: AccountModelId, to: string[]) {
const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPlaylistPrivacy.PUBLIC : VideoPlaylistPrivacy.UNLISTED
return {
}, { concurrency: CRAWL_REQUEST_CONCURRENCY })
}
-async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAccount: AccountModel, to: string[]) {
+async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAccount: AccountModelId, to: string[]) {
const playlistAttributes = playlistObjectToDBAttributes(playlistObject, byAccount, to)
if (isArray(playlistObject.attributedTo) && playlistObject.attributedTo.length === 1) {
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
import { addFetchOutboxJob } from '../actor'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
async function processAcceptActivity (options: APProcessorOptions<ActivityAccept>) {
const { byActor: targetActor, inboxActor } = options
// ---------------------------------------------------------------------------
-async function processAccept (actor: ActorModel, targetActor: ActorModel) {
+async function processAccept (actor: ActorModel, targetActor: SignatureActorModel) {
const follow = await ActorFollowModel.loadByActorAndTarget(actor.id, targetActor.id)
if (!follow) throw new Error('Cannot find associated follow.')
import { ActivityAnnounce } from '../../../../shared/models/activitypub'
import { retryTransactionWrapper } from '../../../helpers/database-utils'
import { sequelizeTypescript } from '../../../initializers'
-import { ActorModel } from '../../../models/activitypub/actor'
import { VideoShareModel } from '../../../models/video/video-share'
import { forwardVideoRelatedActivity } from '../send/utils'
import { getOrCreateVideoAndAccountAndChannel } from '../videos'
import { VideoModel } from '../../../models/video/video'
import { logger } from '../../../helpers/logger'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
async function processAnnounceActivity (options: APProcessorOptions<ActivityAnnounce>) {
const { activity, byActor: actorAnnouncer } = options
// ---------------------------------------------------------------------------
-async function processVideoShare (actorAnnouncer: ActorModel, activity: ActivityAnnounce, notify: boolean) {
+async function processVideoShare (actorAnnouncer: SignatureActorModel, activity: ActivityAnnounce, notify: boolean) {
const objectUri = typeof activity.object === 'string' ? activity.object : activity.object.id
let video: VideoModel
import { retryTransactionWrapper } from '../../../helpers/database-utils'
import { logger } from '../../../helpers/logger'
import { sequelizeTypescript } from '../../../initializers'
-import { ActorModel } from '../../../models/activitypub/actor'
import { resolveThread } from '../video-comments'
import { getOrCreateVideoAndAccountAndChannel } from '../videos'
import { forwardVideoRelatedActivity } from '../send/utils'
import { VideoModel } from '../../../models/video/video'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
import { VideoCommentModel } from '../../../models/video/video-comment'
+import { SignatureActorModel } from '../../../typings/models'
async function processCreateActivity (options: APProcessorOptions<ActivityCreate>) {
const { activity, byActor } = options
return video
}
-async function processCreateCacheFile (activity: ActivityCreate, byActor: ActorModel) {
+async function processCreateCacheFile (activity: ActivityCreate, byActor: SignatureActorModel) {
const cacheFile = activity.object as CacheFileObject
const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: cacheFile.object })
}
}
-async function processCreateVideoComment (activity: ActivityCreate, byActor: ActorModel, notify: boolean) {
+async function processCreateVideoComment (activity: ActivityCreate, byActor: SignatureActorModel, notify: boolean) {
const commentObject = activity.object as VideoCommentObject
const byAccount = byActor.Account
if (created && notify) Notifier.Instance.notifyOnNewComment(comment)
}
-async function processCreatePlaylist (activity: ActivityCreate, byActor: ActorModel) {
+async function processCreatePlaylist (activity: ActivityCreate, byActor: SignatureActorModel) {
const playlistObject = activity.object as PlaylistObject
const byAccount = byActor.Account
import { forwardVideoRelatedActivity } from '../send/utils'
import { VideoPlaylistModel } from '../../../models/video/video-playlist'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
async function processDeleteActivity (options: APProcessorOptions<ActivityDelete>) {
const { activity, byActor } = options
logger.info('Remote video channel %s removed.', videoChannelToRemove.Actor.url)
}
-function processDeleteVideoComment (byActor: ActorModel, videoComment: VideoCommentModel, activity: ActivityDelete) {
+function processDeleteVideoComment (byActor: SignatureActorModel, videoComment: VideoCommentModel, activity: ActivityDelete) {
logger.debug('Removing remote video comment "%s".', videoComment.url)
return sequelizeTypescript.transaction(async t => {
import { retryTransactionWrapper } from '../../../helpers/database-utils'
import { sequelizeTypescript } from '../../../initializers'
import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
-import { ActorModel } from '../../../models/activitypub/actor'
import { getOrCreateVideoAndAccountAndChannel } from '../videos'
import { forwardVideoRelatedActivity } from '../send/utils'
import { getVideoDislikeActivityPubUrl } from '../url'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
async function processDislikeActivity (options: APProcessorOptions<ActivityCreate | ActivityDislike>) {
const { activity, byActor } = options
// ---------------------------------------------------------------------------
-async function processDislike (activity: ActivityCreate | ActivityDislike, byActor: ActorModel) {
+async function processDislike (activity: ActivityCreate | ActivityDislike, byActor: SignatureActorModel) {
const dislikeObject = activity.type === 'Dislike' ? activity.object : (activity.object as DislikeObject).object
const byAccount = byActor.Account
import { retryTransactionWrapper } from '../../../helpers/database-utils'
import { logger } from '../../../helpers/logger'
import { sequelizeTypescript } from '../../../initializers'
-import { ActorModel } from '../../../models/activitypub/actor'
import { VideoAbuseModel } from '../../../models/video/video-abuse'
import { getOrCreateVideoAndAccountAndChannel } from '../videos'
import { Notifier } from '../../notifier'
import { getAPId } from '../../../helpers/activitypub'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
async function processFlagActivity (options: APProcessorOptions<ActivityCreate | ActivityFlag>) {
const { activity, byActor } = options
// ---------------------------------------------------------------------------
-async function processCreateVideoAbuse (activity: ActivityCreate | ActivityFlag, byActor: ActorModel) {
+async function processCreateVideoAbuse (activity: ActivityCreate | ActivityFlag, byActor: SignatureActorModel) {
const flag = activity.type === 'Flag' ? activity : (activity.object as VideoAbuseObject)
logger.debug('Reporting remote abuse for video %s.', getAPId(flag.object))
import { getServerActor } from '../../../helpers/utils'
import { CONFIG } from '../../../initializers/config'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
+import { ActorFollowModelLight } from '../../../typings/models/actor-follow'
async function processFollowActivity (options: APProcessorOptions<ActivityFollow>) {
const { activity, byActor } = options
// ---------------------------------------------------------------------------
-async function processFollow (actor: ActorModel, targetActorURL: string) {
+async function processFollow (byActor: SignatureActorModel, targetActorURL: string) {
const { actorFollow, created, isFollowingInstance } = await sequelizeTypescript.transaction(async t => {
const targetActor = await ActorModel.loadByUrlAndPopulateAccountAndChannel(targetActorURL, t)
if (isFollowingInstance && CONFIG.FOLLOWERS.INSTANCE.ENABLED === false) {
logger.info('Rejecting %s because instance followers are disabled.', targetActor.url)
- await sendReject(actor, targetActor)
+ await sendReject(byActor, targetActor)
return { actorFollow: undefined }
}
const [ actorFollow, created ] = await ActorFollowModel.findOrCreate({
where: {
- actorId: actor.id,
+ actorId: byActor.id,
targetActorId: targetActor.id
},
defaults: {
- actorId: actor.id,
+ actorId: byActor.id,
targetActorId: targetActor.id,
state: CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL ? 'pending' : 'accepted'
},
transaction: t
- })
+ }) as [ ActorFollowModelLight, boolean ]
if (actorFollow.state !== 'accepted' && CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL === false) {
actorFollow.state = 'accepted'
await actorFollow.save({ transaction: t })
}
- actorFollow.ActorFollower = actor
+ actorFollow.ActorFollower = byActor
actorFollow.ActorFollowing = targetActor
// Target sends to actor he accepted the follow request
else Notifier.Instance.notifyOfNewUserFollow(actorFollow)
}
- logger.info('Actor %s is followed by actor %s.', targetActorURL, actor.url)
+ logger.info('Actor %s is followed by actor %s.', targetActorURL, byActor.url)
}
import { retryTransactionWrapper } from '../../../helpers/database-utils'
import { sequelizeTypescript } from '../../../initializers'
import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
-import { ActorModel } from '../../../models/activitypub/actor'
import { forwardVideoRelatedActivity } from '../send/utils'
import { getOrCreateVideoAndAccountAndChannel } from '../videos'
import { getVideoLikeActivityPubUrl } from '../url'
import { getAPId } from '../../../helpers/activitypub'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
async function processLikeActivity (options: APProcessorOptions<ActivityLike>) {
const { activity, byActor } = options
// ---------------------------------------------------------------------------
-async function processLikeVideo (byActor: ActorModel, activity: ActivityLike) {
+async function processLikeVideo (byActor: SignatureActorModel, activity: ActivityLike) {
const videoUrl = getAPId(activity.object)
const byAccount = byActor.Account
import { ActivityReject } from '../../../../shared/models/activitypub/activity'
import { sequelizeTypescript } from '../../../initializers'
-import { ActorModel } from '../../../models/activitypub/actor'
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { ActorModelOnly } from '../../../typings/models'
async function processRejectActivity (options: APProcessorOptions<ActivityReject>) {
const { byActor: targetActor, inboxActor } = options
// ---------------------------------------------------------------------------
-async function processReject (follower: ActorModel, targetActor: ActorModel) {
+async function processReject (follower: ActorModelOnly, targetActor: ActorModelOnly) {
return sequelizeTypescript.transaction(async t => {
const actorFollow = await ActorFollowModel.loadByActorAndTarget(follower.id, targetActor.id, t)
import { VideoShareModel } from '../../../models/video/video-share'
import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
async function processUndoActivity (options: APProcessorOptions<ActivityUndo>) {
const { activity, byActor } = options
// ---------------------------------------------------------------------------
-async function processUndoLike (byActor: ActorModel, activity: ActivityUndo) {
+async function processUndoLike (byActor: SignatureActorModel, activity: ActivityUndo) {
const likeActivity = activity.object as ActivityLike
const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: likeActivity.object })
})
}
-async function processUndoDislike (byActor: ActorModel, activity: ActivityUndo) {
+async function processUndoDislike (byActor: SignatureActorModel, activity: ActivityUndo) {
const dislike = activity.object.type === 'Dislike'
? activity.object
: activity.object.object as DislikeObject
})
}
-async function processUndoCacheFile (byActor: ActorModel, activity: ActivityUndo) {
+async function processUndoCacheFile (byActor: SignatureActorModel, activity: ActivityUndo) {
const cacheFileObject = activity.object.object as CacheFileObject
const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: cacheFileObject.object })
})
}
-function processUndoFollow (follower: ActorModel, followActivity: ActivityFollow) {
+function processUndoFollow (follower: SignatureActorModel, followActivity: ActivityFollow) {
return sequelizeTypescript.transaction(async t => {
const following = await ActorModel.loadByUrlAndPopulateAccountAndChannel(followActivity.object, t)
const actorFollow = await ActorFollowModel.loadByActorAndTarget(follower.id, following.id, t)
})
}
-function processUndoAnnounce (byActor: ActorModel, announceActivity: ActivityAnnounce) {
+function processUndoAnnounce (byActor: SignatureActorModel, announceActivity: ActivityAnnounce) {
return sequelizeTypescript.transaction(async t => {
const share = await VideoShareModel.loadByUrl(announceActivity.id, t)
if (!share) throw new Error(`Unknown video share ${announceActivity.id}.`)
import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
import { createOrUpdateVideoPlaylist } from '../playlist'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
async function processUpdateActivity (options: APProcessorOptions<ActivityUpdate>) {
const { activity, byActor } = options
// ---------------------------------------------------------------------------
-async function processUpdateVideo (actor: ActorModel, activity: ActivityUpdate) {
+async function processUpdateVideo (actor: SignatureActorModel, activity: ActivityUpdate) {
const videoObject = activity.object as VideoTorrentObject
if (sanitizeAndCheckVideoTorrentObject(videoObject) === false) {
return updateVideoFromAP(updateOptions)
}
-async function processUpdateCacheFile (byActor: ActorModel, activity: ActivityUpdate) {
+async function processUpdateCacheFile (byActor: SignatureActorModel, activity: ActivityUpdate) {
const cacheFileObject = activity.object as CacheFileObject
if (!isCacheFileObjectValid(cacheFileObject)) {
}
}
-async function processUpdatePlaylist (byActor: ActorModel, activity: ActivityUpdate) {
+async function processUpdatePlaylist (byActor: SignatureActorModel, activity: ActivityUpdate) {
const playlistObject = activity.object as PlaylistObject
const byAccount = byActor.Account
-import { ActorModel } from '../../../models/activitypub/actor'
import { getOrCreateVideoAndAccountAndChannel } from '../videos'
import { forwardVideoRelatedActivity } from '../send/utils'
import { Redis } from '../../redis'
import { ActivityCreate, ActivityView, ViewObject } from '../../../../shared/models/activitypub'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
async function processViewActivity (options: APProcessorOptions<ActivityCreate | ActivityView>) {
const { activity, byActor } = options
// ---------------------------------------------------------------------------
-async function processCreateView (activity: ActivityView | ActivityCreate, byActor: ActorModel) {
+async function processCreateView (activity: ActivityView | ActivityCreate, byActor: SignatureActorModel) {
const videoObject = activity.type === 'View' ? activity.object : (activity.object as ViewObject).object
const options = {
import { processFlagActivity } from './process-flag'
import { processViewActivity } from './process-view'
import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
+import { SignatureActorModel } from '../../../typings/models'
const processActivity: { [ P in ActivityType ]: (options: APProcessorOptions<Activity>) => Promise<any> } = {
Create: processCreateActivity,
async function processActivities (
activities: Activity[],
options: {
- signatureActor?: ActorModel
+ signatureActor?: SignatureActorModel
inboxActor?: ActorModel
outboxUrl?: string
fromFetch?: boolean
) {
const { outboxUrl, signatureActor, inboxActor, fromFetch = false } = options
- const actorsCache: { [ url: string ]: ActorModel } = {}
+ const actorsCache: { [ url: string ]: SignatureActorModel } = {}
for (const activity of activities) {
if (!signatureActor && [ 'Create', 'Announce', 'Like' ].includes(activity.type) === false) {
import { ActivityAccept, ActivityFollow } from '../../../../shared/models/activitypub'
-import { ActorModel } from '../../../models/activitypub/actor'
-import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
import { getActorFollowAcceptActivityPubUrl, getActorFollowActivityPubUrl } from '../url'
import { unicastTo } from './utils'
import { buildFollowActivity } from './send-follow'
import { logger } from '../../../helpers/logger'
+import { ActorFollowModelLight } from '../../../typings/models/actor-follow'
+import { ActorModelOnly } from '../../../typings/models'
-async function sendAccept (actorFollow: ActorFollowModel) {
+async function sendAccept (actorFollow: ActorFollowModelLight) {
const follower = actorFollow.ActorFollower
const me = actorFollow.ActorFollowing
// ---------------------------------------------------------------------------
-function buildAcceptActivity (url: string, byActor: ActorModel, followActivityData: ActivityFollow): ActivityAccept {
+function buildAcceptActivity (url: string, byActor: ActorModelOnly, followActivityData: ActivityFollow): ActivityAccept {
return {
type: 'Accept',
id: url,
import { Transaction } from 'sequelize'
import { ActivityAnnounce, ActivityAudience } from '../../../../shared/models/activitypub'
-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, getAudienceFromFollowersOf } from '../audience'
import { logger } from '../../../helpers/logger'
-
-async function buildAnnounceWithVideoAudience (byActor: ActorModel, videoShare: VideoShareModel, video: VideoModel, t: Transaction) {
+import { ActorModelOnly } from '../../../typings/models'
+import { VideoShareModelOnly } from '../../../typings/models/video-share'
+
+async function buildAnnounceWithVideoAudience (
+ byActor: ActorModelOnly,
+ videoShare: VideoShareModelOnly,
+ video: VideoModel,
+ t: Transaction
+) {
const announcedObject = video.url
const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, t)
return { activity, actorsInvolvedInVideo }
}
-async function sendVideoAnnounce (byActor: ActorModel, videoShare: VideoShareModel, video: VideoModel, t: Transaction) {
+async function sendVideoAnnounce (byActor: ActorModelOnly, videoShare: VideoShareModelOnly, video: VideoModel, t: Transaction) {
const { activity, actorsInvolvedInVideo } = await buildAnnounceWithVideoAudience(byActor, videoShare, video, t)
logger.info('Creating job to send announce %s.', videoShare.url)
return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, t, followersException)
}
-function buildAnnounceActivity (url: string, byActor: ActorModel, object: string, audience?: ActivityAudience): ActivityAnnounce {
+function buildAnnounceActivity (url: string, byActor: ActorModelOnly, object: string, audience?: ActivityAudience): ActivityAnnounce {
if (!audience) audience = getAudience(byActor)
return audiencify({
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 './utils'
import { logger } from '../../../helpers/logger'
import { Transaction } from 'sequelize'
+import { ActorModelOnly } from '../../../typings/models'
function sendFollow (actorFollow: ActorFollowModel, t: Transaction) {
const me = actorFollow.ActorFollower
t.afterCommit(() => unicastTo(data, me, following.inboxUrl))
}
-function buildFollowActivity (url: string, byActor: ActorModel, targetActor: ActorModel): ActivityFollow {
+function buildFollowActivity (url: string, byActor: ActorModelOnly, targetActor: ActorModelOnly): ActivityFollow {
return {
type: 'Follow',
id: url,
import { unicastTo } from './utils'
import { buildFollowActivity } from './send-follow'
import { logger } from '../../../helpers/logger'
+import { SignatureActorModel } from '../../../typings/models'
-async function sendReject (follower: ActorModel, following: ActorModel) {
+async function sendReject (follower: SignatureActorModel, following: ActorModel) {
if (!follower.serverId) { // This should never happen
logger.warn('Do not sending reject to local follower.')
return
import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience'
import { getServerActor } from '../../../helpers/utils'
import { afterCommitIfTransaction } from '../../../helpers/database-utils'
+import { ActorFollowerException, ActorModelId, ActorModelOnly } from '../../../typings/models'
async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: {
- byActor: ActorModel,
+ byActor: ActorModelOnly,
video: VideoModel,
transaction?: Transaction
}) {
- const actorsInvolvedInVideo = await getActorsInvolvedInVideo(options.video, options.transaction)
+ const { byActor, video, transaction } = options
+
+ const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, transaction)
// Send to origin
- if (options.video.isOwned() === false) {
- const audience = getRemoteVideoAudience(options.video, actorsInvolvedInVideo)
+ if (video.isOwned() === false) {
+ const audience = getRemoteVideoAudience(video, actorsInvolvedInVideo)
const activity = activityBuilder(audience)
- return afterCommitIfTransaction(options.transaction, () => {
- return unicastTo(activity, options.byActor, options.video.VideoChannel.Account.Actor.sharedInboxUrl)
+ return afterCommitIfTransaction(transaction, () => {
+ return unicastTo(activity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl)
})
}
const audience = getAudienceFromFollowersOf(actorsInvolvedInVideo)
const activity = activityBuilder(audience)
- const actorsException = [ options.byActor ]
+ const actorsException = [ byActor ]
- return broadcastToFollowers(activity, options.byActor, actorsInvolvedInVideo, options.transaction, actorsException)
+ return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, transaction, actorsException)
}
async function forwardVideoRelatedActivity (
activity: Activity,
t: Transaction,
- followersException: ActorModel[] = [],
+ followersException: ActorFollowerException[] = [],
video: VideoModel
) {
// Mastodon does not add our announces in audience, so we forward to them manually
async function forwardActivity (
activity: Activity,
t: Transaction,
- followersException: ActorModel[] = [],
+ followersException: ActorFollowerException[] = [],
additionalFollowerUrls: string[] = []
) {
logger.info('Forwarding activity %s.', activity.id)
async function broadcastToFollowers (
data: any,
- byActor: ActorModel,
- toFollowersOf: ActorModel[],
+ byActor: ActorModelId,
+ toFollowersOf: ActorModelId[],
t: Transaction,
- actorsException: ActorModel[] = []
+ actorsException: ActorFollowerException[] = []
) {
const uris = await computeFollowerUris(toFollowersOf, actorsException, t)
async function broadcastToActors (
data: any,
- byActor: ActorModel,
- toActors: ActorModel[],
+ byActor: ActorModelId,
+ toActors: ActorModelOnly[],
t?: Transaction,
- actorsException: ActorModel[] = []
+ actorsException: ActorFollowerException[] = []
) {
const uris = await computeUris(toActors, actorsException)
return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor))
}
-function broadcastTo (uris: string[], data: any, byActor: ActorModel) {
+function broadcastTo (uris: string[], data: any, byActor: ActorModelId) {
if (uris.length === 0) return undefined
logger.debug('Creating broadcast job.', { uris })
return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload })
}
-function unicastTo (data: any, byActor: ActorModel, toActorUrl: string) {
+function unicastTo (data: any, byActor: ActorModelId, toActorUrl: string) {
logger.debug('Creating unicast job.', { uri: toActorUrl })
const payload = {
// ---------------------------------------------------------------------------
-async function computeFollowerUris (toFollowersOf: ActorModel[], actorsException: ActorModel[], t: Transaction) {
+async function computeFollowerUris (toFollowersOf: ActorModelId[], actorsException: ActorFollowerException[], t: Transaction) {
const toActorFollowerIds = toFollowersOf.map(a => a.id)
const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t)
return result.data.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1)
}
-async function computeUris (toActors: ActorModel[], actorsException: ActorModel[] = []) {
+async function computeUris (toActors: ActorModelOnly[], actorsException: ActorFollowerException[] = []) {
const serverActor = await getServerActor()
const targetUrls = toActors
.filter(a => a.id !== serverActor.id) // Don't send to ourselves
.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1)
}
-async function buildSharedInboxesException (actorsException: ActorModel[]) {
+async function buildSharedInboxesException (actorsException: ActorFollowerException[]) {
const serverActor = await getServerActor()
return actorsException
import { WEBSERVER } from '../../initializers/constants'
-import { ActorModel } from '../../models/activitypub/actor'
-import { ActorFollowModel } from '../../models/activitypub/actor-follow'
import { VideoModel } from '../../models/video/video'
import { VideoAbuseModel } from '../../models/video/video-abuse'
import { VideoCommentModel } from '../../models/video/video-comment'
import { VideoFileModel } from '../../models/video/video-file'
import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist'
import { VideoPlaylistModel } from '../../models/video/video-playlist'
+import { ActorModelOnly, ActorModelUrl } from '../../typings/models'
+import { ActorFollowModelLight } from '../../typings/models/actor-follow'
function getVideoActivityPubUrl (video: VideoModel) {
return WEBSERVER.URL + '/videos/watch/' + video.uuid
return WEBSERVER.URL + '/admin/video-abuses/' + videoAbuse.id
}
-function getVideoViewActivityPubUrl (byActor: ActorModel, video: VideoModel) {
+function getVideoViewActivityPubUrl (byActor: ActorModelUrl, video: VideoModel) {
return byActor.url + '/views/videos/' + video.id + '/' + new Date().toISOString()
}
-function getVideoLikeActivityPubUrl (byActor: ActorModel, video: VideoModel | { id: number }) {
+function getVideoLikeActivityPubUrl (byActor: ActorModelUrl, video: VideoModel | { id: number }) {
return byActor.url + '/likes/' + video.id
}
-function getVideoDislikeActivityPubUrl (byActor: ActorModel, video: VideoModel | { id: number }) {
+function getVideoDislikeActivityPubUrl (byActor: ActorModelUrl, video: VideoModel | { id: number }) {
return byActor.url + '/dislikes/' + video.id
}
return video.url + '/dislikes'
}
-function getActorFollowActivityPubUrl (follower: ActorModel, following: ActorModel) {
+function getActorFollowActivityPubUrl (follower: ActorModelOnly, following: ActorModelOnly) {
return follower.url + '/follows/' + following.id
}
-function getActorFollowAcceptActivityPubUrl (actorFollow: ActorFollowModel) {
+function getActorFollowAcceptActivityPubUrl (actorFollow: ActorFollowModelLight) {
const follower = actorFollow.ActorFollower
const me = actorFollow.ActorFollowing
return follower.url + '/accepts/follows/' + me.id
}
-function getActorFollowRejectActivityPubUrl (follower: ActorModel, following: ActorModel) {
+function getActorFollowRejectActivityPubUrl (follower: ActorModelOnly, following: ActorModelOnly) {
return follower.url + '/rejects/follows/' + following.id
}
-function getVideoAnnounceActivityPubUrl (byActor: ActorModel, video: VideoModel) {
+function getVideoAnnounceActivityPubUrl (byActor: ActorModelOnly, video: VideoModel) {
return video.url + '/announces/' + byActor.id
}
import { ActorModel } from '../../models/activitypub/actor'
import { TagModel } from '../../models/video/tag'
import { VideoModel } from '../../models/video/video'
-import { VideoChannelModel } from '../../models/video/video-channel'
import { VideoFileModel } from '../../models/video/video-file'
import { getOrCreateActorAndServerAndModel } from './actor'
import { addVideoComments } from './video-comments'
import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
import { join } from 'path'
import { FilteredModelAttributes } from '../../typings/sequelize'
-import { Hooks } from '../plugins/hooks'
import { autoBlacklistVideoIfNeeded } from '../video-blacklist'
import { ActorFollowScoreCache } from '../files-cache'
+import { AccountModelIdActor, VideoChannelModelId, VideoChannelModelIdActor } from '../../typings/models'
async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) {
if (
async function updateVideoFromAP (options: {
video: VideoModel,
videoObject: VideoTorrentObject,
- account: AccountModel,
- channel: VideoChannelModel,
+ account: AccountModelIdActor,
+ channel: VideoChannelModelIdActor,
overrideTo?: string[]
}) {
const { video, videoObject, account, channel, overrideTo } = options
}
async function videoActivityObjectToDBAttributes (
- videoChannel: VideoChannelModel,
+ videoChannel: VideoChannelModelId,
videoObject: VideoTorrentObject,
to: string[] = []
) {
import { Activity } from '../../shared/models/activitypub'
import { ActorModel } from '../models/activitypub/actor'
+import { SignatureActorModel } from './models'
export type APProcessorOptions<T extends Activity> = {
activity: T
- byActor: ActorModel
+ byActor: SignatureActorModel
inboxActor?: ActorModel
fromFetch?: boolean
}
import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist'
import { RegisteredPlugin } from '../lib/plugins/plugin-manager'
import { PluginModel } from '../models/server/plugin'
+import { SignatureActorModel } from './models'
declare module 'express' {
}
signature?: {
- actor: ActorModel
+ actor: SignatureActorModel
}
authenticated?: boolean
--- /dev/null
+import { ActorFollowModel } from '../../models/activitypub/actor-follow'
+import { ActorModelOnly } from './actor'
+
+export type ActorFollowModelOnly = Omit<ActorFollowModel, 'ActorFollower' | 'ActorFollowing'>
+export type ActorFollowModelLight = ActorFollowModelOnly & {
+ ActorFollower: ActorModelOnly
+ ActorFollowing: ActorModelOnly
+}
--- /dev/null
+import { ActorModel } from '../../models/activitypub/actor'
+import { VideoChannelModel } from '../../models/video/video-channel'
+import { AccountModel } from '../../models/account/account'
+import { FunctionProperties } from '../utils'
+
+export type VideoChannelModelId = FunctionProperties<VideoChannelModel>
+export type AccountModelId = FunctionProperties<AccountModel> | Pick<AccountModel, 'id'>
+
+export type VideoChannelModelIdActor = VideoChannelModelId & Pick<VideoChannelModel, 'Actor'>
+export type AccountModelIdActor = AccountModelId & Pick<AccountModel, 'Actor'>
+
+export type ActorModelUrl = Pick<ActorModel, 'url'>
+export type ActorModelOnly = Omit<ActorModel, 'Account' | 'VideoChannel' | 'ActorFollowing' | 'Avatar' | 'ActorFollowers' | 'Server'>
+export type ActorModelId = Pick<ActorModelOnly, 'id'>
+
+export type SignatureActorModel = ActorModelOnly & {
+ VideoChannel: VideoChannelModelIdActor
+
+ Account: AccountModelIdActor
+}
+
+export type ActorFollowerException = Pick<ActorModel, 'sharedInboxUrl' | 'inboxUrl'>
--- /dev/null
+export * from './actor'
--- /dev/null
+import { VideoShareModel } from '../../models/video/video-share'
+
+export type VideoShareModelOnly = Omit<VideoShareModel, 'Actor' | 'Video'>
--- /dev/null
+export type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]
+
+export type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>>