mirror of https://github.com/Chocobozzz/PeerTube
Refactor AP context builder
parent
7e98a7df7d
commit
a219c9100b
|
@ -186,35 +186,35 @@ export {
|
|||
function accountController (req: express.Request, res: express.Response) {
|
||||
const account = res.locals.account
|
||||
|
||||
return activityPubResponse(activityPubContextify(account.toActivityPubObject()), res)
|
||||
return activityPubResponse(activityPubContextify(account.toActivityPubObject(), 'Actor'), res)
|
||||
}
|
||||
|
||||
async function accountFollowersController (req: express.Request, res: express.Response) {
|
||||
const account = res.locals.account
|
||||
const activityPubResult = await actorFollowers(req, account.Actor)
|
||||
|
||||
return activityPubResponse(activityPubContextify(activityPubResult), res)
|
||||
return activityPubResponse(activityPubContextify(activityPubResult, 'Collection'), res)
|
||||
}
|
||||
|
||||
async function accountFollowingController (req: express.Request, res: express.Response) {
|
||||
const account = res.locals.account
|
||||
const activityPubResult = await actorFollowing(req, account.Actor)
|
||||
|
||||
return activityPubResponse(activityPubContextify(activityPubResult), res)
|
||||
return activityPubResponse(activityPubContextify(activityPubResult, 'Collection'), res)
|
||||
}
|
||||
|
||||
async function accountPlaylistsController (req: express.Request, res: express.Response) {
|
||||
const account = res.locals.account
|
||||
const activityPubResult = await actorPlaylists(req, { account })
|
||||
|
||||
return activityPubResponse(activityPubContextify(activityPubResult), res)
|
||||
return activityPubResponse(activityPubContextify(activityPubResult, 'Collection'), res)
|
||||
}
|
||||
|
||||
async function videoChannelPlaylistsController (req: express.Request, res: express.Response) {
|
||||
const channel = res.locals.videoChannel
|
||||
const activityPubResult = await actorPlaylists(req, { channel })
|
||||
|
||||
return activityPubResponse(activityPubContextify(activityPubResult), res)
|
||||
return activityPubResponse(activityPubContextify(activityPubResult, 'Collection'), res)
|
||||
}
|
||||
|
||||
function getAccountVideoRateFactory (rateType: VideoRateType) {
|
||||
|
@ -226,7 +226,7 @@ function getAccountVideoRateFactory (rateType: VideoRateType) {
|
|||
? buildLikeActivity(accountVideoRate.url, byActor, accountVideoRate.Video)
|
||||
: buildDislikeActivity(accountVideoRate.url, byActor, accountVideoRate.Video)
|
||||
|
||||
return activityPubResponse(activityPubContextify(APObject), res)
|
||||
return activityPubResponse(activityPubContextify(APObject, 'Rate'), res)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,10 +244,10 @@ async function videoController (req: express.Request, res: express.Response) {
|
|||
|
||||
if (req.path.endsWith('/activity')) {
|
||||
const data = buildCreateActivity(videoWithCaptions.url, video.VideoChannel.Account.Actor, videoObject, audience)
|
||||
return activityPubResponse(activityPubContextify(data), res)
|
||||
return activityPubResponse(activityPubContextify(data, 'Video'), res)
|
||||
}
|
||||
|
||||
return activityPubResponse(activityPubContextify(videoObject), res)
|
||||
return activityPubResponse(activityPubContextify(videoObject, 'Video'), res)
|
||||
}
|
||||
|
||||
async function videoAnnounceController (req: express.Request, res: express.Response) {
|
||||
|
@ -274,7 +274,7 @@ async function videoAnnouncesController (req: express.Request, res: express.Resp
|
|||
}
|
||||
const json = await activityPubCollectionPagination(getLocalVideoSharesActivityPubUrl(video), handler, req.query.page)
|
||||
|
||||
return activityPubResponse(activityPubContextify(json), res)
|
||||
return activityPubResponse(activityPubContextify(json, 'Collection'), res)
|
||||
}
|
||||
|
||||
async function videoLikesController (req: express.Request, res: express.Response) {
|
||||
|
@ -284,7 +284,7 @@ async function videoLikesController (req: express.Request, res: express.Response
|
|||
|
||||
const json = await videoRates(req, 'like', video, getLocalVideoLikesActivityPubUrl(video))
|
||||
|
||||
return activityPubResponse(activityPubContextify(json), res)
|
||||
return activityPubResponse(activityPubContextify(json, 'Collection'), res)
|
||||
}
|
||||
|
||||
async function videoDislikesController (req: express.Request, res: express.Response) {
|
||||
|
@ -294,7 +294,7 @@ async function videoDislikesController (req: express.Request, res: express.Respo
|
|||
|
||||
const json = await videoRates(req, 'dislike', video, getLocalVideoDislikesActivityPubUrl(video))
|
||||
|
||||
return activityPubResponse(activityPubContextify(json), res)
|
||||
return activityPubResponse(activityPubContextify(json, 'Collection'), res)
|
||||
}
|
||||
|
||||
async function videoCommentsController (req: express.Request, res: express.Response) {
|
||||
|
@ -312,27 +312,27 @@ async function videoCommentsController (req: express.Request, res: express.Respo
|
|||
}
|
||||
const json = await activityPubCollectionPagination(getLocalVideoCommentsActivityPubUrl(video), handler, req.query.page)
|
||||
|
||||
return activityPubResponse(activityPubContextify(json), res)
|
||||
return activityPubResponse(activityPubContextify(json, 'Collection'), res)
|
||||
}
|
||||
|
||||
function videoChannelController (req: express.Request, res: express.Response) {
|
||||
const videoChannel = res.locals.videoChannel
|
||||
|
||||
return activityPubResponse(activityPubContextify(videoChannel.toActivityPubObject()), res)
|
||||
return activityPubResponse(activityPubContextify(videoChannel.toActivityPubObject(), 'Actor'), res)
|
||||
}
|
||||
|
||||
async function videoChannelFollowersController (req: express.Request, res: express.Response) {
|
||||
const videoChannel = res.locals.videoChannel
|
||||
const activityPubResult = await actorFollowers(req, videoChannel.Actor)
|
||||
|
||||
return activityPubResponse(activityPubContextify(activityPubResult), res)
|
||||
return activityPubResponse(activityPubContextify(activityPubResult, 'Collection'), res)
|
||||
}
|
||||
|
||||
async function videoChannelFollowingController (req: express.Request, res: express.Response) {
|
||||
const videoChannel = res.locals.videoChannel
|
||||
const activityPubResult = await actorFollowing(req, videoChannel.Actor)
|
||||
|
||||
return activityPubResponse(activityPubContextify(activityPubResult), res)
|
||||
return activityPubResponse(activityPubContextify(activityPubResult, 'Collection'), res)
|
||||
}
|
||||
|
||||
async function videoCommentController (req: express.Request, res: express.Response) {
|
||||
|
@ -350,11 +350,11 @@ async function videoCommentController (req: express.Request, res: express.Respon
|
|||
|
||||
if (req.path.endsWith('/activity')) {
|
||||
const data = buildCreateActivity(videoComment.url, videoComment.Account.Actor, videoCommentObject, audience)
|
||||
return activityPubResponse(activityPubContextify(data), res)
|
||||
return activityPubResponse(activityPubContextify(data, 'Comment'), res)
|
||||
}
|
||||
}
|
||||
|
||||
return activityPubResponse(activityPubContextify(videoCommentObject), res)
|
||||
return activityPubResponse(activityPubContextify(videoCommentObject, 'Comment'), res)
|
||||
}
|
||||
|
||||
async function videoRedundancyController (req: express.Request, res: express.Response) {
|
||||
|
@ -387,7 +387,7 @@ async function videoPlaylistController (req: express.Request, res: express.Respo
|
|||
const audience = getAudience(playlist.OwnerAccount.Actor, playlist.privacy === VideoPlaylistPrivacy.PUBLIC)
|
||||
const object = audiencify(json, audience)
|
||||
|
||||
return activityPubResponse(activityPubContextify(object), res)
|
||||
return activityPubResponse(activityPubContextify(object, 'Playlist'), res)
|
||||
}
|
||||
|
||||
function videoPlaylistElementController (req: express.Request, res: express.Response) {
|
||||
|
@ -396,7 +396,7 @@ function videoPlaylistElementController (req: express.Request, res: express.Resp
|
|||
if (redirectIfNotOwned(videoPlaylistElement.url, res)) return
|
||||
|
||||
const json = videoPlaylistElement.toActivityPubObject()
|
||||
return activityPubResponse(activityPubContextify(json), res)
|
||||
return activityPubResponse(activityPubContextify(json, 'Playlist'), res)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -45,7 +45,7 @@ async function outboxController (req: express.Request, res: express.Response) {
|
|||
const handler = (start: number, count: number) => buildActivities(actor, start, count)
|
||||
const json = await activityPubCollectionPagination(actorOutboxUrl, handler, req.query.page, req.query.size)
|
||||
|
||||
return activityPubResponse(activityPubContextify(json), res)
|
||||
return activityPubResponse(activityPubContextify(json, 'Collection'), res)
|
||||
}
|
||||
|
||||
async function buildActivities (actor: MActorLight, start: number, count: number) {
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
import { signJsonLDObject } from '@server/helpers/peertube-crypto'
|
||||
import { MActor } from '@server/types/models'
|
||||
import { ContextType } from '@shared/models'
|
||||
import { activityPubContextify } from './context'
|
||||
|
||||
function buildSignedActivity <T> (byActor: MActor, data: T, contextType?: ContextType) {
|
||||
const activity = activityPubContextify(data, contextType)
|
||||
|
||||
return signJsonLDObject(byActor, activity)
|
||||
}
|
||||
|
||||
function getAPId (object: string | { id: string }) {
|
||||
if (typeof object === 'string') return object
|
||||
|
||||
|
@ -16,6 +5,5 @@ function getAPId (object: string | { id: string }) {
|
|||
}
|
||||
|
||||
export {
|
||||
buildSignedActivity,
|
||||
getAPId
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ function buildAudience (followerUrls: string[], isPublic = true) {
|
|||
}
|
||||
|
||||
function audiencify<T> (object: T, audience: ActivityAudience) {
|
||||
return Object.assign(object, audience)
|
||||
return { ...audience, ...object }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -1,7 +1,151 @@
|
|||
import { ContextType } from '@shared/models'
|
||||
|
||||
function activityPubContextify <T> (data: T, type: ContextType) {
|
||||
return { ...getContextData(type), ...data }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
getContextData,
|
||||
activityPubContextify
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type ContextValue = { [ id: string ]: (string | { '@type': string, '@id': string }) }
|
||||
|
||||
const contextStore = {
|
||||
Video: buildContext({
|
||||
Hashtag: 'as:Hashtag',
|
||||
uuid: 'sc:identifier',
|
||||
category: 'sc:category',
|
||||
licence: 'sc:license',
|
||||
subtitleLanguage: 'sc:subtitleLanguage',
|
||||
sensitive: 'as:sensitive',
|
||||
language: 'sc:inLanguage',
|
||||
|
||||
// TODO: remove in a few versions, introduced in 4.2
|
||||
icons: 'as:icon',
|
||||
|
||||
isLiveBroadcast: 'sc:isLiveBroadcast',
|
||||
liveSaveReplay: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:liveSaveReplay'
|
||||
},
|
||||
permanentLive: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:permanentLive'
|
||||
},
|
||||
latencyMode: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:latencyMode'
|
||||
},
|
||||
|
||||
Infohash: 'pt:Infohash',
|
||||
|
||||
originallyPublishedAt: 'sc:datePublished',
|
||||
views: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:views'
|
||||
},
|
||||
state: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:state'
|
||||
},
|
||||
size: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:size'
|
||||
},
|
||||
fps: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:fps'
|
||||
},
|
||||
commentsEnabled: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:commentsEnabled'
|
||||
},
|
||||
downloadEnabled: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:downloadEnabled'
|
||||
},
|
||||
waitTranscoding: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:waitTranscoding'
|
||||
},
|
||||
support: {
|
||||
'@type': 'sc:Text',
|
||||
'@id': 'pt:support'
|
||||
},
|
||||
likes: {
|
||||
'@id': 'as:likes',
|
||||
'@type': '@id'
|
||||
},
|
||||
dislikes: {
|
||||
'@id': 'as:dislikes',
|
||||
'@type': '@id'
|
||||
},
|
||||
shares: {
|
||||
'@id': 'as:shares',
|
||||
'@type': '@id'
|
||||
},
|
||||
comments: {
|
||||
'@id': 'as:comments',
|
||||
'@type': '@id'
|
||||
}
|
||||
}),
|
||||
|
||||
Playlist: buildContext({
|
||||
Playlist: 'pt:Playlist',
|
||||
PlaylistElement: 'pt:PlaylistElement',
|
||||
position: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:position'
|
||||
},
|
||||
startTimestamp: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:startTimestamp'
|
||||
},
|
||||
stopTimestamp: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:stopTimestamp'
|
||||
}
|
||||
}),
|
||||
|
||||
CacheFile: buildContext({
|
||||
expires: 'sc:expires',
|
||||
CacheFile: 'pt:CacheFile'
|
||||
}),
|
||||
|
||||
Flag: buildContext({
|
||||
Hashtag: 'as:Hashtag'
|
||||
}),
|
||||
|
||||
Actor: buildContext({
|
||||
playlists: {
|
||||
'@id': 'pt:playlists',
|
||||
'@type': '@id'
|
||||
}
|
||||
}),
|
||||
|
||||
Follow: buildContext(),
|
||||
Reject: buildContext(),
|
||||
Accept: buildContext(),
|
||||
View: buildContext(),
|
||||
Announce: buildContext(),
|
||||
Comment: buildContext(),
|
||||
Delete: buildContext(),
|
||||
Rate: buildContext()
|
||||
}
|
||||
|
||||
function getContextData (type: ContextType) {
|
||||
const context: any[] = [
|
||||
return {
|
||||
'@context': contextStore[type]
|
||||
}
|
||||
}
|
||||
|
||||
function buildContext (contextValue?: ContextValue) {
|
||||
const baseContext = [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1',
|
||||
{
|
||||
|
@ -9,129 +153,16 @@ function getContextData (type: ContextType) {
|
|||
}
|
||||
]
|
||||
|
||||
if (type !== 'View' && type !== 'Announce') {
|
||||
const additional = {
|
||||
if (!contextValue) return baseContext
|
||||
|
||||
return [
|
||||
...baseContext,
|
||||
|
||||
{
|
||||
pt: 'https://joinpeertube.org/ns#',
|
||||
sc: 'http://schema.org#'
|
||||
sc: 'http://schema.org#',
|
||||
|
||||
...contextValue
|
||||
}
|
||||
|
||||
if (type === 'CacheFile') {
|
||||
Object.assign(additional, {
|
||||
expires: 'sc:expires',
|
||||
CacheFile: 'pt:CacheFile'
|
||||
})
|
||||
} else {
|
||||
Object.assign(additional, {
|
||||
Hashtag: 'as:Hashtag',
|
||||
uuid: 'sc:identifier',
|
||||
category: 'sc:category',
|
||||
licence: 'sc:license',
|
||||
subtitleLanguage: 'sc:subtitleLanguage',
|
||||
sensitive: 'as:sensitive',
|
||||
language: 'sc:inLanguage',
|
||||
|
||||
// TODO: remove in a few versions, introduced in 4.2
|
||||
icons: 'as:icon',
|
||||
|
||||
isLiveBroadcast: 'sc:isLiveBroadcast',
|
||||
liveSaveReplay: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:liveSaveReplay'
|
||||
},
|
||||
permanentLive: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:permanentLive'
|
||||
},
|
||||
latencyMode: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:latencyMode'
|
||||
},
|
||||
|
||||
Infohash: 'pt:Infohash',
|
||||
Playlist: 'pt:Playlist',
|
||||
PlaylistElement: 'pt:PlaylistElement',
|
||||
|
||||
originallyPublishedAt: 'sc:datePublished',
|
||||
views: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:views'
|
||||
},
|
||||
state: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:state'
|
||||
},
|
||||
size: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:size'
|
||||
},
|
||||
fps: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:fps'
|
||||
},
|
||||
startTimestamp: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:startTimestamp'
|
||||
},
|
||||
stopTimestamp: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:stopTimestamp'
|
||||
},
|
||||
position: {
|
||||
'@type': 'sc:Number',
|
||||
'@id': 'pt:position'
|
||||
},
|
||||
commentsEnabled: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:commentsEnabled'
|
||||
},
|
||||
downloadEnabled: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:downloadEnabled'
|
||||
},
|
||||
waitTranscoding: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:waitTranscoding'
|
||||
},
|
||||
support: {
|
||||
'@type': 'sc:Text',
|
||||
'@id': 'pt:support'
|
||||
},
|
||||
likes: {
|
||||
'@id': 'as:likes',
|
||||
'@type': '@id'
|
||||
},
|
||||
dislikes: {
|
||||
'@id': 'as:dislikes',
|
||||
'@type': '@id'
|
||||
},
|
||||
playlists: {
|
||||
'@id': 'pt:playlists',
|
||||
'@type': '@id'
|
||||
},
|
||||
shares: {
|
||||
'@id': 'as:shares',
|
||||
'@type': '@id'
|
||||
},
|
||||
comments: {
|
||||
'@id': 'as:comments',
|
||||
'@type': '@id'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
context.push(additional)
|
||||
}
|
||||
|
||||
return {
|
||||
'@context': context
|
||||
}
|
||||
}
|
||||
|
||||
function activityPubContextify <T> (data: T, type: ContextType = 'All') {
|
||||
return Object.assign({}, data, getContextData(type))
|
||||
}
|
||||
|
||||
export {
|
||||
getContextData,
|
||||
activityPubContextify
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { buildDigest } from '@server/helpers/peertube-crypto'
|
||||
import { buildSignedActivity } from '@server/lib/activitypub/activity'
|
||||
import { buildDigest, signJsonLDObject } from '@server/helpers/peertube-crypto'
|
||||
import { ACTIVITY_PUB, HTTP_SIGNATURE } from '@server/initializers/constants'
|
||||
import { ActorModel } from '@server/models/actor/actor'
|
||||
import { getServerActor } from '@server/models/application/application'
|
||||
import { MActor } from '@server/types/models'
|
||||
import { ContextType } from '@shared/models/activitypub/context'
|
||||
import { ACTIVITY_PUB, HTTP_SIGNATURE } from '../../../../initializers/constants'
|
||||
import { ActorModel } from '../../../../models/actor/actor'
|
||||
import { MActor } from '../../../../types/models'
|
||||
import { activityPubContextify } from '../context'
|
||||
|
||||
type Payload <T> = { body: T, contextType?: ContextType, signatureActorId?: number }
|
||||
type Payload <T> = { body: T, contextType: ContextType, signatureActorId?: number }
|
||||
|
||||
async function computeBody <T> (
|
||||
payload: Payload<T>
|
||||
|
@ -17,7 +17,7 @@ async function computeBody <T> (
|
|||
const actorSignature = await ActorModel.load(payload.signatureActorId)
|
||||
if (!actorSignature) throw new Error('Unknown signature actor id.')
|
||||
|
||||
body = await buildSignedActivity(actorSignature, payload.body, payload.contextType)
|
||||
body = await signAndContextify(actorSignature, payload.body, payload.contextType)
|
||||
}
|
||||
|
||||
return body
|
||||
|
@ -52,8 +52,17 @@ function buildGlobalHeaders (body: any) {
|
|||
}
|
||||
}
|
||||
|
||||
function signAndContextify <T> (byActor: MActor, data: T, contextType: ContextType | null) {
|
||||
const activity = contextType
|
||||
? activityPubContextify(data, contextType)
|
||||
: data
|
||||
|
||||
return signJsonLDObject(byActor, activity)
|
||||
}
|
||||
|
||||
export {
|
||||
buildGlobalHeaders,
|
||||
computeBody,
|
||||
buildSignedRequestOptions
|
||||
buildSignedRequestOptions,
|
||||
signAndContextify
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
export * from './send-accept'
|
||||
export * from './http'
|
||||
export * from './send-accept'
|
||||
export * from './send-announce'
|
||||
export * from './send-create'
|
||||
|
|
|
@ -21,7 +21,12 @@ function sendAccept (actorFollow: MActorFollowActors) {
|
|||
const url = getLocalActorFollowAcceptActivityPubUrl(actorFollow)
|
||||
const data = buildAcceptActivity(url, me, followData)
|
||||
|
||||
return unicastTo(data, me, follower.inboxUrl)
|
||||
return unicastTo({
|
||||
data,
|
||||
byActor: me,
|
||||
toActorUrl: follower.inboxUrl,
|
||||
contextType: 'Accept'
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -23,13 +23,19 @@ async function buildAnnounceWithVideoAudience (
|
|||
return { activity, actorsInvolvedInVideo }
|
||||
}
|
||||
|
||||
async function sendVideoAnnounce (byActor: MActorLight, videoShare: MVideoShare, video: MVideo, t: Transaction) {
|
||||
const { activity, actorsInvolvedInVideo } = await buildAnnounceWithVideoAudience(byActor, videoShare, video, t)
|
||||
async function sendVideoAnnounce (byActor: MActorLight, videoShare: MVideoShare, video: MVideo, transaction: Transaction) {
|
||||
const { activity, actorsInvolvedInVideo } = await buildAnnounceWithVideoAudience(byActor, videoShare, video, transaction)
|
||||
|
||||
logger.info('Creating job to send announce %s.', videoShare.url)
|
||||
|
||||
const followersException = [ byActor ]
|
||||
return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, t, followersException, 'Announce')
|
||||
return broadcastToFollowers({
|
||||
data: activity,
|
||||
byActor,
|
||||
toFollowersOf: actorsInvolvedInVideo,
|
||||
transaction,
|
||||
actorsException: [ byActor ],
|
||||
contextType: 'Announce'
|
||||
})
|
||||
}
|
||||
|
||||
function buildAnnounceActivity (url: string, byActor: MActorLight, object: string, audience?: ActivityAudience): ActivityAnnounce {
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
|
||||
const lTags = loggerTagsFactory('ap', 'create')
|
||||
|
||||
async function sendCreateVideo (video: MVideoAP, t: Transaction) {
|
||||
async function sendCreateVideo (video: MVideoAP, transaction: Transaction) {
|
||||
if (!video.hasPrivacyForFederation()) return undefined
|
||||
|
||||
logger.info('Creating job to send video creation of %s.', video.url, lTags(video.uuid))
|
||||
|
@ -36,7 +36,13 @@ async function sendCreateVideo (video: MVideoAP, t: Transaction) {
|
|||
const audience = getAudience(byActor, video.privacy === VideoPrivacy.PUBLIC)
|
||||
const createActivity = buildCreateActivity(video.url, byActor, videoObject, audience)
|
||||
|
||||
return broadcastToFollowers(createActivity, byActor, [ byActor ], t)
|
||||
return broadcastToFollowers({
|
||||
data: createActivity,
|
||||
byActor,
|
||||
toFollowersOf: [ byActor ],
|
||||
transaction,
|
||||
contextType: 'Video'
|
||||
})
|
||||
}
|
||||
|
||||
async function sendCreateCacheFile (
|
||||
|
@ -55,7 +61,7 @@ async function sendCreateCacheFile (
|
|||
})
|
||||
}
|
||||
|
||||
async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, t: Transaction) {
|
||||
async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, transaction: Transaction) {
|
||||
if (playlist.privacy === VideoPlaylistPrivacy.PRIVATE) return undefined
|
||||
|
||||
logger.info('Creating job to send create video playlist of %s.', playlist.url, lTags(playlist.uuid))
|
||||
|
@ -63,7 +69,7 @@ async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, t: Transac
|
|||
const byActor = playlist.OwnerAccount.Actor
|
||||
const audience = getAudience(byActor, playlist.privacy === VideoPlaylistPrivacy.PUBLIC)
|
||||
|
||||
const object = await playlist.toActivityPubObject(null, t)
|
||||
const object = await playlist.toActivityPubObject(null, transaction)
|
||||
const createActivity = buildCreateActivity(playlist.url, byActor, object, audience)
|
||||
|
||||
const serverActor = await getServerActor()
|
||||
|
@ -71,19 +77,25 @@ async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, t: Transac
|
|||
|
||||
if (playlist.VideoChannel) toFollowersOf.push(playlist.VideoChannel.Actor)
|
||||
|
||||
return broadcastToFollowers(createActivity, byActor, toFollowersOf, t)
|
||||
return broadcastToFollowers({
|
||||
data: createActivity,
|
||||
byActor,
|
||||
toFollowersOf,
|
||||
transaction,
|
||||
contextType: 'Playlist'
|
||||
})
|
||||
}
|
||||
|
||||
async function sendCreateVideoComment (comment: MCommentOwnerVideo, t: Transaction) {
|
||||
async function sendCreateVideoComment (comment: MCommentOwnerVideo, transaction: Transaction) {
|
||||
logger.info('Creating job to send comment %s.', comment.url)
|
||||
|
||||
const isOrigin = comment.Video.isOwned()
|
||||
|
||||
const byActor = comment.Account.Actor
|
||||
const threadParentComments = await VideoCommentModel.listThreadParentComments(comment, t)
|
||||
const threadParentComments = await VideoCommentModel.listThreadParentComments(comment, transaction)
|
||||
const commentObject = comment.toActivityPubObject(threadParentComments)
|
||||
|
||||
const actorsInvolvedInComment = await getActorsInvolvedInVideo(comment.Video, t)
|
||||
const actorsInvolvedInComment = await getActorsInvolvedInVideo(comment.Video, transaction)
|
||||
// Add the actor that commented too
|
||||
actorsInvolvedInComment.push(byActor)
|
||||
|
||||
|
@ -101,16 +113,45 @@ async function sendCreateVideoComment (comment: MCommentOwnerVideo, t: Transacti
|
|||
|
||||
// This was a reply, send it to the parent actors
|
||||
const actorsException = [ byActor ]
|
||||
await broadcastToActors(createActivity, byActor, parentsCommentActors, t, actorsException)
|
||||
await broadcastToActors({
|
||||
data: createActivity,
|
||||
byActor,
|
||||
toActors: parentsCommentActors,
|
||||
transaction,
|
||||
actorsException,
|
||||
contextType: 'Comment'
|
||||
})
|
||||
|
||||
// Broadcast to our followers
|
||||
await broadcastToFollowers(createActivity, byActor, [ byActor ], t)
|
||||
await broadcastToFollowers({
|
||||
data: createActivity,
|
||||
byActor,
|
||||
toFollowersOf: [ byActor ],
|
||||
transaction,
|
||||
contextType: 'Comment'
|
||||
})
|
||||
|
||||
// Send to actors involved in the comment
|
||||
if (isOrigin) return broadcastToFollowers(createActivity, byActor, actorsInvolvedInComment, t, actorsException)
|
||||
if (isOrigin) {
|
||||
return broadcastToFollowers({
|
||||
data: createActivity,
|
||||
byActor,
|
||||
toFollowersOf: actorsInvolvedInComment,
|
||||
transaction,
|
||||
actorsException,
|
||||
contextType: 'Comment'
|
||||
})
|
||||
}
|
||||
|
||||
// Send to origin
|
||||
t.afterCommit(() => unicastTo(createActivity, byActor, comment.Video.VideoChannel.Account.Actor.getSharedInbox()))
|
||||
return transaction.afterCommit(() => {
|
||||
return unicastTo({
|
||||
data: createActivity,
|
||||
byActor,
|
||||
toActorUrl: comment.Video.VideoChannel.Account.Actor.getSharedInbox(),
|
||||
contextType: 'Comment'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function buildCreateActivity (url: string, byActor: MActorLight, object: any, audience?: ActivityAudience): ActivityCreate {
|
||||
|
@ -144,8 +185,8 @@ async function sendVideoRelatedCreateActivity (options: {
|
|||
video: MVideoAccountLight
|
||||
url: string
|
||||
object: any
|
||||
contextType: ContextType
|
||||
transaction?: Transaction
|
||||
contextType?: ContextType
|
||||
}) {
|
||||
const activityBuilder = (audience: ActivityAudience) => {
|
||||
return buildCreateActivity(options.url, options.byActor, options.object, audience)
|
||||
|
|
|
@ -23,16 +23,16 @@ async function sendDeleteVideo (video: MVideoAccountLight, transaction: Transact
|
|||
return buildDeleteActivity(url, video.url, byActor, audience)
|
||||
}
|
||||
|
||||
return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction })
|
||||
return sendVideoRelatedActivity(activityBuilder, { byActor, video, contextType: 'Delete', transaction })
|
||||
}
|
||||
|
||||
async function sendDeleteActor (byActor: ActorModel, t: Transaction) {
|
||||
async function sendDeleteActor (byActor: ActorModel, transaction: Transaction) {
|
||||
logger.info('Creating job to broadcast delete of actor %s.', byActor.url)
|
||||
|
||||
const url = getDeleteActivityPubUrl(byActor.url)
|
||||
const activity = buildDeleteActivity(url, byActor.url, byActor)
|
||||
|
||||
const actorsInvolved = await VideoShareModel.loadActorsWhoSharedVideosOf(byActor.id, t)
|
||||
const actorsInvolved = await VideoShareModel.loadActorsWhoSharedVideosOf(byActor.id, transaction)
|
||||
|
||||
// In case the actor did not have any videos
|
||||
const serverActor = await getServerActor()
|
||||
|
@ -40,10 +40,16 @@ async function sendDeleteActor (byActor: ActorModel, t: Transaction) {
|
|||
|
||||
actorsInvolved.push(byActor)
|
||||
|
||||
return broadcastToFollowers(activity, byActor, actorsInvolved, t)
|
||||
return broadcastToFollowers({
|
||||
data: activity,
|
||||
byActor,
|
||||
toFollowersOf: actorsInvolved,
|
||||
contextType: 'Delete',
|
||||
transaction
|
||||
})
|
||||
}
|
||||
|
||||
async function sendDeleteVideoComment (videoComment: MCommentOwnerVideo, t: Transaction) {
|
||||
async function sendDeleteVideoComment (videoComment: MCommentOwnerVideo, transaction: Transaction) {
|
||||
logger.info('Creating job to send delete of comment %s.', videoComment.url)
|
||||
|
||||
const isVideoOrigin = videoComment.Video.isOwned()
|
||||
|
@ -53,10 +59,10 @@ async function sendDeleteVideoComment (videoComment: MCommentOwnerVideo, t: Tran
|
|||
? videoComment.Account.Actor
|
||||
: videoComment.Video.VideoChannel.Account.Actor
|
||||
|
||||
const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, t)
|
||||
const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, transaction)
|
||||
const threadParentCommentsFiltered = threadParentComments.filter(c => !c.isDeleted())
|
||||
|
||||
const actorsInvolvedInComment = await getActorsInvolvedInVideo(videoComment.Video, t)
|
||||
const actorsInvolvedInComment = await getActorsInvolvedInVideo(videoComment.Video, transaction)
|
||||
actorsInvolvedInComment.push(byActor) // Add the actor that commented the video
|
||||
|
||||
const audience = getVideoCommentAudience(videoComment, threadParentCommentsFiltered, actorsInvolvedInComment, isVideoOrigin)
|
||||
|
@ -64,19 +70,48 @@ async function sendDeleteVideoComment (videoComment: MCommentOwnerVideo, t: Tran
|
|||
|
||||
// This was a reply, send it to the parent actors
|
||||
const actorsException = [ byActor ]
|
||||
await broadcastToActors(activity, byActor, threadParentCommentsFiltered.map(c => c.Account.Actor), t, actorsException)
|
||||
await broadcastToActors({
|
||||
data: activity,
|
||||
byActor,
|
||||
toActors: threadParentCommentsFiltered.map(c => c.Account.Actor),
|
||||
transaction,
|
||||
contextType: 'Delete',
|
||||
actorsException
|
||||
})
|
||||
|
||||
// Broadcast to our followers
|
||||
await broadcastToFollowers(activity, byActor, [ byActor ], t)
|
||||
await broadcastToFollowers({
|
||||
data: activity,
|
||||
byActor,
|
||||
toFollowersOf: [ byActor ],
|
||||
contextType: 'Delete',
|
||||
transaction
|
||||
})
|
||||
|
||||
// Send to actors involved in the comment
|
||||
if (isVideoOrigin) return broadcastToFollowers(activity, byActor, actorsInvolvedInComment, t, actorsException)
|
||||
if (isVideoOrigin) {
|
||||
return broadcastToFollowers({
|
||||
data: activity,
|
||||
byActor,
|
||||
toFollowersOf: actorsInvolvedInComment,
|
||||
transaction,
|
||||
contextType: 'Delete',
|
||||
actorsException
|
||||
})
|
||||
}
|
||||
|
||||
// Send to origin
|
||||
t.afterCommit(() => unicastTo(activity, byActor, videoComment.Video.VideoChannel.Account.Actor.getSharedInbox()))
|
||||
return transaction.afterCommit(() => {
|
||||
return unicastTo({
|
||||
data: activity,
|
||||
byActor,
|
||||
toActorUrl: videoComment.Video.VideoChannel.Account.Actor.getSharedInbox(),
|
||||
contextType: 'Delete'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function sendDeleteVideoPlaylist (videoPlaylist: MVideoPlaylistFullSummary, t: Transaction) {
|
||||
async function sendDeleteVideoPlaylist (videoPlaylist: MVideoPlaylistFullSummary, transaction: Transaction) {
|
||||
logger.info('Creating job to send delete of playlist %s.', videoPlaylist.url)
|
||||
|
||||
const byActor = videoPlaylist.OwnerAccount.Actor
|
||||
|
@ -89,7 +124,13 @@ async function sendDeleteVideoPlaylist (videoPlaylist: MVideoPlaylistFullSummary
|
|||
|
||||
if (videoPlaylist.VideoChannel) toFollowersOf.push(videoPlaylist.VideoChannel.Actor)
|
||||
|
||||
return broadcastToFollowers(activity, byActor, toFollowersOf, t)
|
||||
return broadcastToFollowers({
|
||||
data: activity,
|
||||
byActor,
|
||||
toFollowersOf,
|
||||
contextType: 'Delete',
|
||||
transaction
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -6,7 +6,7 @@ import { audiencify, getAudience } from '../audience'
|
|||
import { getVideoDislikeActivityPubUrlByLocalActor } from '../url'
|
||||
import { sendVideoActivityToOrigin } from './shared/send-utils'
|
||||
|
||||
function sendDislike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
|
||||
function sendDislike (byActor: MActor, video: MVideoAccountLight, transaction: Transaction) {
|
||||
logger.info('Creating job to dislike %s.', video.url)
|
||||
|
||||
const activityBuilder = (audience: ActivityAudience) => {
|
||||
|
@ -15,7 +15,7 @@ function sendDislike (byActor: MActor, video: MVideoAccountLight, t: Transaction
|
|||
return buildDislikeActivity(url, byActor, video, audience)
|
||||
}
|
||||
|
||||
return sendVideoActivityToOrigin(activityBuilder, { byActor, video, transaction: t })
|
||||
return sendVideoActivityToOrigin(activityBuilder, { byActor, video, transaction, contextType: 'Rate' })
|
||||
}
|
||||
|
||||
function buildDislikeActivity (url: string, byActor: MActorAudience, video: MVideoUrl, audience?: ActivityAudience): ActivityDislike {
|
||||
|
|
|
@ -17,16 +17,20 @@ function sendAbuse (byActor: MActor, abuse: MAbuseAP, flaggedAccount: MAccountLi
|
|||
const audience = { to: [ flaggedAccount.Actor.url ], cc: [] }
|
||||
const flagActivity = buildFlagActivity(url, byActor, abuse, audience)
|
||||
|
||||
t.afterCommit(() => unicastTo(flagActivity, byActor, flaggedAccount.Actor.getSharedInbox()))
|
||||
return t.afterCommit(() => {
|
||||
return unicastTo({
|
||||
data: flagActivity,
|
||||
byActor,
|
||||
toActorUrl: flaggedAccount.Actor.getSharedInbox(),
|
||||
contextType: 'Flag'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function buildFlagActivity (url: string, byActor: MActor, abuse: MAbuseAP, audience: ActivityAudience): ActivityFlag {
|
||||
if (!audience) audience = getAudience(byActor)
|
||||
|
||||
const activity = Object.assign(
|
||||
{ id: url, actor: byActor.url },
|
||||
abuse.toActivityPubObject()
|
||||
)
|
||||
const activity = { id: url, actor: byActor.url, ...abuse.toActivityPubObject() }
|
||||
|
||||
return audiencify(activity, audience)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@ function sendFollow (actorFollow: MActorFollowActors, t: Transaction) {
|
|||
|
||||
const data = buildFollowActivity(actorFollow.url, me, following)
|
||||
|
||||
t.afterCommit(() => unicastTo(data, me, following.inboxUrl))
|
||||
return t.afterCommit(() => {
|
||||
return unicastTo({ data, byActor: me, toActorUrl: following.inboxUrl, contextType: 'Follow' })
|
||||
})
|
||||
}
|
||||
|
||||
function buildFollowActivity (url: string, byActor: MActor, targetActor: MActor): ActivityFollow {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { audiencify, getAudience } from '../audience'
|
|||
import { getVideoLikeActivityPubUrlByLocalActor } from '../url'
|
||||
import { sendVideoActivityToOrigin } from './shared/send-utils'
|
||||
|
||||
function sendLike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
|
||||
function sendLike (byActor: MActor, video: MVideoAccountLight, transaction: Transaction) {
|
||||
logger.info('Creating job to like %s.', video.url)
|
||||
|
||||
const activityBuilder = (audience: ActivityAudience) => {
|
||||
|
@ -15,7 +15,7 @@ function sendLike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
|
|||
return buildLikeActivity(url, byActor, video, audience)
|
||||
}
|
||||
|
||||
return sendVideoActivityToOrigin(activityBuilder, { byActor, video, transaction: t })
|
||||
return sendVideoActivityToOrigin(activityBuilder, { byActor, video, transaction, contextType: 'Rate' })
|
||||
}
|
||||
|
||||
function buildLikeActivity (url: string, byActor: MActorAudience, video: MVideoUrl, audience?: ActivityAudience): ActivityLike {
|
||||
|
|
|
@ -18,7 +18,7 @@ function sendReject (followUrl: string, follower: MActor, following: MActor) {
|
|||
const url = getLocalActorFollowRejectActivityPubUrl(follower, following)
|
||||
const data = buildRejectActivity(url, following, followData)
|
||||
|
||||
return unicastTo(data, following, follower.inboxUrl)
|
||||
return unicastTo({ data, byActor: following, toActorUrl: follower.inboxUrl, contextType: 'Reject' })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -6,7 +6,8 @@ import {
|
|||
ActivityDislike,
|
||||
ActivityFollow,
|
||||
ActivityLike,
|
||||
ActivityUndo
|
||||
ActivityUndo,
|
||||
ContextType
|
||||
} from '@shared/models'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { VideoModel } from '../../../models/video/video'
|
||||
|
@ -43,24 +44,37 @@ function sendUndoFollow (actorFollow: MActorFollowActors, t: Transaction) {
|
|||
const followActivity = buildFollowActivity(actorFollow.url, me, following)
|
||||
const undoActivity = undoActivityData(undoUrl, me, followActivity)
|
||||
|
||||
t.afterCommit(() => unicastTo(undoActivity, me, following.inboxUrl))
|
||||
return t.afterCommit(() => {
|
||||
return unicastTo({
|
||||
data: undoActivity,
|
||||
byActor: me,
|
||||
toActorUrl: following.inboxUrl,
|
||||
contextType: 'Follow'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function sendUndoAnnounce (byActor: MActorLight, videoShare: MVideoShare, video: MVideo, t: Transaction) {
|
||||
async function sendUndoAnnounce (byActor: MActorLight, videoShare: MVideoShare, video: MVideo, transaction: 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 { activity: announce, actorsInvolvedInVideo } = await buildAnnounceWithVideoAudience(byActor, videoShare, video, transaction)
|
||||
const undoActivity = undoActivityData(undoUrl, byActor, announce)
|
||||
|
||||
const followersException = [ byActor ]
|
||||
return broadcastToFollowers(undoActivity, byActor, actorsInvolvedInVideo, t, followersException)
|
||||
return broadcastToFollowers({
|
||||
data: undoActivity,
|
||||
byActor,
|
||||
toFollowersOf: actorsInvolvedInVideo,
|
||||
transaction,
|
||||
actorsException: [ byActor ],
|
||||
contextType: 'Announce'
|
||||
})
|
||||
}
|
||||
|
||||
async function sendUndoCacheFile (byActor: MActor, redundancyModel: MVideoRedundancyVideo, t: Transaction) {
|
||||
async function sendUndoCacheFile (byActor: MActor, redundancyModel: MVideoRedundancyVideo, transaction: Transaction) {
|
||||
logger.info('Creating job to undo cache file %s.', redundancyModel.url)
|
||||
|
||||
const associatedVideo = redundancyModel.getVideo()
|
||||
|
@ -72,7 +86,14 @@ async function sendUndoCacheFile (byActor: MActor, redundancyModel: MVideoRedund
|
|||
const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(associatedVideo.id)
|
||||
const createActivity = buildCreateActivity(redundancyModel.url, byActor, redundancyModel.toActivityPubObject())
|
||||
|
||||
return sendUndoVideoRelatedActivity({ byActor, video, url: redundancyModel.url, activity: createActivity, transaction: t })
|
||||
return sendUndoVideoRelatedActivity({
|
||||
byActor,
|
||||
video,
|
||||
url: redundancyModel.url,
|
||||
activity: createActivity,
|
||||
contextType: 'CacheFile',
|
||||
transaction
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -83,7 +104,7 @@ async function sendUndoLike (byActor: MActor, video: MVideoAccountLight, t: Tran
|
|||
const likeUrl = getVideoLikeActivityPubUrlByLocalActor(byActor, video)
|
||||
const likeActivity = buildLikeActivity(likeUrl, byActor, video)
|
||||
|
||||
return sendUndoVideoToOriginActivity({ byActor, video, url: likeUrl, activity: likeActivity, transaction: t })
|
||||
return sendUndoVideoRateToOriginActivity({ byActor, video, url: likeUrl, activity: likeActivity, transaction: t })
|
||||
}
|
||||
|
||||
async function sendUndoDislike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
|
||||
|
@ -92,7 +113,7 @@ async function sendUndoDislike (byActor: MActor, video: MVideoAccountLight, t: T
|
|||
const dislikeUrl = getVideoDislikeActivityPubUrlByLocalActor(byActor, video)
|
||||
const dislikeActivity = buildDislikeActivity(dislikeUrl, byActor, video)
|
||||
|
||||
return sendUndoVideoToOriginActivity({ byActor, video, url: dislikeUrl, activity: dislikeActivity, transaction: t })
|
||||
return sendUndoVideoRateToOriginActivity({ byActor, video, url: dislikeUrl, activity: dislikeActivity, transaction: t })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -131,6 +152,7 @@ async function sendUndoVideoRelatedActivity (options: {
|
|||
video: MVideoAccountLight
|
||||
url: string
|
||||
activity: ActivityFollow | ActivityCreate | ActivityAnnounce
|
||||
contextType: ContextType
|
||||
transaction: Transaction
|
||||
}) {
|
||||
const activityBuilder = (audience: ActivityAudience) => {
|
||||
|
@ -142,7 +164,7 @@ async function sendUndoVideoRelatedActivity (options: {
|
|||
return sendVideoRelatedActivity(activityBuilder, options)
|
||||
}
|
||||
|
||||
async function sendUndoVideoToOriginActivity (options: {
|
||||
async function sendUndoVideoRateToOriginActivity (options: {
|
||||
byActor: MActor
|
||||
video: MVideoAccountLight
|
||||
url: string
|
||||
|
@ -155,5 +177,5 @@ async function sendUndoVideoToOriginActivity (options: {
|
|||
return undoActivityData(undoUrl, options.byActor, options.activity, audience)
|
||||
}
|
||||
|
||||
return sendVideoActivityToOrigin(activityBuilder, options)
|
||||
return sendVideoActivityToOrigin(activityBuilder, { ...options, contextType: 'Rate' })
|
||||
}
|
||||
|
|
|
@ -20,20 +20,20 @@ import { getUpdateActivityPubUrl } from '../url'
|
|||
import { getActorsInvolvedInVideo } from './shared'
|
||||
import { broadcastToFollowers, sendVideoRelatedActivity } from './shared/send-utils'
|
||||
|
||||
async function sendUpdateVideo (videoArg: MVideoAPWithoutCaption, t: Transaction, overrodeByActor?: MActor) {
|
||||
async function sendUpdateVideo (videoArg: MVideoAPWithoutCaption, transaction: Transaction, overriddenByActor?: MActor) {
|
||||
const video = videoArg as MVideoAP
|
||||
|
||||
if (!video.hasPrivacyForFederation()) return undefined
|
||||
|
||||
logger.info('Creating job to update video %s.', video.url)
|
||||
|
||||
const byActor = overrodeByActor || video.VideoChannel.Account.Actor
|
||||
const byActor = overriddenByActor || video.VideoChannel.Account.Actor
|
||||
|
||||
const url = getUpdateActivityPubUrl(video.url, video.updatedAt.toISOString())
|
||||
|
||||
// Needed to build the AP object
|
||||
if (!video.VideoCaptions) {
|
||||
video.VideoCaptions = await video.$get('VideoCaptions', { transaction: t })
|
||||
video.VideoCaptions = await video.$get('VideoCaptions', { transaction })
|
||||
}
|
||||
|
||||
const videoObject = video.toActivityPubObject()
|
||||
|
@ -41,13 +41,19 @@ async function sendUpdateVideo (videoArg: MVideoAPWithoutCaption, t: Transaction
|
|||
|
||||
const updateActivity = buildUpdateActivity(url, byActor, videoObject, audience)
|
||||
|
||||
const actorsInvolved = await getActorsInvolvedInVideo(video, t)
|
||||
if (overrodeByActor) actorsInvolved.push(overrodeByActor)
|
||||
const actorsInvolved = await getActorsInvolvedInVideo(video, transaction)
|
||||
if (overriddenByActor) actorsInvolved.push(overriddenByActor)
|
||||
|
||||
return broadcastToFollowers(updateActivity, byActor, actorsInvolved, t)
|
||||
return broadcastToFollowers({
|
||||
data: updateActivity,
|
||||
byActor,
|
||||
toFollowersOf: actorsInvolved,
|
||||
contextType: 'Video',
|
||||
transaction
|
||||
})
|
||||
}
|
||||
|
||||
async function sendUpdateActor (accountOrChannel: MChannelDefault | MAccountDefault, t: Transaction) {
|
||||
async function sendUpdateActor (accountOrChannel: MChannelDefault | MAccountDefault, transaction: Transaction) {
|
||||
const byActor = accountOrChannel.Actor
|
||||
|
||||
logger.info('Creating job to update actor %s.', byActor.url)
|
||||
|
@ -60,15 +66,21 @@ async function sendUpdateActor (accountOrChannel: MChannelDefault | MAccountDefa
|
|||
let actorsInvolved: MActor[]
|
||||
if (accountOrChannel instanceof AccountModel) {
|
||||
// Actors that shared my videos are involved too
|
||||
actorsInvolved = await VideoShareModel.loadActorsWhoSharedVideosOf(byActor.id, t)
|
||||
actorsInvolved = await VideoShareModel.loadActorsWhoSharedVideosOf(byActor.id, transaction)
|
||||
} else {
|
||||
// Actors that shared videos of my channel are involved too
|
||||
actorsInvolved = await VideoShareModel.loadActorsByVideoChannel(accountOrChannel.id, t)
|
||||
actorsInvolved = await VideoShareModel.loadActorsByVideoChannel(accountOrChannel.id, transaction)
|
||||
}
|
||||
|
||||
actorsInvolved.push(byActor)
|
||||
|
||||
return broadcastToFollowers(updateActivity, byActor, actorsInvolved, t)
|
||||
return broadcastToFollowers({
|
||||
data: updateActivity,
|
||||
byActor,
|
||||
toFollowersOf: actorsInvolved,
|
||||
transaction,
|
||||
contextType: 'Actor'
|
||||
})
|
||||
}
|
||||
|
||||
async function sendUpdateCacheFile (byActor: MActorLight, redundancyModel: MVideoRedundancyVideo) {
|
||||
|
@ -92,7 +104,7 @@ async function sendUpdateCacheFile (byActor: MActorLight, redundancyModel: MVide
|
|||
return sendVideoRelatedActivity(activityBuilder, { byActor, video, contextType: 'CacheFile' })
|
||||
}
|
||||
|
||||
async function sendUpdateVideoPlaylist (videoPlaylist: MVideoPlaylistFull, t: Transaction) {
|
||||
async function sendUpdateVideoPlaylist (videoPlaylist: MVideoPlaylistFull, transaction: Transaction) {
|
||||
if (videoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) return undefined
|
||||
|
||||
const byActor = videoPlaylist.OwnerAccount.Actor
|
||||
|
@ -101,7 +113,7 @@ async function sendUpdateVideoPlaylist (videoPlaylist: MVideoPlaylistFull, t: Tr
|
|||
|
||||
const url = getUpdateActivityPubUrl(videoPlaylist.url, videoPlaylist.updatedAt.toISOString())
|
||||
|
||||
const object = await videoPlaylist.toActivityPubObject(null, t)
|
||||
const object = await videoPlaylist.toActivityPubObject(null, transaction)
|
||||
const audience = getAudience(byActor, videoPlaylist.privacy === VideoPlaylistPrivacy.PUBLIC)
|
||||
|
||||
const updateActivity = buildUpdateActivity(url, byActor, object, audience)
|
||||
|
@ -111,7 +123,13 @@ async function sendUpdateVideoPlaylist (videoPlaylist: MVideoPlaylistFull, t: Tr
|
|||
|
||||
if (videoPlaylist.VideoChannel) toFollowersOf.push(videoPlaylist.VideoChannel.Actor)
|
||||
|
||||
return broadcastToFollowers(updateActivity, byActor, toFollowersOf, t)
|
||||
return broadcastToFollowers({
|
||||
data: updateActivity,
|
||||
byActor,
|
||||
toFollowersOf,
|
||||
transaction,
|
||||
contextType: 'Playlist'
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Transaction } from 'sequelize'
|
||||
import { ActorFollowHealthCache } from '@server/lib/actor-follow-health-cache'
|
||||
import { getServerActor } from '@server/models/application/application'
|
||||
import { Activity, ActivityAudience } from '@shared/models'
|
||||
import { Activity, ActivityAudience, ActivitypubHttpBroadcastPayload } from '@shared/models'
|
||||
import { ContextType } from '@shared/models/activitypub/context'
|
||||
import { afterCommitIfTransaction } from '../../../../helpers/database-utils'
|
||||
import { logger } from '../../../../helpers/logger'
|
||||
|
@ -14,8 +14,8 @@ import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getOriginVideoAud
|
|||
async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: {
|
||||
byActor: MActorLight
|
||||
video: MVideoImmutable | MVideoAccountLight
|
||||
contextType: ContextType
|
||||
transaction?: Transaction
|
||||
contextType?: ContextType
|
||||
}) {
|
||||
const { byActor, video, transaction, contextType } = options
|
||||
|
||||
|
@ -32,15 +32,23 @@ async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAud
|
|||
|
||||
const actorsException = [ byActor ]
|
||||
|
||||
return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, transaction, actorsException, contextType)
|
||||
return broadcastToFollowers({
|
||||
data: activity,
|
||||
byActor,
|
||||
toFollowersOf: actorsInvolvedInVideo,
|
||||
transaction,
|
||||
actorsException,
|
||||
contextType
|
||||
})
|
||||
}
|
||||
|
||||
async function sendVideoActivityToOrigin (activityBuilder: (audience: ActivityAudience) => Activity, options: {
|
||||
byActor: MActorLight
|
||||
video: MVideoImmutable | MVideoAccountLight
|
||||
contextType: ContextType
|
||||
|
||||
actorsInvolvedInVideo?: MActorLight[]
|
||||
transaction?: Transaction
|
||||
contextType?: ContextType
|
||||
}) {
|
||||
const { byActor, video, actorsInvolvedInVideo, transaction, contextType } = options
|
||||
|
||||
|
@ -53,7 +61,12 @@ async function sendVideoActivityToOrigin (activityBuilder: (audience: ActivityAu
|
|||
const activity = activityBuilder(audience)
|
||||
|
||||
return afterCommitIfTransaction(transaction, () => {
|
||||
return unicastTo(activity, byActor, accountActor.getSharedInbox(), contextType)
|
||||
return unicastTo({
|
||||
data: activity,
|
||||
byActor,
|
||||
toActorUrl: accountActor.getSharedInbox(),
|
||||
contextType
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -100,41 +113,69 @@ async function forwardActivity (
|
|||
|
||||
logger.debug('Creating forwarding job.', { uris })
|
||||
|
||||
const payload = {
|
||||
const payload: ActivitypubHttpBroadcastPayload = {
|
||||
uris,
|
||||
body: activity
|
||||
body: activity,
|
||||
contextType: null
|
||||
}
|
||||
return afterCommitIfTransaction(t, () => JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload }))
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function broadcastToFollowers (
|
||||
data: any,
|
||||
byActor: MActorId,
|
||||
toFollowersOf: MActorId[],
|
||||
t: Transaction,
|
||||
actorsException: MActorWithInboxes[] = [],
|
||||
contextType?: ContextType
|
||||
) {
|
||||
const uris = await computeFollowerUris(toFollowersOf, actorsException, t)
|
||||
async function broadcastToFollowers (options: {
|
||||
data: any
|
||||
byActor: MActorId
|
||||
toFollowersOf: MActorId[]
|
||||
transaction: Transaction
|
||||
contextType: ContextType
|
||||
|
||||
return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor, contextType))
|
||||
actorsException?: MActorWithInboxes[]
|
||||
}) {
|
||||
const { data, byActor, toFollowersOf, transaction, contextType, actorsException = [] } = options
|
||||
|
||||
const uris = await computeFollowerUris(toFollowersOf, actorsException, transaction)
|
||||
|
||||
return afterCommitIfTransaction(transaction, () => {
|
||||
return broadcastTo({
|
||||
uris,
|
||||
data,
|
||||
byActor,
|
||||
contextType
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function broadcastToActors (
|
||||
data: any,
|
||||
byActor: MActorId,
|
||||
toActors: MActor[],
|
||||
t?: Transaction,
|
||||
actorsException: MActorWithInboxes[] = [],
|
||||
contextType?: ContextType
|
||||
) {
|
||||
async function broadcastToActors (options: {
|
||||
data: any
|
||||
byActor: MActorId
|
||||
toActors: MActor[]
|
||||
transaction: Transaction
|
||||
contextType: ContextType
|
||||
actorsException?: MActorWithInboxes[]
|
||||
}) {
|
||||
const { data, byActor, toActors, transaction, contextType, actorsException = [] } = options
|
||||
|
||||
const uris = await computeUris(toActors, actorsException)
|
||||
return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor, contextType))
|
||||
|
||||
return afterCommitIfTransaction(transaction, () => {
|
||||
return broadcastTo({
|
||||
uris,
|
||||
data,
|
||||
byActor,
|
||||
contextType
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function broadcastTo (uris: string[], data: any, byActor: MActorId, contextType?: ContextType) {
|
||||
function broadcastTo (options: {
|
||||
uris: string[]
|
||||
data: any
|
||||
byActor: MActorId
|
||||
contextType: ContextType
|
||||
}) {
|
||||
const { uris, data, byActor, contextType } = options
|
||||
|
||||
if (uris.length === 0) return undefined
|
||||
|
||||
const broadcastUris: string[] = []
|
||||
|
@ -174,7 +215,14 @@ function broadcastTo (uris: string[], data: any, byActor: MActorId, contextType?
|
|||
}
|
||||
}
|
||||
|
||||
function unicastTo (data: any, byActor: MActorId, toActorUrl: string, contextType?: ContextType) {
|
||||
function unicastTo (options: {
|
||||
data: any
|
||||
byActor: MActorId
|
||||
toActorUrl: string
|
||||
contextType: ContextType
|
||||
}) {
|
||||
const { data, byActor, toActorUrl, contextType } = options
|
||||
|
||||
logger.debug('Creating unicast job.', { uri: toActorUrl })
|
||||
|
||||
const payload = {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { map } from 'bluebird'
|
||||
import { Job } from 'bull'
|
||||
import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from '@server/lib/activitypub/send'
|
||||
import { ActorFollowHealthCache } from '@server/lib/actor-follow-health-cache'
|
||||
import { ActivitypubHttpBroadcastPayload } from '@shared/models'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { doRequest } from '../../../helpers/requests'
|
||||
import { BROADCAST_CONCURRENCY } from '../../../initializers/constants'
|
||||
import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from './utils/activitypub-http-utils'
|
||||
|
||||
async function processActivityPubHttpBroadcast (job: Job) {
|
||||
logger.info('Processing ActivityPub broadcast in job %d.', job.id)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { Job } from 'bull'
|
||||
import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from '@server/lib/activitypub/send'
|
||||
import { ActivitypubHttpUnicastPayload } from '@shared/models'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { doRequest } from '../../../helpers/requests'
|
||||
import { ActorFollowHealthCache } from '../../actor-follow-health-cache'
|
||||
import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from './utils/activitypub-http-utils'
|
||||
|
||||
async function processActivityPubHttpUnicast (job: Job) {
|
||||
logger.info('Processing ActivityPub unicast in job %d.', job.id)
|
||||
|
|
|
@ -605,7 +605,7 @@ export class ActorModel extends Model<Partial<AttributesOnly<ActorModel>>> {
|
|||
image
|
||||
}
|
||||
|
||||
return activityPubContextify(json)
|
||||
return activityPubContextify(json, 'Actor')
|
||||
}
|
||||
|
||||
getFollowerSharedInboxUrls (t: Transaction) {
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
import 'mocha'
|
||||
import { expect } from 'chai'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { signAndContextify } from '@server/lib/activitypub/send'
|
||||
import { buildRequestStub } from '@server/tests/shared'
|
||||
import { buildAbsoluteFixturePath } from '@shared/core-utils'
|
||||
import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../../../helpers/peertube-crypto'
|
||||
import { buildSignedActivity } from '../../../lib/activitypub/activity'
|
||||
|
||||
describe('Test activity pub helpers', function () {
|
||||
describe('When checking the Linked Signature', function () {
|
||||
|
@ -46,7 +46,7 @@ describe('Test activity pub helpers', function () {
|
|||
const body = require(buildAbsoluteFixturePath('./ap-json/peertube/announce-without-context.json'))
|
||||
|
||||
const actorSignature = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey }
|
||||
const signedBody = await buildSignedActivity(actorSignature as any, body)
|
||||
const signedBody = await signAndContextify(actorSignature as any, body, 'Announce')
|
||||
|
||||
const fromActor = { publicKey: keys.publicKey, url: 'http://localhost:9002/accounts/peertube' }
|
||||
const result = await isJsonLDSignatureVerified(fromActor as any, signedBody)
|
||||
|
@ -59,7 +59,7 @@ describe('Test activity pub helpers', function () {
|
|||
const body = require(buildAbsoluteFixturePath('./ap-json/peertube/announce-without-context.json'))
|
||||
|
||||
const actorSignature = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey }
|
||||
const signedBody = await buildSignedActivity(actorSignature as any, body)
|
||||
const signedBody = await signAndContextify(actorSignature as any, body, 'Announce')
|
||||
|
||||
const fromActor = { publicKey: keys.publicKey, url: 'http://localhost:9002/accounts/peertube' }
|
||||
const result = await isJsonLDSignatureVerified(fromActor as any, signedBody)
|
||||
|
|
|
@ -4,9 +4,8 @@ import 'mocha'
|
|||
import * as chai from 'chai'
|
||||
import { buildDigest } from '@server/helpers/peertube-crypto'
|
||||
import { HTTP_SIGNATURE } from '@server/initializers/constants'
|
||||
import { buildSignedActivity } from '@server/lib/activitypub/activity'
|
||||
import { activityPubContextify } from '@server/lib/activitypub/context'
|
||||
import { buildGlobalHeaders } from '@server/lib/job-queue/handlers/utils/activitypub-http-utils'
|
||||
import { buildGlobalHeaders, signAndContextify } from '@server/lib/activitypub/send'
|
||||
import { makeFollowRequest, makePOSTAPRequest } from '@server/tests/shared'
|
||||
import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
|
@ -81,7 +80,7 @@ describe('Test ActivityPub security', function () {
|
|||
describe('When checking HTTP signature', function () {
|
||||
|
||||
it('Should fail with an invalid digest', async function () {
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||
const headers = {
|
||||
Digest: buildDigest({ hello: 'coucou' })
|
||||
}
|
||||
|
@ -95,7 +94,7 @@ describe('Test ActivityPub security', function () {
|
|||
})
|
||||
|
||||
it('Should fail with an invalid date', async function () {
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||
const headers = buildGlobalHeaders(body)
|
||||
headers['date'] = 'Wed, 21 Oct 2015 07:28:00 GMT'
|
||||
|
||||
|
@ -111,7 +110,7 @@ describe('Test ActivityPub security', function () {
|
|||
await setKeysOfServer(servers[0], servers[1], invalidKeys.publicKey, invalidKeys.privateKey)
|
||||
await setKeysOfServer(servers[1], servers[1], invalidKeys.publicKey, invalidKeys.privateKey)
|
||||
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||
const headers = buildGlobalHeaders(body)
|
||||
|
||||
try {
|
||||
|
@ -126,7 +125,7 @@ describe('Test ActivityPub security', function () {
|
|||
await setKeysOfServer(servers[0], servers[1], keys.publicKey, keys.privateKey)
|
||||
await setKeysOfServer(servers[1], servers[1], keys.publicKey, keys.privateKey)
|
||||
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||
const headers = buildGlobalHeaders(body)
|
||||
|
||||
const signatureOptions = baseHttpSignature()
|
||||
|
@ -149,7 +148,7 @@ describe('Test ActivityPub security', function () {
|
|||
})
|
||||
|
||||
it('Should succeed with a valid HTTP signature', async function () {
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||
const headers = buildGlobalHeaders(body)
|
||||
|
||||
const { statusCode } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
|
||||
|
@ -168,7 +167,7 @@ describe('Test ActivityPub security', function () {
|
|||
await killallServers([ servers[1] ])
|
||||
await servers[1].run()
|
||||
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||
const headers = buildGlobalHeaders(body)
|
||||
|
||||
try {
|
||||
|
@ -204,7 +203,7 @@ describe('Test ActivityPub security', function () {
|
|||
body.actor = 'http://localhost:' + servers[2].port + '/accounts/peertube'
|
||||
|
||||
const signer: any = { privateKey: invalidKeys.privateKey, url: 'http://localhost:' + servers[2].port + '/accounts/peertube' }
|
||||
const signedBody = await buildSignedActivity(signer, body)
|
||||
const signedBody = await signAndContextify(signer, body, 'Announce')
|
||||
|
||||
const headers = buildGlobalHeaders(signedBody)
|
||||
|
||||
|
@ -226,7 +225,7 @@ describe('Test ActivityPub security', function () {
|
|||
body.actor = 'http://localhost:' + servers[2].port + '/accounts/peertube'
|
||||
|
||||
const signer: any = { privateKey: keys.privateKey, url: 'http://localhost:' + servers[2].port + '/accounts/peertube' }
|
||||
const signedBody = await buildSignedActivity(signer, body)
|
||||
const signedBody = await signAndContextify(signer, body, 'Announce')
|
||||
|
||||
signedBody.actor = 'http://localhost:' + servers[2].port + '/account/peertube'
|
||||
|
||||
|
@ -247,7 +246,7 @@ describe('Test ActivityPub security', function () {
|
|||
body.actor = 'http://localhost:' + servers[2].port + '/accounts/peertube'
|
||||
|
||||
const signer: any = { privateKey: keys.privateKey, url: 'http://localhost:' + servers[2].port + '/accounts/peertube' }
|
||||
const signedBody = await buildSignedActivity(signer, body)
|
||||
const signedBody = await signAndContextify(signer, body, 'Announce')
|
||||
|
||||
const headers = buildGlobalHeaders(signedBody)
|
||||
|
||||
|
@ -269,7 +268,7 @@ describe('Test ActivityPub security', function () {
|
|||
body.actor = 'http://localhost:' + servers[2].port + '/accounts/peertube'
|
||||
|
||||
const signer: any = { privateKey: keys.privateKey, url: 'http://localhost:' + servers[2].port + '/accounts/peertube' }
|
||||
const signedBody = await buildSignedActivity(signer, body)
|
||||
const signedBody = await signAndContextify(signer, body, 'Announce')
|
||||
|
||||
const headers = buildGlobalHeaders(signedBody)
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ export async function makeFollowRequest (to: { url: string }, by: { url: string,
|
|||
object: to.url
|
||||
}
|
||||
|
||||
const body = activityPubContextify(follow)
|
||||
const body = activityPubContextify(follow, 'Follow')
|
||||
|
||||
const httpSignature = {
|
||||
algorithm: HTTP_SIGNATURE.ALGORITHM,
|
||||
|
|
|
@ -1 +1,15 @@
|
|||
export type ContextType = 'All' | 'View' | 'Announce' | 'CacheFile'
|
||||
export type ContextType =
|
||||
'Video' |
|
||||
'Comment' |
|
||||
'Playlist' |
|
||||
'Follow' |
|
||||
'Reject' |
|
||||
'Accept' |
|
||||
'View' |
|
||||
'Announce' |
|
||||
'CacheFile' |
|
||||
'Delete' |
|
||||
'Rate' |
|
||||
'Flag' |
|
||||
'Actor' |
|
||||
'Collection'
|
||||
|
|
|
@ -46,7 +46,7 @@ export type ActivityTrackerUrlObject = {
|
|||
href: string
|
||||
}
|
||||
|
||||
export type ActivityPlaylistInfohashesObject = {
|
||||
export type ActivityStreamingPlaylistInfohashesObject = {
|
||||
type: 'Infohash'
|
||||
name: string
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ export interface ActivityFlagReasonObject {
|
|||
|
||||
export type ActivityTagObject =
|
||||
ActivityPlaylistSegmentHashesObject
|
||||
| ActivityPlaylistInfohashesObject
|
||||
| ActivityStreamingPlaylistInfohashesObject
|
||||
| ActivityVideoUrlObject
|
||||
| ActivityHashTagObject
|
||||
| ActivityMentionObject
|
||||
|
|
|
@ -40,9 +40,9 @@ export interface Job {
|
|||
|
||||
export type ActivitypubHttpBroadcastPayload = {
|
||||
uris: string[]
|
||||
signatureActorId?: number
|
||||
contextType: ContextType
|
||||
body: any
|
||||
contextType?: ContextType
|
||||
signatureActorId?: number
|
||||
}
|
||||
|
||||
export type ActivitypubFollowPayload = {
|
||||
|
@ -62,9 +62,9 @@ export type ActivitypubHttpFetcherPayload = {
|
|||
|
||||
export type ActivitypubHttpUnicastPayload = {
|
||||
uri: string
|
||||
contextType: ContextType
|
||||
signatureActorId?: number
|
||||
body: object
|
||||
contextType?: ContextType
|
||||
}
|
||||
|
||||
export type RefreshPayload = {
|
||||
|
|
Loading…
Reference in New Issue