mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-05 02:39:33 +02:00
Check video rights before providing AP information
This commit is contained in:
parent
b8635c2606
commit
afb28272f5
31 changed files with 254 additions and 233 deletions
|
@ -145,7 +145,7 @@ async function buildElementsDBAttributes (elementUrls: string[], playlist: MVide
|
|||
try {
|
||||
const { elementObject } = await fetchRemotePlaylistElement(elementUrl)
|
||||
|
||||
const { video } = await getOrCreateAPVideo({ videoObject: { id: elementObject.url }, fetchType: 'only-video' })
|
||||
const { video } = await getOrCreateAPVideo({ videoObject: { id: elementObject.url }, fetchType: 'only-video-and-blacklist' })
|
||||
|
||||
elementsToCreate.push(playlistElementObjectToDBAttributes(elementObject, playlist, video))
|
||||
} catch (err) {
|
||||
|
|
|
@ -24,7 +24,7 @@ import { createOrUpdateLocalVideoViewer } from '../local-video-viewer.js'
|
|||
import { createOrUpdateVideoPlaylist } from '../playlists/index.js'
|
||||
import { forwardVideoRelatedActivity } from '../send/shared/send-utils.js'
|
||||
import { resolveThread } from '../video-comments.js'
|
||||
import { getOrCreateAPVideo } from '../videos/index.js'
|
||||
import { canVideoBeFederated, getOrCreateAPVideo } from '../videos/index.js'
|
||||
|
||||
async function processCreateActivity (options: APProcessorOptions<ActivityCreate<ActivityCreateObject>>) {
|
||||
const { activity, byActor } = options
|
||||
|
@ -87,6 +87,11 @@ async function processCreateCacheFile (
|
|||
|
||||
const { video } = await getOrCreateAPVideo({ videoObject: cacheFile.object })
|
||||
|
||||
if (video.isOwned() && !canVideoBeFederated(video)) {
|
||||
logger.warn(`Do not process create cache file ${cacheFile.object} on a video that cannot be federated`)
|
||||
return
|
||||
}
|
||||
|
||||
await sequelizeTypescript.transaction(async t => {
|
||||
return createOrUpdateCacheFile(cacheFile, video, byActor, t)
|
||||
})
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { VideoModel } from '@server/models/video/video.js'
|
||||
import { ActivityDislike } from '@peertube/peertube-models'
|
||||
import { logger } from '@server/helpers/logger.js'
|
||||
import { VideoModel } from '@server/models/video/video.js'
|
||||
import { retryTransactionWrapper } from '../../../helpers/database-utils.js'
|
||||
import { sequelizeTypescript } from '../../../initializers/database.js'
|
||||
import { AccountVideoRateModel } from '../../../models/account/account-video-rate.js'
|
||||
import { APProcessorOptions } from '../../../types/activitypub-processor.model.js'
|
||||
import { MActorSignature } from '../../../types/models/index.js'
|
||||
import { federateVideoIfNeeded, maybeGetOrCreateAPVideo } from '../videos/index.js'
|
||||
import { canVideoBeFederated, federateVideoIfNeeded, maybeGetOrCreateAPVideo } from '../videos/index.js'
|
||||
|
||||
async function processDislikeActivity (options: APProcessorOptions<ActivityDislike>) {
|
||||
const { activity, byActor } = options
|
||||
|
@ -21,14 +22,19 @@ export {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function processDislike (activity: ActivityDislike, byActor: MActorSignature) {
|
||||
const dislikeObject = activity.object
|
||||
const videoUrl = activity.object
|
||||
const byAccount = byActor.Account
|
||||
|
||||
if (!byAccount) throw new Error('Cannot create dislike with the non account actor ' + byActor.url)
|
||||
|
||||
const { video: onlyVideo } = await maybeGetOrCreateAPVideo({ videoObject: dislikeObject, fetchType: 'only-video' })
|
||||
const { video: onlyVideo } = await maybeGetOrCreateAPVideo({ videoObject: videoUrl, fetchType: 'only-video-and-blacklist' })
|
||||
if (!onlyVideo?.isOwned()) return
|
||||
|
||||
if (!canVideoBeFederated(onlyVideo)) {
|
||||
logger.warn(`Do not process dislike on video ${videoUrl} that cannot be federated`)
|
||||
return
|
||||
}
|
||||
|
||||
return sequelizeTypescript.transaction(async t => {
|
||||
const video = await VideoModel.loadFull(onlyVideo.id, t)
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { ActivityLike } from '@peertube/peertube-models'
|
||||
import { logger } from '@server/helpers/logger.js'
|
||||
import { VideoModel } from '@server/models/video/video.js'
|
||||
import { retryTransactionWrapper } from '../../../helpers/database-utils.js'
|
||||
import { sequelizeTypescript } from '../../../initializers/database.js'
|
||||
|
@ -6,7 +7,7 @@ import { getAPId } from '../../../lib/activitypub/activity.js'
|
|||
import { AccountVideoRateModel } from '../../../models/account/account-video-rate.js'
|
||||
import { APProcessorOptions } from '../../../types/activitypub-processor.model.js'
|
||||
import { MActorSignature } from '../../../types/models/index.js'
|
||||
import { federateVideoIfNeeded, maybeGetOrCreateAPVideo } from '../videos/index.js'
|
||||
import { canVideoBeFederated, federateVideoIfNeeded, maybeGetOrCreateAPVideo } from '../videos/index.js'
|
||||
|
||||
async function processLikeActivity (options: APProcessorOptions<ActivityLike>) {
|
||||
const { activity, byActor } = options
|
||||
|
@ -28,9 +29,14 @@ async function processLikeVideo (byActor: MActorSignature, activity: ActivityLik
|
|||
const byAccount = byActor.Account
|
||||
if (!byAccount) throw new Error('Cannot create like with the non account actor ' + byActor.url)
|
||||
|
||||
const { video: onlyVideo } = await maybeGetOrCreateAPVideo({ videoObject: videoUrl, fetchType: 'only-video' })
|
||||
const { video: onlyVideo } = await maybeGetOrCreateAPVideo({ videoObject: videoUrl, fetchType: 'only-video-and-blacklist' })
|
||||
if (!onlyVideo?.isOwned()) return
|
||||
|
||||
if (!canVideoBeFederated(onlyVideo)) {
|
||||
logger.warn(`Do not process like on video ${videoUrl} that cannot be federated`)
|
||||
return
|
||||
}
|
||||
|
||||
return sequelizeTypescript.transaction(async t => {
|
||||
const video = await VideoModel.loadFull(onlyVideo.id, t)
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import { APActorUpdater } from '../actors/updater.js'
|
|||
import { createOrUpdateCacheFile } from '../cache-file.js'
|
||||
import { createOrUpdateVideoPlaylist } from '../playlists/index.js'
|
||||
import { forwardVideoRelatedActivity } from '../send/shared/send-utils.js'
|
||||
import { APVideoUpdater, getOrCreateAPVideo } from '../videos/index.js'
|
||||
import { APVideoUpdater, canVideoBeFederated, getOrCreateAPVideo } from '../videos/index.js'
|
||||
|
||||
async function processUpdateActivity (options: APProcessorOptions<ActivityUpdate<ActivityUpdateObject>>) {
|
||||
const { activity, byActor } = options
|
||||
|
@ -93,6 +93,11 @@ async function processUpdateCacheFile (
|
|||
|
||||
const { video } = await getOrCreateAPVideo({ videoObject: cacheFileObject.object })
|
||||
|
||||
if (video.isOwned() && !canVideoBeFederated(video)) {
|
||||
logger.warn(`Do not process update cache file on video ${activity.object} that cannot be federated`)
|
||||
return
|
||||
}
|
||||
|
||||
await sequelizeTypescript.transaction(async t => {
|
||||
await createOrUpdateCacheFile(cacheFileObject, video, byActor, t)
|
||||
})
|
||||
|
|
|
@ -24,7 +24,7 @@ async function processCreateView (activity: ActivityView, byActor: MActorSignatu
|
|||
|
||||
const { video } = await getOrCreateAPVideo({
|
||||
videoObject,
|
||||
fetchType: 'only-video',
|
||||
fetchType: 'only-video-and-blacklist',
|
||||
allowRefresh: false
|
||||
})
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { Transaction } from 'sequelize'
|
||||
import { getServerActor } from '@server/models/application/application.js'
|
||||
import {
|
||||
ActivityAudience,
|
||||
ActivityCreate,
|
||||
|
@ -9,19 +7,24 @@ import {
|
|||
VideoPlaylistPrivacy,
|
||||
VideoPrivacy
|
||||
} from '@peertube/peertube-models'
|
||||
import { AccountModel } from '@server/models/account/account.js'
|
||||
import { getServerActor } from '@server/models/application/application.js'
|
||||
import { VideoModel } from '@server/models/video/video.js'
|
||||
import { Transaction } from 'sequelize'
|
||||
import { logger, loggerTagsFactory } from '../../../helpers/logger.js'
|
||||
import { VideoCommentModel } from '../../../models/video/video-comment.js'
|
||||
import {
|
||||
MActorLight,
|
||||
MCommentOwnerVideo,
|
||||
MLocalVideoViewerWithWatchSections,
|
||||
MVideoAccountLight,
|
||||
MVideoAP,
|
||||
MVideoAccountLight,
|
||||
MVideoPlaylistFull,
|
||||
MVideoRedundancyFileVideo,
|
||||
MVideoRedundancyStreamingPlaylistVideo
|
||||
} from '../../../types/models/index.js'
|
||||
import { audiencify, getAudience } from '../audience.js'
|
||||
import { canVideoBeFederated } from '../videos/federate.js'
|
||||
import {
|
||||
broadcastToActors,
|
||||
broadcastToFollowers,
|
||||
|
@ -32,12 +35,11 @@ import {
|
|||
sendVideoRelatedActivity,
|
||||
unicastTo
|
||||
} from './shared/index.js'
|
||||
import { AccountModel } from '@server/models/account/account.js'
|
||||
|
||||
const lTags = loggerTagsFactory('ap', 'create')
|
||||
|
||||
async function sendCreateVideo (video: MVideoAP, transaction: Transaction) {
|
||||
if (!video.hasPrivacyForFederation()) return undefined
|
||||
export async function sendCreateVideo (video: MVideoAP, transaction: Transaction) {
|
||||
if (!canVideoBeFederated(video)) return undefined
|
||||
|
||||
logger.info('Creating job to send video creation of %s.', video.url, lTags(video.uuid))
|
||||
|
||||
|
@ -56,7 +58,7 @@ async function sendCreateVideo (video: MVideoAP, transaction: Transaction) {
|
|||
})
|
||||
}
|
||||
|
||||
async function sendCreateCacheFile (
|
||||
export async function sendCreateCacheFile (
|
||||
byActor: MActorLight,
|
||||
video: MVideoAccountLight,
|
||||
fileRedundancy: MVideoRedundancyStreamingPlaylistVideo | MVideoRedundancyFileVideo
|
||||
|
@ -72,7 +74,7 @@ async function sendCreateCacheFile (
|
|||
})
|
||||
}
|
||||
|
||||
async function sendCreateWatchAction (stats: MLocalVideoViewerWithWatchSections, transaction: Transaction) {
|
||||
export async function sendCreateWatchAction (stats: MLocalVideoViewerWithWatchSections, transaction: Transaction) {
|
||||
logger.info('Creating job to send create watch action %s.', stats.url, lTags(stats.uuid))
|
||||
|
||||
const byActor = await getServerActor()
|
||||
|
@ -84,7 +86,7 @@ async function sendCreateWatchAction (stats: MLocalVideoViewerWithWatchSections,
|
|||
return sendVideoActivityToOrigin(activityBuilder, { byActor, video: stats.Video, transaction, contextType: 'WatchAction' })
|
||||
}
|
||||
|
||||
async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, transaction: Transaction) {
|
||||
export 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))
|
||||
|
@ -109,11 +111,20 @@ async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, transactio
|
|||
})
|
||||
}
|
||||
|
||||
async function sendCreateVideoComment (comment: MCommentOwnerVideo, transaction: Transaction) {
|
||||
logger.info('Creating job to send comment %s.', comment.url)
|
||||
|
||||
export async function sendCreateVideoComment (comment: MCommentOwnerVideo, transaction: Transaction) {
|
||||
const isOrigin = comment.Video.isOwned()
|
||||
|
||||
if (isOrigin) {
|
||||
const videoWithBlacklist = await VideoModel.loadWithBlacklist(comment.Video.id)
|
||||
|
||||
if (!canVideoBeFederated(videoWithBlacklist)) {
|
||||
logger.debug(`Do not send comment ${comment.url} on a video that cannot be federated`)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
logger.info('Creating job to send comment %s.', comment.url)
|
||||
|
||||
const byActor = comment.Account.Actor
|
||||
const videoAccount = await AccountModel.load(comment.Video.VideoChannel.Account.id, transaction)
|
||||
|
||||
|
@ -179,7 +190,7 @@ async function sendCreateVideoComment (comment: MCommentOwnerVideo, transaction:
|
|||
})
|
||||
}
|
||||
|
||||
function buildCreateActivity <T extends ActivityCreateObject> (
|
||||
export function buildCreateActivity <T extends ActivityCreateObject> (
|
||||
url: string,
|
||||
byActor: MActorLight,
|
||||
object: T,
|
||||
|
@ -201,16 +212,7 @@ function buildCreateActivity <T extends ActivityCreateObject> (
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
sendCreateVideo,
|
||||
buildCreateActivity,
|
||||
sendCreateVideoComment,
|
||||
sendCreateVideoPlaylist,
|
||||
sendCreateCacheFile,
|
||||
sendCreateWatchAction
|
||||
}
|
||||
|
||||
// Private
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function sendVideoRelatedCreateActivity (options: {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Transaction } from 'sequelize'
|
||||
import { getServerActor } from '@server/models/application/application.js'
|
||||
import { ActivityAudience, ActivityUpdate, ActivityUpdateObject, VideoPlaylistPrivacy, VideoPrivacy } from '@peertube/peertube-models'
|
||||
import { getServerActor } from '@server/models/application/application.js'
|
||||
import { Transaction } from 'sequelize'
|
||||
import { logger } from '../../../helpers/logger.js'
|
||||
import { AccountModel } from '../../../models/account/account.js'
|
||||
import { VideoModel } from '../../../models/video/video.js'
|
||||
import { VideoShareModel } from '../../../models/video/video-share.js'
|
||||
import { VideoModel } from '../../../models/video/video.js'
|
||||
import {
|
||||
MAccountDefault,
|
||||
MActor,
|
||||
|
@ -16,11 +16,12 @@ import {
|
|||
} from '../../../types/models/index.js'
|
||||
import { audiencify, getAudience } from '../audience.js'
|
||||
import { getUpdateActivityPubUrl } from '../url.js'
|
||||
import { canVideoBeFederated } from '../videos/federate.js'
|
||||
import { getActorsInvolvedInVideo } from './shared/index.js'
|
||||
import { broadcastToFollowers, sendVideoRelatedActivity } from './shared/send-utils.js'
|
||||
|
||||
async function sendUpdateVideo (videoArg: MVideoAPLight, transaction: Transaction, overriddenByActor?: MActor) {
|
||||
if (!videoArg.hasPrivacyForFederation()) return undefined
|
||||
export async function sendUpdateVideo (videoArg: MVideoAPLight, transaction: Transaction, overriddenByActor?: MActor) {
|
||||
if (!canVideoBeFederated(videoArg)) return undefined
|
||||
|
||||
const video = await videoArg.lightAPToFullAP(transaction)
|
||||
|
||||
|
@ -47,7 +48,7 @@ async function sendUpdateVideo (videoArg: MVideoAPLight, transaction: Transactio
|
|||
})
|
||||
}
|
||||
|
||||
async function sendUpdateActor (accountOrChannel: MChannelDefault | MAccountDefault, transaction: Transaction) {
|
||||
export async function sendUpdateActor (accountOrChannel: MChannelDefault | MAccountDefault, transaction: Transaction) {
|
||||
const byActor = accountOrChannel.Actor
|
||||
|
||||
logger.info('Creating job to update actor %s.', byActor.url)
|
||||
|
@ -77,7 +78,7 @@ async function sendUpdateActor (accountOrChannel: MChannelDefault | MAccountDefa
|
|||
})
|
||||
}
|
||||
|
||||
async function sendUpdateCacheFile (byActor: MActorLight, redundancyModel: MVideoRedundancyVideo) {
|
||||
export async function sendUpdateCacheFile (byActor: MActorLight, redundancyModel: MVideoRedundancyVideo) {
|
||||
logger.info('Creating job to update cache file %s.', redundancyModel.url)
|
||||
|
||||
const associatedVideo = redundancyModel.getVideo()
|
||||
|
@ -98,7 +99,7 @@ async function sendUpdateCacheFile (byActor: MActorLight, redundancyModel: MVide
|
|||
return sendVideoRelatedActivity(activityBuilder, { byActor, video, contextType: 'CacheFile' })
|
||||
}
|
||||
|
||||
async function sendUpdateVideoPlaylist (videoPlaylist: MVideoPlaylistFull, transaction: Transaction) {
|
||||
export async function sendUpdateVideoPlaylist (videoPlaylist: MVideoPlaylistFull, transaction: Transaction) {
|
||||
if (videoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) return undefined
|
||||
|
||||
const byActor = videoPlaylist.OwnerAccount.Actor
|
||||
|
@ -127,14 +128,7 @@ async function sendUpdateVideoPlaylist (videoPlaylist: MVideoPlaylistFull, trans
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
sendUpdateActor,
|
||||
sendUpdateVideo,
|
||||
sendUpdateCacheFile,
|
||||
sendUpdateVideoPlaylist
|
||||
}
|
||||
|
||||
// Private
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function buildUpdateActivity (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { getServerActor } from '@server/models/application/application.js'
|
||||
import Bluebird from 'bluebird'
|
||||
import { Transaction } from 'sequelize'
|
||||
import { getServerActor } from '@server/models/application/application.js'
|
||||
import { logger, loggerTagsFactory } from '../../helpers/logger.js'
|
||||
import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants.js'
|
||||
import { VideoShareModel } from '../../models/video/video-share.js'
|
||||
|
@ -12,16 +12,7 @@ import { checkUrlsSameHost, getLocalVideoAnnounceActivityPubUrl } from './url.js
|
|||
|
||||
const lTags = loggerTagsFactory('share')
|
||||
|
||||
async function shareVideoByServerAndChannel (video: MVideoAccountLight, t: Transaction) {
|
||||
if (!video.hasPrivacyForFederation()) return undefined
|
||||
|
||||
return Promise.all([
|
||||
shareByServer(video, t),
|
||||
shareByVideoChannel(video, t)
|
||||
])
|
||||
}
|
||||
|
||||
async function changeVideoChannelShare (
|
||||
export async function changeVideoChannelShare (
|
||||
video: MVideoAccountLight,
|
||||
oldVideoChannel: MChannelActorLight,
|
||||
t: Transaction
|
||||
|
@ -36,7 +27,7 @@ async function changeVideoChannelShare (
|
|||
await shareByVideoChannel(video, t)
|
||||
}
|
||||
|
||||
async function addVideoShares (shareUrls: string[], video: MVideoId) {
|
||||
export async function addVideoShares (shareUrls: string[], video: MVideoId) {
|
||||
await Bluebird.map(shareUrls, async shareUrl => {
|
||||
try {
|
||||
await addVideoShare(shareUrl, video)
|
||||
|
@ -46,12 +37,44 @@ async function addVideoShares (shareUrls: string[], video: MVideoId) {
|
|||
}, { concurrency: CRAWL_REQUEST_CONCURRENCY })
|
||||
}
|
||||
|
||||
export {
|
||||
changeVideoChannelShare,
|
||||
addVideoShares,
|
||||
shareVideoByServerAndChannel
|
||||
export async function shareByServer (video: MVideo, t: Transaction) {
|
||||
const serverActor = await getServerActor()
|
||||
|
||||
const serverShareUrl = getLocalVideoAnnounceActivityPubUrl(serverActor, video)
|
||||
const [ serverShare ] = await VideoShareModel.findOrCreate({
|
||||
defaults: {
|
||||
actorId: serverActor.id,
|
||||
videoId: video.id,
|
||||
url: serverShareUrl
|
||||
},
|
||||
where: {
|
||||
url: serverShareUrl
|
||||
},
|
||||
transaction: t
|
||||
})
|
||||
|
||||
return sendVideoAnnounce(serverActor, serverShare, video, t)
|
||||
}
|
||||
|
||||
export async function shareByVideoChannel (video: MVideoAccountLight, t: Transaction) {
|
||||
const videoChannelShareUrl = getLocalVideoAnnounceActivityPubUrl(video.VideoChannel.Actor, video)
|
||||
const [ videoChannelShare ] = await VideoShareModel.findOrCreate({
|
||||
defaults: {
|
||||
actorId: video.VideoChannel.actorId,
|
||||
videoId: video.id,
|
||||
url: videoChannelShareUrl
|
||||
},
|
||||
where: {
|
||||
url: videoChannelShareUrl
|
||||
},
|
||||
transaction: t
|
||||
})
|
||||
|
||||
return sendVideoAnnounce(video.VideoChannel.Actor, videoChannelShare, video, t)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Private
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function addVideoShare (shareUrl: string, video: MVideoId) {
|
||||
|
@ -74,42 +97,6 @@ async function addVideoShare (shareUrl: string, video: MVideoId) {
|
|||
await VideoShareModel.upsert(entry)
|
||||
}
|
||||
|
||||
async function shareByServer (video: MVideo, t: Transaction) {
|
||||
const serverActor = await getServerActor()
|
||||
|
||||
const serverShareUrl = getLocalVideoAnnounceActivityPubUrl(serverActor, video)
|
||||
const [ serverShare ] = await VideoShareModel.findOrCreate({
|
||||
defaults: {
|
||||
actorId: serverActor.id,
|
||||
videoId: video.id,
|
||||
url: serverShareUrl
|
||||
},
|
||||
where: {
|
||||
url: serverShareUrl
|
||||
},
|
||||
transaction: t
|
||||
})
|
||||
|
||||
return sendVideoAnnounce(serverActor, serverShare, video, t)
|
||||
}
|
||||
|
||||
async function shareByVideoChannel (video: MVideoAccountLight, t: Transaction) {
|
||||
const videoChannelShareUrl = getLocalVideoAnnounceActivityPubUrl(video.VideoChannel.Actor, video)
|
||||
const [ videoChannelShare ] = await VideoShareModel.findOrCreate({
|
||||
defaults: {
|
||||
actorId: video.VideoChannel.actorId,
|
||||
videoId: video.id,
|
||||
url: videoChannelShareUrl
|
||||
},
|
||||
where: {
|
||||
url: videoChannelShareUrl
|
||||
},
|
||||
transaction: t
|
||||
})
|
||||
|
||||
return sendVideoAnnounce(video.VideoChannel.Actor, videoChannelShare, video, t)
|
||||
}
|
||||
|
||||
async function undoShareByVideoChannel (video: MVideo, oldVideoChannel: MChannelActorLight, t: Transaction) {
|
||||
// Load old share
|
||||
const oldShare = await VideoShareModel.load(oldVideoChannel.actorId, video.id, t)
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Hooks } from '../plugins/hooks.js'
|
|||
import { fetchAP } from './activity.js'
|
||||
import { getOrCreateAPActor } from './actors/index.js'
|
||||
import { checkUrlsSameHost } from './url.js'
|
||||
import { getOrCreateAPVideo } from './videos/index.js'
|
||||
import { canVideoBeFederated, getOrCreateAPVideo } from './videos/index.js'
|
||||
|
||||
type ResolveThreadParams = {
|
||||
url: string
|
||||
|
@ -92,8 +92,8 @@ async function tryToResolveThreadFromVideo (params: ResolveThreadParams) {
|
|||
const syncParam = { rates: true, shares: true, comments: false, refreshVideo: false }
|
||||
const { video } = await getOrCreateAPVideo({ videoObject: url, syncParam })
|
||||
|
||||
if (video.isOwned() && !video.hasPrivacyForFederation()) {
|
||||
throw new Error('Cannot resolve thread of video with privacy that is not compatible with federation')
|
||||
if (video.isOwned() && !canVideoBeFederated(video)) {
|
||||
throw new Error('Cannot resolve thread of video that is not compatible with federation')
|
||||
}
|
||||
|
||||
let resultComment: MCommentOwnerVideo
|
||||
|
|
|
@ -1,29 +1,53 @@
|
|||
import { forceNumber } from '@peertube/peertube-core-utils'
|
||||
import { VideoPrivacy, VideoPrivacyType, VideoState, VideoStateType } from '@peertube/peertube-models'
|
||||
import { CONFIG } from '@server/initializers/config.js'
|
||||
import { MVideoAPLight, MVideoWithBlacklistRights } from '@server/types/models/index.js'
|
||||
import { Transaction } from 'sequelize'
|
||||
import { MVideoAP, MVideoAPLight } from '@server/types/models/index.js'
|
||||
import { sendCreateVideo, sendUpdateVideo } from '../send/index.js'
|
||||
import { shareVideoByServerAndChannel } from '../share.js'
|
||||
import { shareByServer, shareByVideoChannel } from '../share.js'
|
||||
|
||||
async function federateVideoIfNeeded (videoArg: MVideoAPLight, isNewVideo: boolean, transaction?: Transaction) {
|
||||
const video = videoArg as MVideoAP
|
||||
export async function federateVideoIfNeeded (videoArg: MVideoAPLight, isNewVideo: boolean, transaction?: Transaction) {
|
||||
if (!canVideoBeFederated(videoArg, isNewVideo)) return
|
||||
|
||||
if (
|
||||
// Check this is not a blacklisted video, or unfederated blacklisted video
|
||||
(video.isBlacklisted() === false || (isNewVideo === false && video.VideoBlacklist.unfederated === false)) &&
|
||||
// Check the video is public/unlisted and published
|
||||
video.hasPrivacyForFederation() && video.hasStateForFederation()
|
||||
) {
|
||||
const video = await videoArg.lightAPToFullAP(transaction)
|
||||
const video = await videoArg.lightAPToFullAP(transaction)
|
||||
|
||||
if (isNewVideo) {
|
||||
// Now we'll add the video's meta data to our followers
|
||||
await sendCreateVideo(video, transaction)
|
||||
await shareVideoByServerAndChannel(video, transaction)
|
||||
} else {
|
||||
await sendUpdateVideo(video, transaction)
|
||||
}
|
||||
if (isNewVideo) {
|
||||
// Now we'll add the video's meta data to our followers
|
||||
await sendCreateVideo(video, transaction)
|
||||
|
||||
await Promise.all([
|
||||
shareByServer(video, transaction),
|
||||
shareByVideoChannel(video, transaction)
|
||||
])
|
||||
} else {
|
||||
await sendUpdateVideo(video, transaction)
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
federateVideoIfNeeded
|
||||
export function canVideoBeFederated (video: MVideoWithBlacklistRights, isNewVideo = false) {
|
||||
// Check this is not a blacklisted video
|
||||
if (video.isBlacklisted() === true) {
|
||||
if (isNewVideo === false) return false
|
||||
if (video.VideoBlacklist.unfederated === true) return false
|
||||
}
|
||||
|
||||
// Check the video is public/unlisted and published
|
||||
return isPrivacyForFederation(video.privacy) && isStateForFederation(video.state)
|
||||
}
|
||||
|
||||
export function isNewVideoPrivacyForFederation (currentPrivacy: VideoPrivacyType, newPrivacy: VideoPrivacyType) {
|
||||
return !isPrivacyForFederation(currentPrivacy) && isPrivacyForFederation(newPrivacy)
|
||||
}
|
||||
|
||||
export function isPrivacyForFederation (privacy: VideoPrivacyType) {
|
||||
const castedPrivacy = forceNumber(privacy)
|
||||
|
||||
return castedPrivacy === VideoPrivacy.PUBLIC ||
|
||||
(CONFIG.FEDERATION.VIDEOS.FEDERATE_UNLISTED === true && castedPrivacy === VideoPrivacy.UNLISTED)
|
||||
}
|
||||
|
||||
export function isStateForFederation (state: VideoStateType) {
|
||||
const castedState = forceNumber(state)
|
||||
|
||||
return castedState === VideoState.PUBLISHED || castedState === VideoState.WAITING_FOR_LIVE || castedState === VideoState.LIVE_ENDED
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
import { APObjectId } from '@peertube/peertube-models'
|
||||
import { retryTransactionWrapper } from '@server/helpers/database-utils.js'
|
||||
import { logger } from '@server/helpers/logger.js'
|
||||
import { JobQueue } from '@server/lib/job-queue/index.js'
|
||||
import { loadVideoByUrl, VideoLoadByUrlType } from '@server/lib/model-loaders/index.js'
|
||||
import { MVideoAccountLightBlacklistAllFiles, MVideoImmutable, MVideoThumbnail } from '@server/types/models/index.js'
|
||||
import { APObjectId } from '@peertube/peertube-models'
|
||||
import {
|
||||
MVideoAccountLightBlacklistAllFiles,
|
||||
MVideoImmutable,
|
||||
MVideoThumbnail,
|
||||
MVideoThumbnailBlacklist
|
||||
} from '@server/types/models/index.js'
|
||||
import { getAPId } from '../activity.js'
|
||||
import { refreshVideoIfNeeded } from './refresh.js'
|
||||
import { APVideoCreator, fetchRemoteVideo, SyncParam, syncVideoExternalAttributes } from './shared/index.js'
|
||||
|
@ -24,23 +29,25 @@ type GetVideoParamAll = {
|
|||
type GetVideoParamImmutable = {
|
||||
videoObject: APObjectId
|
||||
syncParam?: SyncParam
|
||||
fetchType: 'only-immutable-attributes'
|
||||
fetchType: 'unsafe-only-immutable-attributes'
|
||||
allowRefresh: false
|
||||
}
|
||||
|
||||
type GetVideoParamOther = {
|
||||
videoObject: APObjectId
|
||||
syncParam?: SyncParam
|
||||
fetchType?: 'all' | 'only-video'
|
||||
fetchType?: 'all' | 'only-video-and-blacklist'
|
||||
allowRefresh?: boolean
|
||||
}
|
||||
|
||||
export function getOrCreateAPVideo (options: GetVideoParamAll): GetVideoResult<MVideoAccountLightBlacklistAllFiles>
|
||||
export function getOrCreateAPVideo (options: GetVideoParamImmutable): GetVideoResult<MVideoImmutable>
|
||||
export function getOrCreateAPVideo (options: GetVideoParamOther): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail>
|
||||
export function getOrCreateAPVideo (
|
||||
options: GetVideoParamOther
|
||||
): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnailBlacklist>
|
||||
export async function getOrCreateAPVideo (
|
||||
options: GetVideoParamAll | GetVideoParamImmutable | GetVideoParamOther
|
||||
): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> {
|
||||
): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnailBlacklist | MVideoImmutable> {
|
||||
// Default params
|
||||
const syncParam = options.syncParam || { rates: true, shares: true, comments: true, refreshVideo: false }
|
||||
const fetchType = options.fetchType || 'all'
|
||||
|
@ -52,7 +59,7 @@ export async function getOrCreateAPVideo (
|
|||
|
||||
if (videoFromDatabase) {
|
||||
if (allowRefresh === true) {
|
||||
// Typings ensure allowRefresh === false in only-immutable-attributes fetch type
|
||||
// Typings ensure allowRefresh === false in unsafe-only-immutable-attributes fetch type
|
||||
videoFromDatabase = await scheduleRefresh(videoFromDatabase as MVideoThumbnail, fetchType, syncParam)
|
||||
}
|
||||
|
||||
|
@ -87,7 +94,9 @@ export async function getOrCreateAPVideo (
|
|||
|
||||
export function maybeGetOrCreateAPVideo (options: GetVideoParamAll): GetVideoResult<MVideoAccountLightBlacklistAllFiles>
|
||||
export function maybeGetOrCreateAPVideo (options: GetVideoParamImmutable): GetVideoResult<MVideoImmutable>
|
||||
export function maybeGetOrCreateAPVideo (options: GetVideoParamOther): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail>
|
||||
export function maybeGetOrCreateAPVideo (
|
||||
options: GetVideoParamOther
|
||||
): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnailBlacklist>
|
||||
export async function maybeGetOrCreateAPVideo (options: GetVideoParamAll | GetVideoParamImmutable | GetVideoParamOther) {
|
||||
try {
|
||||
const result = await getOrCreateAPVideo(options as any)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue