if (fetchType === 'id' || fetchType === 'none') return VideoModel.loadOnlyId(id)
}
-type VideoFetchByUrlType = 'all' | 'only-video'
+type VideoFetchByUrlType = 'all' | 'only-video' | 'only-immutable-attributes'
function fetchVideoByUrl (url: string, fetchType: 'all'): Bluebird<MVideoAccountLightBlacklistAllFiles>
+function fetchVideoByUrl (url: string, fetchType: 'only-immutable-attributes'): Bluebird<MVideoImmutable>
function fetchVideoByUrl (url: string, fetchType: 'only-video'): Bluebird<MVideoThumbnail>
-function fetchVideoByUrl (url: string, fetchType: VideoFetchByUrlType): Bluebird<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail>
-function fetchVideoByUrl (url: string, fetchType: VideoFetchByUrlType): Bluebird<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail> {
+function fetchVideoByUrl (
+ url: string,
+ fetchType: VideoFetchByUrlType
+): Bluebird<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable>
+function fetchVideoByUrl (
+ url: string,
+ fetchType: VideoFetchByUrlType
+): Bluebird<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> {
if (fetchType === 'all') return VideoModel.loadByUrlAndPopulateAccount(url)
+ if (fetchType === 'only-immutable-attributes') return VideoModel.loadByUrlImmutableAttributes(url)
+
if (fetchType === 'only-video') return VideoModel.loadByUrl(url)
}
import { ActorModel } from '../../models/activitypub/actor'
import { VideoModel } from '../../models/video/video'
import { VideoShareModel } from '../../models/video/video-share'
-import { MActorFollowersUrl, MActorLight, MCommentOwner, MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../../typings/models'
+import {
+ MActorFollowersUrl,
+ MActorLight,
+ MCommentOwner,
+ MCommentOwnerVideo,
+ MVideo,
+ MVideoAccountLight,
+ MVideoId
+} from '../../typings/models'
function getRemoteVideoAudience (video: MVideoAccountLight, actorsInvolvedInVideo: MActorFollowersUrl[]): ActivityAudience {
return {
}
}
-async function getActorsInvolvedInVideo (video: MVideo, t: Transaction) {
+async function getActorsInvolvedInVideo (video: MVideoId, t: Transaction) {
const actors: MActorLight[] = await VideoShareModel.loadActorsByShare(video.id, t)
const videoAll = video as VideoModel
const options = {
videoObject,
- fetchType: 'only-video' as 'only-video'
+ fetchType: 'only-immutable-attributes' as 'only-immutable-attributes',
+ allowRefresh: false as false
}
const { video } = await getOrCreateVideoAndAccountAndChannel(options)
import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience'
import { getServerActor } from '../../../helpers/utils'
import { afterCommitIfTransaction } from '../../../helpers/database-utils'
-import { MActorWithInboxes, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models'
+import { MActorWithInboxes, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight, MVideoId } from '../../../typings/models'
import { ContextType } from '@server/helpers/activitypub'
async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: {
activity: Activity,
t: Transaction,
followersException: MActorWithInboxes[] = [],
- video: MVideo
+ video: MVideoId
) {
// Mastodon does not add our announces in audience, so we forward to them manually
const additionalActors = await getActorsInvolvedInVideo(video, t)
MVideoAPWithoutCaption,
MVideoFile,
MVideoFullLight,
- MVideoId,
+ MVideoId, MVideoImmutable,
MVideoThumbnail
} from '../../typings/models'
import { MThumbnail } from '../../typings/models/video/thumbnail'
await Bluebird.map(jobPayloads, payload => JobQueue.Instance.createJobWithPromise({ type: 'activitypub-http-fetcher', payload }))
}
-function getOrCreateVideoAndAccountAndChannel (options: {
+type GetVideoResult <T> = Promise<{
+ video: T
+ created: boolean
+ autoBlacklisted?: boolean
+}>
+
+type GetVideoParamAll = {
videoObject: { id: string } | string
syncParam?: SyncParam
fetchType?: 'all'
allowRefresh?: boolean
-}): Promise<{ video: MVideoAccountLightBlacklistAllFiles, created: boolean, autoBlacklisted?: boolean }>
-function getOrCreateVideoAndAccountAndChannel (options: {
+}
+
+type GetVideoParamImmutable = {
videoObject: { id: string } | string
syncParam?: SyncParam
- fetchType?: VideoFetchByUrlType
- allowRefresh?: boolean
-}): Promise<{ video: MVideoAccountLightBlacklistAllFiles | MVideoThumbnail, created: boolean, autoBlacklisted?: boolean }>
-async function getOrCreateVideoAndAccountAndChannel (options: {
+ fetchType: 'only-immutable-attributes'
+ allowRefresh: false
+}
+
+type GetVideoParamOther = {
videoObject: { id: string } | string
syncParam?: SyncParam
- fetchType?: VideoFetchByUrlType
- allowRefresh?: boolean // true by default
-}): Promise<{ video: MVideoAccountLightBlacklistAllFiles | MVideoThumbnail, created: boolean, autoBlacklisted?: boolean }> {
+ fetchType?: 'all' | 'only-video'
+ allowRefresh?: boolean
+}
+
+function getOrCreateVideoAndAccountAndChannel (options: GetVideoParamAll): GetVideoResult<MVideoAccountLightBlacklistAllFiles>
+function getOrCreateVideoAndAccountAndChannel (options: GetVideoParamImmutable): GetVideoResult<MVideoImmutable>
+function getOrCreateVideoAndAccountAndChannel (
+ options: GetVideoParamOther
+): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail>
+async function getOrCreateVideoAndAccountAndChannel (
+ options: GetVideoParamAll | GetVideoParamImmutable | GetVideoParamOther
+): GetVideoResult<MVideoAccountLightBlacklistAllFiles | MVideoThumbnail | MVideoImmutable> {
// Default params
const syncParam = options.syncParam || { likes: true, dislikes: true, shares: true, comments: true, thumbnail: true, refreshVideo: false }
const fetchType = options.fetchType || 'all'
// Get video url
const videoUrl = getAPId(options.videoObject)
-
let videoFromDatabase = await fetchVideoByUrl(videoUrl, fetchType)
+
if (videoFromDatabase) {
- if (videoFromDatabase.isOutdated() && allowRefresh === true) {
+ // If allowRefresh is true, we could not call this function using 'only-immutable-attributes' fetch type
+ if (allowRefresh === true && (videoFromDatabase as MVideoThumbnail).isOutdated()) {
const refreshOptions = {
- video: videoFromDatabase,
+ video: videoFromDatabase as MVideoThumbnail,
fetchedType: fetchType,
syncParam
}
if (areValidationErrors(req, res)) return
if (!await doesVideoExist(req.params.id, res, fetchType)) return
+ // Controllers does not need to check video rights
+ if (fetchType === 'only-immutable-attributes') return next()
+
const video = getVideoWithAttributes(res)
const videoAll = video as MVideoFullLight
'local-account-name'
| 'local-actor-name'
| 'local-actor-url'
- | 'video-immutable'
+ | 'load-video-immutable-id'
+ | 'load-video-immutable-url'
type DeleteKey =
'video'
'local-account-name': new Map(),
'local-actor-name': new Map(),
'local-actor-url': new Map(),
- 'video-immutable': new Map()
+ 'load-video-immutable-id': new Map(),
+ 'load-video-immutable-url': new Map()
}
private readonly deleteIds: {
WITH_USER_HISTORY = 'WITH_USER_HISTORY',
WITH_STREAMING_PLAYLISTS = 'WITH_STREAMING_PLAYLISTS',
WITH_USER_ID = 'WITH_USER_ID',
+ WITH_IMMUTABLE_ATTRIBUTES = 'WITH_IMMUTABLE_ATTRIBUTES',
WITH_THUMBNAILS = 'WITH_THUMBNAILS'
}
}
@Scopes(() => ({
+ [ScopeNames.WITH_IMMUTABLE_ATTRIBUTES]: {
+ attributes: [ 'id', 'url', 'uuid', 'remote' ]
+ },
[ScopeNames.FOR_API]: (options: ForAPIOptions) => {
const query: FindOptions = {
include: [
static loadImmutableAttributes (id: number | string, t?: Transaction): Bluebird<MVideoImmutable> {
const fun = () => {
- const where = buildWhereIdOrUUID(id)
- const options = {
- attributes: [
- 'id', 'url', 'uuid'
- ],
- where,
+ const query = {
+ where: buildWhereIdOrUUID(id),
transaction: t
}
- return VideoModel.unscoped().findOne(options)
+ return VideoModel.scope(ScopeNames.WITH_IMMUTABLE_ATTRIBUTES).findOne(query)
}
return ModelCache.Instance.doCache({
- cacheType: 'video-immutable',
+ cacheType: 'load-video-immutable-id',
key: '' + id,
deleteKey: 'video',
fun
return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(query)
}
+ static loadByUrlImmutableAttributes (url: string, transaction?: Transaction): Bluebird<MVideoImmutable> {
+ const fun = () => {
+ const query: FindOptions = {
+ where: {
+ url
+ },
+ transaction
+ }
+
+ return VideoModel.scope(ScopeNames.WITH_IMMUTABLE_ATTRIBUTES).findOne(query)
+ }
+
+ return ModelCache.Instance.doCache({
+ cacheType: 'load-video-immutable-url',
+ key: url,
+ deleteKey: 'video',
+ fun
+ })
+ }
+
static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Bluebird<MVideoAccountLightBlacklistAllFiles> {
const query: FindOptions = {
where: {
export type MVideoUrl = Pick<MVideo, 'url'>
export type MVideoUUID = Pick<MVideo, 'uuid'>
-export type MVideoImmutable = Pick<MVideo, 'id' | 'url' | 'uuid'>
+export type MVideoImmutable = Pick<MVideo, 'id' | 'url' | 'uuid' | 'remote' | 'isOwned'>
export type MVideoIdUrl = MVideoId & MVideoUrl
export type MVideoFeed = Pick<MVideo, 'name' | 'uuid'>