Browse Source

Type toActivityPubObject functions

Chocobozzz 4 years ago
parent
commit
b5fecbf441

+ 2 - 2
server/controllers/activitypub/client.ts

@@ -214,7 +214,7 @@ async function videoController (req: express.Request, res: express.Response) {
 
   // 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)
@@ -351,7 +351,7 @@ async function videoPlaylistController (req: express.Request, res: express.Respo
 }
 
 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)

+ 2 - 1
server/controllers/api/video-channel.ts

@@ -35,6 +35,7 @@ import { VideoPlaylistModel } from '../../models/video/video-playlist'
 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 })
@@ -181,7 +182,7 @@ async function updateVideoChannel (req: express.Request, res: express.Response)
         }
       }
 
-      const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions)
+      const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) as MChannelAccountDefault
       await sendUpdateActor(videoChannelInstanceUpdated, t)
 
       auditLogger.update(

+ 4 - 1
server/helpers/utils.ts

@@ -19,7 +19,10 @@ async function generateRandomString (size: number) {
   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))
 

+ 3 - 3
server/lib/activitypub/send/send-update.ts

@@ -12,10 +12,10 @@ import { VideoCaptionModel } from '../../../models/video/video-caption'
 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,
@@ -49,7 +49,7 @@ async function sendUpdateVideo (videoArg: MVideoAPWithoutCaption, t: Transaction
   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)

+ 1 - 1
server/middlewares/validators/videos/video-playlists.ts

@@ -267,7 +267,7 @@ const videoPlaylistElementAPGetValidator = [
       return res.status(403).end()
     }
 
-    res.locals.videoPlaylistElement = videoPlaylistElement
+    res.locals.videoPlaylistElementAP = videoPlaylistElement
 
     return next()
   }

+ 2 - 2
server/models/account/account.ts

@@ -32,7 +32,7 @@ import { FindOptions, IncludeOptions, Op, Transaction, WhereOptions } from 'sequ
 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 {
@@ -380,7 +380,7 @@ export class AccountModel extends Model<AccountModel> {
     }
   }
 
-  toActivityPubObject () {
+  toActivityPubObject (this: MAccountAP) {
     const obj = this.Actor.toActivityPubObject(this.name, 'Account')
 
     return Object.assign(obj, {

+ 7 - 6
server/models/activitypub/actor.ts

@@ -39,12 +39,13 @@ import { VideoModel } from '../video/video'
 import {
   MActor,
   MActorAccountChannelId,
+  MActorAP,
   MActorFormattable,
-  MActorFull, MActorHost,
+  MActorFull,
+  MActorHost,
+  MActorRedundancyAllowedOpt,
   MActorServer,
-  MActorSummaryFormattable,
-  MServerHost,
-  MActorRedundancyAllowed
+  MActorSummaryFormattable
 } from '../../typings/models'
 import * as Bluebird from 'bluebird'
 
@@ -429,7 +430,7 @@ export class ActorModel extends Model<ActorModel> {
     })
   }
 
-  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'
@@ -528,7 +529,7 @@ export class ActorModel extends Model<ActorModel> {
     return this.Server ? this.Server.host : WEBSERVER.HOST
   }
 
-  getRedundancyAllowed (this: MActorRedundancyAllowed) {
+  getRedundancyAllowed () {
     return this.Server ? this.Server.redundancyAllowed : false
   }
 

+ 2 - 2
server/models/redundancy/video-redundancy.ts

@@ -30,7 +30,7 @@ import * as Bluebird from 'bluebird'
 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'
@@ -488,7 +488,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
     return !!this.strategy
   }
 
-  toActivityPubObject (): CacheFileObject {
+  toActivityPubObject (this: MVideoRedundancyAP): CacheFileObject {
     if (this.VideoStreamingPlaylist) {
       return {
         id: this.url,

+ 5 - 2
server/models/video/video-channel.ts

@@ -37,7 +37,10 @@ import * as Bluebird from 'bluebird'
 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
@@ -513,7 +516,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
     return Object.assign(actor, videoChannel)
   }
 
-  toActivityPubObject (): ActivityPubActor {
+  toActivityPubObject (this: MChannelAP): ActivityPubActor {
     const obj = this.Actor.toActivityPubObject(this.name, 'VideoChannel')
 
     return Object.assign(obj, {

+ 2 - 1
server/models/video/video-comment.ts

@@ -17,6 +17,7 @@ import { FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction } from 'se
 import * as Bluebird from 'bluebird'
 import {
   MComment,
+  MCommentAP,
   MCommentFormattable,
   MCommentId,
   MCommentOwner,
@@ -491,7 +492,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
     } 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) {

+ 2 - 2
server/models/video/video-format-utils.ts

@@ -16,7 +16,7 @@ import {
 } 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'
 
@@ -143,7 +143,7 @@ function videoModelToFormattedDetailsJSON (video: MVideoFormattableDetails): Vid
   return Object.assign(formattedJson, detailsJson)
 }
 
-function streamingPlaylistsModelToFormattedJSON (playlists: MStreamingPlaylistRedundancies[]): VideoStreamingPlaylist[] {
+function streamingPlaylistsModelToFormattedJSON (playlists: MStreamingPlaylistRedundanciesOpt[]): VideoStreamingPlaylist[] {
   if (isArray(playlists) === false) return []
 
   return playlists

+ 6 - 2
server/models/video/video-playlist-element.ts

@@ -29,6 +29,7 @@ import {
   MVideoPlaylistElement,
   MVideoPlaylistElementAP,
   MVideoPlaylistElementFormattable,
+  MVideoPlaylistElementVideoUrlPlaylistPrivacy,
   MVideoPlaylistVideoThumbnail
 } from '@server/typings/models/video/video-playlist-element'
 import { MUserAccountId } from '@server/typings/models'
@@ -184,7 +185,10 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
     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 }
 
@@ -336,7 +340,7 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
     }
   }
 
-  toActivityPubObject (): PlaylistElementObject {
+  toActivityPubObject (this: MVideoPlaylistElementAP): PlaylistElementObject {
     const base: PlaylistElementObject = {
       id: this.url,
       type: 'PlaylistElement',

+ 2 - 2
server/models/video/video-playlist.ts

@@ -45,7 +45,7 @@ import { ActivityIconObject } from '../../../shared/models/activitypub/objects'
 import { FindOptions, literal, Op, ScopeOptions, Transaction, WhereOptions } from 'sequelize'
 import * as Bluebird from 'bluebird'
 import {
-  MVideoPlaylistAccountThumbnail,
+  MVideoPlaylistAccountThumbnail, MVideoPlaylistAP,
   MVideoPlaylistFormattable,
   MVideoPlaylistFull,
   MVideoPlaylistFullSummary,
@@ -510,7 +510,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
     }
   }
 
-  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)
     }

+ 9 - 6
server/models/video/video.ts

@@ -127,14 +127,17 @@ import {
   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'
@@ -1879,11 +1882,11 @@ export class VideoModel extends Model<VideoModel> {
     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)
   }
 
@@ -1891,7 +1894,7 @@ export class VideoModel extends Model<VideoModel> {
     return videoFilesModelToFormattedJSON(this, this.VideoFiles)
   }
 
-  toActivityPubObject (): VideoTorrentObject {
+  toActivityPubObject (this: MVideoAP): VideoTorrentObject {
     return videoModelToActivityPubObject(this)
   }
 

+ 2 - 1
server/typings/express.ts

@@ -22,7 +22,7 @@ import {
 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'
@@ -59,6 +59,7 @@ declare module 'express' {
       videoPlaylistSummary?: MVideoPlaylistFullSummary
 
       videoPlaylistElement?: MVideoPlaylistElement
+      videoPlaylistElementAP?: MVideoPlaylistElementVideoUrlPlaylistPrivacy
 
       accountVideoRate?: MAccountVideoRateAccountVideo
 

+ 4 - 0
server/typings/models/account/account.ts

@@ -1,6 +1,7 @@
 import { AccountModel } from '../../../models/account/account'
 import {
   MActor,
+  MActorAP,
   MActorAPI,
   MActorAudience,
   MActorDefault,
@@ -89,3 +90,6 @@ export type MAccountSummaryFormattable = FunctionProperties<MAccount> &
 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>

+ 6 - 3
server/typings/models/account/actor.ts

@@ -1,5 +1,5 @@
 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'
@@ -29,7 +29,7 @@ export type MActorLight = Omit<MActor, 'privateKey' | 'privateKey'>
 // 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> &
@@ -115,4 +115,7 @@ export type MActorSummaryFormattable = FunctionProperties<MActor> &
 
 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>

+ 9 - 1
server/typings/models/video/video-channels.ts

@@ -8,16 +8,18 @@ import {
   MAccountLight,
   MAccountSummaryBlocks,
   MAccountSummaryFormattable,
+  MAccountUrl,
   MAccountUserId,
   MActor,
   MActorAccountChannelId,
+  MActorAP,
   MActorAPI,
   MActorDefault,
   MActorDefaultLight,
   MActorFormattable,
   MActorLight,
   MActorSummary,
-  MActorSummaryFormattable
+  MActorSummaryFormattable, MActorUrl
 } from '../account'
 import { MVideo } from './video'
 
@@ -42,6 +44,8 @@ export type MChannelUserId = Pick<MChannel, 'accountId'> &
 export type MChannelActor = MChannel &
   Use<'Actor', MActor>
 
+export type MChannelUrl = Use<'Actor', MActorUrl>
+
 // Default scope
 export type MChannelDefault = MChannel &
   Use<'Actor', MActorDefault>
@@ -116,3 +120,7 @@ export type MChannelFormattable = FunctionProperties<MChannel> &
   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>

+ 9 - 3
server/typings/models/video/video-comment.ts

@@ -1,7 +1,7 @@
 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>
 
@@ -10,6 +10,7 @@ type Use<K extends keyof VideoCommentModel, M> = PickWith<VideoCommentModel, K,
 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'>
 
 // ############################################################################
 
@@ -49,3 +50,8 @@ export type MCommentAPI = MComment & { totalReplies: number }
 
 export type MCommentFormattable = MCommentTotalReplies &
   Use<'Account', MAccountFormattable>
+
+export type MCommentAP = MComment &
+  Use<'Account', MAccountUrl> &
+  PickWithOpt<VideoCommentModel, 'Video', MVideoUrl> &
+  PickWithOpt<VideoCommentModel, 'InReplyToVideoComment', MCommentUrl>

+ 4 - 5
server/typings/models/video/video-playlist-element.ts

@@ -19,11 +19,7 @@ export type MVideoPlaylistElementLight = Pick<MVideoPlaylistElement, 'id' | 'vid
 export type MVideoPlaylistVideoThumbnail = MVideoPlaylistElement &
   Use<'Video', MVideoThumbnail>
 
-// ############################################################################
-
-// For API
-
-export type MVideoPlaylistElementAP = MVideoPlaylistElement &
+export type MVideoPlaylistElementVideoUrlPlaylistPrivacy = MVideoPlaylistElement &
   Use<'Video', MVideoUrl> &
   Use<'VideoPlaylist', MVideoPlaylistPrivacy>
 
@@ -33,3 +29,6 @@ export type MVideoPlaylistElementAP = MVideoPlaylistElement &
 
 export type MVideoPlaylistElementFormattable = MVideoPlaylistElement &
   Use<'Video', MVideoFormattable>
+
+export type MVideoPlaylistElementAP = MVideoPlaylistElement &
+  Use<'Video', MVideoUrl>

+ 5 - 1
server/typings/models/video/video-playlist.ts

@@ -2,7 +2,7 @@ import { VideoPlaylistModel } from '../../../models/video/video-playlist'
 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>
@@ -86,3 +86,7 @@ export type MVideoPlaylistFullSummary = MVideoPlaylist &
 export type MVideoPlaylistFormattable = MVideoPlaylistVideosLength &
   Use<'OwnerAccount', MAccountSummaryFormattable> &
   Use<'VideoChannel', MChannelSummaryFormattable>
+
+export type MVideoPlaylistAP = MVideoPlaylist &
+  Use<'Thumbnail', MThumbnail> &
+  Use<'VideoChannel', MChannelUrl>

+ 14 - 2
server/typings/models/video/video-redundancy.ts

@@ -1,6 +1,10 @@
 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>
 
@@ -24,3 +28,11 @@ export type MVideoRedundancyStreamingPlaylistVideo = MVideoRedundancy &
 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>>

+ 5 - 2
server/typings/models/video/video-streaming-playlist.ts

@@ -1,7 +1,7 @@
 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>
 
@@ -14,3 +14,6 @@ export type MStreamingPlaylistVideo = MStreamingPlaylist &
 
 export type MStreamingPlaylistRedundancies = MStreamingPlaylist &
   Use<'RedundancyVideos', MVideoRedundancyFileUrl[]>
+
+export type MStreamingPlaylistRedundanciesOpt = MStreamingPlaylist &
+  PickWithOpt<VideoStreamingPlaylistModel, 'RedundancyVideos', MVideoRedundancyFileUrl[]>

+ 2 - 2
server/typings/models/video/video.ts

@@ -10,7 +10,7 @@ import {
 } 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'
@@ -165,5 +165,5 @@ export type MVideoFormattable = MVideo &
 export type MVideoFormattableDetails = MVideoFormattable &
   Use<'VideoChannel', MChannelFormattable> &
   Use<'Tags', MTag[]> &
-  Use<'VideoStreamingPlaylists', MStreamingPlaylistRedundancies[]> &
+  Use<'VideoStreamingPlaylists', MStreamingPlaylistRedundanciesOpt[]> &
   Use<'VideoFiles', MVideoFileRedundanciesOpt[]>