// We need captions to render AP object
const captions = await VideoCaptionModel.listVideoCaptions(video.id)
- const videoWithCaptions: MVideoAPWithoutCaption = Object.assign(video, { VideoCaptions: captions })
+ const videoWithCaptions = Object.assign(video, { VideoCaptions: captions })
const audience = getAudience(videoWithCaptions.VideoChannel.Account.Actor, videoWithCaptions.privacy === VideoPrivacy.PUBLIC)
const videoObject = audiencify(videoWithCaptions.toActivityPubObject(), audience)
}
async function videoPlaylistElementController (req: express.Request, res: express.Response) {
- const videoPlaylistElement = res.locals.videoPlaylistElement
+ const videoPlaylistElement = res.locals.videoPlaylistElementAP
const json = videoPlaylistElement.toActivityPubObject()
return activityPubResponse(activityPubContextify(json), res)
import { commonVideoPlaylistFiltersValidator } from '../../middlewares/validators/videos/video-playlists'
import { CONFIG } from '../../initializers/config'
import { sequelizeTypescript } from '../../initializers/database'
+import { MChannelAccountDefault } from '@server/typings/models'
const auditLogger = auditLoggerFactory('channels')
const reqAvatarFile = createReqFiles([ 'avatarfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR })
}
}
- const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions)
+ const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) as MChannelAccountDefault
await sendUpdateActor(videoChannelInstanceUpdated, t)
auditLogger.update(
return raw.toString('hex')
}
-interface FormattableToJSON<U, V> { toFormattedJSON (args?: U): V }
+interface FormattableToJSON<U, V> {
+ toFormattedJSON (args?: U): V
+}
+
function getFormattedObjects<U, V, T extends FormattableToJSON<U, V>> (objects: T[], objectsTotal: number, formattedArg?: U) {
const formattedObjects = objects.map(o => o.toFormattedJSON(formattedArg))
import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
import { getServerActor } from '../../../helpers/utils'
import {
- MAccountActor,
+ MAccountDefault,
MActor,
MActorLight,
- MChannelActor,
+ MChannelDefault,
MVideoAP,
MVideoAPWithoutCaption,
MVideoPlaylistFull,
return broadcastToFollowers(updateActivity, byActor, actorsInvolved, t)
}
-async function sendUpdateActor (accountOrChannel: MAccountActor | MChannelActor, t: Transaction) {
+async function sendUpdateActor (accountOrChannel: MChannelDefault | MAccountDefault, t: Transaction) {
const byActor = accountOrChannel.Actor
logger.info('Creating job to update actor %s.', byActor.url)
return res.status(403).end()
}
- res.locals.videoPlaylistElement = videoPlaylistElement
+ res.locals.videoPlaylistElementAP = videoPlaylistElement
return next()
}
import { AccountBlocklistModel } from './account-blocklist'
import { ServerBlocklistModel } from '../server/server-blocklist'
import { ActorFollowModel } from '../activitypub/actor-follow'
-import { MAccountActor, MAccountDefault, MAccountSummaryFormattable, MAccountFormattable } from '../../typings/models'
+import { MAccountActor, MAccountDefault, MAccountSummaryFormattable, MAccountFormattable, MAccountAP } from '../../typings/models'
import * as Bluebird from 'bluebird'
export enum ScopeNames {
}
}
- toActivityPubObject () {
+ toActivityPubObject (this: MAccountAP) {
const obj = this.Actor.toActivityPubObject(this.name, 'Account')
return Object.assign(obj, {
import {
MActor,
MActorAccountChannelId,
+ MActorAP,
MActorFormattable,
- MActorFull, MActorHost,
+ MActorFull,
+ MActorHost,
+ MActorRedundancyAllowedOpt,
MActorServer,
- MActorSummaryFormattable,
- MServerHost,
- MActorRedundancyAllowed
+ MActorSummaryFormattable
} from '../../typings/models'
import * as Bluebird from 'bluebird'
})
}
- toActivityPubObject (name: string, type: 'Account' | 'Application' | 'VideoChannel') {
+ toActivityPubObject (this: MActorAP, name: string, type: 'Account' | 'Application' | 'VideoChannel') {
let activityPubType
if (type === 'Account') {
activityPubType = 'Person' as 'Person'
return this.Server ? this.Server.host : WEBSERVER.HOST
}
- getRedundancyAllowed (this: MActorRedundancyAllowed) {
+ getRedundancyAllowed () {
return this.Server ? this.Server.redundancyAllowed : false
}
import { col, FindOptions, fn, literal, Op, Transaction } from 'sequelize'
import { VideoStreamingPlaylistModel } from '../video/video-streaming-playlist'
import { CONFIG } from '../../initializers/config'
-import { MVideoRedundancy, MVideoRedundancyVideo } from '@server/typings/models'
+import { MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/typings/models'
export enum ScopeNames {
WITH_VIDEO = 'WITH_VIDEO'
return !!this.strategy
}
- toActivityPubObject (): CacheFileObject {
+ toActivityPubObject (this: MVideoRedundancyAP): CacheFileObject {
if (this.VideoStreamingPlaylist) {
return {
id: this.url,
import {
MChannelAccountDefault,
MChannelActor,
- MChannelActorAccountDefaultVideos, MChannelSummaryFormattable, MChannelFormattable
+ MChannelActorAccountDefaultVideos,
+ MChannelAP,
+ MChannelFormattable,
+ MChannelSummaryFormattable
} from '../../typings/models/video'
// FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation
return Object.assign(actor, videoChannel)
}
- toActivityPubObject (): ActivityPubActor {
+ toActivityPubObject (this: MChannelAP): ActivityPubActor {
const obj = this.Actor.toActivityPubObject(this.name, 'VideoChannel')
return Object.assign(obj, {
import * as Bluebird from 'bluebird'
import {
MComment,
+ MCommentAP,
MCommentFormattable,
MCommentId,
MCommentOwner,
} as VideoComment
}
- toActivityPubObject (threadParentComments: MCommentOwner[]): VideoCommentObject {
+ toActivityPubObject (this: MCommentAP, threadParentComments: MCommentOwner[]): VideoCommentObject {
let inReplyTo: string
// New thread, so in AS we reply to the video
if (this.inReplyToCommentId === null) {
} from '../../lib/activitypub'
import { isArray } from '../../helpers/custom-validators/misc'
import { VideoStreamingPlaylist } from '../../../shared/models/videos/video-streaming-playlist.model'
-import { MVideo, MVideoAP, MVideoFormattable, MVideoFormattableDetails } from '../../typings/models'
+import { MStreamingPlaylistRedundanciesOpt, MVideo, MVideoAP, MVideoFormattable, MVideoFormattableDetails } from '../../typings/models'
import { MStreamingPlaylistRedundancies } from '../../typings/models/video/video-streaming-playlist'
import { MVideoFileRedundanciesOpt } from '../../typings/models/video/video-file'
return Object.assign(formattedJson, detailsJson)
}
-function streamingPlaylistsModelToFormattedJSON (playlists: MStreamingPlaylistRedundancies[]): VideoStreamingPlaylist[] {
+function streamingPlaylistsModelToFormattedJSON (playlists: MStreamingPlaylistRedundanciesOpt[]): VideoStreamingPlaylist[] {
if (isArray(playlists) === false) return []
return playlists
MVideoPlaylistElement,
MVideoPlaylistElementAP,
MVideoPlaylistElementFormattable,
+ MVideoPlaylistElementVideoUrlPlaylistPrivacy,
MVideoPlaylistVideoThumbnail
} from '@server/typings/models/video/video-playlist-element'
import { MUserAccountId } from '@server/typings/models'
return VideoPlaylistElementModel.findByPk(playlistElementId)
}
- static loadByPlaylistAndVideoForAP (playlistId: number | string, videoId: number | string): Bluebird<MVideoPlaylistElementAP> {
+ static loadByPlaylistAndVideoForAP (
+ playlistId: number | string,
+ videoId: number | string
+ ): Bluebird<MVideoPlaylistElementVideoUrlPlaylistPrivacy> {
const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId }
const videoWhere = validator.isUUID('' + videoId) ? { uuid: videoId } : { id: videoId }
}
}
- toActivityPubObject (): PlaylistElementObject {
+ toActivityPubObject (this: MVideoPlaylistElementAP): PlaylistElementObject {
const base: PlaylistElementObject = {
id: this.url,
type: 'PlaylistElement',
import { FindOptions, literal, Op, ScopeOptions, Transaction, WhereOptions } from 'sequelize'
import * as Bluebird from 'bluebird'
import {
- MVideoPlaylistAccountThumbnail,
+ MVideoPlaylistAccountThumbnail, MVideoPlaylistAP,
MVideoPlaylistFormattable,
MVideoPlaylistFull,
MVideoPlaylistFullSummary,
}
}
- toActivityPubObject (page: number, t: Transaction): Promise<PlaylistObject> {
+ toActivityPubObject (this: MVideoPlaylistAP, page: number, t: Transaction): Promise<PlaylistObject> {
const handler = (start: number, count: number) => {
return VideoPlaylistElementModel.listUrlsOfForAP(this.id, start, count, t)
}
MUserId,
MVideoAccountLight,
MVideoAccountLightBlacklistAllFiles,
+ MVideoAP,
MVideoDetails,
+ MVideoFormattable,
+ MVideoFormattableDetails,
MVideoForUser,
MVideoFullLight,
MVideoIdThumbnail,
MVideoThumbnail,
- MVideoWithAllFiles, MVideoWithFile,
- MVideoWithRights,
- MVideoFormattable
+ MVideoWithAllFiles,
+ MVideoWithFile,
+ MVideoWithRights
} from '../../typings/models'
import { MVideoFile, MVideoFileRedundanciesOpt } from '../../typings/models/video/video-file'
import { MThumbnail } from '../../typings/models/video/thumbnail'
return join(LAZY_STATIC_PATHS.PREVIEWS, preview.filename)
}
- toFormattedJSON <T extends MVideoFormattable> (this: T, options?: VideoFormattingJSONOptions): Video {
+ toFormattedJSON (this: MVideoFormattable, options?: VideoFormattingJSONOptions): Video {
return videoModelToFormattedJSON(this, options)
}
- toFormattedDetailsJSON (): VideoDetails {
+ toFormattedDetailsJSON (this: MVideoFormattableDetails): VideoDetails {
return videoModelToFormattedDetailsJSON(this)
}
return videoFilesModelToFormattedJSON(this, this.VideoFiles)
}
- toActivityPubObject (): VideoTorrentObject {
+ toActivityPubObject (this: MVideoAP): VideoTorrentObject {
return videoModelToActivityPubObject(this)
}
import { MVideoPlaylistFull, MVideoPlaylistFullSummary } from './models/video/video-playlist'
import { MVideoImportDefault } from '@server/typings/models/video/video-import'
import { MAccountBlocklist, MStreamingPlaylist, MVideoFile } from '@server/typings/models'
-import { MVideoPlaylistElement } from '@server/typings/models/video/video-playlist-element'
+import { MVideoPlaylistElement, MVideoPlaylistElementVideoUrlPlaylistPrivacy } from '@server/typings/models/video/video-playlist-element'
import { MAccountVideoRateAccountVideo } from '@server/typings/models/video/video-rate'
import { MVideoChangeOwnershipFull } from './models/video/video-change-ownership'
import { MPlugin, MServer } from '@server/typings/models/server'
videoPlaylistSummary?: MVideoPlaylistFullSummary
videoPlaylistElement?: MVideoPlaylistElement
+ videoPlaylistElementAP?: MVideoPlaylistElementVideoUrlPlaylistPrivacy
accountVideoRate?: MAccountVideoRateAccountVideo
import { AccountModel } from '../../../models/account/account'
import {
MActor,
+ MActorAP,
MActorAPI,
MActorAudience,
MActorDefault,
export type MAccountFormattable = FunctionProperties<MAccount> &
Pick<MAccount, 'id' | 'name' | 'description' | 'createdAt' | 'updatedAt' | 'userId'> &
Use<'Actor', MActorFormattable>
+
+export type MAccountAP = Pick<MAccount, 'name' | 'description'> &
+ Use<'Actor', MActorAP>
import { ActorModel } from '../../../models/activitypub/actor'
-import { FunctionProperties, PickWith } from '../../utils'
+import { FunctionProperties, PickWith, PickWithOpt } from '../../utils'
import { MAccount, MAccountDefault, MAccountId, MAccountIdActor } from './account'
import { MServer, MServerHost, MServerHostBlocks, MServerRedundancyAllowed } from '../server'
import { MAvatar, MAvatarFormattable } from './avatar'
// Some association attributes
export type MActorHost = Use<'Server', MServerHost>
-export type MActorRedundancyAllowed = Use<'Server', MServerRedundancyAllowed>
+export type MActorRedundancyAllowedOpt = PickWithOpt<ActorModel, 'Server', MServerRedundancyAllowed>
export type MActorDefaultLight = MActorLight &
Use<'Server', MServerHost> &
export type MActorFormattable = MActorSummaryFormattable &
Pick<MActor, 'id' | 'followingCount' | 'followersCount' | 'createdAt' | 'updatedAt'> &
- Use<'Server', MServer>
+ Use<'Server', MServerHost & Partial<Pick<MServer, 'redundancyAllowed'>>>
+
+export type MActorAP = MActor &
+ Use<'Avatar', MAvatar>
MAccountLight,
MAccountSummaryBlocks,
MAccountSummaryFormattable,
+ MAccountUrl,
MAccountUserId,
MActor,
MActorAccountChannelId,
+ MActorAP,
MActorAPI,
MActorDefault,
MActorDefaultLight,
MActorFormattable,
MActorLight,
MActorSummary,
- MActorSummaryFormattable
+ MActorSummaryFormattable, MActorUrl
} from '../account'
import { MVideo } from './video'
export type MChannelActor = MChannel &
Use<'Actor', MActor>
+export type MChannelUrl = Use<'Actor', MActorUrl>
+
// Default scope
export type MChannelDefault = MChannel &
Use<'Actor', MActorDefault>
Pick<MChannel, 'id' | 'name' | 'description' | 'createdAt' | 'updatedAt' | 'support'> &
Use<'Actor', MActorFormattable> &
PickWithOpt<VideoChannelModel, 'Account', MAccountFormattable>
+
+export type MChannelAP = Pick<MChannel, 'name' | 'description' | 'support'> &
+ Use<'Actor', MActorAP> &
+ Use<'Account', MAccountUrl>
import { VideoCommentModel } from '../../../models/video/video-comment'
-import { PickWith } from '../../utils'
-import { MAccountDefault, MAccountFormattable } from '../account'
-import { MVideoAccountLight, MVideoFeed, MVideoIdUrl } from './video'
+import { PickWith, PickWithOpt } from '../../utils'
+import { MAccountDefault, MAccountFormattable, MAccountUrl, MActorUrl } from '../account'
+import { MVideoAccountLight, MVideoFeed, MVideoIdUrl, MVideoUrl } from './video'
type Use<K extends keyof VideoCommentModel, M> = PickWith<VideoCommentModel, K, M>
export type MComment = Omit<VideoCommentModel, 'OriginVideoComment' | 'InReplyToVideoComment' | 'Video' | 'Account'>
export type MCommentTotalReplies = MComment & { totalReplies?: number }
export type MCommentId = Pick<MComment, 'id'>
+export type MCommentUrl = Pick<MComment, 'url'>
// ############################################################################
export type MCommentFormattable = MCommentTotalReplies &
Use<'Account', MAccountFormattable>
+
+export type MCommentAP = MComment &
+ Use<'Account', MAccountUrl> &
+ PickWithOpt<VideoCommentModel, 'Video', MVideoUrl> &
+ PickWithOpt<VideoCommentModel, 'InReplyToVideoComment', MCommentUrl>
export type MVideoPlaylistVideoThumbnail = MVideoPlaylistElement &
Use<'Video', MVideoThumbnail>
-// ############################################################################
-
-// For API
-
-export type MVideoPlaylistElementAP = MVideoPlaylistElement &
+export type MVideoPlaylistElementVideoUrlPlaylistPrivacy = MVideoPlaylistElement &
Use<'Video', MVideoUrl> &
Use<'VideoPlaylist', MVideoPlaylistPrivacy>
export type MVideoPlaylistElementFormattable = MVideoPlaylistElement &
Use<'Video', MVideoFormattable>
+
+export type MVideoPlaylistElementAP = MVideoPlaylistElement &
+ Use<'Video', MVideoUrl>
import { PickWith } from '../../utils'
import { MAccount, MAccountDefault, MAccountSummary, MAccountSummaryFormattable } from '../account'
import { MThumbnail } from './thumbnail'
-import { MChannelDefault, MChannelSummary, MChannelSummaryFormattable } from './video-channels'
+import { MChannelDefault, MChannelSummary, MChannelSummaryFormattable, MChannelUrl } from './video-channels'
import { MVideoPlaylistElementLight } from '@server/typings/models/video/video-playlist-element'
type Use<K extends keyof VideoPlaylistModel, M> = PickWith<VideoPlaylistModel, K, M>
export type MVideoPlaylistFormattable = MVideoPlaylistVideosLength &
Use<'OwnerAccount', MAccountSummaryFormattable> &
Use<'VideoChannel', MChannelSummaryFormattable>
+
+export type MVideoPlaylistAP = MVideoPlaylist &
+ Use<'Thumbnail', MThumbnail> &
+ Use<'VideoChannel', MChannelUrl>
import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
-import { PickWith } from '@server/typings/utils'
-import { MStreamingPlaylistVideo, MVideoFile, MVideoFileVideo } from '@server/typings/models'
+import { PickWith, PickWithOpt } from '@server/typings/utils'
+import { MStreamingPlaylistVideo, MVideoFile, MVideoFileVideo, MVideoUrl } from '@server/typings/models'
+import { VideoStreamingPlaylist } from '../../../../shared/models/videos/video-streaming-playlist.model'
+import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
+import { VideoFile } from '../../../../shared/models/videos'
+import { VideoFileModel } from '@server/models/video/video-file'
type Use<K extends keyof VideoRedundancyModel, M> = PickWith<VideoRedundancyModel, K, M>
export type MVideoRedundancyVideo = MVideoRedundancy &
Use<'VideoFile', MVideoFileVideo> &
Use<'VideoStreamingPlaylist', MStreamingPlaylistVideo>
+
+// ############################################################################
+
+// Format for API or AP object
+
+export type MVideoRedundancyAP = MVideoRedundancy &
+ PickWithOpt<VideoRedundancyModel, 'VideoFile', MVideoFile & PickWith<VideoFileModel, 'Video', MVideoUrl>> &
+ PickWithOpt<VideoRedundancyModel, 'VideoStreamingPlaylist', PickWith<VideoStreamingPlaylistModel, 'Video', MVideoUrl>>
import { VideoStreamingPlaylistModel } from '../../../models/video/video-streaming-playlist'
-import { PickWith } from '../../utils'
+import { PickWith, PickWithOpt } from '../../utils'
import { MVideoRedundancyFileUrl } from './video-redundancy'
-import { MVideo } from '@server/typings/models'
+import { MVideo, MVideoUrl } from '@server/typings/models'
type Use<K extends keyof VideoStreamingPlaylistModel, M> = PickWith<VideoStreamingPlaylistModel, K, M>
export type MStreamingPlaylistRedundancies = MStreamingPlaylist &
Use<'RedundancyVideos', MVideoRedundancyFileUrl[]>
+
+export type MStreamingPlaylistRedundanciesOpt = MStreamingPlaylist &
+ PickWithOpt<VideoStreamingPlaylistModel, 'RedundancyVideos', MVideoRedundancyFileUrl[]>
} from './video-channels'
import { MTag } from './tag'
import { MVideoCaptionLanguage } from './video-caption'
-import { MStreamingPlaylist, MStreamingPlaylistRedundancies } from './video-streaming-playlist'
+import { MStreamingPlaylist, MStreamingPlaylistRedundancies, MStreamingPlaylistRedundanciesOpt } from './video-streaming-playlist'
import { MVideoFile, MVideoFileRedundanciesOpt } from './video-file'
import { MThumbnail } from './thumbnail'
import { MVideoBlacklist, MVideoBlacklistLight, MVideoBlacklistUnfederated } from './video-blacklist'
export type MVideoFormattableDetails = MVideoFormattable &
Use<'VideoChannel', MChannelFormattable> &
Use<'Tags', MTag[]> &
- Use<'VideoStreamingPlaylists', MStreamingPlaylistRedundancies[]> &
+ Use<'VideoStreamingPlaylists', MStreamingPlaylistRedundanciesOpt[]> &
Use<'VideoFiles', MVideoFileRedundanciesOpt[]>