Stronger model typings
authorChocobozzz <me@florianbigard.com>
Thu, 15 Aug 2019 09:53:26 +0000 (11:53 +0200)
committerChocobozzz <me@florianbigard.com>
Mon, 19 Aug 2019 15:26:35 +0000 (17:26 +0200)
176 files changed:
server/controllers/activitypub/client.ts
server/controllers/activitypub/inbox.ts
server/controllers/activitypub/outbox.ts
server/controllers/api/search.ts
server/controllers/api/users/index.ts
server/controllers/api/users/me.ts
server/controllers/api/users/my-history.ts
server/controllers/api/video-channel.ts
server/controllers/api/video-playlist.ts
server/controllers/api/videos/abuse.ts
server/controllers/api/videos/blacklist.ts
server/controllers/api/videos/captions.ts
server/controllers/api/videos/comment.ts
server/controllers/api/videos/import.ts
server/controllers/api/videos/index.ts
server/controllers/api/videos/ownership.ts
server/controllers/api/videos/rate.ts
server/controllers/api/videos/watching.ts
server/controllers/feeds.ts
server/controllers/services.ts
server/controllers/static.ts
server/controllers/webfinger.ts
server/helpers/activitypub.ts
server/helpers/actor.ts
server/helpers/captions-utils.ts
server/helpers/custom-validators/video-ownership.ts
server/helpers/middlewares/accounts.ts
server/helpers/middlewares/video-abuses.ts
server/helpers/middlewares/video-captions.ts
server/helpers/middlewares/video-channels.ts
server/helpers/middlewares/video-playlists.ts
server/helpers/middlewares/videos.ts
server/helpers/peertube-crypto.ts
server/helpers/video.ts
server/helpers/webfinger.ts
server/lib/activitypub/actor.ts
server/lib/activitypub/audience.ts
server/lib/activitypub/cache-file.ts
server/lib/activitypub/playlist.ts
server/lib/activitypub/process/process-accept.ts
server/lib/activitypub/process/process-announce.ts
server/lib/activitypub/process/process-create.ts
server/lib/activitypub/process/process-delete.ts
server/lib/activitypub/process/process-dislike.ts
server/lib/activitypub/process/process-flag.ts
server/lib/activitypub/process/process-follow.ts
server/lib/activitypub/process/process-like.ts
server/lib/activitypub/process/process-reject.ts
server/lib/activitypub/process/process-undo.ts
server/lib/activitypub/process/process-update.ts
server/lib/activitypub/process/process-view.ts
server/lib/activitypub/process/process.ts
server/lib/activitypub/send/send-accept.ts
server/lib/activitypub/send/send-announce.ts
server/lib/activitypub/send/send-create.ts
server/lib/activitypub/send/send-delete.ts
server/lib/activitypub/send/send-dislike.ts
server/lib/activitypub/send/send-flag.ts
server/lib/activitypub/send/send-follow.ts
server/lib/activitypub/send/send-like.ts
server/lib/activitypub/send/send-reject.ts
server/lib/activitypub/send/send-undo.ts
server/lib/activitypub/send/send-update.ts
server/lib/activitypub/send/send-view.ts
server/lib/activitypub/send/utils.ts
server/lib/activitypub/share.ts
server/lib/activitypub/url.ts
server/lib/activitypub/video-comments.ts
server/lib/activitypub/video-rates.ts
server/lib/activitypub/videos.ts
server/lib/avatar.ts
server/lib/blocklist.ts
server/lib/client-html.ts
server/lib/emailer.ts
server/lib/hls.ts
server/lib/job-queue/handlers/activitypub-follow.ts
server/lib/job-queue/handlers/activitypub-http-fetcher.ts
server/lib/job-queue/handlers/utils/activitypub-http-utils.ts
server/lib/job-queue/handlers/video-file-import.ts
server/lib/job-queue/handlers/video-import.ts
server/lib/job-queue/handlers/video-transcoding.ts
server/lib/notifier.ts
server/lib/oauth-model.ts
server/lib/peertube-socket.ts
server/lib/redundancy.ts
server/lib/schedulers/videos-redundancy-scheduler.ts
server/lib/thumbnail.ts
server/lib/user.ts
server/lib/video-blacklist.ts
server/lib/video-channel.ts
server/lib/video-comment.ts
server/lib/video-playlist.ts
server/lib/video-transcoding.ts
server/middlewares/validators/follows.ts
server/middlewares/validators/redundancy.ts
server/middlewares/validators/users.ts
server/middlewares/validators/videos/video-abuses.ts
server/middlewares/validators/videos/video-blacklist.ts
server/middlewares/validators/videos/video-captions.ts
server/middlewares/validators/videos/video-channels.ts
server/middlewares/validators/videos/video-comments.ts
server/middlewares/validators/videos/video-playlists.ts
server/middlewares/validators/videos/video-shares.ts
server/middlewares/validators/videos/videos.ts
server/middlewares/validators/webfinger.ts
server/models/account/account-blocklist.ts
server/models/account/account-video-rate.ts
server/models/account/account.ts
server/models/account/user-notification.ts
server/models/account/user-video-history.ts
server/models/account/user.ts
server/models/activitypub/actor-follow.ts
server/models/activitypub/actor.ts
server/models/oauth/oauth-token.ts
server/models/redundancy/video-redundancy.ts
server/models/server/plugin.ts
server/models/server/server-blocklist.ts
server/models/server/server.ts
server/models/video/video-abuse.ts
server/models/video/video-blacklist.ts
server/models/video/video-caption.ts
server/models/video/video-change-ownership.ts
server/models/video/video-channel.ts
server/models/video/video-comment.ts
server/models/video/video-file.ts
server/models/video/video-format-utils.ts
server/models/video/video-import.ts
server/models/video/video-playlist-element.ts
server/models/video/video-playlist.ts
server/models/video/video-share.ts
server/models/video/video-streaming-playlist.ts
server/models/video/video.ts
server/typings/activitypub-processor.model.ts
server/typings/express.ts
server/typings/models/account/account-blocklist.ts [new file with mode: 0644]
server/typings/models/account/account.ts [new file with mode: 0644]
server/typings/models/account/actor-follow.ts [new file with mode: 0644]
server/typings/models/account/actor.ts [new file with mode: 0644]
server/typings/models/account/avatar.ts [new file with mode: 0644]
server/typings/models/account/index.d.ts [new file with mode: 0644]
server/typings/models/actor-follow.ts [deleted file]
server/typings/models/actor.ts [deleted file]
server/typings/models/index.d.ts
server/typings/models/oauth/oauth-client.ts [new file with mode: 0644]
server/typings/models/oauth/oauth-token.ts [new file with mode: 0644]
server/typings/models/server/index.d.ts [new file with mode: 0644]
server/typings/models/server/plugin.ts [new file with mode: 0644]
server/typings/models/server/server-blocklist.ts [new file with mode: 0644]
server/typings/models/server/server.ts [new file with mode: 0644]
server/typings/models/user/index.d.ts [new file with mode: 0644]
server/typings/models/user/user-notification-setting.ts [new file with mode: 0644]
server/typings/models/user/user-notification.ts [new file with mode: 0644]
server/typings/models/user/user-video-history.ts [new file with mode: 0644]
server/typings/models/user/user.ts [new file with mode: 0644]
server/typings/models/video-share.ts [deleted file]
server/typings/models/video/index.d.ts [new file with mode: 0644]
server/typings/models/video/schedule-video-update.ts [new file with mode: 0644]
server/typings/models/video/tag.ts [new file with mode: 0644]
server/typings/models/video/thumbnail.ts [new file with mode: 0644]
server/typings/models/video/video-abuse.ts [new file with mode: 0644]
server/typings/models/video/video-blacklist.ts [new file with mode: 0644]
server/typings/models/video/video-caption.ts [new file with mode: 0644]
server/typings/models/video/video-change-ownership.ts [new file with mode: 0644]
server/typings/models/video/video-channels.ts [new file with mode: 0644]
server/typings/models/video/video-comment.ts [new file with mode: 0644]
server/typings/models/video/video-file.ts [new file with mode: 0644]
server/typings/models/video/video-import.ts [new file with mode: 0644]
server/typings/models/video/video-playlist-element.ts [new file with mode: 0644]
server/typings/models/video/video-playlist.ts [new file with mode: 0644]
server/typings/models/video/video-rate.ts [new file with mode: 0644]
server/typings/models/video/video-redundancy.ts [new file with mode: 0644]
server/typings/models/video/video-share.ts [new file with mode: 0644]
server/typings/models/video/video-streaming-playlist.ts [new file with mode: 0644]
server/typings/models/video/video.ts [new file with mode: 0644]
server/typings/utils.ts
tsconfig.json

index 11504b35427b0883776e750f71f311d5d7a215e2..98f5c8865903c1757881d26cb40dcf235bdfc53f 100644 (file)
@@ -16,7 +16,6 @@ import {
 } from '../../middlewares'
 import { getAccountVideoRateValidator, videoCommentGetValidator } from '../../middlewares/validators'
 import { AccountModel } from '../../models/account/account'
-import { ActorModel } from '../../models/activitypub/actor'
 import { ActorFollowModel } from '../../models/activitypub/actor-follow'
 import { VideoModel } from '../../models/video/video'
 import { VideoCommentModel } from '../../models/video/video-comment'
@@ -38,6 +37,7 @@ import { buildDislikeActivity } from '../../lib/activitypub/send/send-dislike'
 import { videoPlaylistElementAPGetValidator, videoPlaylistsGetValidator } from '../../middlewares/validators/videos/video-playlists'
 import { VideoPlaylistModel } from '../../models/video/video-playlist'
 import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
+import { MAccountId, MActorId, MVideo, MVideoAPWithoutCaption } from '@server/typings/models'
 
 const activityPubClientRouter = express.Router()
 
@@ -148,7 +148,7 @@ activityPubClientRouter.get('/redundancy/streaming-playlists/:streamingPlaylistT
 
 activityPubClientRouter.get('/video-playlists/:playlistId',
   executeIfActivityPub,
-  asyncMiddleware(videoPlaylistsGetValidator),
+  asyncMiddleware(videoPlaylistsGetValidator('all')),
   asyncMiddleware(videoPlaylistController)
 )
 activityPubClientRouter.get('/video-playlists/:playlistId/:videoId',
@@ -208,18 +208,19 @@ function getAccountVideoRate (rateType: VideoRateType) {
 
 async function videoController (req: express.Request, res: express.Response) {
   // We need more attributes
-  const video = await VideoModel.loadForGetAPI({ id: res.locals.video.id })
+  const video = await VideoModel.loadForGetAPI({ id: res.locals.onlyVideoWithRights.id }) as MVideoAPWithoutCaption
 
   if (video.url.startsWith(WEBSERVER.URL) === false) return res.redirect(video.url)
 
   // We need captions to render AP object
-  video.VideoCaptions = await VideoCaptionModel.listVideoCaptions(video.id)
+  const captions = await VideoCaptionModel.listVideoCaptions(video.id)
+  const videoWithCaptions: MVideoAPWithoutCaption = Object.assign(video, { VideoCaptions: captions })
 
-  const audience = getAudience(video.VideoChannel.Account.Actor, video.privacy === VideoPrivacy.PUBLIC)
-  const videoObject = audiencify(video.toActivityPubObject(), audience)
+  const audience = getAudience(videoWithCaptions.VideoChannel.Account.Actor, videoWithCaptions.privacy === VideoPrivacy.PUBLIC)
+  const videoObject = audiencify(videoWithCaptions.toActivityPubObject(), audience)
 
   if (req.path.endsWith('/activity')) {
-    const data = buildCreateActivity(video.url, video.VideoChannel.Account.Actor, videoObject, audience)
+    const data = buildCreateActivity(videoWithCaptions.url, video.VideoChannel.Account.Actor, videoObject, audience)
     return activityPubResponse(activityPubContextify(data), res)
   }
 
@@ -231,13 +232,13 @@ async function videoAnnounceController (req: express.Request, res: express.Respo
 
   if (share.url.startsWith(WEBSERVER.URL) === false) return res.redirect(share.url)
 
-  const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.video, undefined)
+  const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.videoAll, undefined)
 
   return activityPubResponse(activityPubContextify(activity), res)
 }
 
 async function videoAnnouncesController (req: express.Request, res: express.Response) {
-  const video = res.locals.video
+  const video = res.locals.onlyVideo
 
   const handler = async (start: number, count: number) => {
     const result = await VideoShareModel.listAndCountByVideoId(video.id, start, count)
@@ -252,21 +253,21 @@ async function videoAnnouncesController (req: express.Request, res: express.Resp
 }
 
 async function videoLikesController (req: express.Request, res: express.Response) {
-  const video = res.locals.video
+  const video = res.locals.onlyVideo
   const json = await videoRates(req, 'like', video, getVideoLikesActivityPubUrl(video))
 
   return activityPubResponse(activityPubContextify(json), res)
 }
 
 async function videoDislikesController (req: express.Request, res: express.Response) {
-  const video = res.locals.video
+  const video = res.locals.onlyVideo
   const json = await videoRates(req, 'dislike', video, getVideoDislikesActivityPubUrl(video))
 
   return activityPubResponse(activityPubContextify(json), res)
 }
 
 async function videoCommentsController (req: express.Request, res: express.Response) {
-  const video = res.locals.video
+  const video = res.locals.onlyVideo
 
   const handler = async (start: number, count: number) => {
     const result = await VideoCommentModel.listAndCountByVideoId(video.id, start, count)
@@ -301,7 +302,7 @@ async function videoChannelFollowingController (req: express.Request, res: expre
 }
 
 async function videoCommentController (req: express.Request, res: express.Response) {
-  const videoComment = res.locals.videoComment
+  const videoComment = res.locals.videoCommentFull
 
   if (videoComment.url.startsWith(WEBSERVER.URL) === false) return res.redirect(videoComment.url)
 
@@ -337,7 +338,7 @@ async function videoRedundancyController (req: express.Request, res: express.Res
 }
 
 async function videoPlaylistController (req: express.Request, res: express.Response) {
-  const playlist = res.locals.videoPlaylist
+  const playlist = res.locals.videoPlaylistFull
 
   // We need more attributes
   playlist.OwnerAccount = await AccountModel.load(playlist.ownerAccountId)
@@ -358,7 +359,7 @@ async function videoPlaylistElementController (req: express.Request, res: expres
 
 // ---------------------------------------------------------------------------
 
-async function actorFollowing (req: express.Request, actor: ActorModel) {
+async function actorFollowing (req: express.Request, actor: MActorId) {
   const handler = (start: number, count: number) => {
     return ActorFollowModel.listAcceptedFollowingUrlsForApi([ actor.id ], undefined, start, count)
   }
@@ -366,7 +367,7 @@ async function actorFollowing (req: express.Request, actor: ActorModel) {
   return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page)
 }
 
-async function actorFollowers (req: express.Request, actor: ActorModel) {
+async function actorFollowers (req: express.Request, actor: MActorId) {
   const handler = (start: number, count: number) => {
     return ActorFollowModel.listAcceptedFollowerUrlsForAP([ actor.id ], undefined, start, count)
   }
@@ -374,7 +375,7 @@ async function actorFollowers (req: express.Request, actor: ActorModel) {
   return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page)
 }
 
-async function actorPlaylists (req: express.Request, account: AccountModel) {
+async function actorPlaylists (req: express.Request, account: MAccountId) {
   const handler = (start: number, count: number) => {
     return VideoPlaylistModel.listPublicUrlsOfForAP(account.id, start, count)
   }
@@ -382,7 +383,7 @@ async function actorPlaylists (req: express.Request, account: AccountModel) {
   return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page)
 }
 
-function videoRates (req: express.Request, rateType: VideoRateType, video: VideoModel, url: string) {
+function videoRates (req: express.Request, rateType: VideoRateType, video: MVideo, url: string) {
   const handler = async (start: number, count: number) => {
     const result = await AccountVideoRateModel.listAndCountAccountUrlsByVideoId(rateType, video.id, start, count)
     return {
index 2d3eef22247bc726011017ba54ad61071ff7bb7a..d9df253aa28f05bece936b5f8347016b15992bf8 100644 (file)
@@ -7,7 +7,7 @@ import { asyncMiddleware, checkSignature, localAccountValidator, localVideoChann
 import { activityPubValidator } from '../../middlewares/validators/activitypub/activity'
 import { queue } from 'async'
 import { ActorModel } from '../../models/activitypub/actor'
-import { SignatureActorModel } from '../../typings/models'
+import { MActorDefault, MActorSignature } from '../../typings/models'
 
 const inboxRouter = express.Router()
 
@@ -41,7 +41,8 @@ export {
 
 // ---------------------------------------------------------------------------
 
-const inboxQueue = queue<{ activities: Activity[], signatureActor?: SignatureActorModel, inboxActor?: ActorModel }, Error>((task, cb) => {
+type QueueParam = { activities: Activity[], signatureActor?: MActorSignature, inboxActor?: MActorDefault }
+const inboxQueue = queue<QueueParam, Error>((task, cb) => {
   const options = { signatureActor: task.signatureActor, inboxActor: task.inboxActor }
 
   processActivities(task.activities, options)
index 38b6ec9764bd9365c84546b5178d8eb7e163a830..f3dd2ad7d3e5fed8e1be89003813054cde20a24b 100644 (file)
@@ -6,11 +6,9 @@ import { logger } from '../../helpers/logger'
 import { buildAnnounceActivity, buildCreateActivity } from '../../lib/activitypub/send'
 import { buildAudience } from '../../lib/activitypub/audience'
 import { asyncMiddleware, localAccountValidator, localVideoChannelValidator } from '../../middlewares'
-import { AccountModel } from '../../models/account/account'
-import { ActorModel } from '../../models/activitypub/actor'
 import { VideoModel } from '../../models/video/video'
 import { activityPubResponse } from './utils'
-import { VideoChannelModel } from '../../models/video/video-channel'
+import { MActorLight } from '@server/typings/models'
 
 const outboxRouter = express.Router()
 
@@ -45,14 +43,10 @@ async function outboxController (req: express.Request, res: express.Response) {
   return activityPubResponse(activityPubContextify(json), res)
 }
 
-async function buildActivities (actor: ActorModel, start: number, count: number) {
+async function buildActivities (actor: MActorLight, start: number, count: number) {
   const data = await VideoModel.listAllAndSharedByActorForOutbox(actor.id, start, count)
   const activities: Activity[] = []
 
-  // Avoid too many SQL requests
-  const actors = data.data.map(v => v.VideoChannel.Account.Actor)
-  actors.push(actor)
-
   for (const video of data.data) {
     const byActor = video.VideoChannel.Account.Actor
     const createActivityAudience = buildAudience([ byActor.followersUrl ], video.privacy === VideoPrivacy.PUBLIC)
index 9a1e30b8367f301fa3e9d2f111230c4152ee8046..7fef7c1732709bc3eef8fce8058fe2464a1c3cfe 100644 (file)
@@ -19,6 +19,7 @@ import { getOrCreateActorAndServerAndModel, getOrCreateVideoAndAccountAndChannel
 import { logger } from '../../helpers/logger'
 import { VideoChannelModel } from '../../models/video/video-channel'
 import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger'
+import { MChannelAccountDefault, MVideoAccountAllFiles } from '../../typings/models'
 
 const searchRouter = express.Router()
 
@@ -84,7 +85,7 @@ async function searchVideoChannelsDB (query: VideoChannelsSearchQuery, res: expr
 }
 
 async function searchVideoChannelURI (search: string, isWebfingerSearch: boolean, res: express.Response) {
-  let videoChannel: VideoChannelModel
+  let videoChannel: MChannelAccountDefault
   let uri = search
 
   if (isWebfingerSearch) {
@@ -137,7 +138,7 @@ async function searchVideosDB (query: VideosSearchQuery, res: express.Response)
 }
 
 async function searchVideoURI (url: string, res: express.Response) {
-  let video: VideoModel
+  let video: MVideoAccountAllFiles
 
   // Check if we can fetch a remote video with the URL
   if (isUserAbleToSearchRemoteURI(res)) {
index ae40e86f8c194b4972c316ac281f60dee97fe722..e6b678f3a6a13076b29e0cba1e369ba8ad27e5d1 100644 (file)
@@ -48,6 +48,7 @@ import { CONFIG } from '../../../initializers/config'
 import { sequelizeTypescript } from '../../../initializers/database'
 import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
 import { UserRegister } from '../../../../shared/models/users/user-register.model'
+import { MUser, MUserAccountDefault } from '@server/typings/models'
 
 const auditLogger = auditLoggerFactory('users')
 
@@ -359,7 +360,7 @@ function success (req: express.Request, res: express.Response) {
   res.end()
 }
 
-async function changeUserBlock (res: express.Response, user: UserModel, block: boolean, reason?: string) {
+async function changeUserBlock (res: express.Response, user: MUserAccountDefault, block: boolean, reason?: string) {
   const oldUserAuditView = new UserAuditView(user.toFormattedJSON())
 
   user.blocked = block
index e7ed3de6466d7fa8ea21cdc4c36fd789403a54f7..af054f6206d90f46c6ee976462d60010d41eb521 100644 (file)
@@ -147,7 +147,7 @@ async function getUserVideoQuotaUsed (req: express.Request, res: express.Respons
 }
 
 async function getUserVideoRating (req: express.Request, res: express.Response) {
-  const videoId = res.locals.video.id
+  const videoId = res.locals.videoId.id
   const accountId = +res.locals.oauth.token.User.Account.id
 
   const ratingObj = await AccountVideoRateModel.load(accountId, videoId, null)
index 7025c0ff15e88b1aa15c29aa721b5e07737aa1c9..4da1f34963e01638947c3a9565ea0ee808ee906a 100644 (file)
@@ -7,7 +7,6 @@ import {
   setDefaultPagination,
   userHistoryRemoveValidator
 } from '../../../middlewares'
-import { UserModel } from '../../../models/account/user'
 import { getFormattedObjects } from '../../../helpers/utils'
 import { UserVideoHistoryModel } from '../../../models/account/user-video-history'
 import { sequelizeTypescript } from '../../../initializers'
index 81a03a62bc85838d8409d5ea13bbf7d9515b4eda..2b6184a8319ec8c3403082642dc6fe679459154f 100644 (file)
@@ -136,7 +136,7 @@ async function updateVideoChannelAvatar (req: express.Request, res: express.Resp
 async function addVideoChannel (req: express.Request, res: express.Response) {
   const videoChannelInfo: VideoChannelCreate = req.body
 
-  const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => {
+  const videoChannelCreated = await sequelizeTypescript.transaction(async t => {
     const account = await AccountModel.load(res.locals.oauth.token.User.Account.id, t)
 
     return createVideoChannel(videoChannelInfo, account, t)
index bd454f553ee26a58942c33a3cb130969a75d76c4..d9f0ff9257bac20327269d5cad5e68c1982ef35f 100644 (file)
@@ -40,7 +40,7 @@ import { JobQueue } from '../../lib/job-queue'
 import { CONFIG } from '../../initializers/config'
 import { sequelizeTypescript } from '../../initializers/database'
 import { createPlaylistMiniatureFromExisting } from '../../lib/thumbnail'
-import { VideoModel } from '../../models/video/video'
+import { MVideoPlaylistFull, MVideoPlaylistThumbnail, MVideoThumbnail } from '@server/typings/models'
 
 const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { thumbnailfile: CONFIG.STORAGE.TMP_DIR })
 
@@ -58,7 +58,7 @@ videoPlaylistRouter.get('/',
 )
 
 videoPlaylistRouter.get('/:playlistId',
-  asyncMiddleware(videoPlaylistsGetValidator),
+  asyncMiddleware(videoPlaylistsGetValidator('summary')),
   getVideoPlaylist
 )
 
@@ -83,7 +83,7 @@ videoPlaylistRouter.delete('/:playlistId',
 )
 
 videoPlaylistRouter.get('/:playlistId/videos',
-  asyncMiddleware(videoPlaylistsGetValidator),
+  asyncMiddleware(videoPlaylistsGetValidator('summary')),
   paginationValidator,
   setDefaultPagination,
   optionalAuthenticate,
@@ -140,7 +140,7 @@ async function listVideoPlaylists (req: express.Request, res: express.Response)
 }
 
 function getVideoPlaylist (req: express.Request, res: express.Response) {
-  const videoPlaylist = res.locals.videoPlaylist
+  const videoPlaylist = res.locals.videoPlaylistSummary
 
   if (videoPlaylist.isOutdated()) {
     JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video-playlist', url: videoPlaylist.url } })
@@ -159,7 +159,7 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
     description: videoPlaylistInfo.description,
     privacy: videoPlaylistInfo.privacy || VideoPlaylistPrivacy.PRIVATE,
     ownerAccountId: user.Account.id
-  })
+  }) as MVideoPlaylistFull
 
   videoPlaylist.url = getVideoPlaylistActivityPubUrl(videoPlaylist) // We use the UUID, so set the URL after building the object
 
@@ -175,8 +175,8 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
     ? await createPlaylistMiniatureFromExisting(thumbnailField[0].path, videoPlaylist, false)
     : undefined
 
-  const videoPlaylistCreated: VideoPlaylistModel = await sequelizeTypescript.transaction(async t => {
-    const videoPlaylistCreated = await videoPlaylist.save({ transaction: t })
+  const videoPlaylistCreated = await sequelizeTypescript.transaction(async t => {
+    const videoPlaylistCreated = await videoPlaylist.save({ transaction: t }) as MVideoPlaylistFull
 
     if (thumbnailModel) {
       thumbnailModel.automaticallyGenerated = false
@@ -201,7 +201,7 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
 }
 
 async function updateVideoPlaylist (req: express.Request, res: express.Response) {
-  const videoPlaylistInstance = res.locals.videoPlaylist
+  const videoPlaylistInstance = res.locals.videoPlaylistFull
   const videoPlaylistFieldsSave = videoPlaylistInstance.toJSON()
   const videoPlaylistInfoToUpdate = req.body as VideoPlaylistUpdate
 
@@ -275,7 +275,7 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response)
 }
 
 async function removeVideoPlaylist (req: express.Request, res: express.Response) {
-  const videoPlaylistInstance = res.locals.videoPlaylist
+  const videoPlaylistInstance = res.locals.videoPlaylistSummary
 
   await sequelizeTypescript.transaction(async t => {
     await videoPlaylistInstance.destroy({ transaction: t })
@@ -290,10 +290,10 @@ async function removeVideoPlaylist (req: express.Request, res: express.Response)
 
 async function addVideoInPlaylist (req: express.Request, res: express.Response) {
   const body: VideoPlaylistElementCreate = req.body
-  const videoPlaylist = res.locals.videoPlaylist
-  const video = res.locals.video
+  const videoPlaylist = res.locals.videoPlaylistFull
+  const video = res.locals.onlyVideo
 
-  const playlistElement: VideoPlaylistElementModel = await sequelizeTypescript.transaction(async t => {
+  const playlistElement = await sequelizeTypescript.transaction(async t => {
     const position = await VideoPlaylistElementModel.getNextPositionOf(videoPlaylist.id, t)
 
     const playlistElement = await VideoPlaylistElementModel.create({
@@ -330,7 +330,7 @@ async function addVideoInPlaylist (req: express.Request, res: express.Response)
 
 async function updateVideoPlaylistElement (req: express.Request, res: express.Response) {
   const body: VideoPlaylistElementUpdate = req.body
-  const videoPlaylist = res.locals.videoPlaylist
+  const videoPlaylist = res.locals.videoPlaylistFull
   const videoPlaylistElement = res.locals.videoPlaylistElement
 
   const playlistElement: VideoPlaylistElementModel = await sequelizeTypescript.transaction(async t => {
@@ -354,7 +354,7 @@ async function updateVideoPlaylistElement (req: express.Request, res: express.Re
 
 async function removeVideoFromPlaylist (req: express.Request, res: express.Response) {
   const videoPlaylistElement = res.locals.videoPlaylistElement
-  const videoPlaylist = res.locals.videoPlaylist
+  const videoPlaylist = res.locals.videoPlaylistFull
   const positionToDelete = videoPlaylistElement.position
 
   await sequelizeTypescript.transaction(async t => {
@@ -381,7 +381,7 @@ async function removeVideoFromPlaylist (req: express.Request, res: express.Respo
 }
 
 async function reorderVideosPlaylist (req: express.Request, res: express.Response) {
-  const videoPlaylist = res.locals.videoPlaylist
+  const videoPlaylist = res.locals.videoPlaylistFull
   const body: VideoPlaylistReorder = req.body
 
   const start: number = body.startPosition
@@ -434,7 +434,7 @@ async function reorderVideosPlaylist (req: express.Request, res: express.Respons
 }
 
 async function getVideoPlaylistVideos (req: express.Request, res: express.Response) {
-  const videoPlaylistInstance = res.locals.videoPlaylist
+  const videoPlaylistInstance = res.locals.videoPlaylistSummary
   const user = res.locals.oauth ? res.locals.oauth.token.User : undefined
   const server = await getServerActor()
 
@@ -453,7 +453,7 @@ async function getVideoPlaylistVideos (req: express.Request, res: express.Respon
   return res.json(getFormattedObjects(resultList.data, resultList.total, options))
 }
 
-async function regeneratePlaylistThumbnail (videoPlaylist: VideoPlaylistModel) {
+async function regeneratePlaylistThumbnail (videoPlaylist: MVideoPlaylistThumbnail) {
   await videoPlaylist.Thumbnail.destroy()
   videoPlaylist.Thumbnail = null
 
@@ -461,7 +461,7 @@ async function regeneratePlaylistThumbnail (videoPlaylist: VideoPlaylistModel) {
   if (firstElement) await generateThumbnailForPlaylist(videoPlaylist, firstElement.Video)
 }
 
-async function generateThumbnailForPlaylist (videoPlaylist: VideoPlaylistModel, video: VideoModel) {
+async function generateThumbnailForPlaylist (videoPlaylist: MVideoPlaylistThumbnail, video: MVideoThumbnail) {
   logger.info('Generating default thumbnail to playlist %s.', videoPlaylist.url)
 
   const inputPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getMiniature().filename)
index 77808466c3cc8128b33423d89af40c77dc3171fe..39c841ffe1271fd874e74b1ac056887e7836a100 100644 (file)
@@ -21,6 +21,7 @@ import { VideoAbuseModel } from '../../../models/video/video-abuse'
 import { auditLoggerFactory, VideoAbuseAuditView } from '../../../helpers/audit-logger'
 import { Notifier } from '../../../lib/notifier'
 import { sendVideoAbuse } from '../../../lib/activitypub/send/send-flag'
+import { MVideoAbuseAccountVideo } from '../../../typings/models/video'
 
 const auditLogger = auditLoggerFactory('abuse')
 const abuseVideoRouter = express.Router()
@@ -94,10 +95,10 @@ async function deleteVideoAbuse (req: express.Request, res: express.Response) {
 }
 
 async function reportVideoAbuse (req: express.Request, res: express.Response) {
-  const videoInstance = res.locals.video
+  const videoInstance = res.locals.videoAll
   const body: VideoAbuseCreate = req.body
 
-  const videoAbuse: VideoAbuseModel = await sequelizeTypescript.transaction(async t => {
+  const videoAbuse = await sequelizeTypescript.transaction(async t => {
     const reporterAccount = await AccountModel.load(res.locals.oauth.token.User.Account.id, t)
 
     const abuseToCreate = {
@@ -107,7 +108,7 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
       state: VideoAbuseState.PENDING
     }
 
-    const videoAbuseInstance = await VideoAbuseModel.create(abuseToCreate, { transaction: t })
+    const videoAbuseInstance: MVideoAbuseAccountVideo = await VideoAbuseModel.create(abuseToCreate, { transaction: t })
     videoAbuseInstance.Video = videoInstance
     videoAbuseInstance.Account = reporterAccount
 
index 9ff494defbd74746ad8a551190d7db245f4b87ce..2a667480d468397438ec5e48d4f074ecafe13471 100644 (file)
@@ -1,5 +1,5 @@
 import * as express from 'express'
-import { VideoBlacklist, UserRight, VideoBlacklistCreate, VideoBlacklistType } from '../../../../shared'
+import { UserRight, VideoBlacklistCreate, VideoBlacklistType } from '../../../../shared'
 import { logger } from '../../../helpers/logger'
 import { getFormattedObjects } from '../../../helpers/utils'
 import {
@@ -11,15 +11,16 @@ import {
   setBlacklistSort,
   setDefaultPagination,
   videosBlacklistAddValidator,
+  videosBlacklistFiltersValidator,
   videosBlacklistRemoveValidator,
-  videosBlacklistUpdateValidator,
-  videosBlacklistFiltersValidator
+  videosBlacklistUpdateValidator
 } from '../../../middlewares'
 import { VideoBlacklistModel } from '../../../models/video/video-blacklist'
 import { sequelizeTypescript } from '../../../initializers'
 import { Notifier } from '../../../lib/notifier'
 import { sendDeleteVideo } from '../../../lib/activitypub/send'
 import { federateVideoIfNeeded } from '../../../lib/activitypub'
+import { MVideoBlacklistVideo } from '@server/typings/models'
 
 const blacklistRouter = express.Router()
 
@@ -64,7 +65,7 @@ export {
 // ---------------------------------------------------------------------------
 
 async function addVideoToBlacklist (req: express.Request, res: express.Response) {
-  const videoInstance = res.locals.video
+  const videoInstance = res.locals.videoAll
   const body: VideoBlacklistCreate = req.body
 
   const toCreate = {
@@ -74,7 +75,7 @@ async function addVideoToBlacklist (req: express.Request, res: express.Response)
     type: VideoBlacklistType.MANUAL
   }
 
-  const blacklist = await VideoBlacklistModel.create(toCreate)
+  const blacklist: MVideoBlacklistVideo = await VideoBlacklistModel.create(toCreate)
   blacklist.Video = videoInstance
 
   if (body.unfederate === true) {
@@ -83,7 +84,7 @@ async function addVideoToBlacklist (req: express.Request, res: express.Response)
 
   Notifier.Instance.notifyOnVideoBlacklist(blacklist)
 
-  logger.info('Video %s blacklisted.', res.locals.video.uuid)
+  logger.info('Video %s blacklisted.', videoInstance.uuid)
 
   return res.type('json').status(204).end()
 }
@@ -108,7 +109,7 @@ async function listBlacklist (req: express.Request, res: express.Response) {
 
 async function removeVideoFromBlacklistController (req: express.Request, res: express.Response) {
   const videoBlacklist = res.locals.videoBlacklist
-  const video = res.locals.video
+  const video = res.locals.videoAll
 
   const videoBlacklistType = await sequelizeTypescript.transaction(async t => {
     const unfederated = videoBlacklist.unfederated
@@ -135,7 +136,7 @@ async function removeVideoFromBlacklistController (req: express.Request, res: ex
     Notifier.Instance.notifyOnNewVideoIfNeeded(video)
   }
 
-  logger.info('Video %s removed from blacklist.', res.locals.video.uuid)
+  logger.info('Video %s removed from blacklist.', video.uuid)
 
   return res.type('json').status(204).end()
 }
index 44c255232bd83cd8d467139091d32c03c89672cd..37481d12f525b4291868bd626934d5a214a41df4 100644 (file)
@@ -10,6 +10,7 @@ import { federateVideoIfNeeded } from '../../../lib/activitypub'
 import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils'
 import { CONFIG } from '../../../initializers/config'
 import { sequelizeTypescript } from '../../../initializers/database'
+import { MVideoCaptionVideo } from '@server/typings/models'
 
 const reqVideoCaptionAdd = createReqFiles(
   [ 'captionfile' ],
@@ -46,19 +47,19 @@ export {
 // ---------------------------------------------------------------------------
 
 async function listVideoCaptions (req: express.Request, res: express.Response) {
-  const data = await VideoCaptionModel.listVideoCaptions(res.locals.video.id)
+  const data = await VideoCaptionModel.listVideoCaptions(res.locals.videoId.id)
 
   return res.json(getFormattedObjects(data, data.length))
 }
 
 async function addVideoCaption (req: express.Request, res: express.Response) {
   const videoCaptionPhysicalFile = req.files['captionfile'][0]
-  const video = res.locals.video
+  const video = res.locals.videoAll
 
   const videoCaption = new VideoCaptionModel({
     videoId: video.id,
     language: req.params.captionLanguage
-  })
+  }) as MVideoCaptionVideo
   videoCaption.Video = video
 
   // Move physical file
@@ -75,7 +76,7 @@ async function addVideoCaption (req: express.Request, res: express.Response) {
 }
 
 async function deleteVideoCaption (req: express.Request, res: express.Response) {
-  const video = res.locals.video
+  const video = res.locals.videoAll
   const videoCaption = res.locals.videoCaption
 
   await sequelizeTypescript.transaction(async t => {
index bc6d81a7c38f457e7a93032fef2fdfb103c8bc74..b2b06b170ead39981e2fe35c3d01f56afe52b795 100644 (file)
@@ -27,9 +27,6 @@ import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../.
 import { AccountModel } from '../../../models/account/account'
 import { Notifier } from '../../../lib/notifier'
 import { Hooks } from '../../../lib/plugins/hooks'
-import { ActorModel } from '../../../models/activitypub/actor'
-import { VideoChannelModel } from '../../../models/video/video-channel'
-import { VideoModel } from '../../../models/video/video'
 import { sendDeleteVideoComment } from '../../../lib/activitypub/send'
 
 const auditLogger = auditLoggerFactory('comments')
@@ -75,7 +72,7 @@ export {
 // ---------------------------------------------------------------------------
 
 async function listVideoThreads (req: express.Request, res: express.Response) {
-  const video = res.locals.video
+  const video = res.locals.onlyVideo
   const user = res.locals.oauth ? res.locals.oauth.token.User : undefined
 
   let resultList: ResultList<VideoCommentModel>
@@ -86,7 +83,7 @@ async function listVideoThreads (req: express.Request, res: express.Response) {
       start: req.query.start,
       count: req.query.count,
       sort: req.query.sort,
-      user: user
+      user
     }, 'filter:api.video-threads.list.params')
 
     resultList = await Hooks.wrapPromiseFun(
@@ -105,7 +102,7 @@ async function listVideoThreads (req: express.Request, res: express.Response) {
 }
 
 async function listVideoThreadComments (req: express.Request, res: express.Response) {
-  const video = res.locals.video
+  const video = res.locals.onlyVideo
   const user = res.locals.oauth ? res.locals.oauth.token.User : undefined
 
   let resultList: ResultList<VideoCommentModel>
@@ -141,7 +138,7 @@ async function addVideoCommentThread (req: express.Request, res: express.Respons
     return createVideoComment({
       text: videoCommentInfo.text,
       inReplyToComment: null,
-      video: res.locals.video,
+      video: res.locals.videoAll,
       account
     }, t)
   })
@@ -164,8 +161,8 @@ async function addVideoCommentReply (req: express.Request, res: express.Response
 
     return createVideoComment({
       text: videoCommentInfo.text,
-      inReplyToComment: res.locals.videoComment,
-      video: res.locals.video,
+      inReplyToComment: res.locals.videoCommentFull,
+      video: res.locals.videoAll,
       account
     }, t)
   })
@@ -179,7 +176,7 @@ async function addVideoCommentReply (req: express.Request, res: express.Response
 }
 
 async function removeVideoComment (req: express.Request, res: express.Response) {
-  const videoCommentInstance = res.locals.videoComment
+  const videoCommentInstance = res.locals.videoCommentFull
 
   await sequelizeTypescript.transaction(async t => {
     await videoCommentInstance.destroy({ transaction: t })
index 04c9b547be7909079df9130a1c4495bdd6070a20..adc2f9aa2a625b6a9d1ee84338c244e39bcb0efd 100644 (file)
@@ -15,7 +15,6 @@ import { VideoImportModel } from '../../../models/video/video-import'
 import { JobQueue } from '../../../lib/job-queue/job-queue'
 import { join } from 'path'
 import { isArray } from '../../../helpers/custom-validators/misc'
-import { VideoChannelModel } from '../../../models/video/video-channel'
 import * as Bluebird from 'bluebird'
 import * as parseTorrent from 'parse-torrent'
 import { getSecureTorrentName } from '../../../helpers/utils'
@@ -25,8 +24,14 @@ import { CONFIG } from '../../../initializers/config'
 import { sequelizeTypescript } from '../../../initializers/database'
 import { createVideoMiniatureFromExisting } from '../../../lib/thumbnail'
 import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
-import { ThumbnailModel } from '../../../models/video/thumbnail'
-import { UserModel } from '../../../models/account/user'
+import {
+  MChannelActorAccountDefault,
+  MThumbnail,
+  MUser,
+  MVideoThumbnailAccountDefault,
+  MVideoWithBlacklistLight
+} from '@server/typings/models'
+import { MVideoImport, MVideoImportVideo } from '@server/typings/models/video/video-import'
 
 const auditLogger = auditLoggerFactory('video-imports')
 const videoImportsRouter = express.Router()
@@ -225,28 +230,28 @@ async function processPreview (req: express.Request, video: VideoModel) {
 }
 
 function insertIntoDB (parameters: {
-  video: VideoModel,
-  thumbnailModel: ThumbnailModel,
-  previewModel: ThumbnailModel,
-  videoChannel: VideoChannelModel,
+  video: MVideoThumbnailAccountDefault,
+  thumbnailModel: MThumbnail,
+  previewModel: MThumbnail,
+  videoChannel: MChannelActorAccountDefault,
   tags: string[],
-  videoImportAttributes: Partial<VideoImportModel>,
-  user: UserModel
-}): Bluebird<VideoImportModel> {
+  videoImportAttributes: Partial<MVideoImport>,
+  user: MUser
+}): Bluebird<MVideoImportVideo> {
   const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters
 
   return sequelizeTypescript.transaction(async t => {
     const sequelizeOptions = { transaction: t }
 
     // Save video object in database
-    const videoCreated = await video.save(sequelizeOptions)
+    const videoCreated = await video.save(sequelizeOptions) as (MVideoThumbnailAccountDefault & MVideoWithBlacklistLight)
     videoCreated.VideoChannel = videoChannel
 
     if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t)
     if (previewModel) await videoCreated.addAndSaveThumbnail(previewModel, t)
 
     await autoBlacklistVideoIfNeeded({
-      video,
+      video: videoCreated,
       user,
       notify: false,
       isRemote: false,
@@ -259,16 +264,13 @@ function insertIntoDB (parameters: {
       const tagInstances = await TagModel.findOrCreateTags(tags, t)
 
       await videoCreated.$set('Tags', tagInstances, sequelizeOptions)
-      videoCreated.Tags = tagInstances
-    } else {
-      videoCreated.Tags = []
     }
 
     // Create video import object in database
     const videoImport = await VideoImportModel.create(
       Object.assign({ videoId: videoCreated.id }, videoImportAttributes),
       sequelizeOptions
-    )
+    ) as MVideoImportVideo
     videoImport.Video = videoCreated
 
     return videoImport
index 155ca4678f146e6aadc231ddb1d8a68be3ddb675..9af71d276430bd959d7b87575c40b4defb1d1bdb 100644 (file)
@@ -63,6 +63,7 @@ import { createVideoMiniatureFromExisting, generateVideoMiniature } from '../../
 import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
 import { VideoTranscodingPayload } from '../../../lib/job-queue/handlers/video-transcoding'
 import { Hooks } from '../../../lib/plugins/hooks'
+import { MVideoFullLight } from '@server/typings/models'
 
 const auditLogger = auditLoggerFactory('videos')
 const videosRouter = express.Router()
@@ -238,7 +239,7 @@ async function addVideo (req: express.Request, res: express.Response) {
   const { videoCreated } = await sequelizeTypescript.transaction(async t => {
     const sequelizeOptions = { transaction: t }
 
-    const videoCreated = await video.save(sequelizeOptions)
+    const videoCreated = await video.save(sequelizeOptions) as MVideoFullLight
 
     await videoCreated.addAndSaveThumbnail(thumbnailModel, t)
     await videoCreated.addAndSaveThumbnail(previewModel, t)
@@ -318,7 +319,7 @@ async function addVideo (req: express.Request, res: express.Response) {
 }
 
 async function updateVideo (req: express.Request, res: express.Response) {
-  const videoInstance = res.locals.video
+  const videoInstance = res.locals.videoAll
   const videoFieldsSave = videoInstance.toJSON()
   const oldVideoAuditView = new VideoAuditView(videoInstance.toFormattedDetailsJSON())
   const videoInfoToUpdate: VideoUpdate = req.body
@@ -371,7 +372,7 @@ async function updateVideo (req: express.Request, res: express.Response) {
         }
       }
 
-      const videoInstanceUpdated = await videoInstance.save(sequelizeOptions)
+      const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) as MVideoFullLight
 
       if (thumbnailModel) await videoInstanceUpdated.addAndSaveThumbnail(thumbnailModel, t)
       if (previewModel) await videoInstanceUpdated.addAndSaveThumbnail(previewModel, t)
@@ -447,7 +448,7 @@ async function getVideo (req: express.Request, res: express.Response) {
 
   const video = await Hooks.wrapPromiseFun(
     VideoModel.loadForGetAPI,
-    { id: res.locals.video.id, userId },
+    { id: res.locals.onlyVideoWithRights.id, userId },
     'filter:api.video.get.result'
   )
 
@@ -460,7 +461,7 @@ async function getVideo (req: express.Request, res: express.Response) {
 }
 
 async function viewVideo (req: express.Request, res: express.Response) {
-  const videoInstance = res.locals.video
+  const videoInstance = res.locals.videoAll
 
   const ip = req.ip
   const exists = await Redis.Instance.doesVideoIPViewExist(ip, videoInstance.uuid)
@@ -483,7 +484,7 @@ async function viewVideo (req: express.Request, res: express.Response) {
 }
 
 async function getVideoDescription (req: express.Request, res: express.Response) {
-  const videoInstance = res.locals.video
+  const videoInstance = res.locals.videoAll
   let description = ''
 
   if (videoInstance.isOwned()) {
@@ -522,7 +523,7 @@ async function listVideos (req: express.Request, res: express.Response) {
 }
 
 async function removeVideo (req: express.Request, res: express.Response) {
-  const videoInstance = res.locals.video
+  const videoInstance = res.locals.videoAll
 
   await sequelizeTypescript.transaction(async t => {
     await videoInstance.destroy({ transaction: t })
index 5272c1385030125daa36b5f9b94f5b8c0e09819b..abb34082e893c2d4382c74b7d3b947ed7f9bb29a 100644 (file)
@@ -18,6 +18,7 @@ import { getFormattedObjects } from '../../../helpers/utils'
 import { changeVideoChannelShare } from '../../../lib/activitypub'
 import { sendUpdateVideo } from '../../../lib/activitypub/send'
 import { VideoModel } from '../../../models/video/video'
+import { MVideoFullLight } from '@server/typings/models'
 
 const ownershipVideoRouter = express.Router()
 
@@ -56,7 +57,7 @@ export {
 // ---------------------------------------------------------------------------
 
 async function giveVideoOwnership (req: express.Request, res: express.Response) {
-  const videoInstance = res.locals.video
+  const videoInstance = res.locals.videoAll
   const initiatorAccountId = res.locals.oauth.token.User.Account.id
   const nextOwner = res.locals.nextOwner
 
@@ -107,7 +108,7 @@ async function acceptOwnership (req: express.Request, res: express.Response) {
 
     targetVideo.channelId = channel.id
 
-    const targetVideoUpdated = await targetVideo.save({ transaction: t })
+    const targetVideoUpdated = await targetVideo.save({ transaction: t }) as MVideoFullLight
     targetVideoUpdated.VideoChannel = channel
 
     if (targetVideoUpdated.privacy !== VideoPrivacy.PRIVATE && targetVideoUpdated.state === VideoState.PUBLISHED) {
index b65babedf1ccfa3db5670a9f7cee12104465c773..3d2f3d7281bef752ac12b193574be68dcac5fb04 100644 (file)
@@ -27,7 +27,7 @@ export {
 async function rateVideo (req: express.Request, res: express.Response) {
   const body: UserVideoRateUpdate = req.body
   const rateType = body.rating
-  const videoInstance = res.locals.video
+  const videoInstance = res.locals.videoAll
   const userAccount = res.locals.oauth.token.User.Account
 
   await sequelizeTypescript.transaction(async t => {
index dcd1f070d1662ff680a6c32ecec19e83af188f78..036e16f3af57ad62a0605e2c1cae2337828db128 100644 (file)
@@ -23,7 +23,7 @@ async function userWatchVideo (req: express.Request, res: express.Response) {
   const user = res.locals.oauth.token.User
 
   const body: UserWatchingVideo = req.body
-  const { id: videoId } = res.locals.video as { id: number }
+  const { id: videoId } = res.locals.videoId
 
   await UserVideoHistoryModel.upsert({
     videoId,
index d3f581615fb56bcf940325836886dfb3b825d91a..468f7a668dc1a43fe75b72fff956bdc072b31a93 100644 (file)
@@ -43,7 +43,7 @@ export {
 async function generateVideoCommentsFeed (req: express.Request, res: express.Response) {
   const start = 0
 
-  const video = res.locals.video
+  const video = res.locals.videoAll
   const videoId: number = video ? video.id : undefined
 
   const comments = await VideoCommentModel.listForFeed(start, FEEDS.COUNT, videoId)
index c1c53c3fc80466a72aad65ed53493e586d688a8c..ec057235fbb3f6958694dc31330b10f23026e39f 100644 (file)
@@ -23,7 +23,7 @@ export {
 // ---------------------------------------------------------------------------
 
 function generateOEmbed (req: express.Request, res: express.Response) {
-  const video = res.locals.video
+  const video = res.locals.videoAll
   const webserverUrl = WEBSERVER.URL
   const maxHeight = parseInt(req.query.maxheight, 10)
   const maxWidth = parseInt(req.query.maxwidth, 10)
index 8979ef5f388e16b6f487a7a73b7fdde12ba427ac..0f47723100ef165f9f290553b76dba237e1f6293 100644 (file)
@@ -226,14 +226,14 @@ async function generateNodeinfo (req: express.Request, res: express.Response) {
   return res.send(json).end()
 }
 
-async function downloadTorrent (req: express.Request, res: express.Response, next: express.NextFunction) {
+async function downloadTorrent (req: express.Request, res: express.Response) {
   const { video, videoFile } = getVideoAndFile(req, res)
   if (!videoFile) return res.status(404).end()
 
   return res.download(video.getTorrentFilePath(videoFile), `${video.name}-${videoFile.resolution}p.torrent`)
 }
 
-async function downloadVideoFile (req: express.Request, res: express.Response, next: express.NextFunction) {
+async function downloadVideoFile (req: express.Request, res: express.Response) {
   const { video, videoFile } = getVideoAndFile(req, res)
   if (!videoFile) return res.status(404).end()
 
@@ -242,7 +242,7 @@ async function downloadVideoFile (req: express.Request, res: express.Response, n
 
 function getVideoAndFile (req: express.Request, res: express.Response) {
   const resolution = parseInt(req.params.resolution, 10)
-  const video = res.locals.video
+  const video = res.locals.videoAll
 
   const videoFile = video.VideoFiles.find(f => f.resolution === resolution)
 
index f2ba3c8266683db9ea793a1621c252021713d53f..fc9575160bf42e15a74ffc570eb9c2560732eb1d 100644 (file)
@@ -18,7 +18,7 @@ export {
 // ---------------------------------------------------------------------------
 
 function webfingerController (req: express.Request, res: express.Response) {
-  const actor = res.locals.actor
+  const actor = res.locals.actorFull
 
   const json = {
     subject: req.query.resource,
index 951a25669d4e2efb3e079c0cf7f9a748f63b0921..97c809a0c51fae1eaf6e2d5b0f70617f282c448e 100644 (file)
@@ -7,6 +7,7 @@ import { ActorModel } from '../models/activitypub/actor'
 import { signJsonLDObject } from './peertube-crypto'
 import { pageToStartAndCount } from './core-utils'
 import { parse } from 'url'
+import { MActor } from '../typings/models'
 
 function activityPubContextify <T> (data: T) {
   return Object.assign(data, {
@@ -143,7 +144,7 @@ async function activityPubCollectionPagination (baseUrl: string, handler: Activi
 
 }
 
-function buildSignedActivity (byActor: ActorModel, data: Object) {
+function buildSignedActivity (byActor: MActor, data: Object) {
   const activity = activityPubContextify(data)
 
   return signJsonLDObject(byActor, activity) as Promise<Activity>
index 12a7ace9fb7dbc1bdca9ef6a15b67c61720ceb56..117548a60cd9db06a43317cff9190d8c0c96d4e1 100644 (file)
@@ -1,10 +1,13 @@
 import { ActorModel } from '../models/activitypub/actor'
+import * as Bluebird from 'bluebird'
+import { MActorFull, MActorAccountChannelId } from '../typings/models'
 
-type ActorFetchByUrlType = 'all' | 'actor-and-association-ids'
-function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType) {
+type ActorFetchByUrlType = 'all' | 'association-ids'
+
+function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType): Bluebird<MActorFull | MActorAccountChannelId> {
   if (fetchType === 'all') return ActorModel.loadByUrlAndPopulateAccountAndChannel(url)
 
-  if (fetchType === 'actor-and-association-ids') return ActorModel.loadByUrl(url)
+  if (fetchType === 'association-ids') return ActorModel.loadByUrl(url)
 }
 
 export {
index 7174d4654ab9208a7fc0c93057c09e2060df3ef0..4f29058e54b5b68f07d8f466c60ee32323202096 100644 (file)
@@ -1,10 +1,10 @@
 import { join } from 'path'
 import { CONFIG } from '../initializers/config'
-import { VideoCaptionModel } from '../models/video/video-caption'
 import * as srt2vtt from 'srt-to-vtt'
-import { createReadStream, createWriteStream, remove, move } from 'fs-extra'
+import { createReadStream, createWriteStream, move, remove } from 'fs-extra'
+import { MVideoCaption } from '@server/typings/models'
 
-async function moveAndProcessCaptionFile (physicalFile: { filename: string, path: string }, videoCaption: VideoCaptionModel) {
+async function moveAndProcessCaptionFile (physicalFile: { filename: string, path: string }, videoCaption: MVideoCaption) {
   const videoCaptionsDir = CONFIG.STORAGE.CAPTIONS_DIR
   const destination = join(videoCaptionsDir, videoCaption.getCaptionName())
 
index a7771e07b2e0bf6b1266e42407e27588f90e1b75..9570b27995bd3bcc9f3b77fd163dec02a2fd165a 100644 (file)
@@ -1,10 +1,10 @@
 import { Response } from 'express'
-import * as validator from 'validator'
 import { VideoChangeOwnershipModel } from '../../models/video/video-change-ownership'
-import { UserModel } from '../../models/account/user'
+import { MVideoChangeOwnershipFull } from '@server/typings/models/video/video-change-ownership'
+import { MUserId } from '@server/typings/models'
 
-export async function doesChangeVideoOwnershipExist (id: string, res: Response): Promise<boolean> {
-  const videoChangeOwnership = await loadVideoChangeOwnership(id)
+export async function doesChangeVideoOwnershipExist (id: number, res: Response) {
+  const videoChangeOwnership = await VideoChangeOwnershipModel.load(id)
 
   if (!videoChangeOwnership) {
     res.status(404)
@@ -18,19 +18,7 @@ export async function doesChangeVideoOwnershipExist (id: string, res: Response):
   return true
 }
 
-async function loadVideoChangeOwnership (id: string): Promise<VideoChangeOwnershipModel | undefined> {
-  if (validator.isInt(id)) {
-    return VideoChangeOwnershipModel.load(parseInt(id, 10))
-  }
-
-  return undefined
-}
-
-export function checkUserCanTerminateOwnershipChange (
-  user: UserModel,
-  videoChangeOwnership: VideoChangeOwnershipModel,
-  res: Response
-): boolean {
+export function checkUserCanTerminateOwnershipChange (user: MUserId, videoChangeOwnership: MVideoChangeOwnershipFull, res: Response) {
   if (videoChangeOwnership.NextOwner.userId === user.id) {
     return true
   }
index 791022b97d0c8cbabb45e6a33dd902ebc2b67742..f5aa0badad321601f5e8f10579e2008a1add64fb 100644 (file)
@@ -1,6 +1,7 @@
 import { Response } from 'express'
 import { AccountModel } from '../../models/account/account'
 import * as Bluebird from 'bluebird'
+import { MAccountDefault } from '../../typings/models'
 
 function doesAccountIdExist (id: number, res: Response, sendNotFound = true) {
   const promise = AccountModel.load(id)
@@ -15,10 +16,12 @@ function doesLocalAccountNameExist (name: string, res: Response, sendNotFound =
 }
 
 function doesAccountNameWithHostExist (nameWithDomain: string, res: Response, sendNotFound = true) {
-  return doesAccountExist(AccountModel.loadByNameWithHost(nameWithDomain), res, sendNotFound)
+  const promise = AccountModel.loadByNameWithHost(nameWithDomain)
+
+  return doesAccountExist(promise, res, sendNotFound)
 }
 
-async function doesAccountExist (p: Bluebird<AccountModel>, res: Response, sendNotFound: boolean) {
+async function doesAccountExist (p: Bluebird<MAccountDefault>, res: Response, sendNotFound: boolean) {
   const account = await p
 
   if (!account) {
index b23f1f021b1d46d0495ffacecefd4c28c4b3dca7..1b573ca37e7ae2bf0dff4956af95ecb76ac9b2d6 100644 (file)
@@ -1,41 +1,23 @@
-import * as express from 'express'
-import { VideoChannelModel } from '../../models/video/video-channel'
+import { Response } from 'express'
+import { VideoAbuseModel } from '../../models/video/video-abuse'
 
-async function doesLocalVideoChannelNameExist (name: string, res: express.Response) {
-  const videoChannel = await VideoChannelModel.loadLocalByNameAndPopulateAccount(name)
+async function doesVideoAbuseExist (abuseId: number, videoId: number, res: Response) {
+  const videoAbuse = await VideoAbuseModel.loadByIdAndVideoId(abuseId, videoId)
 
-  return processVideoChannelExist(videoChannel, res)
-}
-
-async function doesVideoChannelIdExist (id: number, res: express.Response) {
-  const videoChannel = await VideoChannelModel.loadAndPopulateAccount(+id)
-
-  return processVideoChannelExist(videoChannel, res)
-}
-
-async function doesVideoChannelNameWithHostExist (nameWithDomain: string, res: express.Response) {
-  const videoChannel = await VideoChannelModel.loadByNameWithHostAndPopulateAccount(nameWithDomain)
-
-  return processVideoChannelExist(videoChannel, res)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
-  doesLocalVideoChannelNameExist,
-  doesVideoChannelIdExist,
-  doesVideoChannelNameWithHostExist
-}
-
-function processVideoChannelExist (videoChannel: VideoChannelModel, res: express.Response) {
-  if (!videoChannel) {
+  if (videoAbuse === null) {
     res.status(404)
-       .json({ error: 'Video channel not found' })
+       .json({ error: 'Video abuse not found' })
        .end()
 
     return false
   }
 
-  res.locals.videoChannel = videoChannel
+  res.locals.videoAbuse = videoAbuse
   return true
 }
+
+// ---------------------------------------------------------------------------
+
+export {
+  doesVideoAbuseExist
+}
index dc3d0144bc079c35d4d385878bfd93d2241b934b..1b2513b60111b306dff9bf00ea64fec24409f47b 100644 (file)
@@ -1,8 +1,8 @@
-import { VideoModel } from '../../models/video/video'
 import { Response } from 'express'
 import { VideoCaptionModel } from '../../models/video/video-caption'
+import { MVideoId } from '@server/typings/models'
 
-async function doesVideoCaptionExist (video: VideoModel, language: string, res: Response) {
+async function doesVideoCaptionExist (video: MVideoId, language: string, res: Response) {
   const videoCaption = await VideoCaptionModel.loadByVideoIdAndLanguage(video.id, language)
 
   if (!videoCaption) {
index 1b573ca37e7ae2bf0dff4956af95ecb76ac9b2d6..17b7692c575c9698e577a48f189a98ca3509dde6 100644 (file)
@@ -1,23 +1,42 @@
-import { Response } from 'express'
-import { VideoAbuseModel } from '../../models/video/video-abuse'
+import * as express from 'express'
+import { VideoChannelModel } from '../../models/video/video-channel'
+import { MChannelActorAccountDefault } from '../../typings/models'
 
-async function doesVideoAbuseExist (abuseId: number, videoId: number, res: Response) {
-  const videoAbuse = await VideoAbuseModel.loadByIdAndVideoId(abuseId, videoId)
+async function doesLocalVideoChannelNameExist (name: string, res: express.Response) {
+  const videoChannel = await VideoChannelModel.loadLocalByNameAndPopulateAccount(name)
 
-  if (videoAbuse === null) {
-    res.status(404)
-       .json({ error: 'Video abuse not found' })
-       .end()
+  return processVideoChannelExist(videoChannel, res)
+}
 
-    return false
-  }
+async function doesVideoChannelIdExist (id: number, res: express.Response) {
+  const videoChannel = await VideoChannelModel.loadAndPopulateAccount(+id)
 
-  res.locals.videoAbuse = videoAbuse
-  return true
+  return processVideoChannelExist(videoChannel, res)
+}
+
+async function doesVideoChannelNameWithHostExist (nameWithDomain: string, res: express.Response) {
+  const videoChannel = await VideoChannelModel.loadByNameWithHostAndPopulateAccount(nameWithDomain)
+
+  return processVideoChannelExist(videoChannel, res)
 }
 
 // ---------------------------------------------------------------------------
 
 export {
-  doesVideoAbuseExist
+  doesLocalVideoChannelNameExist,
+  doesVideoChannelIdExist,
+  doesVideoChannelNameWithHostExist
+}
+
+function processVideoChannelExist (videoChannel: MChannelActorAccountDefault, res: express.Response) {
+  if (!videoChannel) {
+    res.status(404)
+       .json({ error: 'Video channel not found' })
+       .end()
+
+    return false
+  }
+
+  res.locals.videoChannel = videoChannel
+  return true
 }
index 735bf362f77b715c16ef4980b7eaefe9ea7f2c98..8e74844835c37e6ff63b0f65582f008edf08f3eb 100644 (file)
@@ -1,11 +1,31 @@
 import * as express from 'express'
 import { VideoPlaylistModel } from '../../models/video/video-playlist'
+import { MVideoPlaylist } from '../../typings/models/video/video-playlist'
 
-async function doesVideoPlaylistExist (id: number | string, res: express.Response, fetchType: 'summary' | 'all' = 'summary') {
-  const videoPlaylist = fetchType === 'summary'
-    ? await VideoPlaylistModel.loadWithAccountAndChannelSummary(id, undefined)
-    : await VideoPlaylistModel.loadWithAccountAndChannel(id, undefined)
+export type VideoPlaylistFetchType = 'summary' | 'all'
+async function doesVideoPlaylistExist (id: number | string, res: express.Response, fetchType: VideoPlaylistFetchType = 'summary') {
+  if (fetchType === 'summary') {
+    const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannelSummary(id, undefined)
+    res.locals.videoPlaylistSummary = videoPlaylist
 
+    return handleVideoPlaylist(videoPlaylist, res)
+  }
+
+  const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannel(id, undefined)
+  res.locals.videoPlaylistFull = videoPlaylist
+
+  return handleVideoPlaylist(videoPlaylist, res)
+}
+
+// ---------------------------------------------------------------------------
+
+export {
+  doesVideoPlaylistExist
+}
+
+// ---------------------------------------------------------------------------
+
+function handleVideoPlaylist (videoPlaylist: MVideoPlaylist, res: express.Response) {
   if (!videoPlaylist) {
     res.status(404)
        .json({ error: 'Video playlist not found' })
@@ -14,12 +34,5 @@ async function doesVideoPlaylistExist (id: number | string, res: express.Respons
     return false
   }
 
-  res.locals.videoPlaylist = videoPlaylist
   return true
 }
-
-// ---------------------------------------------------------------------------
-
-export {
-  doesVideoPlaylistExist
-}
index ceb1058ecb7c4e090705a6cbd0c3513eb7cb1c09..964f0c91a1a7eb2ea32f6cf53efa57dd9f2a7718 100644 (file)
@@ -1,9 +1,8 @@
 import { Response } from 'express'
 import { fetchVideo, VideoFetchType } from '../video'
-import { UserModel } from '../../models/account/user'
 import { UserRight } from '../../../shared/models/users'
 import { VideoChannelModel } from '../../models/video/video-channel'
-import { VideoModel } from '../../models/video/video'
+import { MUser, MUserAccountId, MVideoAccountLight, MVideoFullLight, MVideoWithRights } from '@server/typings/models'
 
 async function doesVideoExist (id: number | string, res: Response, fetchType: VideoFetchType = 'all') {
   const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined
@@ -18,11 +17,28 @@ async function doesVideoExist (id: number | string, res: Response, fetchType: Vi
     return false
   }
 
-  if (fetchType !== 'none') res.locals.video = video
+  switch (fetchType) {
+    case 'all':
+      res.locals.videoAll = video as MVideoFullLight
+      break
+
+    case 'id':
+      res.locals.videoId = video
+      break
+
+    case 'only-video':
+      res.locals.onlyVideo = video
+      break
+
+    case 'only-video-with-rights':
+      res.locals.onlyVideoWithRights = video as MVideoWithRights
+      break
+  }
+
   return true
 }
 
-async function doesVideoChannelOfAccountExist (channelId: number, user: UserModel, res: Response) {
+async function doesVideoChannelOfAccountExist (channelId: number, user: MUserAccountId, res: Response) {
   if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) {
     const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
     if (videoChannel === null) {
@@ -50,7 +66,7 @@ async function doesVideoChannelOfAccountExist (channelId: number, user: UserMode
   return true
 }
 
-function checkUserCanManageVideo (user: UserModel, video: VideoModel, right: UserRight, res: Response) {
+function checkUserCanManageVideo (user: MUser, video: MVideoAccountLight, right: UserRight, res: Response) {
   // Retrieve the user who did the request
   if (video.isOwned() === false) {
     res.status(403)
index 1424949d0a6b6c3054eb58ac1a4fe1c70aa6545b..085cd62c90df1cc5d05610f9b6f9f04f6bf5634d 100644 (file)
@@ -8,6 +8,7 @@ import { cloneDeep } from 'lodash'
 import { createVerify } from 'crypto'
 import { buildDigest } from '../lib/job-queue/handlers/utils/activitypub-http-utils'
 import * as bcrypt from 'bcrypt'
+import { MActor } from '../typings/models'
 
 const bcryptComparePromise = promisify2<any, string, boolean>(bcrypt.compare)
 const bcryptGenSaltPromise = promisify1<number, string>(bcrypt.genSalt)
@@ -46,7 +47,7 @@ function isHTTPSignatureDigestValid (rawBody: Buffer, req: Request): boolean {
   return true
 }
 
-function isHTTPSignatureVerified (httpSignatureParsed: any, actor: ActorModel): boolean {
+function isHTTPSignatureVerified (httpSignatureParsed: any, actor: MActor): boolean {
   return httpSignature.verifySignature(httpSignatureParsed, actor.publicKey) === true
 }
 
@@ -56,7 +57,7 @@ function parseHTTPSignature (req: Request, clockSkew?: number) {
 
 // JSONLD
 
-async function isJsonLDSignatureVerified (fromActor: ActorModel, signedDocument: any): Promise<boolean> {
+async function isJsonLDSignatureVerified (fromActor: MActor, signedDocument: any): Promise<boolean> {
   if (signedDocument.signature.type === 'RsaSignature2017') {
     // Mastodon algorithm
     const res = await isJsonLDRSA2017Verified(fromActor, signedDocument)
@@ -93,7 +94,7 @@ async function isJsonLDSignatureVerified (fromActor: ActorModel, signedDocument:
 }
 
 // Backward compatibility with "other" implementations
-async function isJsonLDRSA2017Verified (fromActor: ActorModel, signedDocument: any) {
+async function isJsonLDRSA2017Verified (fromActor: MActor, signedDocument: any) {
   function hash (obj: any): Promise<any> {
     return jsonld.promises
                  .normalize(obj, {
@@ -130,7 +131,7 @@ async function isJsonLDRSA2017Verified (fromActor: ActorModel, signedDocument: a
   return verify.verify(fromActor.publicKey, signedDocument.signature.signatureValue, 'base64')
 }
 
-function signJsonLDObject (byActor: ActorModel, data: any) {
+function signJsonLDObject (byActor: MActor, data: any) {
   const options = {
     privateKeyPem: byActor.privateKey,
     creator: byActor.url,
index c90fe06c78e2729174f58f5dee75741d9f194cd5..26a72ac5c593162361bac2a6b9776460b9c9a3fa 100644 (file)
@@ -1,8 +1,24 @@
 import { VideoModel } from '../models/video/video'
+import * as Bluebird from 'bluebird'
+import { MVideoAccountAllFiles, MVideoFullLight, MVideoThumbnail, MVideoWithRights, MVideoIdThumbnail } from '@server/typings/models'
+import { Response } from 'express'
 
 type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none'
 
-function fetchVideo (id: number | string, fetchType: VideoFetchType, userId?: number) {
+function fetchVideo (id: number | string, fetchType: 'all', userId?: number): Bluebird<MVideoFullLight>
+function fetchVideo (id: number | string, fetchType: 'only-video', userId?: number): Bluebird<MVideoThumbnail>
+function fetchVideo (id: number | string, fetchType: 'only-video-with-rights', userId?: number): Bluebird<MVideoWithRights>
+function fetchVideo (id: number | string, fetchType: 'id' | 'none', userId?: number): Bluebird<MVideoIdThumbnail>
+function fetchVideo (
+  id: number | string,
+  fetchType: VideoFetchType,
+  userId?: number
+): Bluebird<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail>
+function fetchVideo (
+  id: number | string,
+  fetchType: VideoFetchType,
+  userId?: number
+): Bluebird<MVideoFullLight | MVideoThumbnail | MVideoWithRights | MVideoIdThumbnail> {
   if (fetchType === 'all') return VideoModel.loadAndPopulateAccountAndServerAndTags(id, undefined, userId)
 
   if (fetchType === 'only-video-with-rights') return VideoModel.loadWithRights(id)
@@ -13,15 +29,24 @@ function fetchVideo (id: number | string, fetchType: VideoFetchType, userId?: nu
 }
 
 type VideoFetchByUrlType = 'all' | 'only-video'
-function fetchVideoByUrl (url: string, fetchType: VideoFetchByUrlType) {
+
+function fetchVideoByUrl (url: string, fetchType: 'all'): Bluebird<MVideoAccountAllFiles>
+function fetchVideoByUrl (url: string, fetchType: 'only-video'): Bluebird<MVideoThumbnail>
+function fetchVideoByUrl (url: string, fetchType: VideoFetchByUrlType): Bluebird<MVideoAccountAllFiles> | Bluebird<MVideoThumbnail>
+function fetchVideoByUrl (url: string, fetchType: VideoFetchByUrlType): Bluebird<MVideoAccountAllFiles> | Bluebird<MVideoThumbnail> {
   if (fetchType === 'all') return VideoModel.loadByUrlAndPopulateAccount(url)
 
   if (fetchType === 'only-video') return VideoModel.loadByUrl(url)
 }
 
+function getVideo (res: Response) {
+  return res.locals.videoAll || res.locals.onlyVideo || res.locals.onlyVideoWithRights || res.locals.videoId
+}
+
 export {
   VideoFetchType,
   VideoFetchByUrlType,
   fetchVideo,
+  getVideo,
   fetchVideoByUrl
 }
index d1229e28f4b8b6507acefa93c67291b1138a1260..5443a266b0087de6587659cdb30b493b1b6efa9b 100644 (file)
@@ -4,6 +4,7 @@ import { ActorModel } from '../models/activitypub/actor'
 import { isTestInstance } from './core-utils'
 import { isActivityPubUrlValid } from './custom-validators/activitypub/misc'
 import { WEBSERVER } from '../initializers/constants'
+import { MActorFull } from '../typings/models'
 
 const webfinger = new WebFinger({
   webfist_fallback: false,
@@ -17,7 +18,7 @@ async function loadActorUrlOrGetFromWebfinger (uriArg: string) {
   const uri = uriArg.startsWith('@') ? uriArg.slice(1) : uriArg
 
   const [ name, host ] = uri.split('@')
-  let actor: ActorModel
+  let actor: MActorFull
 
   if (!host || host === WEBSERVER.HOST) {
     actor = await ActorModel.loadLocalByName(name)
index 9f5d12eb4917aec0e2ff064b6362762bd8e8924d..7862b0f004d56660458e8b7d86e9127d4d819118 100644 (file)
@@ -22,13 +22,25 @@ import { JobQueue } from '../job-queue'
 import { getServerActor } from '../../helpers/utils'
 import { ActorFetchByUrlType, fetchActorByUrl } from '../../helpers/actor'
 import { sequelizeTypescript } from '../../initializers/database'
+import {
+  MAccount,
+  MActor,
+  MActorAccountChannelId,
+  MActorAccountId,
+  MActorDefault,
+  MActorFull,
+  MActorId,
+  MActorAccountChannelIdActor,
+  MChannel,
+  MActorFullActor, MAccountActorDefault, MChannelActorDefault, MChannelActorAccountDefault
+} from '../../typings/models'
 
 // Set account keys, this could be long so process after the account creation and do not block the client
-function setAsyncActorKeys (actor: ActorModel) {
+function setAsyncActorKeys (actor: MActor) {
   return createPrivateAndPublicKeys()
     .then(({ publicKey, privateKey }) => {
-      actor.set('publicKey', publicKey)
-      actor.set('privateKey', privateKey)
+      actor.publicKey = publicKey
+      actor.privateKey = privateKey
       return actor.save()
     })
     .catch(err => {
@@ -37,12 +49,26 @@ function setAsyncActorKeys (actor: ActorModel) {
     })
 }
 
+function getOrCreateActorAndServerAndModel (
+  activityActor: string | ActivityPubActor,
+  fetchType: 'all',
+  recurseIfNeeded?: boolean,
+  updateCollections?: boolean
+): Promise<MActorFullActor>
+
+function getOrCreateActorAndServerAndModel (
+  activityActor: string | ActivityPubActor,
+  fetchType?: 'association-ids',
+  recurseIfNeeded?: boolean,
+  updateCollections?: boolean
+): Promise<MActorAccountChannelId>
+
 async function getOrCreateActorAndServerAndModel (
   activityActor: string | ActivityPubActor,
-  fetchType: ActorFetchByUrlType = 'actor-and-association-ids',
+  fetchType: ActorFetchByUrlType = 'association-ids',
   recurseIfNeeded = true,
   updateCollections = false
-) {
+): Promise<MActorFullActor | MActorAccountChannelId> {
   const actorUrl = getAPId(activityActor)
   let created = false
   let accountPlaylistsUrl: string
@@ -61,7 +87,7 @@ async function getOrCreateActorAndServerAndModel (
 
     // Create the attributed to actor
     // In PeerTube a video channel is owned by an account
-    let ownerActor: ActorModel = undefined
+    let ownerActor: MActorFullActor
     if (recurseIfNeeded === true && result.actor.type === 'Group') {
       const accountAttributedTo = result.attributedTo.find(a => a.type === 'Person')
       if (!accountAttributedTo) throw new Error('Cannot find account attributed to video channel ' + actor.url)
@@ -85,8 +111,8 @@ async function getOrCreateActorAndServerAndModel (
     accountPlaylistsUrl = result.playlists
   }
 
-  if (actor.Account) actor.Account.Actor = actor
-  if (actor.VideoChannel) actor.VideoChannel.Actor = actor
+  if (actor.Account) (actor as MActorAccountChannelIdActor).Account.Actor = actor
+  if (actor.VideoChannel) (actor as MActorAccountChannelIdActor).VideoChannel.Actor = actor
 
   const { actor: actorRefreshed, refreshed } = await retryTransactionWrapper(refreshActorIfNeeded, actor, fetchType)
   if (!actorRefreshed) throw new Error('Actor ' + actorRefreshed.url + ' does not exist anymore.')
@@ -140,7 +166,8 @@ async function updateActorInstance (actorInstance: ActorModel, attributes: Activ
   actorInstance.followingUrl = attributes.following
 }
 
-async function updateActorAvatarInstance (actor: ActorModel, info: { name: string, onDisk: boolean, fileUrl: string }, t: Transaction) {
+type AvatarInfo = { name: string, onDisk: boolean, fileUrl: string }
+async function updateActorAvatarInstance (actor: MActorDefault, info: AvatarInfo, t: Transaction) {
   if (info.name !== undefined) {
     if (actor.avatarId) {
       try {
@@ -212,14 +239,16 @@ async function addFetchOutboxJob (actor: Pick<ActorModel, 'id' | 'outboxUrl'>) {
   return JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload })
 }
 
-async function refreshActorIfNeeded (
-  actorArg: ActorModel,
+async function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannelId> (
+  actorArg: T,
   fetchedType: ActorFetchByUrlType
-): Promise<{ actor: ActorModel, refreshed: boolean }> {
+): Promise<{ actor: T | MActorFull, refreshed: boolean }> {
   if (!actorArg.isOutdated()) return { actor: actorArg, refreshed: false }
 
   // We need more attributes
-  const actor = fetchedType === 'all' ? actorArg : await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorArg.url)
+  const actor = fetchedType === 'all'
+    ? actorArg as MActorFull
+    : await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorArg.url)
 
   try {
     let actorUrl: string
@@ -297,9 +326,9 @@ export {
 
 function saveActorAndServerAndModelIfNotExist (
   result: FetchRemoteActorResult,
-  ownerActor?: ActorModel,
+  ownerActor?: MActorFullActor,
   t?: Transaction
-): Bluebird<ActorModel> | Promise<ActorModel> {
+): Bluebird<MActorFullActor> | Promise<MActorFullActor> {
   let actor = result.actor
 
   if (t !== undefined) return save(t)
@@ -336,7 +365,7 @@ function saveActorAndServerAndModelIfNotExist (
 
     // Force the actor creation, sometimes Sequelize skips the save() when it thinks the instance already exists
     // (which could be false in a retried query)
-    const [ actorCreated ] = await ActorModel.findOrCreate({
+    const [ actorCreated ] = await ActorModel.findOrCreate<MActorFullActor>({
       defaults: actor.toJSON(),
       where: {
         url: actor.url
@@ -345,10 +374,10 @@ function saveActorAndServerAndModelIfNotExist (
     })
 
     if (actorCreated.type === 'Person' || actorCreated.type === 'Application') {
-      actorCreated.Account = await saveAccount(actorCreated, result, t)
+      actorCreated.Account = await saveAccount(actorCreated, result, t) as MAccountActorDefault
       actorCreated.Account.Actor = actorCreated
     } else if (actorCreated.type === 'Group') { // Video channel
-      actorCreated.VideoChannel = await saveVideoChannel(actorCreated, result, ownerActor, t)
+      actorCreated.VideoChannel = await saveVideoChannel(actorCreated, result, ownerActor, t) as MChannelActorAccountDefault
       actorCreated.VideoChannel.Actor = actorCreated
       actorCreated.VideoChannel.Account = ownerActor.Account
     }
@@ -360,7 +389,7 @@ function saveActorAndServerAndModelIfNotExist (
 }
 
 type FetchRemoteActorResult = {
-  actor: ActorModel
+  actor: MActor
   name: string
   summary: string
   support?: string
@@ -429,7 +458,7 @@ async function fetchRemoteActor (actorUrl: string): Promise<{ statusCode?: numbe
   }
 }
 
-async function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t: Transaction) {
+async function saveAccount (actor: MActorId, result: FetchRemoteActorResult, t: Transaction) {
   const [ accountCreated ] = await AccountModel.findOrCreate({
     defaults: {
       name: result.name,
@@ -442,10 +471,10 @@ async function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t
     transaction: t
   })
 
-  return accountCreated
+  return accountCreated as MAccount
 }
 
-async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResult, ownerActor: ActorModel, t: Transaction) {
+async function saveVideoChannel (actor: MActorId, result: FetchRemoteActorResult, ownerActor: MActorAccountId, t: Transaction) {
   const [ videoChannelCreated ] = await VideoChannelModel.findOrCreate({
     defaults: {
       name: result.name,
@@ -460,5 +489,5 @@ async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResu
     transaction: t
   })
 
-  return videoChannelCreated
+  return videoChannelCreated as MChannel
 }
index 0e3d78590dfa78be4bc1a65a9a3a9a1f18e2d61e..f2ab54cf7fd1895c4a866c81b343512f11aeae17 100644 (file)
@@ -3,11 +3,10 @@ import { ActivityAudience } from '../../../shared/models/activitypub'
 import { ACTIVITY_PUB } from '../../initializers/constants'
 import { ActorModel } from '../../models/activitypub/actor'
 import { VideoModel } from '../../models/video/video'
-import { VideoCommentModel } from '../../models/video/video-comment'
 import { VideoShareModel } from '../../models/video/video-share'
-import { ActorModelOnly } from '../../typings/models'
+import { MActorFollowersUrl, MActorLight, MCommentOwner, MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../../typings/models'
 
-function getRemoteVideoAudience (video: VideoModel, actorsInvolvedInVideo: ActorModel[]): ActivityAudience {
+function getRemoteVideoAudience (video: MVideoAccountLight, actorsInvolvedInVideo: MActorFollowersUrl[]): ActivityAudience {
   return {
     to: [ video.VideoChannel.Account.Actor.url ],
     cc: actorsInvolvedInVideo.map(a => a.followersUrl)
@@ -15,9 +14,9 @@ function getRemoteVideoAudience (video: VideoModel, actorsInvolvedInVideo: Actor
 }
 
 function getVideoCommentAudience (
-  videoComment: VideoCommentModel,
-  threadParentComments: VideoCommentModel[],
-  actorsInvolvedInVideo: ActorModel[],
+  videoComment: MCommentOwnerVideo,
+  threadParentComments: MCommentOwner[],
+  actorsInvolvedInVideo: MActorFollowersUrl[],
   isOrigin = false
 ): ActivityAudience {
   const to = [ ACTIVITY_PUB.PUBLIC ]
@@ -42,26 +41,28 @@ function getVideoCommentAudience (
   }
 }
 
-function getAudienceFromFollowersOf (actorsInvolvedInObject: ActorModel[]): ActivityAudience {
+function getAudienceFromFollowersOf (actorsInvolvedInObject: MActorFollowersUrl[]): ActivityAudience {
   return {
     to: [ ACTIVITY_PUB.PUBLIC ].concat(actorsInvolvedInObject.map(a => a.followersUrl)),
     cc: []
   }
 }
 
-async function getActorsInvolvedInVideo (video: VideoModel, t: Transaction) {
-  const actors = await VideoShareModel.loadActorsByShare(video.id, t)
+async function getActorsInvolvedInVideo (video: MVideo, t: Transaction) {
+  const actors: MActorLight[] = await VideoShareModel.loadActorsByShare(video.id, t)
 
-  const videoActor = video.VideoChannel && video.VideoChannel.Account
-    ? video.VideoChannel.Account.Actor
-    : await ActorModel.loadAccountActorByVideoId(video.id, t)
+  const videoAll = video as VideoModel
+
+  const videoActor = videoAll.VideoChannel && videoAll.VideoChannel.Account
+    ? videoAll.VideoChannel.Account.Actor
+    : await ActorModel.loadFromAccountByVideoId(video.id, t)
 
   actors.push(videoActor)
 
   return actors
 }
 
-function getAudience (actorSender: ActorModelOnly, isPublic = true) {
+function getAudience (actorSender: MActorFollowersUrl, isPublic = true) {
   return buildAudience([ actorSender.followersUrl ], isPublic)
 }
 
index de5cc54accc5fddf9677cb40888a2914a5fa5b12..65b2dcb494d337317fb380276c0cb49eaac4c809 100644 (file)
@@ -1,10 +1,10 @@
 import { CacheFileObject } from '../../../shared/index'
-import { VideoModel } from '../../models/video/video'
 import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy'
 import { Transaction } from 'sequelize'
 import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type'
+import { MActorId, MVideoRedundancy, MVideoWithAllFiles } from '@server/typings/models'
 
-function cacheFileActivityObjectToDBAttributes (cacheFileObject: CacheFileObject, video: VideoModel, byActor: { id?: number }) {
+function cacheFileActivityObjectToDBAttributes (cacheFileObject: CacheFileObject, video: MVideoWithAllFiles, byActor: MActorId) {
 
   if (cacheFileObject.url.mediaType === 'application/x-mpegURL') {
     const url = cacheFileObject.url
@@ -39,7 +39,7 @@ function cacheFileActivityObjectToDBAttributes (cacheFileObject: CacheFileObject
   }
 }
 
-async function createOrUpdateCacheFile (cacheFileObject: CacheFileObject, video: VideoModel, byActor: { id?: number }, t: Transaction) {
+async function createOrUpdateCacheFile (cacheFileObject: CacheFileObject, video: MVideoWithAllFiles, byActor: MActorId, t: Transaction) {
   const redundancyModel = await VideoRedundancyModel.loadByUrl(cacheFileObject.id, t)
 
   if (!redundancyModel) {
@@ -49,7 +49,7 @@ async function createOrUpdateCacheFile (cacheFileObject: CacheFileObject, video:
   }
 }
 
-function createCacheFile (cacheFileObject: CacheFileObject, video: VideoModel, byActor: { id?: number }, t: Transaction) {
+function createCacheFile (cacheFileObject: CacheFileObject, video: MVideoWithAllFiles, byActor: MActorId, t: Transaction) {
   const attributes = cacheFileActivityObjectToDBAttributes(cacheFileObject, video, byActor)
 
   return VideoRedundancyModel.create(attributes, { transaction: t })
@@ -57,9 +57,9 @@ function createCacheFile (cacheFileObject: CacheFileObject, video: VideoModel, b
 
 function updateCacheFile (
   cacheFileObject: CacheFileObject,
-  redundancyModel: VideoRedundancyModel,
-  video: VideoModel,
-  byActor: { id?: number },
+  redundancyModel: MVideoRedundancy,
+  video: MVideoWithAllFiles,
+  byActor: MActorId,
   t: Transaction
 ) {
   if (redundancyModel.actorId !== byActor.id) {
index c2e2a3283fe5e9fc16d0f73b3b616bec5a881ea4..c52b715ef212a9a942767f71b124edfbf67f9f5f 100644 (file)
@@ -1,7 +1,6 @@
 import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object'
 import { crawlCollectionPage } from './crawl'
 import { ACTIVITY_PUB, CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants'
-import { AccountModel } from '../../models/account/account'
 import { isArray } from '../../helpers/custom-validators/misc'
 import { getOrCreateActorAndServerAndModel } from './actor'
 import { logger } from '../../helpers/logger'
@@ -13,14 +12,14 @@ import { PlaylistElementObject } from '../../../shared/models/activitypub/object
 import { getOrCreateVideoAndAccountAndChannel } from './videos'
 import { isPlaylistElementObjectValid, isPlaylistObjectValid } from '../../helpers/custom-validators/activitypub/playlist'
 import { VideoPlaylistElementModel } from '../../models/video/video-playlist-element'
-import { VideoModel } from '../../models/video/video'
 import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
 import { sequelizeTypescript } from '../../initializers/database'
 import { createPlaylistMiniatureFromUrl } from '../thumbnail'
 import { FilteredModelAttributes } from '../../typings/sequelize'
-import { AccountModelId } from '../../typings/models'
+import { MAccountDefault, MAccountId, MVideoId } from '../../typings/models'
+import { MVideoPlaylist, MVideoPlaylistId, MVideoPlaylistOwner } from '../../typings/models/video/video-playlist'
 
-function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: AccountModelId, to: string[]) {
+function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: MAccountId, to: string[]) {
   const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPlaylistPrivacy.PUBLIC : VideoPlaylistPrivacy.UNLISTED
 
   return {
@@ -36,7 +35,7 @@ function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount
   }
 }
 
-function playlistElementObjectToDBAttributes (elementObject: PlaylistElementObject, videoPlaylist: VideoPlaylistModel, video: VideoModel) {
+function playlistElementObjectToDBAttributes (elementObject: PlaylistElementObject, videoPlaylist: MVideoPlaylistId, video: MVideoId) {
   return {
     position: elementObject.position,
     url: elementObject.id,
@@ -47,7 +46,7 @@ function playlistElementObjectToDBAttributes (elementObject: PlaylistElementObje
   }
 }
 
-async function createAccountPlaylists (playlistUrls: string[], account: AccountModel) {
+async function createAccountPlaylists (playlistUrls: string[], account: MAccountDefault) {
   await Bluebird.map(playlistUrls, async playlistUrl => {
     try {
       const exists = await VideoPlaylistModel.doesPlaylistExist(playlistUrl)
@@ -75,7 +74,7 @@ async function createAccountPlaylists (playlistUrls: string[], account: AccountM
   }, { concurrency: CRAWL_REQUEST_CONCURRENCY })
 }
 
-async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAccount: AccountModelId, to: string[]) {
+async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAccount: MAccountId, to: string[]) {
   const playlistAttributes = playlistObjectToDBAttributes(playlistObject, byAccount, to)
 
   if (isArray(playlistObject.attributedTo) && playlistObject.attributedTo.length === 1) {
@@ -88,7 +87,7 @@ async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAc
     }
   }
 
-  const [ playlist ] = await VideoPlaylistModel.upsert<VideoPlaylistModel>(playlistAttributes, { returning: true })
+  const [ playlist ] = await VideoPlaylistModel.upsert<MVideoPlaylist>(playlistAttributes, { returning: true })
 
   let accItems: string[] = []
   await crawlCollectionPage<string>(playlistObject.id, items => {
@@ -114,7 +113,7 @@ async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAc
   return resetVideoPlaylistElements(accItems, refreshedPlaylist)
 }
 
-async function refreshVideoPlaylistIfNeeded (videoPlaylist: VideoPlaylistModel): Promise<VideoPlaylistModel> {
+async function refreshVideoPlaylistIfNeeded (videoPlaylist: MVideoPlaylistOwner): Promise<MVideoPlaylistOwner> {
   if (!videoPlaylist.isOutdated()) return videoPlaylist
 
   try {
@@ -157,7 +156,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function resetVideoPlaylistElements (elementUrls: string[], playlist: VideoPlaylistModel) {
+async function resetVideoPlaylistElements (elementUrls: string[], playlist: MVideoPlaylist) {
   const elementsToCreate: FilteredModelAttributes<VideoPlaylistElementModel>[] = []
 
   await Bluebird.map(elementUrls, async elementUrl => {
index cf27e6c32e6e5280684c05c85674e73545ebcdb7..86f7c764db163b93e7b6b3eca3fc0229c2faf2c5 100644 (file)
@@ -1,9 +1,8 @@
 import { ActivityAccept } from '../../../../shared/models/activitypub'
-import { ActorModel } from '../../../models/activitypub/actor'
 import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
 import { addFetchOutboxJob } from '../actor'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorDefault, MActorSignature } from '../../../typings/models'
 
 async function processAcceptActivity (options: APProcessorOptions<ActivityAccept>) {
   const { byActor: targetActor, inboxActor } = options
@@ -20,7 +19,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processAccept (actor: ActorModel, targetActor: SignatureActorModel) {
+async function processAccept (actor: MActorDefault, targetActor: MActorSignature) {
   const follow = await ActorFollowModel.loadByActorAndTarget(actor.id, targetActor.id)
   if (!follow) throw new Error('Cannot find associated follow.')
 
index b3cdc4441cb0dbe9d8db63e3e376e6a33b3ed712..91a9ad72c3f4b7a50b06c167f175d49252dc89d2 100644 (file)
@@ -5,10 +5,9 @@ import { VideoShareModel } from '../../../models/video/video-share'
 import { forwardVideoRelatedActivity } from '../send/utils'
 import { getOrCreateVideoAndAccountAndChannel } from '../videos'
 import { Notifier } from '../../notifier'
-import { VideoModel } from '../../../models/video/video'
 import { logger } from '../../../helpers/logger'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorSignature, MVideoAccountAllFiles } from '../../../typings/models'
 
 async function processAnnounceActivity (options: APProcessorOptions<ActivityAnnounce>) {
   const { activity, byActor: actorAnnouncer } = options
@@ -26,10 +25,10 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processVideoShare (actorAnnouncer: SignatureActorModel, activity: ActivityAnnounce, notify: boolean) {
+async function processVideoShare (actorAnnouncer: MActorSignature, activity: ActivityAnnounce, notify: boolean) {
   const objectUri = typeof activity.object === 'string' ? activity.object : activity.object.id
 
-  let video: VideoModel
+  let video: MVideoAccountAllFiles
   let videoCreated: boolean
 
   try {
index 6815c6997399398aed1bdd055d94332ccaa3f90b..c45f09f52fd9eea5acee483348e00a9dc039a4a7 100644 (file)
@@ -10,10 +10,8 @@ import { createOrUpdateCacheFile } from '../cache-file'
 import { Notifier } from '../../notifier'
 import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
 import { createOrUpdateVideoPlaylist } from '../playlist'
-import { VideoModel } from '../../../models/video/video'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { VideoCommentModel } from '../../../models/video/video-comment'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorSignature, MCommentOwnerVideo, MVideoAccountAllFiles } from '../../../typings/models'
 
 async function processCreateActivity (options: APProcessorOptions<ActivityCreate>) {
   const { activity, byActor } = options
@@ -61,7 +59,7 @@ async function processCreateVideo (activity: ActivityCreate, notify: boolean) {
   return video
 }
 
-async function processCreateCacheFile (activity: ActivityCreate, byActor: SignatureActorModel) {
+async function processCreateCacheFile (activity: ActivityCreate, byActor: MActorSignature) {
   const cacheFile = activity.object as CacheFileObject
 
   const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: cacheFile.object })
@@ -77,15 +75,15 @@ async function processCreateCacheFile (activity: ActivityCreate, byActor: Signat
   }
 }
 
-async function processCreateVideoComment (activity: ActivityCreate, byActor: SignatureActorModel, notify: boolean) {
+async function processCreateVideoComment (activity: ActivityCreate, byActor: MActorSignature, notify: boolean) {
   const commentObject = activity.object as VideoCommentObject
   const byAccount = byActor.Account
 
   if (!byAccount) throw new Error('Cannot create video comment with the non account actor ' + byActor.url)
 
-  let video: VideoModel
+  let video: MVideoAccountAllFiles
   let created: boolean
-  let comment: VideoCommentModel
+  let comment: MCommentOwnerVideo
   try {
     const resolveThreadResult = await resolveThread({ url: commentObject.id, isVideo: false })
     video = resolveThreadResult.video
@@ -110,7 +108,7 @@ async function processCreateVideoComment (activity: ActivityCreate, byActor: Sig
   if (created && notify) Notifier.Instance.notifyOnNewComment(comment)
 }
 
-async function processCreatePlaylist (activity: ActivityCreate, byActor: SignatureActorModel) {
+async function processCreatePlaylist (activity: ActivityCreate, byActor: MActorSignature) {
   const playlistObject = activity.object as PlaylistObject
   const byAccount = byActor.Account
 
index 344d14322686b9bedd77a541fb3a563302fe8004..79d0e0d79424901d8226f7a3b9ba8ab664b92cc2 100644 (file)
@@ -2,15 +2,13 @@ import { ActivityDelete } from '../../../../shared/models/activitypub'
 import { retryTransactionWrapper } from '../../../helpers/database-utils'
 import { logger } from '../../../helpers/logger'
 import { sequelizeTypescript } from '../../../initializers'
-import { AccountModel } from '../../../models/account/account'
 import { ActorModel } from '../../../models/activitypub/actor'
 import { VideoModel } from '../../../models/video/video'
-import { VideoChannelModel } from '../../../models/video/video-channel'
 import { VideoCommentModel } from '../../../models/video/video-comment'
 import { forwardVideoRelatedActivity } from '../send/utils'
 import { VideoPlaylistModel } from '../../../models/video/video-playlist'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MAccountActor, MActor, MActorSignature, MChannelActor, MChannelActorAccountActor } from '../../../typings/models'
 
 async function processDeleteActivity (options: APProcessorOptions<ActivityDelete>) {
   const { activity, byActor } = options
@@ -24,13 +22,17 @@ async function processDeleteActivity (options: APProcessorOptions<ActivityDelete
     if (byActorFull.type === 'Person') {
       if (!byActorFull.Account) throw new Error('Actor ' + byActorFull.url + ' is a person but we cannot find it in database.')
 
-      byActorFull.Account.Actor = await byActorFull.Account.$get('Actor') as ActorModel
-      return retryTransactionWrapper(processDeleteAccount, byActorFull.Account)
+      const accountToDelete = byActorFull.Account as MAccountActor
+      accountToDelete.Actor = byActorFull
+
+      return retryTransactionWrapper(processDeleteAccount, accountToDelete)
     } else if (byActorFull.type === 'Group') {
       if (!byActorFull.VideoChannel) throw new Error('Actor ' + byActorFull.url + ' is a group but we cannot find it in database.')
 
-      byActorFull.VideoChannel.Actor = await byActorFull.VideoChannel.$get('Actor') as ActorModel
-      return retryTransactionWrapper(processDeleteVideoChannel, byActorFull.VideoChannel)
+      const channelToDelete = byActorFull.VideoChannel as MChannelActorAccountActor
+      channelToDelete.Actor = byActorFull
+
+      return retryTransactionWrapper(processDeleteVideoChannel, channelToDelete)
     }
   }
 
@@ -70,7 +72,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processDeleteVideo (actor: ActorModel, videoToDelete: VideoModel) {
+async function processDeleteVideo (actor: MActor, videoToDelete: VideoModel) {
   logger.debug('Removing remote video "%s".', videoToDelete.uuid)
 
   await sequelizeTypescript.transaction(async t => {
@@ -84,7 +86,7 @@ async function processDeleteVideo (actor: ActorModel, videoToDelete: VideoModel)
   logger.info('Remote video with uuid %s removed.', videoToDelete.uuid)
 }
 
-async function processDeleteVideoPlaylist (actor: ActorModel, playlistToDelete: VideoPlaylistModel) {
+async function processDeleteVideoPlaylist (actor: MActor, playlistToDelete: VideoPlaylistModel) {
   logger.debug('Removing remote video playlist "%s".', playlistToDelete.uuid)
 
   await sequelizeTypescript.transaction(async t => {
@@ -98,7 +100,7 @@ async function processDeleteVideoPlaylist (actor: ActorModel, playlistToDelete:
   logger.info('Remote video playlist with uuid %s removed.', playlistToDelete.uuid)
 }
 
-async function processDeleteAccount (accountToRemove: AccountModel) {
+async function processDeleteAccount (accountToRemove: MAccountActor) {
   logger.debug('Removing remote account "%s".', accountToRemove.Actor.url)
 
   await sequelizeTypescript.transaction(async t => {
@@ -108,7 +110,7 @@ async function processDeleteAccount (accountToRemove: AccountModel) {
   logger.info('Remote account %s removed.', accountToRemove.Actor.url)
 }
 
-async function processDeleteVideoChannel (videoChannelToRemove: VideoChannelModel) {
+async function processDeleteVideoChannel (videoChannelToRemove: MChannelActor) {
   logger.debug('Removing remote video channel "%s".', videoChannelToRemove.Actor.url)
 
   await sequelizeTypescript.transaction(async t => {
@@ -118,7 +120,7 @@ async function processDeleteVideoChannel (videoChannelToRemove: VideoChannelMode
   logger.info('Remote video channel %s removed.', videoChannelToRemove.Actor.url)
 }
 
-function processDeleteVideoComment (byActor: SignatureActorModel, videoComment: VideoCommentModel, activity: ActivityDelete) {
+function processDeleteVideoComment (byActor: MActorSignature, videoComment: VideoCommentModel, activity: ActivityDelete) {
   logger.debug('Removing remote video comment "%s".', videoComment.url)
 
   return sequelizeTypescript.transaction(async t => {
index 727fcfee0c7bef041f9a9b0567e2b7a39948d581..debd8a67ca43d4346d6b2d8e28761fd479f32733 100644 (file)
@@ -7,7 +7,7 @@ import { getOrCreateVideoAndAccountAndChannel } from '../videos'
 import { forwardVideoRelatedActivity } from '../send/utils'
 import { getVideoDislikeActivityPubUrl } from '../url'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorSignature } from '../../../typings/models'
 
 async function processDislikeActivity (options: APProcessorOptions<ActivityCreate | ActivityDislike>) {
   const { activity, byActor } = options
@@ -22,7 +22,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processDislike (activity: ActivityCreate | ActivityDislike, byActor: SignatureActorModel) {
+async function processDislike (activity: ActivityCreate | ActivityDislike, byActor: MActorSignature) {
   const dislikeObject = activity.type === 'Dislike' ? activity.object : (activity.object as DislikeObject).object
   const byAccount = byActor.Account
 
index 1f8a80c140bb29758c718971d75a20ffda9696ad..422386540fc635184a8eadb6053726344d098193 100644 (file)
@@ -8,7 +8,7 @@ import { getOrCreateVideoAndAccountAndChannel } from '../videos'
 import { Notifier } from '../../notifier'
 import { getAPId } from '../../../helpers/activitypub'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorSignature, MVideoAbuseVideo } from '../../../typings/models'
 
 async function processFlagActivity (options: APProcessorOptions<ActivityCreate | ActivityFlag>) {
   const { activity, byActor } = options
@@ -23,7 +23,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processCreateVideoAbuse (activity: ActivityCreate | ActivityFlag, byActor: SignatureActorModel) {
+async function processCreateVideoAbuse (activity: ActivityCreate | ActivityFlag, byActor: MActorSignature) {
   const flag = activity.type === 'Flag' ? activity : (activity.object as VideoAbuseObject)
 
   logger.debug('Reporting remote abuse for video %s.', getAPId(flag.object))
@@ -41,7 +41,7 @@ async function processCreateVideoAbuse (activity: ActivityCreate | ActivityFlag,
       state: VideoAbuseState.PENDING
     }
 
-    const videoAbuseInstance = await VideoAbuseModel.create(videoAbuseData, { transaction: t })
+    const videoAbuseInstance = await VideoAbuseModel.create(videoAbuseData, { transaction: t }) as MVideoAbuseVideo
     videoAbuseInstance.Video = video
 
     logger.info('Remote abuse for video uuid %s created', flag.object)
index 240aa57998bbaaf09ecf4cce846434326365b5d8..bc5660395ae92a78df35544e50fb0b4b7b0394bf 100644 (file)
@@ -10,8 +10,7 @@ import { getAPId } from '../../../helpers/activitypub'
 import { getServerActor } from '../../../helpers/utils'
 import { CONFIG } from '../../../initializers/config'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
-import { ActorFollowModelLight } from '../../../typings/models/actor-follow'
+import { MAccount, MActorFollowActors, MActorFollowFull, MActorSignature } from '../../../typings/models'
 
 async function processFollowActivity (options: APProcessorOptions<ActivityFollow>) {
   const { activity, byActor } = options
@@ -28,7 +27,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processFollow (byActor: SignatureActorModel, targetActorURL: string) {
+async function processFollow (byActor: MActorSignature, targetActorURL: string) {
   const { actorFollow, created, isFollowingInstance } = await sequelizeTypescript.transaction(async t => {
     const targetActor = await ActorModel.loadByUrlAndPopulateAccountAndChannel(targetActorURL, t)
 
@@ -43,10 +42,10 @@ async function processFollow (byActor: SignatureActorModel, targetActorURL: stri
 
       await sendReject(byActor, targetActor)
 
-      return { actorFollow: undefined }
+      return { actorFollow: undefined as MActorFollowActors }
     }
 
-    const [ actorFollow, created ] = await ActorFollowModel.findOrCreate({
+    const [ actorFollow, created ] = await ActorFollowModel.findOrCreate<MActorFollowActors>({
       where: {
         actorId: byActor.id,
         targetActorId: targetActor.id
@@ -57,7 +56,7 @@ async function processFollow (byActor: SignatureActorModel, targetActorURL: stri
         state: CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL ? 'pending' : 'accepted'
       },
       transaction: t
-    }) as [ ActorFollowModelLight, boolean ]
+    })
 
     if (actorFollow.state !== 'accepted' && CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL === false) {
       actorFollow.state = 'accepted'
@@ -77,8 +76,14 @@ async function processFollow (byActor: SignatureActorModel, targetActorURL: stri
   if (!actorFollow) return
 
   if (created) {
-    if (isFollowingInstance) Notifier.Instance.notifyOfNewInstanceFollow(actorFollow)
-    else Notifier.Instance.notifyOfNewUserFollow(actorFollow)
+    if (isFollowingInstance) {
+      Notifier.Instance.notifyOfNewInstanceFollow(actorFollow)
+    } else {
+      const actorFollowFull = actorFollow as MActorFollowFull
+      actorFollowFull.ActorFollower.Account = await actorFollow.ActorFollower.$get('Account') as MAccount
+
+      Notifier.Instance.notifyOfNewUserFollow(actorFollowFull)
+    }
   }
 
   logger.info('Actor %s is followed by actor %s.', targetActorURL, byActor.url)
index cf559af721c4c65b816ce60acbf8f913f1ecf863..62be0de42f30aa82b076f6d41e64539f5effcc1a 100644 (file)
@@ -7,7 +7,7 @@ import { getOrCreateVideoAndAccountAndChannel } from '../videos'
 import { getVideoLikeActivityPubUrl } from '../url'
 import { getAPId } from '../../../helpers/activitypub'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorSignature } from '../../../typings/models'
 
 async function processLikeActivity (options: APProcessorOptions<ActivityLike>) {
   const { activity, byActor } = options
@@ -22,7 +22,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processLikeVideo (byActor: SignatureActorModel, activity: ActivityLike) {
+async function processLikeVideo (byActor: MActorSignature, activity: ActivityLike) {
   const videoUrl = getAPId(activity.object)
 
   const byAccount = byActor.Account
index 22e311cebf1e6bc9151b15d9c89c0e0c7b17c206..00e9afa109035443b328617d550e2c87e4e149dc 100644 (file)
@@ -2,7 +2,7 @@ import { ActivityReject } from '../../../../shared/models/activitypub/activity'
 import { sequelizeTypescript } from '../../../initializers'
 import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { ActorModelOnly } from '../../../typings/models'
+import { MActor } from '../../../typings/models'
 
 async function processRejectActivity (options: APProcessorOptions<ActivityReject>) {
   const { byActor: targetActor, inboxActor } = options
@@ -19,7 +19,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processReject (follower: ActorModelOnly, targetActor: ActorModelOnly) {
+async function processReject (follower: MActor, targetActor: MActor) {
   return sequelizeTypescript.transaction(async t => {
     const actorFollow = await ActorFollowModel.loadByActorAndTarget(follower.id, targetActor.id, t)
 
index c37ee38bb7b008e8ac82f345798c810b72c2d4fb..10643b2e99d9210535aa5998740abea0d479d4f1 100644 (file)
@@ -11,7 +11,7 @@ import { getOrCreateVideoAndAccountAndChannel } from '../videos'
 import { VideoShareModel } from '../../../models/video/video-share'
 import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorSignature } from '../../../typings/models'
 
 async function processUndoActivity (options: APProcessorOptions<ActivityUndo>) {
   const { activity, byActor } = options
@@ -54,7 +54,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processUndoLike (byActor: SignatureActorModel, activity: ActivityUndo) {
+async function processUndoLike (byActor: MActorSignature, activity: ActivityUndo) {
   const likeActivity = activity.object as ActivityLike
 
   const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: likeActivity.object })
@@ -77,7 +77,7 @@ async function processUndoLike (byActor: SignatureActorModel, activity: Activity
   })
 }
 
-async function processUndoDislike (byActor: SignatureActorModel, activity: ActivityUndo) {
+async function processUndoDislike (byActor: MActorSignature, activity: ActivityUndo) {
   const dislike = activity.object.type === 'Dislike'
     ? activity.object
     : activity.object.object as DislikeObject
@@ -102,7 +102,7 @@ async function processUndoDislike (byActor: SignatureActorModel, activity: Activ
   })
 }
 
-async function processUndoCacheFile (byActor: SignatureActorModel, activity: ActivityUndo) {
+async function processUndoCacheFile (byActor: MActorSignature, activity: ActivityUndo) {
   const cacheFileObject = activity.object.object as CacheFileObject
 
   const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: cacheFileObject.object })
@@ -127,7 +127,7 @@ async function processUndoCacheFile (byActor: SignatureActorModel, activity: Act
   })
 }
 
-function processUndoFollow (follower: SignatureActorModel, followActivity: ActivityFollow) {
+function processUndoFollow (follower: MActorSignature, followActivity: ActivityFollow) {
   return sequelizeTypescript.transaction(async t => {
     const following = await ActorModel.loadByUrlAndPopulateAccountAndChannel(followActivity.object, t)
     const actorFollow = await ActorFollowModel.loadByActorAndTarget(follower.id, following.id, t)
@@ -140,7 +140,7 @@ function processUndoFollow (follower: SignatureActorModel, followActivity: Activ
   })
 }
 
-function processUndoAnnounce (byActor: SignatureActorModel, announceActivity: ActivityAnnounce) {
+function processUndoAnnounce (byActor: MActorSignature, announceActivity: ActivityAnnounce) {
   return sequelizeTypescript.transaction(async t => {
     const share = await VideoShareModel.loadByUrl(announceActivity.id, t)
     if (!share) throw new Error(`Unknown video share ${announceActivity.id}.`)
index 414f9e375762d81c0b0185b8e79924a7b6a28102..9f80a0ce9cb95219637d435b6caf4666b10d3bee 100644 (file)
@@ -15,7 +15,7 @@ import { forwardVideoRelatedActivity } from '../send/utils'
 import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
 import { createOrUpdateVideoPlaylist } from '../playlist'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorSignature } from '../../../typings/models'
 
 async function processUpdateActivity (options: APProcessorOptions<ActivityUpdate>) {
   const { activity, byActor } = options
@@ -53,7 +53,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processUpdateVideo (actor: SignatureActorModel, activity: ActivityUpdate) {
+async function processUpdateVideo (actor: MActorSignature, activity: ActivityUpdate) {
   const videoObject = activity.object as VideoTorrentObject
 
   if (sanitizeAndCheckVideoTorrentObject(videoObject) === false) {
@@ -61,20 +61,20 @@ async function processUpdateVideo (actor: SignatureActorModel, activity: Activit
     return undefined
   }
 
-  const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoObject.id, allowRefresh: false })
+  const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoObject.id, allowRefresh: false, fetchType: 'all' })
   const channelActor = await getOrCreateVideoChannelFromVideoObject(videoObject)
 
   const updateOptions = {
     video,
     videoObject,
-    account: actor.Account,
+    account: channelActor.VideoChannel.Account,
     channel: channelActor.VideoChannel,
     overrideTo: activity.to
   }
   return updateVideoFromAP(updateOptions)
 }
 
-async function processUpdateCacheFile (byActor: SignatureActorModel, activity: ActivityUpdate) {
+async function processUpdateCacheFile (byActor: MActorSignature, activity: ActivityUpdate) {
   const cacheFileObject = activity.object as CacheFileObject
 
   if (!isCacheFileObjectValid(cacheFileObject)) {
@@ -150,7 +150,7 @@ async function processUpdateActor (actor: ActorModel, activity: ActivityUpdate)
   }
 }
 
-async function processUpdatePlaylist (byActor: SignatureActorModel, activity: ActivityUpdate) {
+async function processUpdatePlaylist (byActor: MActorSignature, activity: ActivityUpdate) {
   const playlistObject = activity.object as PlaylistObject
   const byAccount = byActor.Account
 
index e4997b8282a492d606e56cca6cf08d0bb3cab5d1..df29ee968b85fe7c22fd20c6eed427683fa1a2e8 100644 (file)
@@ -3,7 +3,7 @@ import { forwardVideoRelatedActivity } from '../send/utils'
 import { Redis } from '../../redis'
 import { ActivityCreate, ActivityView, ViewObject } from '../../../../shared/models/activitypub'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorSignature } from '../../../typings/models'
 
 async function processViewActivity (options: APProcessorOptions<ActivityCreate | ActivityView>) {
   const { activity, byActor } = options
@@ -18,11 +18,11 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function processCreateView (activity: ActivityView | ActivityCreate, byActor: SignatureActorModel) {
+async function processCreateView (activity: ActivityView | ActivityCreate, byActor: MActorSignature) {
   const videoObject = activity.type === 'View' ? activity.object : (activity.object as ViewObject).object
 
   const options = {
-    videoObject: videoObject,
+    videoObject,
     fetchType: 'only-video' as 'only-video'
   }
   const { video } = await getOrCreateVideoAndAccountAndChannel(options)
index d108fe321b4e9a59c88bdaccf42c88ace93d0628..c602bf2181edf6f2fc45df13bbc32b443a63b44a 100644 (file)
@@ -1,7 +1,6 @@
 import { Activity, ActivityType } from '../../../../shared/models/activitypub'
 import { checkUrlsSameHost, getAPId } from '../../../helpers/activitypub'
 import { logger } from '../../../helpers/logger'
-import { ActorModel } from '../../../models/activitypub/actor'
 import { processAcceptActivity } from './process-accept'
 import { processAnnounceActivity } from './process-announce'
 import { processCreateActivity } from './process-create'
@@ -16,7 +15,7 @@ import { processDislikeActivity } from './process-dislike'
 import { processFlagActivity } from './process-flag'
 import { processViewActivity } from './process-view'
 import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActorDefault, MActorSignature } from '../../../typings/models'
 
 const processActivity: { [ P in ActivityType ]: (options: APProcessorOptions<Activity>) => Promise<any> } = {
   Create: processCreateActivity,
@@ -36,15 +35,15 @@ const processActivity: { [ P in ActivityType ]: (options: APProcessorOptions<Act
 async function processActivities (
   activities: Activity[],
   options: {
-    signatureActor?: SignatureActorModel
-    inboxActor?: ActorModel
+    signatureActor?: MActorSignature
+    inboxActor?: MActorDefault
     outboxUrl?: string
     fromFetch?: boolean
   } = {}
 ) {
   const { outboxUrl, signatureActor, inboxActor, fromFetch = false } = options
 
-  const actorsCache: { [ url: string ]: SignatureActorModel } = {}
+  const actorsCache: { [ url: string ]: MActorSignature } = {}
 
   for (const activity of activities) {
     if (!signatureActor && [ 'Create', 'Announce', 'Like' ].includes(activity.type) === false) {
@@ -75,7 +74,7 @@ async function processActivities (
     }
 
     try {
-      await activityProcessor({ activity, byActor, inboxActor: inboxActor, fromFetch })
+      await activityProcessor({ activity, byActor, inboxActor, fromFetch })
     } catch (err) {
       logger.warn('Cannot process activity %s.', activity.type, { err })
     }
index 813c42e15dc643e2270369c6f970bdba45a6ad7a..9f0225b644746bf8e20421d86f831d8ddba191ab 100644 (file)
@@ -3,10 +3,9 @@ import { getActorFollowAcceptActivityPubUrl, getActorFollowActivityPubUrl } from
 import { unicastTo } from './utils'
 import { buildFollowActivity } from './send-follow'
 import { logger } from '../../../helpers/logger'
-import { ActorFollowModelLight } from '../../../typings/models/actor-follow'
-import { ActorModelOnly } from '../../../typings/models'
+import { MActor, MActorFollowActors } from '../../../typings/models'
 
-async function sendAccept (actorFollow: ActorFollowModelLight) {
+async function sendAccept (actorFollow: MActorFollowActors) {
   const follower = actorFollow.ActorFollower
   const me = actorFollow.ActorFollowing
 
@@ -34,7 +33,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function buildAcceptActivity (url: string, byActor: ActorModelOnly, followActivityData: ActivityFollow): ActivityAccept {
+function buildAcceptActivity (url: string, byActor: MActor, followActivityData: ActivityFollow): ActivityAccept {
   return {
     type: 'Accept',
     id: url,
index 7fe4ca180f5f46b9e53b8a9e503b1982e56b55b1..a0f33852ca79a7a8a07b0f26037db975c30274a5 100644 (file)
@@ -1,16 +1,15 @@
 import { Transaction } from 'sequelize'
 import { ActivityAnnounce, ActivityAudience } from '../../../../shared/models/activitypub'
-import { VideoModel } from '../../../models/video/video'
 import { broadcastToFollowers } from './utils'
 import { audiencify, getActorsInvolvedInVideo, getAudience, getAudienceFromFollowersOf } from '../audience'
 import { logger } from '../../../helpers/logger'
-import { ActorModelOnly } from '../../../typings/models'
-import { VideoShareModelOnly } from '../../../typings/models/video-share'
+import { MActorLight, MVideo } from '../../../typings/models'
+import { MVideoShare } from '../../../typings/models/video'
 
 async function buildAnnounceWithVideoAudience (
-  byActor: ActorModelOnly,
-  videoShare: VideoShareModelOnly,
-  video: VideoModel,
+  byActor: MActorLight,
+  videoShare: MVideoShare,
+  video: MVideo,
   t: Transaction
 ) {
   const announcedObject = video.url
@@ -23,7 +22,7 @@ async function buildAnnounceWithVideoAudience (
   return { activity, actorsInvolvedInVideo }
 }
 
-async function sendVideoAnnounce (byActor: ActorModelOnly, videoShare: VideoShareModelOnly, video: VideoModel, t: Transaction) {
+async function sendVideoAnnounce (byActor: MActorLight, videoShare: MVideoShare, video: MVideo, t: Transaction) {
   const { activity, actorsInvolvedInVideo } = await buildAnnounceWithVideoAudience(byActor, videoShare, video, t)
 
   logger.info('Creating job to send announce %s.', videoShare.url)
@@ -32,7 +31,7 @@ async function sendVideoAnnounce (byActor: ActorModelOnly, videoShare: VideoShar
   return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, t, followersException)
 }
 
-function buildAnnounceActivity (url: string, byActor: ActorModelOnly, object: string, audience?: ActivityAudience): ActivityAnnounce {
+function buildAnnounceActivity (url: string, byActor: MActorLight, object: string, audience?: ActivityAudience): ActivityAnnounce {
   if (!audience) audience = getAudience(byActor)
 
   return audiencify({
index 9c21149f20c184b34febb92f89f8029bf8b8c1ad..26ec3e94873ea619796754fd5ffc50ce3525bb9e 100644 (file)
@@ -1,19 +1,23 @@
 import { Transaction } from 'sequelize'
 import { ActivityAudience, ActivityCreate } from '../../../../shared/models/activitypub'
 import { VideoPrivacy } from '../../../../shared/models/videos'
-import { ActorModel } from '../../../models/activitypub/actor'
-import { VideoModel } from '../../../models/video/video'
 import { VideoCommentModel } from '../../../models/video/video-comment'
 import { broadcastToActors, broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils'
 import { audiencify, getActorsInvolvedInVideo, getAudience, getAudienceFromFollowersOf, getVideoCommentAudience } from '../audience'
 import { logger } from '../../../helpers/logger'
-import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
-import { VideoPlaylistModel } from '../../../models/video/video-playlist'
 import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
 import { getServerActor } from '../../../helpers/utils'
-import * as Bluebird from 'bluebird'
-
-async function sendCreateVideo (video: VideoModel, t: Transaction) {
+import {
+  MActorLight,
+  MCommentOwnerVideo,
+  MVideoAccountLight,
+  MVideoAP,
+  MVideoPlaylistFull,
+  MVideoRedundancyFileVideo,
+  MVideoRedundancyStreamingPlaylistVideo
+} from '../../../typings/models'
+
+async function sendCreateVideo (video: MVideoAP, t: Transaction) {
   if (video.privacy === VideoPrivacy.PRIVATE) return undefined
 
   logger.info('Creating job to send video creation of %s.', video.url)
@@ -27,7 +31,11 @@ async function sendCreateVideo (video: VideoModel, t: Transaction) {
   return broadcastToFollowers(createActivity, byActor, [ byActor ], t)
 }
 
-async function sendCreateCacheFile (byActor: ActorModel, video: VideoModel, fileRedundancy: VideoRedundancyModel) {
+async function sendCreateCacheFile (
+  byActor: MActorLight,
+  video: MVideoAccountLight,
+  fileRedundancy: MVideoRedundancyStreamingPlaylistVideo | MVideoRedundancyFileVideo
+) {
   logger.info('Creating job to send file cache of %s.', fileRedundancy.url)
 
   return sendVideoRelatedCreateActivity({
@@ -38,7 +46,7 @@ async function sendCreateCacheFile (byActor: ActorModel, video: VideoModel, file
   })
 }
 
-async function sendCreateVideoPlaylist (playlist: VideoPlaylistModel, t: Transaction) {
+async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, t: Transaction) {
   if (playlist.privacy === VideoPlaylistPrivacy.PRIVATE) return undefined
 
   logger.info('Creating job to send create video playlist of %s.', playlist.url)
@@ -57,7 +65,7 @@ async function sendCreateVideoPlaylist (playlist: VideoPlaylistModel, t: Transac
   return broadcastToFollowers(createActivity, byActor, toFollowersOf, t)
 }
 
-async function sendCreateVideoComment (comment: VideoCommentModel, t: Transaction) {
+async function sendCreateVideoComment (comment: MCommentOwnerVideo, t: Transaction) {
   logger.info('Creating job to send comment %s.', comment.url)
 
   const isOrigin = comment.Video.isOwned()
@@ -95,7 +103,7 @@ async function sendCreateVideoComment (comment: VideoCommentModel, t: Transactio
   t.afterCommit(() => unicastTo(createActivity, byActor, comment.Video.VideoChannel.Account.Actor.sharedInboxUrl))
 }
 
-function buildCreateActivity (url: string, byActor: ActorModel, object: any, audience?: ActivityAudience): ActivityCreate {
+function buildCreateActivity (url: string, byActor: MActorLight, object: any, audience?: ActivityAudience): ActivityCreate {
   if (!audience) audience = getAudience(byActor)
 
   return audiencify(
@@ -122,8 +130,8 @@ export {
 // ---------------------------------------------------------------------------
 
 async function sendVideoRelatedCreateActivity (options: {
-  byActor: ActorModel,
-  video: VideoModel,
+  byActor: MActorLight,
+  video: MVideoAccountLight,
   url: string,
   object: any,
   transaction?: Transaction
index 6c7fb844935365e2540a1c32f922784159d9df2c..4b1ff8dc5739345aff971016c31e2010563bca02 100644 (file)
@@ -1,17 +1,17 @@
 import { Transaction } from 'sequelize'
 import { ActivityAudience, ActivityDelete } from '../../../../shared/models/activitypub'
 import { ActorModel } from '../../../models/activitypub/actor'
-import { VideoModel } from '../../../models/video/video'
 import { VideoCommentModel } from '../../../models/video/video-comment'
 import { VideoShareModel } from '../../../models/video/video-share'
 import { getDeleteActivityPubUrl } from '../url'
 import { broadcastToActors, broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils'
 import { audiencify, getActorsInvolvedInVideo, getVideoCommentAudience } from '../audience'
 import { logger } from '../../../helpers/logger'
-import { VideoPlaylistModel } from '../../../models/video/video-playlist'
 import { getServerActor } from '../../../helpers/utils'
+import { MCommentOwnerVideoReply, MVideoAccountLight, MVideoPlaylistFullSummary } from '../../../typings/models/video'
+import { MActorUrl } from '../../../typings/models'
 
-async function sendDeleteVideo (video: VideoModel, transaction: Transaction) {
+async function sendDeleteVideo (video: MVideoAccountLight, transaction: Transaction) {
   logger.info('Creating job to broadcast delete of video %s.', video.url)
 
   const byActor = video.VideoChannel.Account.Actor
@@ -42,7 +42,7 @@ async function sendDeleteActor (byActor: ActorModel, t: Transaction) {
   return broadcastToFollowers(activity, byActor, actorsInvolved, t)
 }
 
-async function sendDeleteVideoComment (videoComment: VideoCommentModel, t: Transaction) {
+async function sendDeleteVideoComment (videoComment: MCommentOwnerVideoReply, t: Transaction) {
   logger.info('Creating job to send delete of comment %s.', videoComment.url)
 
   const isVideoOrigin = videoComment.Video.isOwned()
@@ -74,7 +74,7 @@ async function sendDeleteVideoComment (videoComment: VideoCommentModel, t: Trans
   t.afterCommit(() => unicastTo(activity, byActor, videoComment.Video.VideoChannel.Account.Actor.sharedInboxUrl))
 }
 
-async function sendDeleteVideoPlaylist (videoPlaylist: VideoPlaylistModel, t: Transaction) {
+async function sendDeleteVideoPlaylist (videoPlaylist: MVideoPlaylistFullSummary, t: Transaction) {
   logger.info('Creating job to send delete of playlist %s.', videoPlaylist.url)
 
   const byActor = videoPlaylist.OwnerAccount.Actor
@@ -101,7 +101,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function buildDeleteActivity (url: string, object: string, byActor: ActorModel, audience?: ActivityAudience): ActivityDelete {
+function buildDeleteActivity (url: string, object: string, byActor: MActorUrl, audience?: ActivityAudience): ActivityDelete {
   const activity = {
     type: 'Delete' as 'Delete',
     id: url,
index a88436f2c963ee061e07dbc0f531d4109212cdb6..6e41f241f74421bb080c00dce1d9065bb07ba8b1 100644 (file)
@@ -1,13 +1,12 @@
 import { Transaction } from 'sequelize'
-import { ActorModel } from '../../../models/activitypub/actor'
-import { VideoModel } from '../../../models/video/video'
 import { getVideoDislikeActivityPubUrl } from '../url'
 import { logger } from '../../../helpers/logger'
 import { ActivityAudience, ActivityDislike } from '../../../../shared/models/activitypub'
 import { sendVideoRelatedActivity } from './utils'
 import { audiencify, getAudience } from '../audience'
+import { MActor, MActorAudience, MVideoAccountLight, MVideoUrl } from '../../../typings/models'
 
-async function sendDislike (byActor: ActorModel, video: VideoModel, t: Transaction) {
+async function sendDislike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
   logger.info('Creating job to dislike %s.', video.url)
 
   const activityBuilder = (audience: ActivityAudience) => {
@@ -19,7 +18,7 @@ async function sendDislike (byActor: ActorModel, video: VideoModel, t: Transacti
   return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction: t })
 }
 
-function buildDislikeActivity (url: string, byActor: ActorModel, video: VideoModel, audience?: ActivityAudience): ActivityDislike {
+function buildDislikeActivity (url: string, byActor: MActorAudience, video: MVideoUrl, audience?: ActivityAudience): ActivityDislike {
   if (!audience) audience = getAudience(byActor)
 
   return audiencify(
index 61ee389a61157a84cee8d35ed9c1ad9f95e7f62f..5ae1614ab63d8c5f6467249bef01efc6617c91f6 100644 (file)
@@ -1,14 +1,13 @@
-import { ActorModel } from '../../../models/activitypub/actor'
-import { VideoModel } from '../../../models/video/video'
-import { VideoAbuseModel } from '../../../models/video/video-abuse'
 import { getVideoAbuseActivityPubUrl } from '../url'
 import { unicastTo } from './utils'
 import { logger } from '../../../helpers/logger'
 import { ActivityAudience, ActivityFlag } from '../../../../shared/models/activitypub'
 import { audiencify, getAudience } from '../audience'
 import { Transaction } from 'sequelize'
+import { MActor, MVideoFullLight } from '../../../typings/models'
+import { MVideoAbuseVideo } from '../../../typings/models/video'
 
-async function sendVideoAbuse (byActor: ActorModel, videoAbuse: VideoAbuseModel, video: VideoModel, t: Transaction) {
+async function sendVideoAbuse (byActor: MActor, videoAbuse: MVideoAbuseVideo, video: MVideoFullLight, t: Transaction) {
   if (!video.VideoChannel.Account.Actor.serverId) return // Local user
 
   const url = getVideoAbuseActivityPubUrl(videoAbuse)
@@ -22,7 +21,7 @@ async function sendVideoAbuse (byActor: ActorModel, videoAbuse: VideoAbuseModel,
   t.afterCommit(() => unicastTo(flagActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl))
 }
 
-function buildFlagActivity (url: string, byActor: ActorModel, videoAbuse: VideoAbuseModel, audience: ActivityAudience): ActivityFlag {
+function buildFlagActivity (url: string, byActor: MActor, videoAbuse: MVideoAbuseVideo, audience: ActivityAudience): ActivityFlag {
   if (!audience) audience = getAudience(byActor)
 
   const activity = Object.assign(
index a59ed50cf9d9d9d52523e19dce36cb291cb3dc56..6b17b25da188d7f3d2cafae5d13a021048339b9d 100644 (file)
@@ -4,9 +4,9 @@ import { getActorFollowActivityPubUrl } from '../url'
 import { unicastTo } from './utils'
 import { logger } from '../../../helpers/logger'
 import { Transaction } from 'sequelize'
-import { ActorModelOnly } from '../../../typings/models'
+import { MActor, MActorFollowActors } from '../../../typings/models'
 
-function sendFollow (actorFollow: ActorFollowModel, t: Transaction) {
+function sendFollow (actorFollow: MActorFollowActors, t: Transaction) {
   const me = actorFollow.ActorFollower
   const following = actorFollow.ActorFollowing
 
@@ -21,7 +21,7 @@ function sendFollow (actorFollow: ActorFollowModel, t: Transaction) {
   t.afterCommit(() => unicastTo(data, me, following.inboxUrl))
 }
 
-function buildFollowActivity (url: string, byActor: ActorModelOnly, targetActor: ActorModelOnly): ActivityFollow {
+function buildFollowActivity (url: string, byActor: MActor, targetActor: MActor): ActivityFollow {
   return {
     type: 'Follow',
     id: url,
index 35227887abfec4925b275e11426549cc33afa98e..e84a6f98b08112a7efd80ab7d081a365b0034a5a 100644 (file)
@@ -1,13 +1,12 @@
 import { Transaction } from 'sequelize'
 import { ActivityAudience, ActivityLike } from '../../../../shared/models/activitypub'
-import { ActorModel } from '../../../models/activitypub/actor'
-import { VideoModel } from '../../../models/video/video'
 import { getVideoLikeActivityPubUrl } from '../url'
 import { sendVideoRelatedActivity } from './utils'
 import { audiencify, getAudience } from '../audience'
 import { logger } from '../../../helpers/logger'
+import { MActor, MActorAudience, MVideoAccountLight, MVideoUrl } from '../../../typings/models'
 
-async function sendLike (byActor: ActorModel, video: VideoModel, t: Transaction) {
+async function sendLike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
   logger.info('Creating job to like %s.', video.url)
 
   const activityBuilder = (audience: ActivityAudience) => {
@@ -19,7 +18,7 @@ async function sendLike (byActor: ActorModel, video: VideoModel, t: Transaction)
   return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction: t })
 }
 
-function buildLikeActivity (url: string, byActor: ActorModel, video: VideoModel, audience?: ActivityAudience): ActivityLike {
+function buildLikeActivity (url: string, byActor: MActorAudience, video: MVideoUrl, audience?: ActivityAudience): ActivityLike {
   if (!audience) audience = getAudience(byActor)
 
   return audiencify(
index 63110b43395dbfa7e7941ad1c142d00ab5e08d38..4258a3c36335ed4ea79d31b0cea0e9b7cd233747 100644 (file)
@@ -1,12 +1,11 @@
 import { ActivityFollow, ActivityReject } from '../../../../shared/models/activitypub'
-import { ActorModel } from '../../../models/activitypub/actor'
 import { getActorFollowActivityPubUrl, getActorFollowRejectActivityPubUrl } from '../url'
 import { unicastTo } from './utils'
 import { buildFollowActivity } from './send-follow'
 import { logger } from '../../../helpers/logger'
-import { SignatureActorModel } from '../../../typings/models'
+import { MActor } from '../../../typings/models'
 
-async function sendReject (follower: SignatureActorModel, following: ActorModel) {
+async function sendReject (follower: MActor, following: MActor) {
   if (!follower.serverId) { // This should never happen
     logger.warn('Do not sending reject to local follower.')
     return
@@ -31,7 +30,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function buildRejectActivity (url: string, byActor: ActorModel, followActivityData: ActivityFollow): ActivityReject {
+function buildRejectActivity (url: string, byActor: MActor, followActivityData: ActivityFollow): ActivityReject {
   return {
     type: 'Reject',
     id: url,
index 8fcbbac5c95a94a0dfa35e96d38f4607a078c9a4..e9ab5b3c59acaee8da7edce9fa7b2436313f4060 100644 (file)
@@ -2,13 +2,12 @@ import { Transaction } from 'sequelize'
 import {
   ActivityAnnounce,
   ActivityAudience,
-  ActivityCreate, ActivityDislike,
+  ActivityCreate,
+  ActivityDislike,
   ActivityFollow,
   ActivityLike,
   ActivityUndo
 } from '../../../../shared/models/activitypub'
-import { ActorModel } from '../../../models/activitypub/actor'
-import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
 import { VideoModel } from '../../../models/video/video'
 import { getActorFollowActivityPubUrl, getUndoActivityPubUrl, getVideoDislikeActivityPubUrl, getVideoLikeActivityPubUrl } from '../url'
 import { broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils'
@@ -16,13 +15,20 @@ import { audiencify, getAudience } from '../audience'
 import { buildCreateActivity } from './send-create'
 import { buildFollowActivity } from './send-follow'
 import { buildLikeActivity } from './send-like'
-import { VideoShareModel } from '../../../models/video/video-share'
 import { buildAnnounceWithVideoAudience } from './send-announce'
 import { logger } from '../../../helpers/logger'
-import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
 import { buildDislikeActivity } from './send-dislike'
-
-async function sendUndoFollow (actorFollow: ActorFollowModel, t: Transaction) {
+import {
+  MActor, MActorAudience,
+  MActorFollowActors,
+  MActorLight,
+  MVideo,
+  MVideoAccountLight,
+  MVideoRedundancyVideo,
+  MVideoShare
+} from '../../../typings/models'
+
+async function sendUndoFollow (actorFollow: MActorFollowActors, t: Transaction) {
   const me = actorFollow.ActorFollower
   const following = actorFollow.ActorFollowing
 
@@ -40,7 +46,7 @@ async function sendUndoFollow (actorFollow: ActorFollowModel, t: Transaction) {
   t.afterCommit(() => unicastTo(undoActivity, me, following.inboxUrl))
 }
 
-async function sendUndoAnnounce (byActor: ActorModel, videoShare: VideoShareModel, video: VideoModel, t: Transaction) {
+async function sendUndoAnnounce (byActor: MActorLight, videoShare: MVideoShare, video: MVideo, t: Transaction) {
   logger.info('Creating job to undo announce %s.', videoShare.url)
 
   const undoUrl = getUndoActivityPubUrl(videoShare.url)
@@ -52,7 +58,7 @@ async function sendUndoAnnounce (byActor: ActorModel, videoShare: VideoShareMode
   return broadcastToFollowers(undoActivity, byActor, actorsInvolvedInVideo, t, followersException)
 }
 
-async function sendUndoLike (byActor: ActorModel, video: VideoModel, t: Transaction) {
+async function sendUndoLike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
   logger.info('Creating job to undo a like of video %s.', video.url)
 
   const likeUrl = getVideoLikeActivityPubUrl(byActor, video)
@@ -61,7 +67,7 @@ async function sendUndoLike (byActor: ActorModel, video: VideoModel, t: Transact
   return sendUndoVideoRelatedActivity({ byActor, video, url: likeUrl, activity: likeActivity, transaction: t })
 }
 
-async function sendUndoDislike (byActor: ActorModel, video: VideoModel, t: Transaction) {
+async function sendUndoDislike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
   logger.info('Creating job to undo a dislike of video %s.', video.url)
 
   const dislikeUrl = getVideoDislikeActivityPubUrl(byActor, video)
@@ -70,7 +76,7 @@ async function sendUndoDislike (byActor: ActorModel, video: VideoModel, t: Trans
   return sendUndoVideoRelatedActivity({ byActor, video, url: dislikeUrl, activity: dislikeActivity, transaction: t })
 }
 
-async function sendUndoCacheFile (byActor: ActorModel, redundancyModel: VideoRedundancyModel, t: Transaction) {
+async function sendUndoCacheFile (byActor: MActor, redundancyModel: MVideoRedundancyVideo, t: Transaction) {
   logger.info('Creating job to undo cache file %s.', redundancyModel.url)
 
   const videoId = redundancyModel.getVideo().id
@@ -94,7 +100,7 @@ export {
 
 function undoActivityData (
   url: string,
-  byActor: ActorModel,
+  byActor: MActorAudience,
   object: ActivityFollow | ActivityLike | ActivityDislike | ActivityCreate | ActivityAnnounce,
   audience?: ActivityAudience
 ): ActivityUndo {
@@ -112,8 +118,8 @@ function undoActivityData (
 }
 
 async function sendUndoVideoRelatedActivity (options: {
-  byActor: ActorModel,
-  video: VideoModel,
+  byActor: MActor,
+  video: MVideoAccountLight,
   url: string,
   activity: ActivityFollow | ActivityLike | ActivityDislike | ActivityCreate | ActivityAnnounce,
   transaction: Transaction
index 5bf092894eba54a65b5d6548712f018f511b444b..3a5cc185367e854ebe05bee2f27028eba121397b 100644 (file)
@@ -2,21 +2,29 @@ import { Transaction } from 'sequelize'
 import { ActivityAudience, ActivityUpdate } from '../../../../shared/models/activitypub'
 import { VideoPrivacy } from '../../../../shared/models/videos'
 import { AccountModel } from '../../../models/account/account'
-import { ActorModel } from '../../../models/activitypub/actor'
 import { VideoModel } from '../../../models/video/video'
-import { VideoChannelModel } from '../../../models/video/video-channel'
 import { VideoShareModel } from '../../../models/video/video-share'
 import { getUpdateActivityPubUrl } from '../url'
 import { broadcastToFollowers, sendVideoRelatedActivity } from './utils'
 import { audiencify, getActorsInvolvedInVideo, getAudience } from '../audience'
 import { logger } from '../../../helpers/logger'
 import { VideoCaptionModel } from '../../../models/video/video-caption'
-import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
-import { VideoPlaylistModel } from '../../../models/video/video-playlist'
 import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
 import { getServerActor } from '../../../helpers/utils'
+import {
+  MAccountActor,
+  MActor,
+  MActorLight,
+  MChannelActor,
+  MVideoAP,
+  MVideoAPWithoutCaption,
+  MVideoPlaylistFull,
+  MVideoRedundancyVideo
+} from '../../../typings/models'
+
+async function sendUpdateVideo (videoArg: MVideoAPWithoutCaption, t: Transaction, overrodeByActor?: MActor) {
+  const video = videoArg as MVideoAP
 
-async function sendUpdateVideo (video: VideoModel, t: Transaction, overrodeByActor?: ActorModel) {
   if (video.privacy === VideoPrivacy.PRIVATE) return undefined
 
   logger.info('Creating job to update video %s.', video.url)
@@ -41,7 +49,7 @@ async function sendUpdateVideo (video: VideoModel, t: Transaction, overrodeByAct
   return broadcastToFollowers(updateActivity, byActor, actorsInvolved, t)
 }
 
-async function sendUpdateActor (accountOrChannel: AccountModel | VideoChannelModel, t: Transaction) {
+async function sendUpdateActor (accountOrChannel: MAccountActor | MChannelActor, t: Transaction) {
   const byActor = accountOrChannel.Actor
 
   logger.info('Creating job to update actor %s.', byActor.url)
@@ -51,7 +59,7 @@ async function sendUpdateActor (accountOrChannel: AccountModel | VideoChannelMod
   const audience = getAudience(byActor)
   const updateActivity = buildUpdateActivity(url, byActor, accountOrChannelObject, audience)
 
-  let actorsInvolved: ActorModel[]
+  let actorsInvolved: MActor[]
   if (accountOrChannel instanceof AccountModel) {
     // Actors that shared my videos are involved too
     actorsInvolved = await VideoShareModel.loadActorsWhoSharedVideosOf(byActor.id, t)
@@ -65,7 +73,7 @@ async function sendUpdateActor (accountOrChannel: AccountModel | VideoChannelMod
   return broadcastToFollowers(updateActivity, byActor, actorsInvolved, t)
 }
 
-async function sendUpdateCacheFile (byActor: ActorModel, redundancyModel: VideoRedundancyModel) {
+async function sendUpdateCacheFile (byActor: MActorLight, redundancyModel: MVideoRedundancyVideo) {
   logger.info('Creating job to update cache file %s.', redundancyModel.url)
 
   const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(redundancyModel.getVideo().id)
@@ -80,7 +88,7 @@ async function sendUpdateCacheFile (byActor: ActorModel, redundancyModel: VideoR
   return sendVideoRelatedActivity(activityBuilder, { byActor, video })
 }
 
-async function sendUpdateVideoPlaylist (videoPlaylist: VideoPlaylistModel, t: Transaction) {
+async function sendUpdateVideoPlaylist (videoPlaylist: MVideoPlaylistFull, t: Transaction) {
   if (videoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) return undefined
 
   const byActor = videoPlaylist.OwnerAccount.Actor
@@ -113,7 +121,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function buildUpdateActivity (url: string, byActor: ActorModel, object: any, audience?: ActivityAudience): ActivityUpdate {
+function buildUpdateActivity (url: string, byActor: MActorLight, object: any, audience?: ActivityAudience): ActivityUpdate {
   if (!audience) audience = getAudience(byActor)
 
   return audiencify(
@@ -121,8 +129,7 @@ function buildUpdateActivity (url: string, byActor: ActorModel, object: any, aud
       type: 'Update' as 'Update',
       id: url,
       actor: byActor.url,
-      object: audiencify(object, audience
-      )
+      object: audiencify(object, audience)
     },
     audience
   )
index 8ad126be05f2eba0cf7ebbe02cec62fba0152bda..8809417f9b16bcf76df88ec81b0f75cd30ccc1eb 100644 (file)
@@ -1,13 +1,13 @@
 import { Transaction } from 'sequelize'
 import { ActivityAudience, ActivityView } from '../../../../shared/models/activitypub'
 import { ActorModel } from '../../../models/activitypub/actor'
-import { VideoModel } from '../../../models/video/video'
 import { getVideoLikeActivityPubUrl } from '../url'
 import { sendVideoRelatedActivity } from './utils'
 import { audiencify, getAudience } from '../audience'
 import { logger } from '../../../helpers/logger'
+import { MActorAudience, MVideoAccountLight, MVideoUrl } from '@server/typings/models'
 
-async function sendView (byActor: ActorModel, video: VideoModel, t: Transaction) {
+async function sendView (byActor: ActorModel, video: MVideoAccountLight, t: Transaction) {
   logger.info('Creating job to send view of %s.', video.url)
 
   const activityBuilder = (audience: ActivityAudience) => {
@@ -19,7 +19,7 @@ async function sendView (byActor: ActorModel, video: VideoModel, t: Transaction)
   return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction: t })
 }
 
-function buildViewActivity (url: string, byActor: ActorModel, video: VideoModel, audience?: ActivityAudience): ActivityView {
+function buildViewActivity (url: string, byActor: MActorAudience, video: MVideoUrl, audience?: ActivityAudience): ActivityView {
   if (!audience) audience = getAudience(byActor)
 
   return audiencify(
index 4f69afb00098efd3683916ebd7691615f032112c..8129ab32a8f617310b5b0ffcebd3722e1e6d410d 100644 (file)
@@ -4,15 +4,14 @@ import { logger } from '../../../helpers/logger'
 import { ActorModel } from '../../../models/activitypub/actor'
 import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
 import { JobQueue } from '../../job-queue'
-import { VideoModel } from '../../../models/video/video'
 import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience'
 import { getServerActor } from '../../../helpers/utils'
 import { afterCommitIfTransaction } from '../../../helpers/database-utils'
-import { ActorFollowerException, ActorModelId, ActorModelOnly } from '../../../typings/models'
+import { MActorFollowerException, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models'
 
 async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: {
-  byActor: ActorModelOnly,
-  video: VideoModel,
+  byActor: MActorLight,
+  video: MVideoAccountLight,
   transaction?: Transaction
 }) {
   const { byActor, video, transaction } = options
@@ -41,8 +40,8 @@ async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAud
 async function forwardVideoRelatedActivity (
   activity: Activity,
   t: Transaction,
-  followersException: ActorFollowerException[] = [],
-  video: VideoModel
+  followersException: MActorFollowerException[] = [],
+  video: MVideo
 ) {
   // Mastodon does not add our announces in audience, so we forward to them manually
   const additionalActors = await getActorsInvolvedInVideo(video, t)
@@ -54,7 +53,7 @@ async function forwardVideoRelatedActivity (
 async function forwardActivity (
   activity: Activity,
   t: Transaction,
-  followersException: ActorFollowerException[] = [],
+  followersException: MActorFollowerException[] = [],
   additionalFollowerUrls: string[] = []
 ) {
   logger.info('Forwarding activity %s.', activity.id)
@@ -88,10 +87,10 @@ async function forwardActivity (
 
 async function broadcastToFollowers (
   data: any,
-  byActor: ActorModelId,
-  toFollowersOf: ActorModelId[],
+  byActor: MActorId,
+  toFollowersOf: MActorId[],
   t: Transaction,
-  actorsException: ActorFollowerException[] = []
+  actorsException: MActorFollowerException[] = []
 ) {
   const uris = await computeFollowerUris(toFollowersOf, actorsException, t)
 
@@ -100,16 +99,16 @@ async function broadcastToFollowers (
 
 async function broadcastToActors (
   data: any,
-  byActor: ActorModelId,
-  toActors: ActorModelOnly[],
+  byActor: MActorId,
+  toActors: MActor[],
   t?: Transaction,
-  actorsException: ActorFollowerException[] = []
+  actorsException: MActorFollowerException[] = []
 ) {
   const uris = await computeUris(toActors, actorsException)
   return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor))
 }
 
-function broadcastTo (uris: string[], data: any, byActor: ActorModelId) {
+function broadcastTo (uris: string[], data: any, byActor: MActorId) {
   if (uris.length === 0) return undefined
 
   logger.debug('Creating broadcast job.', { uris })
@@ -123,7 +122,7 @@ function broadcastTo (uris: string[], data: any, byActor: ActorModelId) {
   return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload })
 }
 
-function unicastTo (data: any, byActor: ActorModelId, toActorUrl: string) {
+function unicastTo (data: any, byActor: MActorId, toActorUrl: string) {
   logger.debug('Creating unicast job.', { uri: toActorUrl })
 
   const payload = {
@@ -148,7 +147,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function computeFollowerUris (toFollowersOf: ActorModelId[], actorsException: ActorFollowerException[], t: Transaction) {
+async function computeFollowerUris (toFollowersOf: MActorId[], actorsException: MActorFollowerException[], t: Transaction) {
   const toActorFollowerIds = toFollowersOf.map(a => a.id)
 
   const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t)
@@ -157,7 +156,7 @@ async function computeFollowerUris (toFollowersOf: ActorModelId[], actorsExcepti
   return result.data.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1)
 }
 
-async function computeUris (toActors: ActorModelOnly[], actorsException: ActorFollowerException[] = []) {
+async function computeUris (toActors: MActor[], actorsException: MActorFollowerException[] = []) {
   const serverActor = await getServerActor()
   const targetUrls = toActors
     .filter(a => a.id !== serverActor.id) // Don't send to ourselves
@@ -170,7 +169,7 @@ async function computeUris (toActors: ActorModelOnly[], actorsException: ActorFo
               .filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1)
 }
 
-async function buildSharedInboxesException (actorsException: ActorFollowerException[]) {
+async function buildSharedInboxesException (actorsException: MActorFollowerException[]) {
   const serverActor = await getServerActor()
 
   return actorsException
index 7f38402b666debaeedd7a519212571e6a7d8518a..fdca9bed75c3e14c487f1af3164f0544cce99cac 100644 (file)
@@ -1,19 +1,18 @@
 import { Transaction } from 'sequelize'
 import { VideoPrivacy } from '../../../shared/models/videos'
 import { getServerActor } from '../../helpers/utils'
-import { VideoModel } from '../../models/video/video'
 import { VideoShareModel } from '../../models/video/video-share'
 import { sendUndoAnnounce, sendVideoAnnounce } from './send'
 import { getVideoAnnounceActivityPubUrl } from './url'
-import { VideoChannelModel } from '../../models/video/video-channel'
 import * as Bluebird from 'bluebird'
 import { doRequest } from '../../helpers/requests'
 import { getOrCreateActorAndServerAndModel } from './actor'
 import { logger } from '../../helpers/logger'
 import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants'
 import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub'
+import { MChannelActor, MChannelActorLight, MVideo, MVideoAccountLight, MVideoId } from '../../typings/models/video'
 
-async function shareVideoByServerAndChannel (video: VideoModel, t: Transaction) {
+async function shareVideoByServerAndChannel (video: MVideoAccountLight, t: Transaction) {
   if (video.privacy === VideoPrivacy.PRIVATE) return undefined
 
   return Promise.all([
@@ -22,7 +21,11 @@ async function shareVideoByServerAndChannel (video: VideoModel, t: Transaction)
   ])
 }
 
-async function changeVideoChannelShare (video: VideoModel, oldVideoChannel: VideoChannelModel, t: Transaction) {
+async function changeVideoChannelShare (
+  video: MVideoAccountLight,
+  oldVideoChannel: MChannelActorLight,
+  t: Transaction
+) {
   logger.info('Updating video channel of video %s: %s -> %s.', video.uuid, oldVideoChannel.name, video.VideoChannel.name)
 
   await undoShareByVideoChannel(video, oldVideoChannel, t)
@@ -30,7 +33,7 @@ async function changeVideoChannelShare (video: VideoModel, oldVideoChannel: Vide
   await shareByVideoChannel(video, t)
 }
 
-async function addVideoShares (shareUrls: string[], instance: VideoModel) {
+async function addVideoShares (shareUrls: string[], video: MVideoId) {
   await Bluebird.map(shareUrls, async shareUrl => {
     try {
       // Fetch url
@@ -50,7 +53,7 @@ async function addVideoShares (shareUrls: string[], instance: VideoModel) {
 
       const entry = {
         actorId: actor.id,
-        videoId: instance.id,
+        videoId: video.id,
         url: shareUrl
       }
 
@@ -69,7 +72,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function shareByServer (video: VideoModel, t: Transaction) {
+async function shareByServer (video: MVideo, t: Transaction) {
   const serverActor = await getServerActor()
 
   const serverShareUrl = getVideoAnnounceActivityPubUrl(serverActor, video)
@@ -88,7 +91,7 @@ async function shareByServer (video: VideoModel, t: Transaction) {
   return sendVideoAnnounce(serverActor, serverShare, video, t)
 }
 
-async function shareByVideoChannel (video: VideoModel, t: Transaction) {
+async function shareByVideoChannel (video: MVideoAccountLight, t: Transaction) {
   const videoChannelShareUrl = getVideoAnnounceActivityPubUrl(video.VideoChannel.Actor, video)
   const [ videoChannelShare ] = await VideoShareModel.findOrCreate({
     defaults: {
@@ -105,7 +108,7 @@ async function shareByVideoChannel (video: VideoModel, t: Transaction) {
   return sendVideoAnnounce(video.VideoChannel.Actor, videoChannelShare, video, t)
 }
 
-async function undoShareByVideoChannel (video: VideoModel, oldVideoChannel: VideoChannelModel, t: Transaction) {
+async function undoShareByVideoChannel (video: MVideo, oldVideoChannel: MChannelActorLight, t: Transaction) {
   // Load old share
   const oldShare = await VideoShareModel.load(oldVideoChannel.actorId, video.id, t)
   if (!oldShare) return new Error('Cannot find old video channel share ' + oldVideoChannel.actorId + ' for video ' + video.id)
index dfcb3c6688192c769b59dfc8cd88fcb3c641ecf0..6290af34ba91c5ecb399c07b6b521b05cefc6a98 100644 (file)
@@ -1,36 +1,42 @@
 import { WEBSERVER } from '../../initializers/constants'
-import { VideoModel } from '../../models/video/video'
-import { VideoAbuseModel } from '../../models/video/video-abuse'
-import { VideoCommentModel } from '../../models/video/video-comment'
-import { VideoFileModel } from '../../models/video/video-file'
-import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist'
-import { VideoPlaylistModel } from '../../models/video/video-playlist'
-import { ActorModelOnly, ActorModelUrl } from '../../typings/models'
-import { ActorFollowModelLight } from '../../typings/models/actor-follow'
-
-function getVideoActivityPubUrl (video: VideoModel) {
+import {
+  MActor,
+  MActorFollowActors,
+  MActorId,
+  MActorUrl,
+  MCommentId,
+  MVideoAbuseId,
+  MVideoId,
+  MVideoUrl,
+  MVideoUUID
+} from '../../typings/models'
+import { MVideoPlaylist, MVideoPlaylistUUID } from '../../typings/models/video/video-playlist'
+import { MVideoFileVideoUUID } from '../../typings/models/video/video-file'
+import { MStreamingPlaylist } from '../../typings/models/video/video-streaming-playlist'
+
+function getVideoActivityPubUrl (video: MVideoUUID) {
   return WEBSERVER.URL + '/videos/watch/' + video.uuid
 }
 
-function getVideoPlaylistActivityPubUrl (videoPlaylist: VideoPlaylistModel) {
+function getVideoPlaylistActivityPubUrl (videoPlaylist: MVideoPlaylist) {
   return WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid
 }
 
-function getVideoPlaylistElementActivityPubUrl (videoPlaylist: VideoPlaylistModel, video: VideoModel) {
+function getVideoPlaylistElementActivityPubUrl (videoPlaylist: MVideoPlaylistUUID, video: MVideoUUID) {
   return WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid + '/' + video.uuid
 }
 
-function getVideoCacheFileActivityPubUrl (videoFile: VideoFileModel) {
+function getVideoCacheFileActivityPubUrl (videoFile: MVideoFileVideoUUID) {
   const suffixFPS = videoFile.fps && videoFile.fps !== -1 ? '-' + videoFile.fps : ''
 
   return `${WEBSERVER.URL}/redundancy/videos/${videoFile.Video.uuid}/${videoFile.resolution}${suffixFPS}`
 }
 
-function getVideoCacheStreamingPlaylistActivityPubUrl (video: VideoModel, playlist: VideoStreamingPlaylistModel) {
+function getVideoCacheStreamingPlaylistActivityPubUrl (video: MVideoUUID, playlist: MStreamingPlaylist) {
   return `${WEBSERVER.URL}/redundancy/streaming-playlists/${playlist.getStringType()}/${video.uuid}`
 }
 
-function getVideoCommentActivityPubUrl (video: VideoModel, videoComment: VideoCommentModel) {
+function getVideoCommentActivityPubUrl (video: MVideoUUID, videoComment: MCommentId) {
   return WEBSERVER.URL + '/videos/watch/' + video.uuid + '/comments/' + videoComment.id
 }
 
@@ -42,54 +48,54 @@ function getAccountActivityPubUrl (accountName: string) {
   return WEBSERVER.URL + '/accounts/' + accountName
 }
 
-function getVideoAbuseActivityPubUrl (videoAbuse: VideoAbuseModel) {
+function getVideoAbuseActivityPubUrl (videoAbuse: MVideoAbuseId) {
   return WEBSERVER.URL + '/admin/video-abuses/' + videoAbuse.id
 }
 
-function getVideoViewActivityPubUrl (byActor: ActorModelUrl, video: VideoModel) {
+function getVideoViewActivityPubUrl (byActor: MActorUrl, video: MVideoId) {
   return byActor.url + '/views/videos/' + video.id + '/' + new Date().toISOString()
 }
 
-function getVideoLikeActivityPubUrl (byActor: ActorModelUrl, video: VideoModel | { id: number }) {
+function getVideoLikeActivityPubUrl (byActor: MActorUrl, video: MVideoId) {
   return byActor.url + '/likes/' + video.id
 }
 
-function getVideoDislikeActivityPubUrl (byActor: ActorModelUrl, video: VideoModel | { id: number }) {
+function getVideoDislikeActivityPubUrl (byActor: MActorUrl, video: MVideoId) {
   return byActor.url + '/dislikes/' + video.id
 }
 
-function getVideoSharesActivityPubUrl (video: VideoModel) {
+function getVideoSharesActivityPubUrl (video: MVideoUrl) {
   return video.url + '/announces'
 }
 
-function getVideoCommentsActivityPubUrl (video: VideoModel) {
+function getVideoCommentsActivityPubUrl (video: MVideoUrl) {
   return video.url + '/comments'
 }
 
-function getVideoLikesActivityPubUrl (video: VideoModel) {
+function getVideoLikesActivityPubUrl (video: MVideoUrl) {
   return video.url + '/likes'
 }
 
-function getVideoDislikesActivityPubUrl (video: VideoModel) {
+function getVideoDislikesActivityPubUrl (video: MVideoUrl) {
   return video.url + '/dislikes'
 }
 
-function getActorFollowActivityPubUrl (follower: ActorModelOnly, following: ActorModelOnly) {
+function getActorFollowActivityPubUrl (follower: MActor, following: MActorId) {
   return follower.url + '/follows/' + following.id
 }
 
-function getActorFollowAcceptActivityPubUrl (actorFollow: ActorFollowModelLight) {
+function getActorFollowAcceptActivityPubUrl (actorFollow: MActorFollowActors) {
   const follower = actorFollow.ActorFollower
   const me = actorFollow.ActorFollowing
 
   return follower.url + '/accepts/follows/' + me.id
 }
 
-function getActorFollowRejectActivityPubUrl (follower: ActorModelOnly, following: ActorModelOnly) {
+function getActorFollowRejectActivityPubUrl (follower: MActorUrl, following: MActorId) {
   return follower.url + '/rejects/follows/' + following.id
 }
 
-function getVideoAnnounceActivityPubUrl (byActor: ActorModelOnly, video: VideoModel) {
+function getVideoAnnounceActivityPubUrl (byActor: MActorId, video: MVideoUrl) {
   return video.url + '/announces/' + byActor.id
 }
 
index 8d2c1ade318b8e32bb439e3433f422b8e67debd5..375ac0aad4cff122485cc8baa71fc7d6df059d60 100644 (file)
@@ -2,20 +2,20 @@ import { sanitizeAndCheckVideoCommentObject } from '../../helpers/custom-validat
 import { logger } from '../../helpers/logger'
 import { doRequest } from '../../helpers/requests'
 import { ACTIVITY_PUB, CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants'
-import { VideoModel } from '../../models/video/video'
 import { VideoCommentModel } from '../../models/video/video-comment'
 import { getOrCreateActorAndServerAndModel } from './actor'
 import { getOrCreateVideoAndAccountAndChannel } from './videos'
 import * as Bluebird from 'bluebird'
 import { checkUrlsSameHost } from '../../helpers/activitypub'
+import { MCommentOwner, MCommentOwnerVideo, MVideoAccountAllFiles } from '../../typings/models/video'
 
 type ResolveThreadParams = {
   url: string,
-  comments?: VideoCommentModel[],
+  comments?: MCommentOwner[],
   isVideo?: boolean,
   commentCreated?: boolean
 }
-type ResolveThreadResult = Promise<{ video: VideoModel, comment: VideoCommentModel, commentCreated: boolean }>
+type ResolveThreadResult = Promise<{ video: MVideoAccountAllFiles, comment: MCommentOwnerVideo, commentCreated: boolean }>
 
 async function addVideoComments (commentUrls: string[]) {
   return Bluebird.map(commentUrls, commentUrl => {
@@ -85,9 +85,9 @@ async function tryResolveThreadFromVideo (params: ResolveThreadParams) {
   const syncParam = { likes: true, dislikes: true, shares: true, comments: false, thumbnail: true, refreshVideo: false }
   const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: url, syncParam })
 
-  let resultComment: VideoCommentModel
+  let resultComment: MCommentOwnerVideo
   if (comments.length !== 0) {
-    const firstReply = comments[ comments.length - 1 ]
+    const firstReply = comments[ comments.length - 1 ] as MCommentOwnerVideo
     firstReply.inReplyToCommentId = null
     firstReply.originCommentId = null
     firstReply.videoId = video.id
@@ -97,7 +97,7 @@ async function tryResolveThreadFromVideo (params: ResolveThreadParams) {
     comments[comments.length - 1] = await firstReply.save()
 
     for (let i = comments.length - 2; i >= 0; i--) {
-      const comment = comments[ i ]
+      const comment = comments[ i ] as MCommentOwnerVideo
       comment.originCommentId = firstReply.id
       comment.inReplyToCommentId = comments[ i + 1 ].id
       comment.videoId = video.id
@@ -107,7 +107,7 @@ async function tryResolveThreadFromVideo (params: ResolveThreadParams) {
       comments[i] = await comment.save()
     }
 
-    resultComment = comments[0]
+    resultComment = comments[0] as MCommentOwnerVideo
   }
 
   return { video, comment: resultComment, commentCreated }
@@ -151,7 +151,7 @@ async function resolveParentComment (params: ResolveThreadParams) {
     originCommentId: null,
     createdAt: new Date(body.published),
     updatedAt: new Date(body.updated)
-  })
+  }) as MCommentOwner
   comment.Account = actor.Account
 
   return resolveThread({
index cda5b2981da1d523d7f3b249f40f3ff03abaf580..6bd46bb585654582bdfde6121f64f75139b27ef7 100644 (file)
@@ -1,6 +1,4 @@
 import { Transaction } from 'sequelize'
-import { AccountModel } from '../../models/account/account'
-import { VideoModel } from '../../models/video/video'
 import { sendLike, sendUndoDislike, sendUndoLike } from './send'
 import { VideoRateType } from '../../../shared/models/videos'
 import * as Bluebird from 'bluebird'
@@ -10,11 +8,11 @@ import { logger } from '../../helpers/logger'
 import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants'
 import { doRequest } from '../../helpers/requests'
 import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub'
-import { ActorModel } from '../../models/activitypub/actor'
 import { getVideoDislikeActivityPubUrl, getVideoLikeActivityPubUrl } from './url'
 import { sendDislike } from './send/send-dislike'
+import { MAccountActor, MActorUrl, MVideo, MVideoAccountLight, MVideoId } from '../../typings/models'
 
-async function createRates (ratesUrl: string[], video: VideoModel, rate: VideoRateType) {
+async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateType) {
   let rateCounts = 0
 
   await Bluebird.map(ratesUrl, async rateUrl => {
@@ -64,11 +62,13 @@ async function createRates (ratesUrl: string[], video: VideoModel, rate: VideoRa
   return
 }
 
-async function sendVideoRateChange (account: AccountModel,
-                              video: VideoModel,
-                              likes: number,
-                              dislikes: number,
-                              t: Transaction) {
+async function sendVideoRateChange (
+  account: MAccountActor,
+  video: MVideoAccountLight,
+  likes: number,
+  dislikes: number,
+  t: Transaction
+) {
   const actor = account.Actor
 
   // Keep the order: first we undo and then we create
@@ -84,8 +84,10 @@ async function sendVideoRateChange (account: AccountModel,
   if (dislikes > 0) await sendDislike(actor, video, t)
 }
 
-function getRateUrl (rateType: VideoRateType, actor: ActorModel, video: VideoModel) {
-  return rateType === 'like' ? getVideoLikeActivityPubUrl(actor, video) : getVideoDislikeActivityPubUrl(actor, video)
+function getRateUrl (rateType: VideoRateType, actor: MActorUrl, video: MVideoId) {
+  return rateType === 'like'
+    ? getVideoLikeActivityPubUrl(actor, video)
+    : getVideoDislikeActivityPubUrl(actor, video)
 }
 
 export {
index 3a8451a326116c91c78bfcf04a40dc4d2efdebc9..5c10f976468451af0044d3dedf8c62aaf736c616 100644 (file)
@@ -24,7 +24,6 @@ import {
   REMOTE_SCHEME,
   STATIC_PATHS
 } from '../../initializers/constants'
-import { ActorModel } from '../../models/activitypub/actor'
 import { TagModel } from '../../models/video/tag'
 import { VideoModel } from '../../models/video/video'
 import { VideoFileModel } from '../../models/video/video-file'
@@ -38,7 +37,6 @@ import { JobQueue } from '../job-queue'
 import { ActivitypubHttpFetcherPayload } from '../job-queue/handlers/activitypub-http-fetcher'
 import { createRates } from './video-rates'
 import { addVideoShares, shareVideoByServerAndChannel } from './share'
-import { AccountModel } from '../../models/account/account'
 import { fetchVideoByUrl, VideoFetchByUrlType } from '../../helpers/video'
 import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub'
 import { Notifier } from '../notifier'
@@ -49,15 +47,33 @@ import { VideoShareModel } from '../../models/video/video-share'
 import { VideoCommentModel } from '../../models/video/video-comment'
 import { sequelizeTypescript } from '../../initializers/database'
 import { createPlaceholderThumbnail, createVideoMiniatureFromUrl } from '../thumbnail'
-import { ThumbnailModel } from '../../models/video/thumbnail'
 import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
 import { join } from 'path'
 import { FilteredModelAttributes } from '../../typings/sequelize'
 import { autoBlacklistVideoIfNeeded } from '../video-blacklist'
 import { ActorFollowScoreCache } from '../files-cache'
-import { AccountModelIdActor, VideoChannelModelId, VideoChannelModelIdActor } from '../../typings/models'
+import {
+  MAccountActor,
+  MChannelAccountLight,
+  MChannelDefault,
+  MChannelId,
+  MVideo,
+  MVideoAccountAllFiles,
+  MVideoAccountLight,
+  MVideoAP,
+  MVideoAPWithoutCaption,
+  MVideoFile,
+  MVideoFullLight,
+  MVideoId,
+  MVideoTag,
+  MVideoThumbnail,
+  MVideoWithAllFiles
+} from '../../typings/models'
+import { MThumbnail } from '../../typings/models/video/thumbnail'
+
+async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVideo: boolean, transaction?: sequelize.Transaction) {
+  const video = videoArg as MVideoAP
 
-async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) {
   if (
     // Check this is not a blacklisted video, or unfederated blacklisted video
     (video.isBlacklisted() === false || (isNewVideo === false && video.VideoBlacklist.unfederated === false)) &&
@@ -102,7 +118,7 @@ async function fetchRemoteVideo (videoUrl: string): Promise<{ response: request.
   return { response, videoObject: body }
 }
 
-async function fetchRemoteVideoDescription (video: VideoModel) {
+async function fetchRemoteVideoDescription (video: MVideoAccountLight) {
   const host = video.VideoChannel.Account.Actor.Server.host
   const path = video.getDescriptionAPIPath()
   const options = {
@@ -114,14 +130,14 @@ async function fetchRemoteVideoDescription (video: VideoModel) {
   return body.description ? body.description : ''
 }
 
-function fetchRemoteVideoStaticFile (video: VideoModel, path: string, destPath: string) {
+function fetchRemoteVideoStaticFile (video: MVideoAccountLight, path: string, destPath: string) {
   const url = buildRemoteBaseUrl(video, path)
 
   // We need to provide a callback, if no we could have an uncaught exception
   return doRequestAndSaveToFile({ uri: url }, destPath)
 }
 
-function buildRemoteBaseUrl (video: VideoModel, path: string) {
+function buildRemoteBaseUrl (video: MVideoAccountLight, path: string) {
   const host = video.VideoChannel.Account.Actor.Server.host
 
   return REMOTE_SCHEME.HTTP + '://' + host + path
@@ -146,7 +162,7 @@ type SyncParam = {
   thumbnail: boolean
   refreshVideo?: boolean
 }
-async function syncVideoExternalAttributes (video: VideoModel, fetchedVideo: VideoTorrentObject, syncParam: SyncParam) {
+async function syncVideoExternalAttributes (video: MVideo, fetchedVideo: VideoTorrentObject, syncParam: SyncParam) {
   logger.info('Adding likes/dislikes/shares/comments of video %s.', video.uuid)
 
   const jobPayloads: ActivitypubHttpFetcherPayload[] = []
@@ -194,12 +210,24 @@ async function syncVideoExternalAttributes (video: VideoModel, fetchedVideo: Vid
   await Bluebird.map(jobPayloads, payload => JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload }))
 }
 
+function getOrCreateVideoAndAccountAndChannel (options: {
+  videoObject: { id: string } | string,
+  syncParam?: SyncParam,
+  fetchType?: 'all',
+  allowRefresh?: boolean
+}): Promise<{ video: MVideoAccountAllFiles, created: boolean, autoBlacklisted?: boolean }>
+function getOrCreateVideoAndAccountAndChannel (options: {
+  videoObject: { id: string } | string,
+  syncParam?: SyncParam,
+  fetchType?: VideoFetchByUrlType,
+  allowRefresh?: boolean
+}): Promise<{ video: MVideoAccountAllFiles | MVideoThumbnail, created: boolean, autoBlacklisted?: boolean }>
 async function getOrCreateVideoAndAccountAndChannel (options: {
   videoObject: { id: string } | string,
   syncParam?: SyncParam,
   fetchType?: VideoFetchByUrlType,
   allowRefresh?: boolean // true by default
-}) {
+}): Promise<{ video: MVideoAccountAllFiles | MVideoThumbnail, created: boolean, autoBlacklisted?: boolean }> {
   // Default params
   const syncParam = options.syncParam || { likes: true, dislikes: true, shares: true, comments: true, thumbnail: true, refreshVideo: false }
   const fetchType = options.fetchType || 'all'
@@ -227,8 +255,9 @@ async function getOrCreateVideoAndAccountAndChannel (options: {
   const { videoObject: fetchedVideo } = await fetchRemoteVideo(videoUrl)
   if (!fetchedVideo) throw new Error('Cannot fetch remote video with url: ' + videoUrl)
 
-  const channelActor = await getOrCreateVideoChannelFromVideoObject(fetchedVideo)
-  const { autoBlacklisted, videoCreated } = await retryTransactionWrapper(createVideo, fetchedVideo, channelActor, syncParam.thumbnail)
+  const actor = await getOrCreateVideoChannelFromVideoObject(fetchedVideo)
+  const videoChannel = actor.VideoChannel
+  const { autoBlacklisted, videoCreated } = await retryTransactionWrapper(createVideo, fetchedVideo, videoChannel, syncParam.thumbnail)
 
   await syncVideoExternalAttributes(videoCreated, fetchedVideo, syncParam)
 
@@ -236,22 +265,22 @@ async function getOrCreateVideoAndAccountAndChannel (options: {
 }
 
 async function updateVideoFromAP (options: {
-  video: VideoModel,
+  video: MVideoAccountAllFiles,
   videoObject: VideoTorrentObject,
-  account: AccountModelIdActor,
-  channel: VideoChannelModelIdActor,
+  account: MAccountActor,
+  channel: MChannelDefault,
   overrideTo?: string[]
 }) {
   const { video, videoObject, account, channel, overrideTo } = options
 
-  logger.debug('Updating remote video "%s".', options.videoObject.uuid)
+  logger.debug('Updating remote video "%s".', options.videoObject.uuid, { account, channel })
 
   let videoFieldsSave: any
   const wasPrivateVideo = video.privacy === VideoPrivacy.PRIVATE
   const wasUnlistedVideo = video.privacy === VideoPrivacy.UNLISTED
 
   try {
-    let thumbnailModel: ThumbnailModel
+    let thumbnailModel: MThumbnail
 
     try {
       thumbnailModel = await createVideoMiniatureFromUrl(videoObject.icon.url, video, ThumbnailType.MINIATURE)
@@ -259,7 +288,7 @@ async function updateVideoFromAP (options: {
       logger.warn('Cannot generate thumbnail of %s.', videoObject.id, { err })
     }
 
-    await sequelizeTypescript.transaction(async t => {
+    const videoUpdated = await sequelizeTypescript.transaction(async t => {
       const sequelizeOptions = { transaction: t }
 
       videoFieldsSave = video.toJSON()
@@ -293,21 +322,21 @@ async function updateVideoFromAP (options: {
       video.channelId = videoData.channelId
       video.views = videoData.views
 
-      await video.save(sequelizeOptions)
+      const videoUpdated = await video.save(sequelizeOptions) as MVideoFullLight
 
-      if (thumbnailModel) await video.addAndSaveThumbnail(thumbnailModel, t)
+      if (thumbnailModel) await videoUpdated.addAndSaveThumbnail(thumbnailModel, t)
 
       // FIXME: use icon URL instead
-      const previewUrl = buildRemoteBaseUrl(video, join(STATIC_PATHS.PREVIEWS, video.getPreview().filename))
+      const previewUrl = buildRemoteBaseUrl(videoUpdated, join(STATIC_PATHS.PREVIEWS, videoUpdated.getPreview().filename))
       const previewModel = createPlaceholderThumbnail(previewUrl, video, ThumbnailType.PREVIEW, PREVIEWS_SIZE)
-      await video.addAndSaveThumbnail(previewModel, t)
+      await videoUpdated.addAndSaveThumbnail(previewModel, t)
 
       {
-        const videoFileAttributes = videoFileActivityUrlToDBAttributes(video, videoObject)
+        const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoUpdated, videoObject)
         const newVideoFiles = videoFileAttributes.map(a => new VideoFileModel(a))
 
         // Remove video files that do not exist anymore
-        const destroyTasks = video.VideoFiles
+        const destroyTasks = videoUpdated.VideoFiles
                                   .filter(f => !newVideoFiles.find(newFile => newFile.hasSameUniqueKeysThan(f)))
                                   .map(f => f.destroy(sequelizeOptions))
         await Promise.all(destroyTasks)
@@ -318,15 +347,15 @@ async function updateVideoFromAP (options: {
             .then(([ file ]) => file)
         })
 
-        video.VideoFiles = await Promise.all(upsertTasks)
+        videoUpdated.VideoFiles = await Promise.all(upsertTasks)
       }
 
       {
-        const streamingPlaylistAttributes = streamingPlaylistActivityUrlToDBAttributes(video, videoObject, video.VideoFiles)
+        const streamingPlaylistAttributes = streamingPlaylistActivityUrlToDBAttributes(videoUpdated, videoObject, videoUpdated.VideoFiles)
         const newStreamingPlaylists = streamingPlaylistAttributes.map(a => new VideoStreamingPlaylistModel(a))
 
         // Remove video files that do not exist anymore
-        const destroyTasks = video.VideoStreamingPlaylists
+        const destroyTasks = videoUpdated.VideoStreamingPlaylists
                                   .filter(f => !newStreamingPlaylists.find(newPlaylist => newPlaylist.hasSameUniqueKeysThan(f)))
                                   .map(f => f.destroy(sequelizeOptions))
         await Promise.all(destroyTasks)
@@ -337,38 +366,42 @@ async function updateVideoFromAP (options: {
                                .then(([ streamingPlaylist ]) => streamingPlaylist)
         })
 
-        video.VideoStreamingPlaylists = await Promise.all(upsertTasks)
+        videoUpdated.VideoStreamingPlaylists = await Promise.all(upsertTasks)
       }
 
       {
         // Update Tags
         const tags = videoObject.tag.map(tag => tag.name)
         const tagInstances = await TagModel.findOrCreateTags(tags, t)
-        await video.$set('Tags', tagInstances, sequelizeOptions)
+        await videoUpdated.$set('Tags', tagInstances, sequelizeOptions)
       }
 
       {
         // Update captions
-        await VideoCaptionModel.deleteAllCaptionsOfRemoteVideo(video.id, t)
+        await VideoCaptionModel.deleteAllCaptionsOfRemoteVideo(videoUpdated.id, t)
 
         const videoCaptionsPromises = videoObject.subtitleLanguage.map(c => {
-          return VideoCaptionModel.insertOrReplaceLanguage(video.id, c.identifier, t)
+          return VideoCaptionModel.insertOrReplaceLanguage(videoUpdated.id, c.identifier, t)
         })
-        video.VideoCaptions = await Promise.all(videoCaptionsPromises)
+        await Promise.all(videoCaptionsPromises)
       }
+
+      return videoUpdated
     })
 
     await autoBlacklistVideoIfNeeded({
-      video,
+      video: videoUpdated,
       user: undefined,
       isRemote: true,
       isNew: false,
       transaction: undefined
     })
 
-    if (wasPrivateVideo || wasUnlistedVideo) Notifier.Instance.notifyOnNewVideoIfNeeded(video) // Notify our users?
+    if (wasPrivateVideo || wasUnlistedVideo) Notifier.Instance.notifyOnNewVideoIfNeeded(videoUpdated) // Notify our users?
 
     logger.info('Remote video with uuid %s updated', videoObject.uuid)
+
+    return videoUpdated
   } catch (err) {
     if (video !== undefined && videoFieldsSave !== undefined) {
       resetSequelizeInstance(video, videoFieldsSave)
@@ -381,15 +414,15 @@ async function updateVideoFromAP (options: {
 }
 
 async function refreshVideoIfNeeded (options: {
-  video: VideoModel,
+  video: MVideoThumbnail,
   fetchedType: VideoFetchByUrlType,
   syncParam: SyncParam
-}): Promise<VideoModel> {
+}): Promise<MVideoThumbnail> {
   if (!options.video.isOutdated()) return options.video
 
   // We need more attributes if the argument video was fetched with not enough joints
   const video = options.fetchedType === 'all'
-    ? options.video
+    ? options.video as MVideoAccountAllFiles
     : await VideoModel.loadByUrlAndPopulateAccount(options.video.url)
 
   try {
@@ -410,12 +443,11 @@ async function refreshVideoIfNeeded (options: {
     }
 
     const channelActor = await getOrCreateVideoChannelFromVideoObject(videoObject)
-    const account = await AccountModel.load(channelActor.VideoChannel.accountId)
 
     const updateOptions = {
       video,
       videoObject,
-      account,
+      account: channelActor.VideoChannel.Account,
       channel: channelActor.VideoChannel
     }
     await retryTransactionWrapper(updateVideoFromAP, updateOptions)
@@ -467,15 +499,15 @@ function isAPPlaylistSegmentHashesUrlObject (tag: any): tag is ActivityPlaylistS
   return tag.name === 'sha256' && tag.type === 'Link' && urlMediaType === 'application/json'
 }
 
-async function createVideo (videoObject: VideoTorrentObject, channelActor: ActorModel, waitThumbnail = false) {
+async function createVideo (videoObject: VideoTorrentObject, channel: MChannelAccountLight, waitThumbnail = false) {
   logger.debug('Adding remote video %s.', videoObject.id)
 
-  const videoData = await videoActivityObjectToDBAttributes(channelActor.VideoChannel, videoObject, videoObject.to)
-  const video = VideoModel.build(videoData)
+  const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, videoObject.to)
+  const video = VideoModel.build(videoData) as MVideoThumbnail
 
   const promiseThumbnail = createVideoMiniatureFromUrl(videoObject.icon.url, video, ThumbnailType.MINIATURE)
 
-  let thumbnailModel: ThumbnailModel
+  let thumbnailModel: MThumbnail
   if (waitThumbnail === true) {
     thumbnailModel = await promiseThumbnail
   }
@@ -483,8 +515,8 @@ async function createVideo (videoObject: VideoTorrentObject, channelActor: Actor
   const { autoBlacklisted, videoCreated } = await sequelizeTypescript.transaction(async t => {
     const sequelizeOptions = { transaction: t }
 
-    const videoCreated = await video.save(sequelizeOptions)
-    videoCreated.VideoChannel = channelActor.VideoChannel
+    const videoCreated = await video.save(sequelizeOptions) as MVideoFullLight
+    videoCreated.VideoChannel = channel
 
     if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t)
 
@@ -517,15 +549,14 @@ async function createVideo (videoObject: VideoTorrentObject, channelActor: Actor
     const videoCaptionsPromises = videoObject.subtitleLanguage.map(c => {
       return VideoCaptionModel.insertOrReplaceLanguage(videoCreated.id, c.identifier, t)
     })
-    const captions = await Promise.all(videoCaptionsPromises)
+    await Promise.all(videoCaptionsPromises)
 
-    video.VideoFiles = videoFiles
-    video.VideoStreamingPlaylists = streamingPlaylists
-    video.Tags = tagInstances
-    video.VideoCaptions = captions
+    videoCreated.VideoFiles = videoFiles
+    videoCreated.VideoStreamingPlaylists = streamingPlaylists
+    videoCreated.Tags = tagInstances
 
     const autoBlacklisted = await autoBlacklistVideoIfNeeded({
-      video,
+      video: videoCreated,
       user: undefined,
       isRemote: true,
       isNew: true,
@@ -548,11 +579,7 @@ async function createVideo (videoObject: VideoTorrentObject, channelActor: Actor
   return { autoBlacklisted, videoCreated }
 }
 
-async function videoActivityObjectToDBAttributes (
-  videoChannel: VideoChannelModelId,
-  videoObject: VideoTorrentObject,
-  to: string[] = []
-) {
+async function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObject: VideoTorrentObject, to: string[] = []) {
   const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPrivacy.PUBLIC : VideoPrivacy.UNLISTED
   const duration = videoObject.duration.replace(/[^\d]+/, '')
 
@@ -603,7 +630,7 @@ async function videoActivityObjectToDBAttributes (
   }
 }
 
-function videoFileActivityUrlToDBAttributes (video: VideoModel, videoObject: VideoTorrentObject) {
+function videoFileActivityUrlToDBAttributes (video: MVideo, videoObject: VideoTorrentObject) {
   const fileUrls = videoObject.url.filter(u => isAPVideoUrlObject(u)) as ActivityVideoUrlObject[]
 
   if (fileUrls.length === 0) {
@@ -641,7 +668,7 @@ function videoFileActivityUrlToDBAttributes (video: VideoModel, videoObject: Vid
   return attributes
 }
 
-function streamingPlaylistActivityUrlToDBAttributes (video: VideoModel, videoObject: VideoTorrentObject, videoFiles: VideoFileModel[]) {
+function streamingPlaylistActivityUrlToDBAttributes (video: MVideoId, videoObject: VideoTorrentObject, videoFiles: MVideoFile[]) {
   const playlistUrls = videoObject.url.filter(u => isAPStreamingPlaylistUrlObject(u)) as ActivityPlaylistUrlObject[]
   if (playlistUrls.length === 0) return []
 
index 1b38e6cb59060743240f003e212f8f4dcf0ea5d2..9005b3e225e1270fe696f24149784421cb87b12f 100644 (file)
@@ -3,8 +3,6 @@ import { sendUpdateActor } from './activitypub/send'
 import { AVATARS_SIZE, LRU_CACHE, QUEUE_CONCURRENCY } from '../initializers/constants'
 import { updateActorAvatarInstance } from './activitypub'
 import { processImage } from '../helpers/image-utils'
-import { AccountModel } from '../models/account/account'
-import { VideoChannelModel } from '../models/video/video-channel'
 import { extname, join } from 'path'
 import { retryTransactionWrapper } from '../helpers/database-utils'
 import * as uuidv4 from 'uuid/v4'
@@ -13,8 +11,12 @@ import { sequelizeTypescript } from '../initializers/database'
 import * as LRUCache from 'lru-cache'
 import { queue } from 'async'
 import { downloadImage } from '../helpers/requests'
+import { MAccountActorDefault, MChannelActorDefault } from '../typings/models'
 
-async function updateActorAvatarFile (avatarPhysicalFile: Express.Multer.File, accountOrChannel: AccountModel | VideoChannelModel) {
+async function updateActorAvatarFile (
+  avatarPhysicalFile: Express.Multer.File,
+  accountOrChannel: MAccountActorDefault | MChannelActorDefault
+) {
   const extension = extname(avatarPhysicalFile.filename)
   const avatarName = uuidv4() + extension
   const destination = join(CONFIG.STORAGE.AVATARS_DIR, avatarName)
index 1633e500cb34964b9d9252adfc43c6f41ce6c9b3..28c69b46e767744a73d267fa97f9fcabb9aaba8d 100644 (file)
@@ -1,6 +1,7 @@
 import { sequelizeTypescript } from '../initializers'
 import { AccountBlocklistModel } from '../models/account/account-blocklist'
 import { ServerBlocklistModel } from '../models/server/server-blocklist'
+import { MAccountBlocklist, MServerBlocklist } from '@server/typings/models'
 
 function addAccountInBlocklist (byAccountId: number, targetAccountId: number) {
   return sequelizeTypescript.transaction(async t => {
@@ -20,13 +21,13 @@ function addServerInBlocklist (byAccountId: number, targetServerId: number) {
   })
 }
 
-function removeAccountFromBlocklist (accountBlock: AccountBlocklistModel) {
+function removeAccountFromBlocklist (accountBlock: MAccountBlocklist) {
   return sequelizeTypescript.transaction(async t => {
     return accountBlock.destroy({ transaction: t })
   })
 }
 
-function removeServerFromBlocklist (serverBlock: ServerBlocklistModel) {
+function removeServerFromBlocklist (serverBlock: MServerBlocklist) {
   return sequelizeTypescript.transaction(async t => {
     return serverBlock.destroy({ transaction: t })
   })
index 8841dd2ac2a69f02e88c26eb0caf3760cf49c851..a33aef26d20bd5953bc71e9c61d39370dfce9901 100644 (file)
@@ -13,6 +13,7 @@ import { VideoChannelModel } from '../models/video/video-channel'
 import * as Bluebird from 'bluebird'
 import { CONFIG } from '../initializers/config'
 import { logger } from '../helpers/logger'
+import { MAccountActor, MChannelActor, MVideo } from '../typings/models'
 
 export class ClientHtml {
 
@@ -65,7 +66,7 @@ export class ClientHtml {
   }
 
   private static async getAccountOrChannelHTMLPage (
-    loader: () => Bluebird<AccountModel | VideoChannelModel>,
+    loader: () => Bluebird<MAccountActor | MChannelActor>,
     req: express.Request,
     res: express.Response
   ) {
@@ -157,7 +158,7 @@ export class ClientHtml {
     return htmlStringPage.replace('</head>', linkTag + '</head>')
   }
 
-  private static addVideoOpenGraphAndOEmbedTags (htmlStringPage: string, video: VideoModel) {
+  private static addVideoOpenGraphAndOEmbedTags (htmlStringPage: string, video: MVideo) {
     const previewUrl = WEBSERVER.URL + video.getPreviewStaticPath()
     const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
 
@@ -236,7 +237,7 @@ export class ClientHtml {
     return this.addOpenGraphAndOEmbedTags(htmlStringPage, tagsString)
   }
 
-  private static addAccountOrChannelMetaTags (htmlStringPage: string, entity: AccountModel | VideoChannelModel) {
+  private static addAccountOrChannelMetaTags (htmlStringPage: string, entity: MAccountActor | MChannelActor) {
     // SEO, use origin account or channel URL
     const metaTags = `<link rel="canonical" href="${entity.Actor.url}" />`
 
index 73c2bcb1b520bb0cf022b6100ad96c0fd1c037d4..fe57a3e4caf5108e3a45a03e21df766a694d1da9 100644 (file)
@@ -3,16 +3,14 @@ import { isTestInstance } from '../helpers/core-utils'
 import { bunyanLogger, logger } from '../helpers/logger'
 import { CONFIG } from '../initializers/config'
 import { UserModel } from '../models/account/user'
-import { VideoModel } from '../models/video/video'
 import { JobQueue } from './job-queue'
 import { EmailPayload } from './job-queue/handlers/email'
 import { readFileSync } from 'fs-extra'
-import { VideoCommentModel } from '../models/video/video-comment'
-import { VideoAbuseModel } from '../models/video/video-abuse'
 import { VideoBlacklistModel } from '../models/video/video-blacklist'
-import { VideoImportModel } from '../models/video/video-import'
-import { ActorFollowModel } from '../models/activitypub/actor-follow'
 import { WEBSERVER } from '../initializers/constants'
+import { MCommentOwnerVideo, MVideo, MVideoAbuseVideo, MVideoAccountLight, MVideoBlacklistVideo } from '../typings/models/video'
+import { MActorFollowActors, MActorFollowFull, MUser } from '../typings/models'
+import { MVideoImport, MVideoImportVideo } from '@server/typings/models/video/video-import'
 
 type SendEmailOptions = {
   to: string[]
@@ -90,7 +88,7 @@ class Emailer {
     }
   }
 
-  addNewVideoFromSubscriberNotification (to: string[], video: VideoModel) {
+  addNewVideoFromSubscriberNotification (to: string[], video: MVideoAccountLight) {
     const channelName = video.VideoChannel.getDisplayName()
     const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
 
@@ -111,7 +109,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addNewFollowNotification (to: string[], actorFollow: ActorFollowModel, followType: 'account' | 'channel') {
+  addNewFollowNotification (to: string[], actorFollow: MActorFollowFull, followType: 'account' | 'channel') {
     const followerName = actorFollow.ActorFollower.Account.getDisplayName()
     const followingName = (actorFollow.ActorFollowing.VideoChannel || actorFollow.ActorFollowing.Account).getDisplayName()
 
@@ -130,7 +128,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addNewInstanceFollowerNotification (to: string[], actorFollow: ActorFollowModel) {
+  addNewInstanceFollowerNotification (to: string[], actorFollow: MActorFollowActors) {
     const awaitingApproval = actorFollow.state === 'pending' ? ' awaiting manual approval.' : ''
 
     const text = `Hi dear admin,\n\n` +
@@ -148,7 +146,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  myVideoPublishedNotification (to: string[], video: VideoModel) {
+  myVideoPublishedNotification (to: string[], video: MVideo) {
     const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
 
     const text = `Hi dear user,\n\n` +
@@ -168,7 +166,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  myVideoImportSuccessNotification (to: string[], videoImport: VideoImportModel) {
+  myVideoImportSuccessNotification (to: string[], videoImport: MVideoImportVideo) {
     const videoUrl = WEBSERVER.URL + videoImport.Video.getWatchStaticPath()
 
     const text = `Hi dear user,\n\n` +
@@ -188,7 +186,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  myVideoImportErrorNotification (to: string[], videoImport: VideoImportModel) {
+  myVideoImportErrorNotification (to: string[], videoImport: MVideoImport) {
     const importUrl = WEBSERVER.URL + '/my-account/video-imports'
 
     const text = `Hi dear user,\n\n` +
@@ -208,7 +206,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addNewCommentOnMyVideoNotification (to: string[], comment: VideoCommentModel) {
+  addNewCommentOnMyVideoNotification (to: string[], comment: MCommentOwnerVideo) {
     const accountName = comment.Account.getDisplayName()
     const video = comment.Video
     const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath()
@@ -230,7 +228,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addNewCommentMentionNotification (to: string[], comment: VideoCommentModel) {
+  addNewCommentMentionNotification (to: string[], comment: MCommentOwnerVideo) {
     const accountName = comment.Account.getDisplayName()
     const video = comment.Video
     const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath()
@@ -252,7 +250,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addVideoAbuseModeratorsNotification (to: string[], videoAbuse: VideoAbuseModel) {
+  addVideoAbuseModeratorsNotification (to: string[], videoAbuse: MVideoAbuseVideo) {
     const videoUrl = WEBSERVER.URL + videoAbuse.Video.getWatchStaticPath()
 
     const text = `Hi,\n\n` +
@@ -269,7 +267,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addVideoAutoBlacklistModeratorsNotification (to: string[], video: VideoModel) {
+  addVideoAutoBlacklistModeratorsNotification (to: string[], video: MVideo) {
     const VIDEO_AUTO_BLACKLIST_URL = WEBSERVER.URL + '/admin/moderation/video-auto-blacklist/list'
     const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
 
@@ -292,7 +290,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addNewUserRegistrationNotification (to: string[], user: UserModel) {
+  addNewUserRegistrationNotification (to: string[], user: MUser) {
     const text = `Hi,\n\n` +
       `User ${user.username} just registered on ${WEBSERVER.HOST} PeerTube instance.\n\n` +
       `Cheers,\n` +
@@ -307,7 +305,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addVideoBlacklistNotification (to: string[], videoBlacklist: VideoBlacklistModel) {
+  addVideoBlacklistNotification (to: string[], videoBlacklist: MVideoBlacklistVideo) {
     const videoName = videoBlacklist.Video.name
     const videoUrl = WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath()
 
@@ -329,7 +327,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addVideoUnblacklistNotification (to: string[], video: VideoModel) {
+  addVideoUnblacklistNotification (to: string[], video: MVideo) {
     const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
 
     const text = 'Hi,\n\n' +
@@ -381,7 +379,7 @@ class Emailer {
     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
   }
 
-  addUserBlockJob (user: UserModel, blocked: boolean, reason?: string) {
+  addUserBlockJob (user: MUser, blocked: boolean, reason?: string) {
     const reasonString = reason ? ` for the following reason: ${reason}` : ''
     const blockedWord = blocked ? 'blocked' : 'unblocked'
     const blockedString = `Your account ${user.username} on ${WEBSERVER.HOST} has been ${blockedWord}${reasonString}.`
index 98da4dcd8a80f80683f4111c1cc8fc68e1abd74f..05136c21cdd2bc85fc83c9348da492e1cff87b91 100644 (file)
@@ -1,4 +1,3 @@
-import { VideoModel } from '../models/video/video'
 import { basename, dirname, join } from 'path'
 import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION } from '../initializers/constants'
 import { close, ensureDir, move, open, outputJSON, pathExists, read, readFile, remove, writeFile } from 'fs-extra'
@@ -12,6 +11,7 @@ import { flatten, uniq } from 'lodash'
 import { VideoFileModel } from '../models/video/video-file'
 import { CONFIG } from '../initializers/config'
 import { sequelizeTypescript } from '../initializers/database'
+import { MVideoWithFile } from '@server/typings/models'
 
 async function updateStreamingPlaylistsInfohashesIfNeeded () {
   const playlistsToUpdate = await VideoStreamingPlaylistModel.listByIncorrectPeerVersion()
@@ -28,7 +28,7 @@ async function updateStreamingPlaylistsInfohashesIfNeeded () {
   }
 }
 
-async function updateMasterHLSPlaylist (video: VideoModel) {
+async function updateMasterHLSPlaylist (video: MVideoWithFile) {
   const directory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)
   const masterPlaylists: string[] = [ '#EXTM3U', '#EXT-X-VERSION:3' ]
   const masterPlaylistPath = join(directory, VideoStreamingPlaylistModel.getMasterHlsPlaylistFilename())
@@ -55,7 +55,7 @@ async function updateMasterHLSPlaylist (video: VideoModel) {
   await writeFile(masterPlaylistPath, masterPlaylists.join('\n') + '\n')
 }
 
-async function updateSha256Segments (video: VideoModel) {
+async function updateSha256Segments (video: MVideoWithFile) {
   const json: { [filename: string]: { [range: string]: string } } = {}
 
   const playlistDirectory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)
index 4ae66cd0165de75fce6cf939ed1b1028d8563a1e..741b1ffdefa23f52eec765cdeded47860f17f0b6 100644 (file)
@@ -10,6 +10,7 @@ import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
 import { ActorModel } from '../../../models/activitypub/actor'
 import { Notifier } from '../../notifier'
 import { sequelizeTypescript } from '../../../initializers/database'
+import { MActorFollowFull, MActorFull } from '../../../typings/models'
 
 export type ActivitypubFollowPayload = {
   followerActorId: number
@@ -23,13 +24,13 @@ async function processActivityPubFollow (job: Bull.Job) {
 
   logger.info('Processing ActivityPub follow in job %d.', job.id)
 
-  let targetActor: ActorModel
+  let targetActor: MActorFull
   if (!host || host === WEBSERVER.HOST) {
     targetActor = await ActorModel.loadLocalByName(payload.name)
   } else {
     const sanitizedHost = sanitizeHost(host, REMOTE_SCHEME.HTTP)
     const actorUrl = await loadActorUrlOrGetFromWebfinger(payload.name + '@' + sanitizedHost)
-    targetActor = await getOrCreateActorAndServerAndModel(actorUrl)
+    targetActor = await getOrCreateActorAndServerAndModel(actorUrl, 'all')
   }
 
   const fromActor = await ActorModel.load(payload.followerActorId)
@@ -44,7 +45,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function follow (fromActor: ActorModel, targetActor: ActorModel) {
+async function follow (fromActor: MActorFull, targetActor: MActorFull) {
   if (fromActor.id === targetActor.id) {
     throw new Error('Follower is the same than target actor.')
   }
@@ -53,7 +54,7 @@ async function follow (fromActor: ActorModel, targetActor: ActorModel) {
   const state = !fromActor.serverId && !targetActor.serverId ? 'accepted' : 'pending'
 
   const actorFollow = await sequelizeTypescript.transaction(async t => {
-    const [ actorFollow ] = await ActorFollowModel.findOrCreate({
+    const [ actorFollow ] = await ActorFollowModel.findOrCreate<MActorFollowFull>({
       where: {
         actorId: fromActor.id,
         targetActorId: targetActor.id
index c3f59dc7781186d4dfc797b66298bd0fafe50e67..0182c5169f17ac0c2be83afdee3337499f64fea0 100644 (file)
@@ -11,6 +11,7 @@ import { AccountModel } from '../../../models/account/account'
 import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
 import { VideoShareModel } from '../../../models/video/video-share'
 import { VideoCommentModel } from '../../../models/video/video-comment'
+import { MAccountDefault, MVideoFullLight } from '../../../typings/models'
 
 type FetchType = 'activity' | 'video-likes' | 'video-dislikes' | 'video-shares' | 'video-comments' | 'account-playlists'
 
@@ -26,10 +27,10 @@ async function processActivityPubHttpFetcher (job: Bull.Job) {
 
   const payload = job.data as ActivitypubHttpFetcherPayload
 
-  let video: VideoModel
+  let video: MVideoFullLight
   if (payload.videoId) video = await VideoModel.loadAndPopulateAccountAndServerAndTags(payload.videoId)
 
-  let account: AccountModel
+  let account: MAccountDefault
   if (payload.accountId) account = await AccountModel.load(payload.accountId)
 
   const fetcherType: { [ id in FetchType ]: (items: any[]) => Promise<any> } = {
index cdee1f6fd4eb2636b803788420b5b1548535c651..d3bde6e6a25f2d57897d02e1dcc4ce6b7f79faba 100644 (file)
@@ -3,6 +3,7 @@ import { getServerActor } from '../../../../helpers/utils'
 import { ActorModel } from '../../../../models/activitypub/actor'
 import { sha256 } from '../../../../helpers/core-utils'
 import { HTTP_SIGNATURE } from '../../../../initializers/constants'
+import { MActor } from '../../../../typings/models'
 
 type Payload = { body: any, signatureActorId?: number }
 
@@ -19,7 +20,8 @@ async function computeBody (payload: Payload) {
 }
 
 async function buildSignedRequestOptions (payload: Payload) {
-  let actor: ActorModel | null
+  let actor: MActor | null
+
   if (payload.signatureActorId) {
     actor = await ActorModel.load(payload.signatureActorId)
     if (!actor) throw new Error('Unknown signature actor id.')
index 8cacb0ef3ea3b902f788b2d4e0f92fb1540b8320..5c5b7dccb77c5bac463080d492427d1b4ee5e2b3 100644 (file)
@@ -6,6 +6,7 @@ import { getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg
 import { copy, stat } from 'fs-extra'
 import { VideoFileModel } from '../../../models/video/video-file'
 import { extname } from 'path'
+import { MVideoFile, MVideoWithFile } from '@server/typings/models'
 
 export type VideoFileImportPayload = {
   videoUUID: string,
@@ -37,7 +38,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function updateVideoFile (video: VideoModel, inputFilePath: string) {
+async function updateVideoFile (video: MVideoWithFile, inputFilePath: string) {
   const { videoFileResolution } = await getVideoFileResolution(inputFilePath)
   const { size } = await stat(inputFilePath)
   const fps = await getVideoFileFPS(inputFilePath)
@@ -48,7 +49,7 @@ async function updateVideoFile (video: VideoModel, inputFilePath: string) {
     size,
     fps,
     videoId: video.id
-  })
+  }) as MVideoFile
 
   const currentVideoFile = video.VideoFiles.find(videoFile => videoFile.resolution === updatedVideoFile.resolution)
 
@@ -60,9 +61,9 @@ async function updateVideoFile (video: VideoModel, inputFilePath: string) {
     video.VideoFiles = video.VideoFiles.filter(f => f !== currentVideoFile)
 
     // Update the database
-    currentVideoFile.set('extname', updatedVideoFile.extname)
-    currentVideoFile.set('size', updatedVideoFile.size)
-    currentVideoFile.set('fps', updatedVideoFile.fps)
+    currentVideoFile.extname = updatedVideoFile.extname
+    currentVideoFile.size = updatedVideoFile.size
+    currentVideoFile.fps = updatedVideoFile.fps
 
     updatedVideoFile = currentVideoFile
   }
index 13b741180daefdc15a8d400a0a4f3b2bf3d8d0b6..f9dda79f83717cb0b1df430e1a4d9a34db5e2d40 100644 (file)
@@ -17,9 +17,10 @@ import { move, remove, stat } from 'fs-extra'
 import { Notifier } from '../../notifier'
 import { CONFIG } from '../../../initializers/config'
 import { sequelizeTypescript } from '../../../initializers/database'
-import { ThumbnailModel } from '../../../models/video/thumbnail'
 import { createVideoMiniatureFromUrl, generateVideoMiniature } from '../../thumbnail'
 import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
+import { MThumbnail } from '../../../typings/models/video/thumbnail'
+import { MVideoImportDefault, MVideoImportDefaultFiles, MVideoImportVideo } from '@server/typings/models/video/video-import'
 
 type VideoImportYoutubeDLPayload = {
   type: 'youtube-dl'
@@ -110,11 +111,13 @@ type ProcessFileOptions = {
   generateThumbnail: boolean
   generatePreview: boolean
 }
-async function processFile (downloader: () => Promise<string>, videoImport: VideoImportModel, options: ProcessFileOptions) {
+async function processFile (downloader: () => Promise<string>, videoImportArg: MVideoImportDefault, options: ProcessFileOptions) {
   let tempVideoPath: string
   let videoDestFile: string
   let videoFile: VideoFileModel
 
+  const videoImport = videoImportArg as MVideoImportDefaultFiles
+
   try {
     // Download video from youtubeDL
     tempVideoPath = await downloader()
@@ -148,7 +151,7 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
     tempVideoPath = null // This path is not used anymore
 
     // Process thumbnail
-    let thumbnailModel: ThumbnailModel
+    let thumbnailModel: MThumbnail
     if (options.downloadThumbnail && options.thumbnailUrl) {
       thumbnailModel = await createVideoMiniatureFromUrl(options.thumbnailUrl, videoImport.Video, ThumbnailType.MINIATURE)
     } else if (options.generateThumbnail || options.downloadThumbnail) {
@@ -156,7 +159,7 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
     }
 
     // Process preview
-    let previewModel: ThumbnailModel
+    let previewModel: MThumbnail
     if (options.downloadPreview && options.thumbnailUrl) {
       previewModel = await createVideoMiniatureFromUrl(options.thumbnailUrl, videoImport.Video, ThumbnailType.PREVIEW)
     } else if (options.generatePreview || options.downloadPreview) {
@@ -166,14 +169,15 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
     // Create torrent
     await videoImport.Video.createTorrentAndSetInfoHash(videoFile)
 
-    const videoImportUpdated: VideoImportModel = await sequelizeTypescript.transaction(async t => {
+    const { videoImportUpdated, video } = await sequelizeTypescript.transaction(async t => {
+      const videoImportToUpdate = videoImport as MVideoImportVideo
+
       // Refresh video
-      const video = await VideoModel.load(videoImport.videoId, t)
-      if (!video) throw new Error('Video linked to import ' + videoImport.videoId + ' does not exist anymore.')
-      videoImport.Video = video
+      const video = await VideoModel.load(videoImportToUpdate.videoId, t)
+      if (!video) throw new Error('Video linked to import ' + videoImportToUpdate.videoId + ' does not exist anymore.')
 
       const videoFileCreated = await videoFile.save({ transaction: t })
-      video.VideoFiles = [ videoFileCreated ]
+      videoImportToUpdate.Video = Object.assign(video, { VideoFiles: [ videoFileCreated ] })
 
       // Update video DB object
       video.duration = duration
@@ -188,25 +192,25 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
       await federateVideoIfNeeded(videoForFederation, true, t)
 
       // Update video import object
-      videoImport.state = VideoImportState.SUCCESS
-      const videoImportUpdated = await videoImport.save({ transaction: t })
+      videoImportToUpdate.state = VideoImportState.SUCCESS
+      const videoImportUpdated = await videoImportToUpdate.save({ transaction: t }) as MVideoImportVideo
+      videoImportUpdated.Video = video
 
       logger.info('Video %s imported.', video.uuid)
 
-      videoImportUpdated.Video = videoForFederation
-      return videoImportUpdated
+      return { videoImportUpdated, video: videoForFederation }
     })
 
     Notifier.Instance.notifyOnFinishedVideoImport(videoImportUpdated, true)
 
-    if (videoImportUpdated.Video.isBlacklisted()) {
-      Notifier.Instance.notifyOnVideoAutoBlacklist(videoImportUpdated.Video)
+    if (video.isBlacklisted()) {
+      Notifier.Instance.notifyOnVideoAutoBlacklist(video)
     } else {
-      Notifier.Instance.notifyOnNewVideoIfNeeded(videoImportUpdated.Video)
+      Notifier.Instance.notifyOnNewVideoIfNeeded(video)
     }
 
     // Create transcoding jobs?
-    if (videoImportUpdated.Video.state === VideoState.TO_TRANSCODE) {
+    if (video.state === VideoState.TO_TRANSCODE) {
       // Put uuid because we don't have id auto incremented for now
       const dataInput = {
         type: 'optimize' as 'optimize',
index 981daf9a1a5003e46ad920264fc0957b211dee99..2ebe15bcb0bd0a0fed813e39cf7956ac1e5439ac 100644 (file)
@@ -11,6 +11,7 @@ import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils'
 import { generateHlsPlaylist, optimizeVideofile, transcodeOriginalVideofile, mergeAudioVideofile } from '../../video-transcoding'
 import { Notifier } from '../../notifier'
 import { CONFIG } from '../../../initializers/config'
+import { MVideoUUID, MVideoWithFile } from '@server/typings/models'
 
 interface BaseTranscodingPayload {
   videoUUID: string
@@ -73,7 +74,7 @@ async function processVideoTranscoding (job: Bull.Job) {
   return video
 }
 
-async function onHlsPlaylistGenerationSuccess (video: VideoModel) {
+async function onHlsPlaylistGenerationSuccess (video: MVideoUUID) {
   if (video === undefined) return undefined
 
   await sequelizeTypescript.transaction(async t => {
@@ -87,7 +88,7 @@ async function onHlsPlaylistGenerationSuccess (video: VideoModel) {
   })
 }
 
-async function publishNewResolutionIfNeeded (video: VideoModel, payload?: NewResolutionTranscodingPayload | MergeAudioTranscodingPayload) {
+async function publishNewResolutionIfNeeded (video: MVideoUUID, payload?: NewResolutionTranscodingPayload | MergeAudioTranscodingPayload) {
   const { videoDatabase, videoPublished } = await sequelizeTypescript.transaction(async t => {
     // Maybe the video changed in database, refresh it
     let videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t)
@@ -119,7 +120,7 @@ async function publishNewResolutionIfNeeded (video: VideoModel, payload?: NewRes
   await createHlsJobIfEnabled(payload)
 }
 
-async function onVideoFileOptimizerSuccess (videoArg: VideoModel, payload: OptimizeTranscodingPayload) {
+async function onVideoFileOptimizerSuccess (videoArg: MVideoWithFile, payload: OptimizeTranscodingPayload) {
   if (videoArg === undefined) return undefined
 
   // Outside the transaction (IO on disk)
index a7dfb09794017c1a14d64253a13c2f78d61672f6..f01101b8e5de59bb0a4063845ae0a0e080dff7e8 100644 (file)
@@ -8,13 +8,23 @@ import { UserModel } from '../models/account/user'
 import { PeerTubeSocket } from './peertube-socket'
 import { CONFIG } from '../initializers/config'
 import { VideoPrivacy, VideoState } from '../../shared/models/videos'
-import { VideoAbuseModel } from '../models/video/video-abuse'
 import { VideoBlacklistModel } from '../models/video/video-blacklist'
 import * as Bluebird from 'bluebird'
 import { VideoImportModel } from '../models/video/video-import'
 import { AccountBlocklistModel } from '../models/account/account-blocklist'
+import {
+  MCommentOwnerVideo,
+  MVideo,
+  MVideoAbuseVideo,
+  MVideoAccountLight,
+  MVideoBlacklistVideo,
+  MVideoFullLight
+} from '../typings/models/video'
+import { MUser, MUserAccount, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/typings/models/user'
+import { MActorFollowActors, MActorFollowFull } from '../typings/models'
 import { ActorFollowModel } from '../models/activitypub/actor-follow'
-import { AccountModel } from '../models/account/account'
+import { MVideoImportVideo } from '@server/typings/models/video/video-import'
+import { AccountModel } from '@server/models/account/account'
 
 class Notifier {
 
@@ -22,7 +32,7 @@ class Notifier {
 
   private constructor () {}
 
-  notifyOnNewVideoIfNeeded (video: VideoModel): void {
+  notifyOnNewVideoIfNeeded (video: MVideoAccountLight): void {
     // Only notify on public and published videos which are not blacklisted
     if (video.privacy !== VideoPrivacy.PUBLIC || video.state !== VideoState.PUBLISHED || video.isBlacklisted()) return
 
@@ -30,7 +40,7 @@ class Notifier {
       .catch(err => logger.error('Cannot notify subscribers of new video %s.', video.url, { err }))
   }
 
-  notifyOnVideoPublishedAfterTranscoding (video: VideoModel): void {
+  notifyOnVideoPublishedAfterTranscoding (video: MVideoFullLight): void {
     // don't notify if didn't wait for transcoding or video is still blacklisted/waiting for scheduled update
     if (!video.waitTranscoding || video.VideoBlacklist || video.ScheduleVideoUpdate) return
 
@@ -38,7 +48,7 @@ class Notifier {
         .catch(err => logger.error('Cannot notify owner that its video %s has been published after transcoding.', video.url, { err }))
   }
 
-  notifyOnVideoPublishedAfterScheduledUpdate (video: VideoModel): void {
+  notifyOnVideoPublishedAfterScheduledUpdate (video: MVideoFullLight): void {
     // don't notify if video is still blacklisted or waiting for transcoding
     if (video.VideoBlacklist || (video.waitTranscoding && video.state !== VideoState.PUBLISHED)) return
 
@@ -46,7 +56,7 @@ class Notifier {
         .catch(err => logger.error('Cannot notify owner that its video %s has been published after scheduled update.', video.url, { err }))
   }
 
-  notifyOnVideoPublishedAfterRemovedFromAutoBlacklist (video: VideoModel): void {
+  notifyOnVideoPublishedAfterRemovedFromAutoBlacklist (video: MVideoFullLight): void {
     // don't notify if video is still waiting for transcoding or scheduled update
     if (video.ScheduleVideoUpdate || (video.waitTranscoding && video.state !== VideoState.PUBLISHED)) return
 
@@ -54,7 +64,7 @@ class Notifier {
         .catch(err => logger.error('Cannot notify owner that its video %s has been published after removed from auto-blacklist.', video.url, { err })) // tslint:disable-line:max-line-length
   }
 
-  notifyOnNewComment (comment: VideoCommentModel): void {
+  notifyOnNewComment (comment: MCommentOwnerVideo): void {
     this.notifyVideoOwnerOfNewComment(comment)
         .catch(err => logger.error('Cannot notify video owner of new comment %s.', comment.url, { err }))
 
@@ -62,37 +72,37 @@ class Notifier {
         .catch(err => logger.error('Cannot notify mentions of comment %s.', comment.url, { err }))
   }
 
-  notifyOnNewVideoAbuse (videoAbuse: VideoAbuseModel): void {
+  notifyOnNewVideoAbuse (videoAbuse: MVideoAbuseVideo): void {
     this.notifyModeratorsOfNewVideoAbuse(videoAbuse)
       .catch(err => logger.error('Cannot notify of new video abuse of video %s.', videoAbuse.Video.url, { err }))
   }
 
-  notifyOnVideoAutoBlacklist (video: VideoModel): void {
+  notifyOnVideoAutoBlacklist (video: MVideo): void {
     this.notifyModeratorsOfVideoAutoBlacklist(video)
       .catch(err => logger.error('Cannot notify of auto-blacklist of video %s.', video.url, { err }))
   }
 
-  notifyOnVideoBlacklist (videoBlacklist: VideoBlacklistModel): void {
+  notifyOnVideoBlacklist (videoBlacklist: MVideoBlacklistVideo): void {
     this.notifyVideoOwnerOfBlacklist(videoBlacklist)
       .catch(err => logger.error('Cannot notify video owner of new video blacklist of %s.', videoBlacklist.Video.url, { err }))
   }
 
-  notifyOnVideoUnblacklist (video: VideoModel): void {
+  notifyOnVideoUnblacklist (video: MVideo): void {
     this.notifyVideoOwnerOfUnblacklist(video)
         .catch(err => logger.error('Cannot notify video owner of unblacklist of %s.', video.url, { err }))
   }
 
-  notifyOnFinishedVideoImport (videoImport: VideoImportModel, success: boolean): void {
+  notifyOnFinishedVideoImport (videoImport: MVideoImportVideo, success: boolean): void {
     this.notifyOwnerVideoImportIsFinished(videoImport, success)
       .catch(err => logger.error('Cannot notify owner that its video import %s is finished.', videoImport.getTargetIdentifier(), { err }))
   }
 
-  notifyOnNewUserRegistration (user: UserModel): void {
+  notifyOnNewUserRegistration (user: MUserAccount): void {
     this.notifyModeratorsOfNewUserRegistration(user)
         .catch(err => logger.error('Cannot notify moderators of new user registration (%s).', user.username, { err }))
   }
 
-  notifyOfNewUserFollow (actorFollow: ActorFollowModel): void {
+  notifyOfNewUserFollow (actorFollow: MActorFollowFull): void {
     this.notifyUserOfNewActorFollow(actorFollow)
       .catch(err => {
         logger.error(
@@ -104,14 +114,14 @@ class Notifier {
       })
   }
 
-  notifyOfNewInstanceFollow (actorFollow: ActorFollowModel): void {
+  notifyOfNewInstanceFollow (actorFollow: MActorFollowActors): void {
     this.notifyAdminsOfNewInstanceFollow(actorFollow)
         .catch(err => {
           logger.error('Cannot notify administrators of new follower %s.', actorFollow.ActorFollower.url, { err })
         })
   }
 
-  private async notifySubscribersOfNewVideo (video: VideoModel) {
+  private async notifySubscribersOfNewVideo (video: MVideoAccountLight) {
     // List all followers that are users
     const users = await UserModel.listUserSubscribersOf(video.VideoChannel.actorId)
 
@@ -127,7 +137,7 @@ class Notifier {
         userId: user.id,
         videoId: video.id
       })
-      notification.Video = video
+      notification.Video = video as VideoModel
 
       return notification
     }
@@ -139,7 +149,7 @@ class Notifier {
     return this.notify({ users, settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyVideoOwnerOfNewComment (comment: VideoCommentModel) {
+  private async notifyVideoOwnerOfNewComment (comment: MCommentOwnerVideo) {
     if (comment.Video.isOwned() === false) return
 
     const user = await UserModel.loadByVideoId(comment.videoId)
@@ -162,7 +172,7 @@ class Notifier {
         userId: user.id,
         commentId: comment.id
       })
-      notification.Comment = comment
+      notification.Comment = comment as VideoCommentModel
 
       return notification
     }
@@ -174,7 +184,7 @@ class Notifier {
     return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyOfCommentMention (comment: VideoCommentModel) {
+  private async notifyOfCommentMention (comment: MCommentOwnerVideo) {
     const extractedUsernames = comment.extractMentions()
     logger.debug(
       'Extracted %d username from comment %s.', extractedUsernames.length, comment.url,
@@ -209,7 +219,7 @@ class Notifier {
         userId: user.id,
         commentId: comment.id
       })
-      notification.Comment = comment
+      notification.Comment = comment as VideoCommentModel
 
       return notification
     }
@@ -221,7 +231,7 @@ class Notifier {
     return this.notify({ users, settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyUserOfNewActorFollow (actorFollow: ActorFollowModel) {
+  private async notifyUserOfNewActorFollow (actorFollow: MActorFollowFull) {
     if (actorFollow.ActorFollowing.isOwned() === false) return
 
     // Account follows one of our account?
@@ -236,9 +246,6 @@ class Notifier {
 
     if (!user) return
 
-    if (!actorFollow.ActorFollower.Account || !actorFollow.ActorFollower.Account.name) {
-      actorFollow.ActorFollower.Account = await actorFollow.ActorFollower.$get('Account') as AccountModel
-    }
     const followerAccount = actorFollow.ActorFollower.Account
 
     const accountMuted = await AccountBlocklistModel.isAccountMutedBy(user.Account.id, followerAccount.id)
@@ -256,7 +263,7 @@ class Notifier {
         userId: user.id,
         actorFollowId: actorFollow.id
       })
-      notification.ActorFollow = actorFollow
+      notification.ActorFollow = actorFollow as ActorFollowModel
 
       return notification
     }
@@ -268,7 +275,7 @@ class Notifier {
     return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyAdminsOfNewInstanceFollow (actorFollow: ActorFollowModel) {
+  private async notifyAdminsOfNewInstanceFollow (actorFollow: MActorFollowActors) {
     const admins = await UserModel.listWithRight(UserRight.MANAGE_SERVER_FOLLOW)
 
     logger.info('Notifying %d administrators of new instance follower: %s.', admins.length, actorFollow.ActorFollower.url)
@@ -283,7 +290,7 @@ class Notifier {
         userId: user.id,
         actorFollowId: actorFollow.id
       })
-      notification.ActorFollow = actorFollow
+      notification.ActorFollow = actorFollow as ActorFollowModel
 
       return notification
     }
@@ -295,7 +302,7 @@ class Notifier {
     return this.notify({ users: admins, settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyModeratorsOfNewVideoAbuse (videoAbuse: VideoAbuseModel) {
+  private async notifyModeratorsOfNewVideoAbuse (videoAbuse: MVideoAbuseVideo) {
     const moderators = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_ABUSES)
     if (moderators.length === 0) return
 
@@ -306,7 +313,7 @@ class Notifier {
     }
 
     async function notificationCreator (user: UserModel) {
-      const notification = await UserNotificationModel.create({
+      const notification: UserNotificationModelForApi = await UserNotificationModel.create({
         type: UserNotificationType.NEW_VIDEO_ABUSE_FOR_MODERATORS,
         userId: user.id,
         videoAbuseId: videoAbuse.id
@@ -323,7 +330,7 @@ class Notifier {
     return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyModeratorsOfVideoAutoBlacklist (video: VideoModel) {
+  private async notifyModeratorsOfVideoAutoBlacklist (video: MVideo) {
     const moderators = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_BLACKLIST)
     if (moderators.length === 0) return
 
@@ -339,7 +346,7 @@ class Notifier {
         userId: user.id,
         videoId: video.id
       })
-      notification.Video = video
+      notification.Video = video as VideoModel
 
       return notification
     }
@@ -351,7 +358,7 @@ class Notifier {
     return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyVideoOwnerOfBlacklist (videoBlacklist: VideoBlacklistModel) {
+  private async notifyVideoOwnerOfBlacklist (videoBlacklist: MVideoBlacklistVideo) {
     const user = await UserModel.loadByVideoId(videoBlacklist.videoId)
     if (!user) return
 
@@ -367,7 +374,7 @@ class Notifier {
         userId: user.id,
         videoBlacklistId: videoBlacklist.id
       })
-      notification.VideoBlacklist = videoBlacklist
+      notification.VideoBlacklist = videoBlacklist as VideoBlacklistModel
 
       return notification
     }
@@ -379,7 +386,7 @@ class Notifier {
     return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyVideoOwnerOfUnblacklist (video: VideoModel) {
+  private async notifyVideoOwnerOfUnblacklist (video: MVideo) {
     const user = await UserModel.loadByVideoId(video.id)
     if (!user) return
 
@@ -395,7 +402,7 @@ class Notifier {
         userId: user.id,
         videoId: video.id
       })
-      notification.Video = video
+      notification.Video = video as VideoModel
 
       return notification
     }
@@ -407,7 +414,7 @@ class Notifier {
     return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyOwnedVideoHasBeenPublished (video: VideoModel) {
+  private async notifyOwnedVideoHasBeenPublished (video: MVideoFullLight) {
     const user = await UserModel.loadByVideoId(video.id)
     if (!user) return
 
@@ -423,7 +430,7 @@ class Notifier {
         userId: user.id,
         videoId: video.id
       })
-      notification.Video = video
+      notification.Video = video as VideoModel
 
       return notification
     }
@@ -435,7 +442,7 @@ class Notifier {
     return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyOwnerVideoImportIsFinished (videoImport: VideoImportModel, success: boolean) {
+  private async notifyOwnerVideoImportIsFinished (videoImport: MVideoImportVideo, success: boolean) {
     const user = await UserModel.loadByVideoImportId(videoImport.id)
     if (!user) return
 
@@ -451,7 +458,7 @@ class Notifier {
         userId: user.id,
         videoImportId: videoImport.id
       })
-      notification.VideoImport = videoImport
+      notification.VideoImport = videoImport as VideoImportModel
 
       return notification
     }
@@ -465,13 +472,13 @@ class Notifier {
     return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
   }
 
-  private async notifyModeratorsOfNewUserRegistration (registeredUser: UserModel) {
+  private async notifyModeratorsOfNewUserRegistration (registeredUser: MUserAccount) {
     const moderators = await UserModel.listWithRight(UserRight.MANAGE_USERS)
     if (moderators.length === 0) return
 
     logger.info(
       'Notifying %s moderators of new user registration of %s.',
-      moderators.length, registeredUser.Account.Actor.preferredUsername
+      moderators.length, registeredUser.username
     )
 
     function settingGetter (user: UserModel) {
@@ -484,7 +491,7 @@ class Notifier {
         userId: user.id,
         accountId: registeredUser.Account.id
       })
-      notification.Account = registeredUser.Account
+      notification.Account = registeredUser.Account as AccountModel
 
       return notification
     }
@@ -497,10 +504,10 @@ class Notifier {
   }
 
   private async notify (options: {
-    users: UserModel[],
-    notificationCreator: (user: UserModel) => Promise<UserNotificationModel>,
+    users: MUserWithNotificationSetting[],
+    notificationCreator: (user: MUserWithNotificationSetting) => Promise<UserNotificationModelForApi>,
     emailSender: (emails: string[]) => Promise<any> | Bluebird<any>,
-    settingGetter: (user: UserModel) => UserNotificationSettingValue
+    settingGetter: (user: MUserWithNotificationSetting) => UserNotificationSettingValue
   }) {
     const emails: string[] = []
 
@@ -521,7 +528,7 @@ class Notifier {
     }
   }
 
-  private isEmailEnabled (user: UserModel, value: UserNotificationSettingValue) {
+  private isEmailEnabled (user: MUser, value: UserNotificationSettingValue) {
     if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION === true && user.emailVerified === false) return false
 
     return value & UserNotificationSettingValue.EMAIL
index a1153e88a73822f83738e51dffb3a3acccda1775..086856f41e3a0fc64469f450e6b8044f8a694ba2 100644 (file)
@@ -8,10 +8,11 @@ import { LRU_CACHE } from '../initializers/constants'
 import { Transaction } from 'sequelize'
 import { CONFIG } from '../initializers/config'
 import * as LRUCache from 'lru-cache'
+import { MOAuthTokenUser } from '@server/typings/models/oauth/oauth-token'
 
 type TokenInfo = { accessToken: string, refreshToken: string, accessTokenExpiresAt: Date, refreshTokenExpiresAt: Date }
 
-const accessTokenCache = new LRUCache<string, OAuthTokenModel>({ max: LRU_CACHE.USER_TOKENS.MAX_SIZE })
+const accessTokenCache = new LRUCache<string, MOAuthTokenUser>({ max: LRU_CACHE.USER_TOKENS.MAX_SIZE })
 const userHavingToken = new LRUCache<number, string>({ max: LRU_CACHE.USER_TOKENS.MAX_SIZE })
 
 // ---------------------------------------------------------------------------
index eb84ecd4bbb134a3216f2ca62576b9459f0a7274..1c7b09175720c287c74751a9a9f3042a334bd066 100644 (file)
@@ -1,8 +1,8 @@
 import * as SocketIO from 'socket.io'
 import { authenticateSocket } from '../middlewares'
-import { UserNotificationModel } from '../models/account/user-notification'
 import { logger } from '../helpers/logger'
 import { Server } from 'http'
+import { UserNotificationModelForApi } from '@server/typings/models/user'
 
 class PeerTubeSocket {
 
@@ -32,7 +32,7 @@ class PeerTubeSocket {
       })
   }
 
-  sendNotification (userId: number, notification: UserNotificationModel) {
+  sendNotification (userId: number, notification: UserNotificationModelForApi) {
     const socket = this.userNotificationSockets[userId]
 
     if (!socket) return
index 04d3ded8fabec8b0bf0f0b171c01257875510744..1b4ecd7c04875d6abc3e98475a3fc14a257fc373 100644 (file)
@@ -2,8 +2,9 @@ import { VideoRedundancyModel } from '../models/redundancy/video-redundancy'
 import { sendUndoCacheFile } from './activitypub/send'
 import { Transaction } from 'sequelize'
 import { getServerActor } from '../helpers/utils'
+import { MVideoRedundancyVideo } from '@server/typings/models'
 
-async function removeVideoRedundancy (videoRedundancy: VideoRedundancyModel, t?: Transaction) {
+async function removeVideoRedundancy (videoRedundancy: MVideoRedundancyVideo, t?: Transaction) {
   const serverActor = await getServerActor()
 
   // Local cache, send undo to remote instances
index 04f601bfb9266f8cd2ec693c38d813e75495737f..de8fc075b29a2f5a10ee48ac8570d827112fe544 100644 (file)
@@ -3,7 +3,6 @@ import { HLS_REDUNDANCY_DIRECTORY, REDUNDANCY, VIDEO_IMPORT_TIMEOUT, WEBSERVER }
 import { logger } from '../../helpers/logger'
 import { VideosRedundancy } from '../../../shared/models/redundancy'
 import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy'
-import { VideoFileModel } from '../../models/video/video-file'
 import { downloadWebTorrentVideo } from '../../helpers/webtorrent'
 import { join } from 'path'
 import { move } from 'fs-extra'
@@ -12,16 +11,29 @@ import { sendCreateCacheFile, sendUpdateCacheFile } from '../activitypub/send'
 import { getVideoCacheFileActivityPubUrl, getVideoCacheStreamingPlaylistActivityPubUrl } from '../activitypub/url'
 import { removeVideoRedundancy } from '../redundancy'
 import { getOrCreateVideoAndAccountAndChannel } from '../activitypub'
-import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist'
-import { VideoModel } from '../../models/video/video'
 import { downloadPlaylistSegments } from '../hls'
 import { CONFIG } from '../../initializers/config'
+import {
+  MStreamingPlaylist,
+  MStreamingPlaylistVideo,
+  MVideoAccountLight,
+  MVideoFile,
+  MVideoFileVideo,
+  MVideoRedundancyFileVideo,
+  MVideoRedundancyStreamingPlaylistVideo,
+  MVideoRedundancyVideo,
+  MVideoWithAllFiles
+} from '@server/typings/models'
 
 type CandidateToDuplicate = {
   redundancy: VideosRedundancy,
-  video: VideoModel,
-  files: VideoFileModel[],
-  streamingPlaylists: VideoStreamingPlaylistModel[]
+  video: MVideoWithAllFiles,
+  files: MVideoFile[],
+  streamingPlaylists: MStreamingPlaylist[]
+}
+
+function isMVideoRedundancyFileVideo (o: MVideoRedundancyVideo): o is MVideoRedundancyFileVideo {
+  return !!(o as MVideoRedundancyFileVideo).VideoFile
 }
 
 export class VideosRedundancyScheduler extends AbstractScheduler {
@@ -102,7 +114,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
     }
   }
 
-  private async extendsRedundancy (redundancyModel: VideoRedundancyModel) {
+  private async extendsRedundancy (redundancyModel: MVideoRedundancyVideo) {
     const redundancy = CONFIG.REDUNDANCY.VIDEOS.STRATEGIES.find(s => s.strategy === redundancyModel.strategy)
     // Redundancy strategy disabled, remove our redundancy instead of extending expiration
     if (!redundancy) {
@@ -172,7 +184,8 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
     }
   }
 
-  private async createVideoFileRedundancy (redundancy: VideosRedundancy, video: VideoModel, file: VideoFileModel) {
+  private async createVideoFileRedundancy (redundancy: VideosRedundancy, video: MVideoAccountLight, fileArg: MVideoFile) {
+    const file = fileArg as MVideoFileVideo
     file.Video = video
 
     const serverActor = await getServerActor()
@@ -187,7 +200,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
     const destPath = join(CONFIG.STORAGE.REDUNDANCY_DIR, video.getVideoFilename(file))
     await move(tmpPath, destPath)
 
-    const createdModel = await VideoRedundancyModel.create({
+    const createdModel: MVideoRedundancyFileVideo = await VideoRedundancyModel.create({
       expiresOn: this.buildNewExpiration(redundancy.minLifetime),
       url: getVideoCacheFileActivityPubUrl(file),
       fileUrl: video.getVideoRedundancyUrl(file, WEBSERVER.URL),
@@ -203,7 +216,12 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
     logger.info('Duplicated %s - %d -> %s.', video.url, file.resolution, createdModel.url)
   }
 
-  private async createStreamingPlaylistRedundancy (redundancy: VideosRedundancy, video: VideoModel, playlist: VideoStreamingPlaylistModel) {
+  private async createStreamingPlaylistRedundancy (
+    redundancy: VideosRedundancy,
+    video: MVideoAccountLight,
+    playlistArg: MStreamingPlaylist
+  ) {
+    const playlist = playlistArg as MStreamingPlaylistVideo
     playlist.Video = video
 
     const serverActor = await getServerActor()
@@ -213,7 +231,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
     const destDirectory = join(HLS_REDUNDANCY_DIRECTORY, video.uuid)
     await downloadPlaylistSegments(playlist.playlistUrl, destDirectory, VIDEO_IMPORT_TIMEOUT)
 
-    const createdModel = await VideoRedundancyModel.create({
+    const createdModel: MVideoRedundancyStreamingPlaylistVideo = await VideoRedundancyModel.create({
       expiresOn: this.buildNewExpiration(redundancy.minLifetime),
       url: getVideoCacheStreamingPlaylistActivityPubUrl(video, playlist),
       fileUrl: playlist.getVideoRedundancyUrl(WEBSERVER.URL),
@@ -229,7 +247,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
     logger.info('Duplicated playlist %s -> %s.', playlist.playlistUrl, createdModel.url)
   }
 
-  private async extendsExpirationOf (redundancy: VideoRedundancyModel, expiresAfterMs: number) {
+  private async extendsExpirationOf (redundancy: MVideoRedundancyVideo, expiresAfterMs: number) {
     logger.info('Extending expiration of %s.', redundancy.url)
 
     const serverActor = await getServerActor()
@@ -243,7 +261,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
   private async purgeCacheIfNeeded (candidateToDuplicate: CandidateToDuplicate) {
     while (this.isTooHeavy(candidateToDuplicate)) {
       const redundancy = candidateToDuplicate.redundancy
-      const toDelete = await VideoRedundancyModel.loadOldestLocalThatAlreadyExpired(redundancy.strategy, redundancy.minLifetime)
+      const toDelete = await VideoRedundancyModel.loadOldestLocalExpired(redundancy.strategy, redundancy.minLifetime)
       if (!toDelete) return
 
       await removeVideoRedundancy(toDelete)
@@ -263,14 +281,14 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
     return new Date(Date.now() + expiresAfterMs)
   }
 
-  private buildEntryLogId (object: VideoRedundancyModel) {
-    if (object.VideoFile) return `${object.VideoFile.Video.url}-${object.VideoFile.resolution}`
+  private buildEntryLogId (object: MVideoRedundancyFileVideo | MVideoRedundancyStreamingPlaylistVideo) {
+    if (isMVideoRedundancyFileVideo(object)) return `${object.VideoFile.Video.url}-${object.VideoFile.resolution}`
 
     return `${object.VideoStreamingPlaylist.playlistUrl}`
   }
 
-  private getTotalFileSizes (files: VideoFileModel[], playlists: VideoStreamingPlaylistModel[]) {
-    const fileReducer = (previous: number, current: VideoFileModel) => previous + current.size
+  private getTotalFileSizes (files: MVideoFile[], playlists: MStreamingPlaylist[]) {
+    const fileReducer = (previous: number, current: MVideoFile) => previous + current.size
 
     const totalSize = files.reduce(fileReducer, 0)
     if (playlists.length === 0) return totalSize
index a59773f5a5512f086dd8159855274a2108e8de63..84791955e0cc00c908b9882dae22377b93dd9188 100644 (file)
@@ -1,20 +1,20 @@
-import { VideoFileModel } from '../models/video/video-file'
 import { generateImageFromVideoFile } from '../helpers/ffmpeg-utils'
 import { CONFIG } from '../initializers/config'
-import { PREVIEWS_SIZE, THUMBNAILS_SIZE, ASSETS_PATH } from '../initializers/constants'
-import { VideoModel } from '../models/video/video'
+import { ASSETS_PATH, PREVIEWS_SIZE, THUMBNAILS_SIZE } from '../initializers/constants'
 import { ThumbnailModel } from '../models/video/thumbnail'
 import { ThumbnailType } from '../../shared/models/videos/thumbnail.type'
 import { processImage } from '../helpers/image-utils'
 import { join } from 'path'
 import { downloadImage } from '../helpers/requests'
-import { VideoPlaylistModel } from '../models/video/video-playlist'
+import { MVideoPlaylistThumbnail } from '../typings/models/video/video-playlist'
+import { MVideoFile, MVideoThumbnail } from '../typings/models'
+import { MThumbnail } from '../typings/models/video/thumbnail'
 
 type ImageSize = { height: number, width: number }
 
 function createPlaylistMiniatureFromExisting (
   inputPath: string,
-  playlist: VideoPlaylistModel,
+  playlist: MVideoPlaylistThumbnail,
   automaticallyGenerated: boolean,
   keepOriginal = false,
   size?: ImageSize
@@ -26,7 +26,7 @@ function createPlaylistMiniatureFromExisting (
   return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, automaticallyGenerated, existingThumbnail })
 }
 
-function createPlaylistMiniatureFromUrl (fileUrl: string, playlist: VideoPlaylistModel, size?: ImageSize) {
+function createPlaylistMiniatureFromUrl (fileUrl: string, playlist: MVideoPlaylistThumbnail, size?: ImageSize) {
   const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size)
   const type = ThumbnailType.MINIATURE
 
@@ -34,7 +34,7 @@ function createPlaylistMiniatureFromUrl (fileUrl: string, playlist: VideoPlaylis
   return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, fileUrl })
 }
 
-function createVideoMiniatureFromUrl (fileUrl: string, video: VideoModel, type: ThumbnailType, size?: ImageSize) {
+function createVideoMiniatureFromUrl (fileUrl: string, video: MVideoThumbnail, type: ThumbnailType, size?: ImageSize) {
   const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
   const thumbnailCreator = () => downloadImage(fileUrl, basePath, filename, { width, height })
 
@@ -43,7 +43,7 @@ function createVideoMiniatureFromUrl (fileUrl: string, video: VideoModel, type:
 
 function createVideoMiniatureFromExisting (
   inputPath: string,
-  video: VideoModel,
+  video: MVideoThumbnail,
   type: ThumbnailType,
   automaticallyGenerated: boolean,
   size?: ImageSize
@@ -54,7 +54,7 @@ function createVideoMiniatureFromExisting (
   return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, automaticallyGenerated, existingThumbnail })
 }
 
-function generateVideoMiniature (video: VideoModel, videoFile: VideoFileModel, type: ThumbnailType) {
+function generateVideoMiniature (video: MVideoThumbnail, videoFile: MVideoFile, type: ThumbnailType) {
   const input = video.getVideoFilePath(videoFile)
 
   const { filename, basePath, height, width, existingThumbnail, outputPath } = buildMetadataFromVideo(video, type)
@@ -65,7 +65,7 @@ function generateVideoMiniature (video: VideoModel, videoFile: VideoFileModel, t
   return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, automaticallyGenerated: true, existingThumbnail })
 }
 
-function createPlaceholderThumbnail (fileUrl: string, video: VideoModel, type: ThumbnailType, size: ImageSize) {
+function createPlaceholderThumbnail (fileUrl: string, video: MVideoThumbnail, type: ThumbnailType, size: ImageSize) {
   const { filename, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
 
   const thumbnail = existingThumbnail ? existingThumbnail : new ThumbnailModel()
@@ -90,7 +90,7 @@ export {
   createPlaylistMiniatureFromExisting
 }
 
-function buildMetadataFromPlaylist (playlist: VideoPlaylistModel, size: ImageSize) {
+function buildMetadataFromPlaylist (playlist: MVideoPlaylistThumbnail, size: ImageSize) {
   const filename = playlist.generateThumbnailName()
   const basePath = CONFIG.STORAGE.THUMBNAILS_DIR
 
@@ -104,7 +104,7 @@ function buildMetadataFromPlaylist (playlist: VideoPlaylistModel, size: ImageSiz
   }
 }
 
-function buildMetadataFromVideo (video: VideoModel, type: ThumbnailType, size?: ImageSize) {
+function buildMetadataFromVideo (video: MVideoThumbnail, type: ThumbnailType, size?: ImageSize) {
   const existingThumbnail = Array.isArray(video.Thumbnails)
     ? video.Thumbnails.find(t => t.type === type)
     : undefined
@@ -148,7 +148,7 @@ async function createThumbnailFromFunction (parameters: {
   type: ThumbnailType,
   automaticallyGenerated?: boolean,
   fileUrl?: string,
-  existingThumbnail?: ThumbnailModel
+  existingThumbnail?: MThumbnail
 }) {
   const { thumbnailCreator, filename, width, height, type, existingThumbnail, automaticallyGenerated = null, fileUrl = null } = parameters
 
index 0e40077707fc823a8719674a891437821e004def..266974cacecfd9767b4cb29e1e73708d7b3c1e3b 100644 (file)
@@ -5,7 +5,6 @@ import { AccountModel } from '../models/account/account'
 import { UserModel } from '../models/account/user'
 import { buildActorInstance, getAccountActivityPubUrl, setAsyncActorKeys } from './activitypub'
 import { createVideoChannel } from './video-channel'
-import { VideoChannelModel } from '../models/video/video-channel'
 import { ActorModel } from '../models/activitypub/actor'
 import { UserNotificationSettingModel } from '../models/account/user-notification-setting'
 import { UserNotificationSetting, UserNotificationSettingValue } from '../../shared/models/users'
@@ -14,14 +13,17 @@ import { sequelizeTypescript } from '../initializers/database'
 import { Transaction } from 'sequelize/types'
 import { Redis } from './redis'
 import { Emailer } from './emailer'
+import { MAccountActor, MActor, MChannelActor } from '../typings/models'
+import { MUser, MUserId, MUserNotifSettingAccount } from '../typings/models/user'
 
 type ChannelNames = { name: string, displayName: string }
+
 async function createUserAccountAndChannelAndPlaylist (parameters: {
   userToCreate: UserModel,
   userDisplayName?: string,
   channelNames?: ChannelNames,
   validateUser?: boolean
-}) {
+}): Promise<{ user: MUserNotifSettingAccount, account: MAccountActor, videoChannel: MChannelActor }> {
   const { userToCreate, userDisplayName, channelNames, validateUser = true } = parameters
 
   const { user, account, videoChannel } = await sequelizeTypescript.transaction(async t => {
@@ -30,7 +32,7 @@ async function createUserAccountAndChannelAndPlaylist (parameters: {
       validate: validateUser
     }
 
-    const userCreated = await userToCreate.save(userOptions)
+    const userCreated: MUserNotifSettingAccount = await userToCreate.save(userOptions)
     userCreated.NotificationSetting = await createDefaultUserNotificationSettings(userCreated, t)
 
     const accountCreated = await createLocalAccountWithoutKeys({
@@ -50,15 +52,15 @@ async function createUserAccountAndChannelAndPlaylist (parameters: {
     return { user: userCreated, account: accountCreated, videoChannel, videoPlaylist }
   })
 
-  const [ accountKeys, channelKeys ] = await Promise.all([
+  const [ accountActorWithKeys, channelActorWithKeys ] = await Promise.all([
     setAsyncActorKeys(account.Actor),
     setAsyncActorKeys(videoChannel.Actor)
   ])
 
-  account.Actor = accountKeys
-  videoChannel.Actor = channelKeys
+  account.Actor = accountActorWithKeys
+  videoChannel.Actor = channelActorWithKeys
 
-  return { user, account, videoChannel } as { user: UserModel, account: AccountModel, videoChannel: VideoChannelModel }
+  return { user, account, videoChannel }
 }
 
 async function createLocalAccountWithoutKeys (parameters: {
@@ -73,7 +75,7 @@ async function createLocalAccountWithoutKeys (parameters: {
   const url = getAccountActivityPubUrl(name)
 
   const actorInstance = buildActorInstance(type, url, name)
-  const actorInstanceCreated = await actorInstance.save({ transaction: t })
+  const actorInstanceCreated: MActor = await actorInstance.save({ transaction: t })
 
   const accountInstance = new AccountModel({
     name: displayName || name,
@@ -82,7 +84,7 @@ async function createLocalAccountWithoutKeys (parameters: {
     actorId: actorInstanceCreated.id
   })
 
-  const accountInstanceCreated = await accountInstance.save({ transaction: t })
+  const accountInstanceCreated: MAccountActor = await accountInstance.save({ transaction: t })
   accountInstanceCreated.Actor = actorInstanceCreated
 
   return accountInstanceCreated
@@ -102,7 +104,7 @@ async function createApplicationActor (applicationId: number) {
   return accountCreated
 }
 
-async function sendVerifyUserEmail (user: UserModel, isPendingEmail = false) {
+async function sendVerifyUserEmail (user: MUser, isPendingEmail = false) {
   const verificationString = await Redis.Instance.setVerifyEmailVerificationString(user.id)
   let url = WEBSERVER.URL + '/verify-account/email?userId=' + user.id + '&verificationString=' + verificationString
 
@@ -124,7 +126,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function createDefaultUserNotificationSettings (user: UserModel, t: Transaction | undefined) {
+function createDefaultUserNotificationSettings (user: MUserId, t: Transaction | undefined) {
   const values: UserNotificationSetting & { userId: number } = {
     userId: user.id,
     newVideoFromSubscription: UserNotificationSettingValue.WEB,
@@ -143,7 +145,7 @@ function createDefaultUserNotificationSettings (user: UserModel, t: Transaction
   return UserNotificationSettingModel.create(values, { transaction: t })
 }
 
-async function buildChannelAttributes (user: UserModel, channelNames?: ChannelNames) {
+async function buildChannelAttributes (user: MUser, channelNames?: ChannelNames) {
   if (channelNames) return channelNames
 
   let channelName = user.username + '_channel'
index bdaecd8e24bef5351c9a582e22b77691479c24e0..a0fc26e84a4ad2bca309db8f1c65d90ff8e390af 100644 (file)
@@ -2,16 +2,15 @@ import { Transaction } from 'sequelize'
 import { CONFIG } from '../initializers/config'
 import { UserRight, VideoBlacklistType } from '../../shared/models'
 import { VideoBlacklistModel } from '../models/video/video-blacklist'
-import { UserModel } from '../models/account/user'
-import { VideoModel } from '../models/video/video'
 import { logger } from '../helpers/logger'
 import { UserAdminFlag } from '../../shared/models/users/user-flag.model'
 import { Hooks } from './plugins/hooks'
 import { Notifier } from './notifier'
+import { MUser, MVideoBlacklist, MVideoWithBlacklistLight } from '@server/typings/models'
 
 async function autoBlacklistVideoIfNeeded (parameters: {
-  video: VideoModel,
-  user?: UserModel,
+  video: MVideoWithBlacklistLight,
+  user?: MUser,
   isRemote: boolean,
   isNew: boolean,
   notify?: boolean,
@@ -32,7 +31,7 @@ async function autoBlacklistVideoIfNeeded (parameters: {
     reason: 'Auto-blacklisted. Moderator review required.',
     type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
   }
-  const [ videoBlacklist ] = await VideoBlacklistModel.findOrCreate({
+  const [ videoBlacklist ] = await VideoBlacklistModel.findOrCreate<MVideoBlacklist>({
     where: {
       videoId: video.id
     },
@@ -49,10 +48,10 @@ async function autoBlacklistVideoIfNeeded (parameters: {
 }
 
 async function autoBlacklistNeeded (parameters: {
-  video: VideoModel,
+  video: MVideoWithBlacklistLight,
   isRemote: boolean,
   isNew: boolean,
-  user?: UserModel
+  user?: MUser
 }) {
   const { user, video, isRemote, isNew } = parameters
 
index ee0482c3612919b3715eb64aca12e59aa178ef0d..ee8eb656825850ae136f125122fd645575e2012b 100644 (file)
@@ -1,12 +1,19 @@
 import * as Sequelize from 'sequelize'
 import * as uuidv4 from 'uuid/v4'
 import { VideoChannelCreate } from '../../shared/models'
-import { AccountModel } from '../models/account/account'
 import { VideoChannelModel } from '../models/video/video-channel'
 import { buildActorInstance, federateVideoIfNeeded, getVideoChannelActivityPubUrl } from './activitypub'
 import { VideoModel } from '../models/video/video'
+import { MAccountId, MChannelActor, MChannelId } from '../typings/models'
 
-async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account: AccountModel, t: Sequelize.Transaction) {
+type CustomVideoChannelModelAccount <T extends MAccountId> = MChannelActor &
+  { Account?: T }
+
+async function createVideoChannel <T extends MAccountId> (
+  videoChannelInfo: VideoChannelCreate,
+  account: T,
+  t: Sequelize.Transaction
+): Promise<CustomVideoChannelModelAccount<T>> {
   const uuid = uuidv4()
   const url = getVideoChannelActivityPubUrl(videoChannelInfo.name)
   const actorInstance = buildActorInstance('Group', url, videoChannelInfo.name, uuid)
@@ -21,10 +28,10 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account
     actorId: actorInstanceCreated.id
   }
 
-  const videoChannel = VideoChannelModel.build(videoChannelData)
+  const videoChannel = new VideoChannelModel(videoChannelData)
 
   const options = { transaction: t }
-  const videoChannelCreated = await videoChannel.save(options)
+  const videoChannelCreated: CustomVideoChannelModelAccount<T> = await videoChannel.save(options) as MChannelActor
 
   // Do not forget to add Account/Actor information to the created video channel
   videoChannelCreated.Account = account
@@ -34,7 +41,7 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account
   return videoChannelCreated
 }
 
-async function federateAllVideosOfChannel (videoChannel: VideoChannelModel) {
+async function federateAllVideosOfChannel (videoChannel: MChannelId) {
   const videoIds = await VideoModel.getAllIdsFromChannel(videoChannel)
 
   for (const videoId of videoIds) {
index 449aa74cb10a1f503bf48e58fd6229078c380f1f..bb811bd2c3d4b5749eb075b56cf3e428d15d80fe 100644 (file)
@@ -1,17 +1,16 @@
 import * as Sequelize from 'sequelize'
 import { ResultList } from '../../shared/models'
 import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model'
-import { AccountModel } from '../models/account/account'
-import { VideoModel } from '../models/video/video'
 import { VideoCommentModel } from '../models/video/video-comment'
 import { getVideoCommentActivityPubUrl } from './activitypub'
 import { sendCreateVideoComment } from './activitypub/send'
+import { MAccountDefault, MComment, MCommentOwnerVideoReply, MVideoFullLight } from '../typings/models'
 
 async function createVideoComment (obj: {
   text: string,
-  inReplyToComment: VideoCommentModel | null,
-  video: VideoModel
-  account: AccountModel
+  inReplyToComment: MComment | null,
+  video: MVideoFullLight,
+  account: MAccountDefault
 }, t: Sequelize.Transaction) {
   let originCommentId: number | null = null
   let inReplyToCommentId: number | null = null
@@ -32,7 +31,7 @@ async function createVideoComment (obj: {
 
   comment.url = getVideoCommentActivityPubUrl(obj.video, comment)
 
-  const savedComment = await comment.save({ transaction: t })
+  const savedComment: MCommentOwnerVideoReply = await comment.save({ transaction: t })
   savedComment.InReplyToVideoComment = obj.inReplyToComment
   savedComment.Video = obj.video
   savedComment.Account = obj.account
index 6e214e60f226c852235641a714a63eb1f55f6bf2..29b70cfda0b4bd3507769c6012326d7cc0a73d1c 100644 (file)
@@ -1,12 +1,13 @@
 import * as Sequelize from 'sequelize'
-import { AccountModel } from '../models/account/account'
 import { VideoPlaylistModel } from '../models/video/video-playlist'
 import { VideoPlaylistPrivacy } from '../../shared/models/videos/playlist/video-playlist-privacy.model'
 import { getVideoPlaylistActivityPubUrl } from './activitypub'
 import { VideoPlaylistType } from '../../shared/models/videos/playlist/video-playlist-type.model'
+import { MAccount } from '../typings/models'
+import { MVideoPlaylistOwner } from '../typings/models/video/video-playlist'
 
-async function createWatchLaterPlaylist (account: AccountModel, t: Sequelize.Transaction) {
-  const videoPlaylist = new VideoPlaylistModel({
+async function createWatchLaterPlaylist (account: MAccount, t: Sequelize.Transaction) {
+  const videoPlaylist: MVideoPlaylistOwner = new VideoPlaylistModel({
     name: 'Watch later',
     privacy: VideoPlaylistPrivacy.PRIVATE,
     type: VideoPlaylistType.WATCH_LATER,
index ba6b29163c880c4ec3fb8bbfe2b2bf74abed89c4..a204c0c634d473aa8fdb901eb4811bffa31fe21e 100644 (file)
@@ -5,16 +5,16 @@ import { ensureDir, move, remove, stat } from 'fs-extra'
 import { logger } from '../helpers/logger'
 import { VideoResolution } from '../../shared/models/videos'
 import { VideoFileModel } from '../models/video/video-file'
-import { VideoModel } from '../models/video/video'
 import { updateMasterHLSPlaylist, updateSha256Segments } from './hls'
 import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist'
 import { VideoStreamingPlaylistType } from '../../shared/models/videos/video-streaming-playlist.type'
 import { CONFIG } from '../initializers/config'
+import { MVideoFile, MVideoWithFile, MVideoWithFileThumbnail } from '@server/typings/models'
 
 /**
  * Optimize the original video file and replace it. The resolution is not changed.
  */
-async function optimizeVideofile (video: VideoModel, inputVideoFileArg?: VideoFileModel) {
+async function optimizeVideofile (video: MVideoWithFile, inputVideoFileArg?: MVideoFile) {
   const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
   const transcodeDirectory = CONFIG.STORAGE.TMP_DIR
   const newExtname = '.mp4'
@@ -57,7 +57,7 @@ async function optimizeVideofile (video: VideoModel, inputVideoFileArg?: VideoFi
 /**
  * Transcode the original video file to a lower resolution.
  */
-async function transcodeOriginalVideofile (video: VideoModel, resolution: VideoResolution, isPortrait: boolean) {
+async function transcodeOriginalVideofile (video: MVideoWithFile, resolution: VideoResolution, isPortrait: boolean) {
   const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
   const transcodeDirectory = CONFIG.STORAGE.TMP_DIR
   const extname = '.mp4'
@@ -87,7 +87,7 @@ async function transcodeOriginalVideofile (video: VideoModel, resolution: VideoR
   return onVideoFileTranscoding(video, newVideoFile, videoTranscodedPath, videoOutputPath)
 }
 
-async function mergeAudioVideofile (video: VideoModel, resolution: VideoResolution) {
+async function mergeAudioVideofile (video: MVideoWithFileThumbnail, resolution: VideoResolution) {
   const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
   const transcodeDirectory = CONFIG.STORAGE.TMP_DIR
   const newExtname = '.mp4'
@@ -117,7 +117,7 @@ async function mergeAudioVideofile (video: VideoModel, resolution: VideoResoluti
   return onVideoFileTranscoding(video, inputVideoFile, videoTranscodedPath, videoOutputPath)
 }
 
-async function generateHlsPlaylist (video: VideoModel, resolution: VideoResolution, isPortraitMode: boolean) {
+async function generateHlsPlaylist (video: MVideoWithFile, resolution: VideoResolution, isPortraitMode: boolean) {
   const baseHlsDirectory = join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid)
   await ensureDir(join(HLS_STREAMING_PLAYLIST_DIRECTORY, video.uuid))
 
@@ -165,14 +165,14 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function onVideoFileTranscoding (video: VideoModel, videoFile: VideoFileModel, transcodingPath: string, outputPath: string) {
+async function onVideoFileTranscoding (video: MVideoWithFile, videoFile: MVideoFile, transcodingPath: string, outputPath: string) {
   const stats = await stat(transcodingPath)
   const fps = await getVideoFileFPS(transcodingPath)
 
   await move(transcodingPath, outputPath)
 
-  videoFile.set('size', stats.size)
-  videoFile.set('fps', fps)
+  videoFile.size = stats.size
+  videoFile.fps = fps
 
   await video.createTorrentAndSetInfoHash(videoFile)
 
index c3d772297eb303fbf904316ba02a3b5714daea86..7887356630a54191824bdf3d039247f4ddd7fe19 100644 (file)
@@ -10,6 +10,7 @@ import { areValidationErrors } from './utils'
 import { ActorModel } from '../../models/activitypub/actor'
 import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger'
 import { isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor'
+import { MActorFollowActorsDefault } from '@server/typings/models'
 
 const followValidator = [
   body('hosts').custom(isEachUniqueHostValid).withMessage('Should have an array of unique hosts'),
@@ -65,7 +66,7 @@ const getFollowerValidator = [
 
     if (areValidationErrors(req, res)) return
 
-    let follow: ActorFollowModel
+    let follow: MActorFollowActorsDefault
     try {
       const actorUrl = await loadActorUrlOrGetFromWebfinger(req.params.nameWithHost)
       const actor = await ActorModel.loadByUrl(actorUrl)
index 1fdac0e4e2c38f38ad3c9a6f03130ee4f87b5900..e65d3b8d3d874c4495f3e11e1f2890e19e307cc1 100644 (file)
@@ -24,7 +24,7 @@ const videoFileRedundancyGetValidator = [
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
 
-    const video = res.locals.video
+    const video = res.locals.videoAll
     const videoFile = video.VideoFiles.find(f => {
       return f.resolution === req.params.resolution && (!req.params.fps || f.fps === req.params.fps)
     })
@@ -50,7 +50,7 @@ const videoPlaylistRedundancyGetValidator = [
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
 
-    const video = res.locals.video
+    const video = res.locals.videoAll
     const videoStreamingPlaylist = video.VideoStreamingPlaylists.find(p => p === req.params.streamingPlaylistType)
 
     if (!videoStreamingPlaylist) return res.status(404).json({ error: 'Video playlist not found.' })
index 16d2970470681af6962e7cdd144ef3ff2ae7a67f..40dd0f0e96b85413aab764cd11019925c6b68807 100644 (file)
@@ -2,7 +2,7 @@ import * as Bluebird from 'bluebird'
 import * as express from 'express'
 import { body, param } from 'express-validator'
 import { omit } from 'lodash'
-import { isIdOrUUIDValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
+import { isIdOrUUIDValid, toBooleanOrNull } from '../../helpers/custom-validators/misc'
 import {
   isUserAdminFlagsValid,
   isUserAutoPlayVideoValid,
@@ -31,6 +31,7 @@ import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
 import { isThemeRegistered } from '../../lib/plugins/theme-utils'
 import { doesVideoExist } from '../../helpers/middlewares'
 import { UserRole } from '../../../shared/models/users'
+import { MUserDefault } from '@server/typings/models'
 
 const usersAddValidator = [
   body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'),
@@ -457,7 +458,7 @@ async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email:
   return true
 }
 
-async function checkUserExist (finder: () => Bluebird<UserModel>, res: express.Response, abortResponse = true) {
+async function checkUserExist (finder: () => Bluebird<MUserDefault>, res: express.Response, abortResponse = true) {
   const user = await finder()
 
   if (!user) {
index e27d91bb12cb4e3820de54d3e6b6f78e6fe8b448..a4aef4024a8d9e470cbe1c3f0163df9bd1e0d699 100644 (file)
@@ -33,7 +33,7 @@ const videoAbuseGetValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
-    if (!await doesVideoAbuseExist(req.params.id, res.locals.video.id, res)) return
+    if (!await doesVideoAbuseExist(req.params.id, res.locals.videoAll.id, res)) return
 
     return next()
   }
@@ -54,7 +54,7 @@ const videoAbuseUpdateValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
-    if (!await doesVideoAbuseExist(req.params.id, res.locals.video.id, res)) return
+    if (!await doesVideoAbuseExist(req.params.id, res.locals.videoAll.id, res)) return
 
     return next()
   }
index 3e8c5b30c96942b4f0de830b0a906206dd0456d8..5440e57e7b9b870365a60bc9f3ec20acba1ffaf1 100644 (file)
@@ -14,7 +14,7 @@ const videosBlacklistRemoveValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
-    if (!await doesVideoBlacklistExist(res.locals.video.id, res)) return
+    if (!await doesVideoBlacklistExist(res.locals.videoAll.id, res)) return
 
     return next()
   }
@@ -36,7 +36,7 @@ const videosBlacklistAddValidator = [
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
 
-    const video = res.locals.video
+    const video = res.locals.videoAll
     if (req.body.unfederate === true && video.remote === true) {
       return res
         .status(409)
@@ -59,7 +59,7 @@ const videosBlacklistUpdateValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
-    if (!await doesVideoBlacklistExist(res.locals.video.id, res)) return
+    if (!await doesVideoBlacklistExist(res.locals.videoAll.id, res)) return
 
     return next()
   }
index f5610222aceb4f0bfede12862d14869fa8b9a38e..2fb1da5ce403581efa9f503f5a4871e8231b69ef 100644 (file)
@@ -26,7 +26,7 @@ const addVideoCaptionValidator = [
 
     // Check if the user who did the request is able to update the video
     const user = res.locals.oauth.token.User
-    if (!checkUserCanManageVideo(user, res.locals.video, UserRight.UPDATE_ANY_VIDEO, res)) return cleanUpReqFiles(req)
+    if (!checkUserCanManageVideo(user, res.locals.videoAll, UserRight.UPDATE_ANY_VIDEO, res)) return cleanUpReqFiles(req)
 
     return next()
   }
@@ -41,11 +41,11 @@ const deleteVideoCaptionValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
-    if (!await doesVideoCaptionExist(res.locals.video, req.params.captionLanguage, res)) return
+    if (!await doesVideoCaptionExist(res.locals.videoAll, req.params.captionLanguage, res)) return
 
     // Check if the user who did the request is able to update the video
     const user = res.locals.oauth.token.User
-    if (!checkUserCanManageVideo(user, res.locals.video, UserRight.UPDATE_ANY_VIDEO, res)) return
+    if (!checkUserCanManageVideo(user, res.locals.videoAll, UserRight.UPDATE_ANY_VIDEO, res)) return
 
     return next()
   }
index 3ee5064fc6990002c519cde97d359dab0bdd6329..a0df03f7ebc68e879d81d1aa931b37894e2a9832 100644 (file)
@@ -7,13 +7,14 @@ import {
   isVideoChannelSupportValid
 } from '../../../helpers/custom-validators/video-channels'
 import { logger } from '../../../helpers/logger'
-import { UserModel } from '../../../models/account/user'
 import { VideoChannelModel } from '../../../models/video/video-channel'
 import { areValidationErrors } from '../utils'
 import { isActorPreferredUsernameValid } from '../../../helpers/custom-validators/activitypub/actor'
 import { ActorModel } from '../../../models/activitypub/actor'
 import { isBooleanValid } from '../../../helpers/custom-validators/misc'
 import { doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } from '../../../helpers/middlewares'
+import { MChannelActorAccountDefault } from '../../../typings/models/video'
+import { MUser } from '@server/typings/models'
 
 const videoChannelsAddValidator = [
   body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'),
@@ -131,7 +132,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function checkUserCanDeleteVideoChannel (user: UserModel, videoChannel: VideoChannelModel, res: express.Response) {
+function checkUserCanDeleteVideoChannel (user: MUser, videoChannel: MChannelActorAccountDefault, res: express.Response) {
   if (videoChannel.Actor.isOwned() === false) {
     res.status(403)
               .json({ error: 'Cannot remove video channel of another server.' })
index 83a0c24b030ca49a05467fb79a1329a10b9be9df..8adbb02ba13187a67ff4ad6d6732c12bc3b57ec8 100644 (file)
@@ -4,13 +4,13 @@ import { UserRight } from '../../../../shared'
 import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc'
 import { isValidVideoCommentText } from '../../../helpers/custom-validators/video-comments'
 import { logger } from '../../../helpers/logger'
-import { UserModel } from '../../../models/account/user'
-import { VideoModel } from '../../../models/video/video'
 import { VideoCommentModel } from '../../../models/video/video-comment'
 import { areValidationErrors } from '../utils'
 import { Hooks } from '../../../lib/plugins/hooks'
-import { isLocalVideoThreadAccepted, isLocalVideoCommentReplyAccepted, AcceptResult } from '../../../lib/moderation'
+import { AcceptResult, isLocalVideoCommentReplyAccepted, isLocalVideoThreadAccepted } from '../../../lib/moderation'
 import { doesVideoExist } from '../../../helpers/middlewares'
+import { MCommentOwner, MVideo, MVideoFullLight, MVideoId } from '../../../typings/models/video'
+import { MUser } from '@server/typings/models'
 
 const listVideoCommentThreadsValidator = [
   param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
@@ -34,7 +34,7 @@ const listVideoThreadCommentsValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res, 'only-video')) return
-    if (!await doesVideoCommentThreadExist(req.params.threadId, res.locals.video, res)) return
+    if (!await doesVideoCommentThreadExist(req.params.threadId, res.locals.onlyVideo, res)) return
 
     return next()
   }
@@ -49,8 +49,8 @@ const addVideoCommentThreadValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
-    if (!isVideoCommentsEnabled(res.locals.video, res)) return
-    if (!await isVideoCommentAccepted(req, res, false)) return
+    if (!isVideoCommentsEnabled(res.locals.videoAll, res)) return
+    if (!await isVideoCommentAccepted(req, res, res.locals.videoAll,false)) return
 
     return next()
   }
@@ -66,9 +66,9 @@ const addVideoCommentReplyValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
-    if (!isVideoCommentsEnabled(res.locals.video, res)) return
-    if (!await doesVideoCommentExist(req.params.commentId, res.locals.video, res)) return
-    if (!await isVideoCommentAccepted(req, res, true)) return
+    if (!isVideoCommentsEnabled(res.locals.videoAll, res)) return
+    if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoAll, res)) return
+    if (!await isVideoCommentAccepted(req, res, res.locals.videoAll, true)) return
 
     return next()
   }
@@ -83,7 +83,7 @@ const videoCommentGetValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res, 'id')) return
-    if (!await doesVideoCommentExist(req.params.commentId, res.locals.video, res)) return
+    if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoId, res)) return
 
     return next()
   }
@@ -98,10 +98,10 @@ const removeVideoCommentValidator = [
 
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.videoId, res)) return
-    if (!await doesVideoCommentExist(req.params.commentId, res.locals.video, res)) return
+    if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoAll, res)) return
 
     // Check if the user who did the request is able to delete the video
-    if (!checkUserCanDeleteVideoComment(res.locals.oauth.token.User, res.locals.videoComment, res)) return
+    if (!checkUserCanDeleteVideoComment(res.locals.oauth.token.User, res.locals.videoCommentFull, res)) return
 
     return next()
   }
@@ -120,7 +120,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-async function doesVideoCommentThreadExist (id: number, video: VideoModel, res: express.Response) {
+async function doesVideoCommentThreadExist (id: number, video: MVideoId, res: express.Response) {
   const videoComment = await VideoCommentModel.loadById(id)
 
   if (!videoComment) {
@@ -151,7 +151,7 @@ async function doesVideoCommentThreadExist (id: number, video: VideoModel, res:
   return true
 }
 
-async function doesVideoCommentExist (id: number, video: VideoModel, res: express.Response) {
+async function doesVideoCommentExist (id: number, video: MVideoId, res: express.Response) {
   const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id)
 
   if (!videoComment) {
@@ -170,11 +170,11 @@ async function doesVideoCommentExist (id: number, video: VideoModel, res: expres
     return false
   }
 
-  res.locals.videoComment = videoComment
+  res.locals.videoCommentFull = videoComment
   return true
 }
 
-function isVideoCommentsEnabled (video: VideoModel, res: express.Response) {
+function isVideoCommentsEnabled (video: MVideo, res: express.Response) {
   if (video.commentsEnabled !== true) {
     res.status(409)
       .json({ error: 'Video comments are disabled for this video.' })
@@ -186,7 +186,7 @@ function isVideoCommentsEnabled (video: VideoModel, res: express.Response) {
   return true
 }
 
-function checkUserCanDeleteVideoComment (user: UserModel, videoComment: VideoCommentModel, res: express.Response) {
+function checkUserCanDeleteVideoComment (user: MUser, videoComment: MCommentOwner, res: express.Response) {
   const account = videoComment.Account
   if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) === false && account.userId !== user.id) {
     res.status(403)
@@ -198,9 +198,9 @@ function checkUserCanDeleteVideoComment (user: UserModel, videoComment: VideoCom
   return true
 }
 
-async function isVideoCommentAccepted (req: express.Request, res: express.Response, isReply: boolean) {
+async function isVideoCommentAccepted (req: express.Request, res: express.Response, video: MVideoFullLight, isReply: boolean) {
   const acceptParameters = {
-    video: res.locals.video,
+    video,
     commentBody: req.body,
     user: res.locals.oauth.token.User
   }
@@ -208,7 +208,7 @@ async function isVideoCommentAccepted (req: express.Request, res: express.Respon
   let acceptedResult: AcceptResult
 
   if (isReply) {
-    const acceptReplyParameters = Object.assign(acceptParameters, { parentComment: res.locals.videoComment })
+    const acceptReplyParameters = Object.assign(acceptParameters, { parentComment: res.locals.videoCommentFull })
 
     acceptedResult = await Hooks.wrapFun(
       isLocalVideoCommentReplyAccepted,
index 5823795be4a7af41c59b3036711effed4539f285..ca36d419a98438d40756ae211583984e808f130d 100644 (file)
@@ -2,7 +2,6 @@ import * as express from 'express'
 import { body, param, query, ValidationChain } from 'express-validator'
 import { UserRight, VideoPlaylistCreate, VideoPlaylistUpdate } from '../../../../shared'
 import { logger } from '../../../helpers/logger'
-import { UserModel } from '../../../models/account/user'
 import { areValidationErrors } from '../utils'
 import { isVideoImage } from '../../../helpers/custom-validators/videos'
 import { CONSTRAINTS_FIELDS } from '../../../initializers/constants'
@@ -22,13 +21,14 @@ import {
   isVideoPlaylistTimestampValid,
   isVideoPlaylistTypeValid
 } from '../../../helpers/custom-validators/video-playlists'
-import { VideoPlaylistModel } from '../../../models/video/video-playlist'
 import { cleanUpReqFiles } from '../../../helpers/express-utils'
 import { VideoPlaylistElementModel } from '../../../models/video/video-playlist-element'
 import { authenticatePromiseIfNeeded } from '../../oauth'
 import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
 import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model'
-import { doesVideoChannelIdExist, doesVideoExist, doesVideoPlaylistExist } from '../../../helpers/middlewares'
+import { doesVideoChannelIdExist, doesVideoExist, doesVideoPlaylistExist, VideoPlaylistFetchType } from '../../../helpers/middlewares'
+import { MVideoPlaylist } from '../../../typings/models/video/video-playlist'
+import { MUserAccountId } from '@server/typings/models'
 
 const videoPlaylistsAddValidator = getCommonPlaylistEditAttributes().concat([
   body('displayName')
@@ -67,9 +67,9 @@ const videoPlaylistsUpdateValidator = getCommonPlaylistEditAttributes().concat([
 
     if (!await doesVideoPlaylistExist(req.params.playlistId, res, 'all')) return cleanUpReqFiles(req)
 
-    const videoPlaylist = res.locals.videoPlaylist
+    const videoPlaylist = getPlaylist(res)
 
-    if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, res.locals.videoPlaylist, UserRight.REMOVE_ANY_VIDEO_PLAYLIST, res)) {
+    if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, videoPlaylist, UserRight.REMOVE_ANY_VIDEO_PLAYLIST, res)) {
       return cleanUpReqFiles(req)
     }
 
@@ -110,13 +110,13 @@ const videoPlaylistsDeleteValidator = [
 
     if (!await doesVideoPlaylistExist(req.params.playlistId, res)) return
 
-    const videoPlaylist = res.locals.videoPlaylist
+    const videoPlaylist = getPlaylist(res)
     if (videoPlaylist.type === VideoPlaylistType.WATCH_LATER) {
       return res.status(400)
                 .json({ error: 'Cannot delete a watch later playlist.' })
     }
 
-    if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, res.locals.videoPlaylist, UserRight.REMOVE_ANY_VIDEO_PLAYLIST, res)) {
+    if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, videoPlaylist, UserRight.REMOVE_ANY_VIDEO_PLAYLIST, res)) {
       return
     }
 
@@ -124,45 +124,47 @@ const videoPlaylistsDeleteValidator = [
   }
 ]
 
-const videoPlaylistsGetValidator = [
-  param('playlistId')
-    .custom(isIdOrUUIDValid).withMessage('Should have a valid playlist id/uuid'),
+const videoPlaylistsGetValidator = (fetchType: VideoPlaylistFetchType) => {
+  return [
+    param('playlistId')
+      .custom(isIdOrUUIDValid).withMessage('Should have a valid playlist id/uuid'),
 
-  async (req: express.Request, res: express.Response, next: express.NextFunction) => {
-    logger.debug('Checking videoPlaylistsGetValidator parameters', { parameters: req.params })
+    async (req: express.Request, res: express.Response, next: express.NextFunction) => {
+      logger.debug('Checking videoPlaylistsGetValidator parameters', { parameters: req.params })
 
-    if (areValidationErrors(req, res)) return
+      if (areValidationErrors(req, res)) return
 
-    if (!await doesVideoPlaylistExist(req.params.playlistId, res)) return
+      if (!await doesVideoPlaylistExist(req.params.playlistId, res, fetchType)) return
 
-    const videoPlaylist = res.locals.videoPlaylist
+      const videoPlaylist = res.locals.videoPlaylistFull || res.locals.videoPlaylistSummary
 
-    // Video is unlisted, check we used the uuid to fetch it
-    if (videoPlaylist.privacy === VideoPlaylistPrivacy.UNLISTED) {
-      if (isUUIDValid(req.params.playlistId)) return next()
+      // Video is unlisted, check we used the uuid to fetch it
+      if (videoPlaylist.privacy === VideoPlaylistPrivacy.UNLISTED) {
+        if (isUUIDValid(req.params.playlistId)) return next()
 
-      return res.status(404).end()
-    }
+        return res.status(404).end()
+      }
 
-    if (videoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) {
-      await authenticatePromiseIfNeeded(req, res)
+      if (videoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) {
+        await authenticatePromiseIfNeeded(req, res)
 
-      const user = res.locals.oauth ? res.locals.oauth.token.User : null
+        const user = res.locals.oauth ? res.locals.oauth.token.User : null
 
-      if (
-        !user ||
-        (videoPlaylist.OwnerAccount.id !== user.Account.id && !user.hasRight(UserRight.UPDATE_ANY_VIDEO_PLAYLIST))
-      ) {
-        return res.status(403)
-                  .json({ error: 'Cannot get this private video playlist.' })
+        if (
+          !user ||
+          (videoPlaylist.OwnerAccount.id !== user.Account.id && !user.hasRight(UserRight.UPDATE_ANY_VIDEO_PLAYLIST))
+        ) {
+          return res.status(403)
+                    .json({ error: 'Cannot get this private video playlist.' })
+        }
+
+        return next()
       }
 
       return next()
     }
-
-    return next()
-  }
-]
+  ]
+}
 
 const videoPlaylistsAddVideoValidator = [
   param('playlistId')
@@ -184,8 +186,8 @@ const videoPlaylistsAddVideoValidator = [
     if (!await doesVideoPlaylistExist(req.params.playlistId, res, 'all')) return
     if (!await doesVideoExist(req.body.videoId, res, 'only-video')) return
 
-    const videoPlaylist = res.locals.videoPlaylist
-    const video = res.locals.video
+    const videoPlaylist = getPlaylist(res)
+    const video = res.locals.onlyVideo
 
     const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndVideo(videoPlaylist.id, video.id)
     if (videoPlaylistElement) {
@@ -196,7 +198,7 @@ const videoPlaylistsAddVideoValidator = [
       return
     }
 
-    if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, res.locals.videoPlaylist, UserRight.UPDATE_ANY_VIDEO_PLAYLIST, res)) {
+    if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, videoPlaylist, UserRight.UPDATE_ANY_VIDEO_PLAYLIST, res)) {
       return
     }
 
@@ -223,7 +225,7 @@ const videoPlaylistsUpdateOrRemoveVideoValidator = [
 
     if (!await doesVideoPlaylistExist(req.params.playlistId, res, 'all')) return
 
-    const videoPlaylist = res.locals.videoPlaylist
+    const videoPlaylist = getPlaylist(res)
 
     const videoPlaylistElement = await VideoPlaylistElementModel.loadById(req.params.playlistElementId)
     if (!videoPlaylistElement) {
@@ -289,7 +291,7 @@ const videoPlaylistsReorderVideosValidator = [
 
     if (!await doesVideoPlaylistExist(req.params.playlistId, res, 'all')) return
 
-    const videoPlaylist = res.locals.videoPlaylist
+    const videoPlaylist = getPlaylist(res)
     if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, videoPlaylist, UserRight.UPDATE_ANY_VIDEO_PLAYLIST, res)) return
 
     const nextPosition = await VideoPlaylistElementModel.getNextPositionOf(videoPlaylist.id)
@@ -388,7 +390,7 @@ function getCommonPlaylistEditAttributes () {
   ] as (ValidationChain | express.Handler)[]
 }
 
-function checkUserCanManageVideoPlaylist (user: UserModel, videoPlaylist: VideoPlaylistModel, right: UserRight, res: express.Response) {
+function checkUserCanManageVideoPlaylist (user: MUserAccountId, videoPlaylist: MVideoPlaylist, right: UserRight, res: express.Response) {
   if (videoPlaylist.isOwned() === false) {
     res.status(403)
        .json({ error: 'Cannot manage video playlist of another server.' })
@@ -410,3 +412,7 @@ function checkUserCanManageVideoPlaylist (user: UserModel, videoPlaylist: VideoP
 
   return true
 }
+
+function getPlaylist (res: express.Response) {
+  return res.locals.videoPlaylistFull || res.locals.videoPlaylistSummary
+}
index ace62be5cade3a1171e6043cd8cad653c356bd05..20fc962438f591f97c8bb07e62f236b67c6bc44a 100644 (file)
@@ -16,7 +16,7 @@ const videosShareValidator = [
     if (areValidationErrors(req, res)) return
     if (!await doesVideoExist(req.params.id, res)) return
 
-    const video = res.locals.video
+    const video = res.locals.videoAll
 
     const share = await VideoShareModel.load(req.params.actorId, video.id)
     if (!share) {
index af06f3c629e1426538045bfd7456ad5051f8aa27..a194d14b3a529f4f9d623bbd1fbfd64ac5284479 100644 (file)
@@ -37,13 +37,14 @@ import { VideoModel } from '../../../models/video/video'
 import { checkUserCanTerminateOwnershipChange, doesChangeVideoOwnershipExist } from '../../../helpers/custom-validators/video-ownership'
 import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/video-change-ownership-accept.model'
 import { AccountModel } from '../../../models/account/account'
-import { VideoFetchType } from '../../../helpers/video'
 import { isNSFWQueryValid, isNumberArray, isStringArray } from '../../../helpers/custom-validators/search'
 import { getServerActor } from '../../../helpers/utils'
 import { CONFIG } from '../../../initializers/config'
 import { isLocalVideoAccepted } from '../../../lib/moderation'
 import { Hooks } from '../../../lib/plugins/hooks'
 import { checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '../../../helpers/middlewares'
+import { MVideoFullLight } from '@server/typings/models'
+import { getVideo } from '../../../helpers/video'
 
 const videosAddValidator = getCommonVideoEditAttributes().concat([
   body('videofile')
@@ -113,7 +114,7 @@ const videosUpdateValidator = getCommonVideoEditAttributes().concat([
 
     // Check if the user who did the request is able to update the video
     const user = res.locals.oauth.token.User
-    if (!checkUserCanManageVideo(user, res.locals.video, UserRight.UPDATE_ANY_VIDEO, res)) return cleanUpReqFiles(req)
+    if (!checkUserCanManageVideo(user, res.locals.videoAll, UserRight.UPDATE_ANY_VIDEO, res)) return cleanUpReqFiles(req)
 
     if (req.body.channelId && !await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
 
@@ -122,7 +123,7 @@ const videosUpdateValidator = getCommonVideoEditAttributes().concat([
 ])
 
 async function checkVideoFollowConstraints (req: express.Request, res: express.Response, next: express.NextFunction) {
-  const video = res.locals.video
+  const video = getVideo(res)
 
   // Anybody can watch local videos
   if (video.isOwned() === true) return next()
@@ -146,7 +147,7 @@ async function checkVideoFollowConstraints (req: express.Request, res: express.R
             })
 }
 
-const videosCustomGetValidator = (fetchType: VideoFetchType) => {
+const videosCustomGetValidator = (fetchType: 'all' | 'only-video' | 'only-video-with-rights') => {
   return [
     param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
 
@@ -156,10 +157,11 @@ const videosCustomGetValidator = (fetchType: VideoFetchType) => {
       if (areValidationErrors(req, res)) return
       if (!await doesVideoExist(req.params.id, res, fetchType)) return
 
-      const video = res.locals.video
+      const video = getVideo(res)
+      const videoAll = video as MVideoFullLight
 
       // Video private or blacklisted
-      if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) {
+      if (video.privacy === VideoPrivacy.PRIVATE || videoAll.VideoBlacklist) {
         await authenticatePromiseIfNeeded(req, res)
 
         const user = res.locals.oauth ? res.locals.oauth.token.User : null
@@ -167,7 +169,7 @@ const videosCustomGetValidator = (fetchType: VideoFetchType) => {
         // Only the owner or a user that have blacklist rights can see the video
         if (
           !user ||
-          (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST))
+          (videoAll.VideoChannel && videoAll.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST))
         ) {
           return res.status(403)
                     .json({ error: 'Cannot get this private or blacklisted video.' })
@@ -202,7 +204,7 @@ const videosRemoveValidator = [
     if (!await doesVideoExist(req.params.id, res)) return
 
     // Check if the user who did the request is able to delete the video
-    if (!checkUserCanManageVideo(res.locals.oauth.token.User, res.locals.video, UserRight.REMOVE_ANY_VIDEO, res)) return
+    if (!checkUserCanManageVideo(res.locals.oauth.token.User, res.locals.videoAll, UserRight.REMOVE_ANY_VIDEO, res)) return
 
     return next()
   }
@@ -218,7 +220,7 @@ const videosChangeOwnershipValidator = [
     if (!await doesVideoExist(req.params.videoId, res)) return
 
     // Check if the user who did the request is able to change the ownership of the video
-    if (!checkUserCanManageVideo(res.locals.oauth.token.User, res.locals.video, UserRight.CHANGE_VIDEO_OWNERSHIP, res)) return
+    if (!checkUserCanManageVideo(res.locals.oauth.token.User, res.locals.videoAll, UserRight.CHANGE_VIDEO_OWNERSHIP, res)) return
 
     const nextOwner = await AccountModel.loadLocalByName(req.body.username)
     if (!nextOwner) {
index d7cfe17f00ea41ab0c43e7f6dfc002e999109f2e..d50e6527fe4ac7ab3d9764c6372e90b96df91163 100644 (file)
@@ -18,6 +18,7 @@ const webfingerValidator = [
     const nameWithHost = getHostWithPort(req.query.resource.substr(5))
     const [ name ] = nameWithHost.split('@')
 
+    // FIXME: we don't need the full actor
     const actor = await ActorModel.loadLocalByName(name)
     if (!actor) {
       return res.status(404)
@@ -25,7 +26,7 @@ const webfingerValidator = [
         .end()
     }
 
-    res.locals.actor = actor
+    res.locals.actorFull = actor
     return next()
   }
 ]
index d5746ad7614e416b812240bc1dee87ecff2827da..bb537139515c0eeb7727c75436f7d14af9d9df5e 100644 (file)
@@ -3,6 +3,8 @@ import { AccountModel } from './account'
 import { getSort } from '../utils'
 import { AccountBlock } from '../../../shared/models/blocklist'
 import { Op } from 'sequelize'
+import * as Bluebird from 'bluebird'
+import { MAccountBlocklist, MAccountBlocklistAccounts } from '@server/typings/models'
 
 enum ScopeNames {
   WITH_ACCOUNTS = 'WITH_ACCOUNTS'
@@ -103,7 +105,7 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
                                 })
   }
 
-  static loadByAccountAndTarget (accountId: number, targetAccountId: number) {
+  static loadByAccountAndTarget (accountId: number, targetAccountId: number): Bluebird<MAccountBlocklist> {
     const query = {
       where: {
         accountId,
@@ -126,7 +128,7 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
 
     return AccountBlocklistModel
       .scope([ ScopeNames.WITH_ACCOUNTS ])
-      .findAndCountAll(query)
+      .findAndCountAll<MAccountBlocklistAccounts>(query)
       .then(({ rows, count }) => {
         return { total: count, data: rows }
       })
index 4bd8114cf6e2a718a781b89a25fd8b4d42d64bc6..8b62dd05ff9b833a4f0c94ba48853a46564fa670 100644 (file)
@@ -10,6 +10,8 @@ import { buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
 import { AccountVideoRate } from '../../../shared'
 import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel'
+import * as Bluebird from 'bluebird'
+import { MAccountVideoRate, MAccountVideoRateAccountUrl, MAccountVideoRateAccountVideo } from '@server/typings/models/video/video-rate'
 
 /*
   Account rates per video.
@@ -77,7 +79,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
   })
   Account: AccountModel
 
-  static load (accountId: number, videoId: number, transaction?: Transaction) {
+  static load (accountId: number, videoId: number, transaction?: Transaction): Bluebird<MAccountVideoRate> {
     const options: FindOptions = {
       where: {
         accountId,
@@ -89,7 +91,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
     return AccountVideoRateModel.findOne(options)
   }
 
-  static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, transaction?: Transaction) {
+  static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, t?: Transaction): Bluebird<MAccountVideoRate> {
     const options: FindOptions = {
       where: {
         [ Op.or]: [
@@ -103,7 +105,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
         ]
       }
     }
-    if (transaction) options.transaction = transaction
+    if (t) options.transaction = t
 
     return AccountVideoRateModel.findOne(options)
   }
@@ -140,7 +142,12 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
     return AccountVideoRateModel.findAndCountAll(query)
   }
 
-  static loadLocalAndPopulateVideo (rateType: VideoRateType, accountName: string, videoId: number, transaction?: Transaction) {
+  static loadLocalAndPopulateVideo (
+    rateType: VideoRateType,
+    accountName: string,
+    videoId: number,
+    t?: Transaction
+  ): Bluebird<MAccountVideoRateAccountVideo> {
     const options: FindOptions = {
       where: {
         videoId,
@@ -152,7 +159,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
           required: true,
           include: [
             {
-              attributes: [ 'id', 'url', 'preferredUsername' ],
+              attributes: [ 'id', 'url', 'followersUrl', 'preferredUsername' ],
               model: ActorModel.unscoped(),
               required: true,
               where: {
@@ -167,7 +174,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
         }
       ]
     }
-    if (transaction) options.transaction = transaction
+    if (t) options.transaction = t
 
     return AccountVideoRateModel.findOne(options)
   }
@@ -208,7 +215,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
       ]
     }
 
-    return AccountVideoRateModel.findAndCountAll(query)
+    return AccountVideoRateModel.findAndCountAll<MAccountVideoRateAccountUrl>(query)
   }
 
   static cleanOldRatesOf (videoId: number, type: VideoRateType, beforeUpdatedAt: Date) {
index 4dc4123018a5fc2dc6713df5afe447fa2786b9ff..4cc731075dcb9730c1b968ebc3d88a08a6b8e1ce 100644 (file)
@@ -3,7 +3,8 @@ import {
   BeforeDestroy,
   BelongsTo,
   Column,
-  CreatedAt, DataType,
+  CreatedAt,
+  DataType,
   Default,
   DefaultScope,
   ForeignKey,
@@ -31,6 +32,8 @@ 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 } from '../../typings/models'
+import * as Bluebird from 'bluebird'
 
 export enum ScopeNames {
   SUMMARY = 'SUMMARY'
@@ -229,11 +232,11 @@ export class AccountModel extends Model<AccountModel> {
     return undefined
   }
 
-  static load (id: number, transaction?: Transaction) {
+  static load (id: number, transaction?: Transaction): Bluebird<MAccountDefault> {
     return AccountModel.findByPk(id, { transaction })
   }
 
-  static loadByNameWithHost (nameWithHost: string) {
+  static loadByNameWithHost (nameWithHost: string): Bluebird<MAccountDefault> {
     const [ accountName, host ] = nameWithHost.split('@')
 
     if (!host || host === WEBSERVER.HOST) return AccountModel.loadLocalByName(accountName)
@@ -241,7 +244,7 @@ export class AccountModel extends Model<AccountModel> {
     return AccountModel.loadByNameAndHost(accountName, host)
   }
 
-  static loadLocalByName (name: string) {
+  static loadLocalByName (name: string): Bluebird<MAccountDefault> {
     const query = {
       where: {
         [ Op.or ]: [
@@ -271,7 +274,7 @@ export class AccountModel extends Model<AccountModel> {
     return AccountModel.findOne(query)
   }
 
-  static loadByNameAndHost (name: string, host: string) {
+  static loadByNameAndHost (name: string, host: string): Bluebird<MAccountDefault> {
     const query = {
       include: [
         {
@@ -296,7 +299,7 @@ export class AccountModel extends Model<AccountModel> {
     return AccountModel.findOne(query)
   }
 
-  static loadByUrl (url: string, transaction?: Transaction) {
+  static loadByUrl (url: string, transaction?: Transaction): Bluebird<MAccountDefault> {
     const query = {
       include: [
         {
@@ -329,7 +332,7 @@ export class AccountModel extends Model<AccountModel> {
       })
   }
 
-  static listLocalsForSitemap (sort: string) {
+  static listLocalsForSitemap (sort: string): Bluebird<MAccountActor[]> {
     const query = {
       attributes: [ ],
       offset: 0,
index f38cd7e781346415059e03aebda6e11e49292a6a..9b13a83763eb572f688665429c639b1d2003abbb 100644 (file)
@@ -16,6 +16,7 @@ import { ActorModel } from '../activitypub/actor'
 import { ActorFollowModel } from '../activitypub/actor-follow'
 import { AvatarModel } from '../avatar/avatar'
 import { ServerModel } from '../server/server'
+import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/typings/models/user'
 
 enum ScopeNames {
   WITH_ALL = 'WITH_ALL'
@@ -371,7 +372,7 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
     return UserNotificationModel.update({ read: true }, query)
   }
 
-  toFormattedJSON (): UserNotification {
+  toFormattedJSON (this: UserNotificationModelForApi): UserNotification {
     const video = this.Video
       ? Object.assign(this.formatVideo(this.Video),{ channel: this.formatActor(this.Video.VideoChannel) })
       : undefined
@@ -436,7 +437,7 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
     }
   }
 
-  private formatVideo (video: VideoModel) {
+  formatVideo (this: UserNotificationModelForApi, video: UserNotificationIncludes.VideoInclude) {
     return {
       id: video.id,
       uuid: video.uuid,
@@ -444,7 +445,10 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
     }
   }
 
-  private formatActor (accountOrChannel: AccountModel | VideoChannelModel) {
+  formatActor (
+    this: UserNotificationModelForApi,
+    accountOrChannel: UserNotificationIncludes.AccountIncludeActor | UserNotificationIncludes.VideoChannelIncludeActor
+  ) {
     const avatar = accountOrChannel.Actor.Avatar
       ? { path: accountOrChannel.Actor.Avatar.getStaticPath() }
       : undefined
index a862fc45fb859b0d842877c888b76233aec0962a..3fe4c8db1c8823921c9e5b07209e58e799f7a5ec 100644 (file)
@@ -1,7 +1,8 @@
 import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript'
 import { VideoModel } from '../video/video'
 import { UserModel } from './user'
-import { Transaction, Op, DestroyOptions } from 'sequelize'
+import { DestroyOptions, Op, Transaction } from 'sequelize'
+import { MUserAccountId, MUserId } from '@server/typings/models'
 
 @Table({
   tableName: 'userVideoHistory',
@@ -54,7 +55,7 @@ export class UserVideoHistoryModel extends Model<UserVideoHistoryModel> {
   })
   User: UserModel
 
-  static listForApi (user: UserModel, start: number, count: number) {
+  static listForApi (user: MUserAccountId, start: number, count: number) {
     return VideoModel.listForApi({
       start,
       count,
@@ -67,7 +68,7 @@ export class UserVideoHistoryModel extends Model<UserVideoHistoryModel> {
     })
   }
 
-  static removeUserHistoryBefore (user: UserModel, beforeDate: string, t: Transaction) {
+  static removeUserHistoryBefore (user: MUserId, beforeDate: string, t: Transaction) {
     const query: DestroyOptions = {
       where: {
         userId: user.id
index 0041bf5770f07de24c58d11c7a6980f771c43453..24b1626e77f17aa490ed31fb2c4372cd674b6b10 100644 (file)
@@ -54,6 +54,8 @@ import { VideoImportModel } from '../video/video-import'
 import { UserAdminFlag } from '../../../shared/models/users/user-flag.model'
 import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
 import { getThemeOrDefault } from '../../lib/plugins/theme-utils'
+import * as Bluebird from 'bluebird'
+import { MUserChannel, MUserDefault, MUserId, MUserWithNotificationSetting } from '@server/typings/models'
 
 enum ScopeNames {
   WITH_VIDEO_CHANNEL = 'WITH_VIDEO_CHANNEL'
@@ -303,7 +305,7 @@ export class UserModel extends Model<UserModel> {
       })
   }
 
-  static listWithRight (right: UserRight) {
+  static listWithRight (right: UserRight): Bluebird<MUserDefault[]> {
     const roles = Object.keys(USER_ROLE_LABELS)
       .map(k => parseInt(k, 10) as UserRole)
       .filter(role => hasUserRight(role, right))
@@ -319,7 +321,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findAll(query)
   }
 
-  static listUserSubscribersOf (actorId: number) {
+  static listUserSubscribersOf (actorId: number): Bluebird<MUserWithNotificationSetting[]> {
     const query = {
       include: [
         {
@@ -358,7 +360,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.unscoped().findAll(query)
   }
 
-  static listByUsernames (usernames: string[]) {
+  static listByUsernames (usernames: string[]): Bluebird<MUserDefault[]> {
     const query = {
       where: {
         username: usernames
@@ -368,11 +370,11 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findAll(query)
   }
 
-  static loadById (id: number) {
+  static loadById (id: number): Bluebird<MUserDefault> {
     return UserModel.findByPk(id)
   }
 
-  static loadByUsername (username: string) {
+  static loadByUsername (username: string): Bluebird<MUserDefault> {
     const query = {
       where: {
         username: { [ Op.iLike ]: username }
@@ -382,7 +384,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByUsernameAndPopulateChannels (username: string) {
+  static loadByUsernameAndPopulateChannels (username: string): Bluebird<MUserChannel> {
     const query = {
       where: {
         username: { [ Op.iLike ]: username }
@@ -392,7 +394,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.scope(ScopeNames.WITH_VIDEO_CHANNEL).findOne(query)
   }
 
-  static loadByEmail (email: string) {
+  static loadByEmail (email: string): Bluebird<MUserDefault> {
     const query = {
       where: {
         email
@@ -402,7 +404,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByUsernameOrEmail (username: string, email?: string) {
+  static loadByUsernameOrEmail (username: string, email?: string): Bluebird<MUserDefault> {
     if (!email) email = username
 
     const query = {
@@ -414,7 +416,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByVideoId (videoId: number) {
+  static loadByVideoId (videoId: number): Bluebird<MUserDefault> {
     const query = {
       include: [
         {
@@ -445,7 +447,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByVideoImportId (videoImportId: number) {
+  static loadByVideoImportId (videoImportId: number): Bluebird<MUserDefault> {
     const query = {
       include: [
         {
@@ -462,7 +464,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByChannelActorId (videoChannelActorId: number) {
+  static loadByChannelActorId (videoChannelActorId: number): Bluebird<MUserDefault> {
     const query = {
       include: [
         {
@@ -486,7 +488,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static loadByAccountActorId (accountActorId: number) {
+  static loadByAccountActorId (accountActorId: number): Bluebird<MUserDefault> {
     const query = {
       include: [
         {
@@ -503,7 +505,7 @@ export class UserModel extends Model<UserModel> {
     return UserModel.findOne(query)
   }
 
-  static getOriginalVideoFileTotalFromUser (user: UserModel) {
+  static getOriginalVideoFileTotalFromUser (user: MUserId) {
     // Don't use sequelize because we need to use a sub query
     const query = UserModel.generateUserQuotaBaseSQL()
 
@@ -511,7 +513,7 @@ export class UserModel extends Model<UserModel> {
   }
 
   // Returns cumulative size of all video files uploaded in the last 24 hours.
-  static getOriginalVideoFileTotalDailyFromUser (user: UserModel) {
+  static getOriginalVideoFileTotalDailyFromUser (user: MUserId) {
     // Don't use sequelize because we need to use a sub query
     const query = UserModel.generateUserQuotaBaseSQL('"video"."createdAt" > now() - interval \'24 hours\'')
 
index 51b09e09be14c039d7fcc712bbf6d81ee660fc88..8ef770cd4933d92eb7b11d8a7d6c313a2cbf982d 100644 (file)
@@ -27,7 +27,13 @@ import { createSafeIn, getSort } from '../utils'
 import { ActorModel, unusedActorAttributesForAPI } from './actor'
 import { VideoChannelModel } from '../video/video-channel'
 import { AccountModel } from '../account/account'
-import { IncludeOptions, Op, Transaction, QueryTypes } from 'sequelize'
+import { IncludeOptions, Op, QueryTypes, Transaction } from 'sequelize'
+import {
+  MActorFollowActorsDefault,
+  MActorFollowActorsDefaultSubscription,
+  MActorFollowFollowingHost,
+  MActorFollowSubscriptions
+} from '@server/typings/models'
 
 @Table({
   tableName: 'actorFollow',
@@ -143,7 +149,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
     if (numberOfActorFollowsRemoved) logger.info('Removed bad %d actor follows.', numberOfActorFollowsRemoved)
   }
 
-  static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Transaction) {
+  static loadByActorAndTarget (actorId: number, targetActorId: number, t?: Transaction): Bluebird<MActorFollowActorsDefault> {
     const query = {
       where: {
         actorId,
@@ -167,7 +173,12 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
     return ActorFollowModel.findOne(query)
   }
 
-  static loadByActorAndTargetNameAndHostForAPI (actorId: number, targetName: string, targetHost: string, t?: Transaction) {
+  static loadByActorAndTargetNameAndHostForAPI (
+    actorId: number,
+    targetName: string,
+    targetHost: string,
+    t?: Transaction
+  ): Bluebird<MActorFollowActorsDefaultSubscription> {
     const actorFollowingPartInclude: IncludeOptions = {
       model: ActorModel,
       required: true,
@@ -220,7 +231,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
       })
   }
 
-  static listSubscribedIn (actorId: number, targets: { name: string, host?: string }[]) {
+  static listSubscribedIn (actorId: number, targets: { name: string, host?: string }[]): Bluebird<MActorFollowFollowingHost[]> {
     const whereTab = targets
       .map(t => {
         if (t.host) {
@@ -314,7 +325,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
       ]
     }
 
-    return ActorFollowModel.findAndCountAll(query)
+    return ActorFollowModel.findAndCountAll<MActorFollowActorsDefault>(query)
       .then(({ rows, count }) => {
         return {
           data: rows,
@@ -357,7 +368,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
       ]
     }
 
-    return ActorFollowModel.findAndCountAll(query)
+    return ActorFollowModel.findAndCountAll<MActorFollowActorsDefault>(query)
                            .then(({ rows, count }) => {
                              return {
                                data: rows,
@@ -414,7 +425,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
       ]
     }
 
-    return ActorFollowModel.findAndCountAll(query)
+    return ActorFollowModel.findAndCountAll<MActorFollowSubscriptions>(query)
                            .then(({ rows, count }) => {
                              return {
                                data: rows.map(r => r.ActorFollowing.VideoChannel),
index 9cc53f78ab4bcc34fe83c3169979f397ddc635d5..2312127b42108985d52c5441bb8406f7a8a19488 100644 (file)
@@ -36,6 +36,8 @@ import { isOutdated, throwIfNotValid } from '../utils'
 import { VideoChannelModel } from '../video/video-channel'
 import { ActorFollowModel } from './actor-follow'
 import { VideoModel } from '../video/video'
+import { MActor, MActorAccountChannelId, MActorFull } from '../../typings/models'
+import * as Bluebird from 'bluebird'
 
 enum ScopeNames {
   FULL = 'FULL'
@@ -252,11 +254,15 @@ export class ActorModel extends Model<ActorModel> {
   })
   VideoChannel: VideoChannelModel
 
-  static load (id: number) {
+  static load (id: number): Bluebird<MActor> {
     return ActorModel.unscoped().findByPk(id)
   }
 
-  static loadAccountActorByVideoId (videoId: number, transaction: Sequelize.Transaction) {
+  static loadFull (id: number): Bluebird<MActorFull> {
+    return ActorModel.scope(ScopeNames.FULL).findByPk(id)
+  }
+
+  static loadFromAccountByVideoId (videoId: number, transaction: Sequelize.Transaction): Bluebird<MActor> {
     const query = {
       include: [
         {
@@ -300,7 +306,7 @@ export class ActorModel extends Model<ActorModel> {
       .then(a => !!a)
   }
 
-  static listByFollowersUrls (followersUrls: string[], transaction?: Sequelize.Transaction) {
+  static listByFollowersUrls (followersUrls: string[], transaction?: Sequelize.Transaction): Bluebird<MActorFull[]> {
     const query = {
       where: {
         followersUrl: {
@@ -313,7 +319,7 @@ export class ActorModel extends Model<ActorModel> {
     return ActorModel.scope(ScopeNames.FULL).findAll(query)
   }
 
-  static loadLocalByName (preferredUsername: string, transaction?: Sequelize.Transaction) {
+  static loadLocalByName (preferredUsername: string, transaction?: Sequelize.Transaction): Bluebird<MActorFull> {
     const query = {
       where: {
         preferredUsername,
@@ -325,7 +331,7 @@ export class ActorModel extends Model<ActorModel> {
     return ActorModel.scope(ScopeNames.FULL).findOne(query)
   }
 
-  static loadByNameAndHost (preferredUsername: string, host: string) {
+  static loadByNameAndHost (preferredUsername: string, host: string): Bluebird<MActorFull> {
     const query = {
       where: {
         preferredUsername
@@ -344,7 +350,7 @@ export class ActorModel extends Model<ActorModel> {
     return ActorModel.scope(ScopeNames.FULL).findOne(query)
   }
 
-  static loadByUrl (url: string, transaction?: Sequelize.Transaction) {
+  static loadByUrl (url: string, transaction?: Sequelize.Transaction): Bluebird<MActorAccountChannelId> {
     const query = {
       where: {
         url
@@ -367,7 +373,7 @@ export class ActorModel extends Model<ActorModel> {
     return ActorModel.unscoped().findOne(query)
   }
 
-  static loadByUrlAndPopulateAccountAndChannel (url: string, transaction?: Sequelize.Transaction) {
+  static loadByUrlAndPopulateAccountAndChannel (url: string, transaction?: Sequelize.Transaction): Bluebird<MActorFull> {
     const query = {
       where: {
         url
index 903d551dfec8fc5e12bb14bcea4ac4c1a9dc993e..b680be237a1bb1d5a2242f5c683ad9077378cca4 100644 (file)
@@ -18,6 +18,8 @@ import { Transaction } from 'sequelize'
 import { AccountModel } from '../account/account'
 import { ActorModel } from '../activitypub/actor'
 import { clearCacheByToken } from '../../lib/oauth-model'
+import * as Bluebird from 'bluebird'
+import { MOAuthTokenUser } from '@server/typings/models/oauth/oauth-token'
 
 export type OAuthTokenInfo = {
   refreshToken: string
@@ -160,7 +162,7 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
       })
   }
 
-  static getByTokenAndPopulateUser (bearerToken: string) {
+  static getByTokenAndPopulateUser (bearerToken: string): Bluebird<MOAuthTokenUser> {
     const query = {
       where: {
         accessToken: bearerToken
@@ -170,13 +172,13 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
     return OAuthTokenModel.scope(ScopeNames.WITH_USER)
                           .findOne(query)
                           .then(token => {
-                            if (token) token[ 'user' ] = token.User
+                            if (!token) return null
 
-                            return token
+                            return Object.assign(token, { user: token.User })
                           })
   }
 
-  static getByRefreshTokenAndPopulateUser (refreshToken: string) {
+  static getByRefreshTokenAndPopulateUser (refreshToken: string): Bluebird<MOAuthTokenUser> {
     const query = {
       where: {
         refreshToken: refreshToken
@@ -186,12 +188,9 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
     return OAuthTokenModel.scope(ScopeNames.WITH_USER)
       .findOne(query)
       .then(token => {
-        if (token) {
-          token['user'] = token.User
-          return token
-        } else {
-          return new OAuthTokenModel()
-        }
+        if (!token) return new OAuthTokenModel()
+
+        return Object.assign(token, { user: token.User })
       })
   }
 
index 3df1c4f9cf1fa76977ef7ac942ca444df353b6a9..1c216b30082e7a18be828965b19b1223799b991d 100644 (file)
@@ -30,6 +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'
 
 export enum ScopeNames {
   WITH_VIDEO = 'WITH_VIDEO'
@@ -166,7 +167,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
     return undefined
   }
 
-  static async loadLocalByFileId (videoFileId: number) {
+  static async loadLocalByFileId (videoFileId: number): Promise<MVideoRedundancyVideo> {
     const actor = await getServerActor()
 
     const query = {
@@ -179,7 +180,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
     return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query)
   }
 
-  static async loadLocalByStreamingPlaylistId (videoStreamingPlaylistId: number) {
+  static async loadLocalByStreamingPlaylistId (videoStreamingPlaylistId: number): Promise<MVideoRedundancyVideo> {
     const actor = await getServerActor()
 
     const query = {
@@ -192,7 +193,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
     return VideoRedundancyModel.scope(ScopeNames.WITH_VIDEO).findOne(query)
   }
 
-  static loadByUrl (url: string, transaction?: Transaction) {
+  static loadByUrl (url: string, transaction?: Transaction): Bluebird<MVideoRedundancy> {
     const query = {
       where: {
         url
@@ -306,7 +307,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
     return VideoRedundancyModel.getVideoSample(VideoModel.unscoped().findAll(query))
   }
 
-  static async loadOldestLocalThatAlreadyExpired (strategy: VideoRedundancyStrategy, expiresAfterMs: number) {
+  static async loadOldestLocalExpired (strategy: VideoRedundancyStrategy, expiresAfterMs: number): Promise<MVideoRedundancyVideo> {
     const expiredDate = new Date()
     expiredDate.setMilliseconds(expiredDate.getMilliseconds() - expiresAfterMs)
 
index a15f9a7e28c905dd94bc3519a6028846baf2d41d..debd25ea199d276793e84da7835729f7158e74fb 100644 (file)
@@ -11,6 +11,8 @@ import { PluginType } from '../../../shared/models/plugins/plugin.type'
 import { PeerTubePlugin } from '../../../shared/models/plugins/peertube-plugin.model'
 import { FindAndCountOptions, json } from 'sequelize'
 import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model'
+import * as Bluebird from 'bluebird'
+import { MPlugin } from '@server/typings/models'
 
 @DefaultScope(() => ({
   attributes: {
@@ -85,7 +87,7 @@ export class PluginModel extends Model<PluginModel> {
   @UpdatedAt
   updatedAt: Date
 
-  static listEnabledPluginsAndThemes () {
+  static listEnabledPluginsAndThemes (): Bluebird<MPlugin[]> {
     const query = {
       where: {
         enabled: true,
@@ -96,7 +98,7 @@ export class PluginModel extends Model<PluginModel> {
     return PluginModel.findAll(query)
   }
 
-  static loadByNpmName (npmName: string) {
+  static loadByNpmName (npmName: string): Bluebird<MPlugin> {
     const name = this.normalizePluginName(npmName)
     const type = this.getTypeFromNpmName(npmName)
 
@@ -206,13 +208,13 @@ export class PluginModel extends Model<PluginModel> {
     if (options.pluginType) query.where['type'] = options.pluginType
 
     return PluginModel
-      .findAndCountAll(query)
+      .findAndCountAll<MPlugin>(query)
       .then(({ rows, count }) => {
         return { total: count, data: rows }
       })
   }
 
-  static listInstalled () {
+  static listInstalled (): Bluebird<MPlugin[]> {
     const query = {
       where: {
         uninstalled: false
index 5138b0f76367b8e6e183375515508efab2b2c0ee..e4db93dfc53d71016cd21c1796424d44b15cf0e7 100644 (file)
@@ -3,6 +3,8 @@ import { AccountModel } from '../account/account'
 import { ServerModel } from './server'
 import { ServerBlock } from '../../../shared/models/blocklist'
 import { getSort } from '../utils'
+import * as Bluebird from 'bluebird'
+import { MServerBlocklist, MServerBlocklistAccountServer } from '@server/typings/models'
 
 enum ScopeNames {
   WITH_ACCOUNT = 'WITH_ACCOUNT',
@@ -73,7 +75,7 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
   })
   BlockedServer: ServerModel
 
-  static loadByAccountAndHost (accountId: number, host: string) {
+  static loadByAccountAndHost (accountId: number, host: string): Bluebird<MServerBlocklist> {
     const query = {
       where: {
         accountId
@@ -104,7 +106,7 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
 
     return ServerBlocklistModel
       .scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_SERVER ])
-      .findAndCountAll(query)
+      .findAndCountAll<MServerBlocklistAccountServer>(query)
       .then(({ rows, count }) => {
         return { total: count, data: rows }
       })
index 1d211f1e06b2619bd6a4142c31bfd0852d3b0792..b0bdd2b0bcb4316e38b08d8fca33175b35ad80a1 100644 (file)
@@ -2,8 +2,9 @@ import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, Updat
 import { isHostValid } from '../../helpers/custom-validators/servers'
 import { ActorModel } from '../activitypub/actor'
 import { throwIfNotValid } from '../utils'
-import { AccountBlocklistModel } from '../account/account-blocklist'
 import { ServerBlocklistModel } from './server-blocklist'
+import * as Bluebird from 'bluebird'
+import { MServer } from '@server/typings/models/server'
 
 @Table({
   tableName: 'server',
@@ -50,7 +51,7 @@ export class ServerModel extends Model<ServerModel> {
   })
   BlockedByAccounts: ServerBlocklistModel[]
 
-  static loadByHost (host: string) {
+  static loadByHost (host: string): Bluebird<MServer> {
     const query = {
       where: {
         host
index 1ac7919b31e2c70f8d06c08a6ffd881e205565c8..af7b40d11f9ed215390b1654561ccb97d064314c 100644 (file)
@@ -11,6 +11,8 @@ import { getSort, throwIfNotValid } from '../utils'
 import { VideoModel } from './video'
 import { VideoAbuseState } from '../../../shared'
 import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants'
+import { MVideoAbuse, MVideoAbuseAccountVideo, MVideoAbuseVideo } from '../../typings/models'
+import * as Bluebird from 'bluebird'
 
 @Table({
   tableName: 'videoAbuse',
@@ -73,7 +75,7 @@ export class VideoAbuseModel extends Model<VideoAbuseModel> {
   })
   Video: VideoModel
 
-  static loadByIdAndVideoId (id: number, videoId: number) {
+  static loadByIdAndVideoId (id: number, videoId: number): Bluebird<MVideoAbuse> {
     const query = {
       where: {
         id,
@@ -106,7 +108,7 @@ export class VideoAbuseModel extends Model<VideoAbuseModel> {
       })
   }
 
-  toFormattedJSON (): VideoAbuse {
+  toFormattedJSON (this: MVideoAbuseAccountVideo): VideoAbuse {
     return {
       id: this.id,
       reason: this.reason,
@@ -125,7 +127,7 @@ export class VideoAbuseModel extends Model<VideoAbuseModel> {
     }
   }
 
-  toActivityPubObject (): VideoAbuseObject {
+  toActivityPubObject (this: MVideoAbuseVideo): VideoAbuseObject {
     return {
       type: 'Flag' as 'Flag',
       content: this.reason,
index 22d949da0f75723b1ad7b826e1cde03b357895e2..5a0cac94a663a667654044a13b198e5baec85ae3 100644 (file)
@@ -1,12 +1,14 @@
 import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
 import { getSortOnModel, SortType, throwIfNotValid } from '../utils'
-import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
+import { VideoModel } from './video'
 import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
 import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
 import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos'
 import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
 import { FindOptions } from 'sequelize'
 import { ThumbnailModel } from './thumbnail'
+import * as Bluebird from 'bluebird'
+import { MVideoBlacklist } from '@server/typings/models'
 
 @Table({
   tableName: 'videoBlacklist',
@@ -99,7 +101,7 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
     })
   }
 
-  static loadByVideoId (id: number) {
+  static loadByVideoId (id: number): Bluebird<MVideoBlacklist> {
     const query = {
       where: {
         videoId: id
index a01565851d2d0bfc621c33ceefec5fb1b949eb52..9ce350d1280c4799062abd44b87ecfae6b0179ae 100644 (file)
@@ -21,6 +21,8 @@ import { join } from 'path'
 import { logger } from '../../helpers/logger'
 import { remove } from 'fs-extra'
 import { CONFIG } from '../../initializers/config'
+import * as Bluebird from 'bluebird'
+import { MVideoCaptionVideo } from '@server/typings/models'
 
 export enum ScopeNames {
   WITH_VIDEO_UUID_AND_REMOTE = 'WITH_VIDEO_UUID_AND_REMOTE'
@@ -30,7 +32,7 @@ export enum ScopeNames {
   [ScopeNames.WITH_VIDEO_UUID_AND_REMOTE]: {
     include: [
       {
-        attributes: [ 'uuid', 'remote' ],
+        attributes: [ 'id', 'uuid', 'remote' ],
         model: VideoModel.unscoped(),
         required: true
       }
@@ -93,7 +95,7 @@ export class VideoCaptionModel extends Model<VideoCaptionModel> {
     return undefined
   }
 
-  static loadByVideoIdAndLanguage (videoId: string | number, language: string) {
+  static loadByVideoIdAndLanguage (videoId: string | number, language: string): Bluebird<MVideoCaptionVideo> {
     const videoInclude = {
       model: VideoModel.unscoped(),
       attributes: [ 'id', 'remote', 'uuid' ],
@@ -122,7 +124,7 @@ export class VideoCaptionModel extends Model<VideoCaptionModel> {
       .then(([ caption ]) => caption)
   }
 
-  static listVideoCaptions (videoId: number) {
+  static listVideoCaptions (videoId: number): Bluebird<MVideoCaptionVideo[]> {
     const query = {
       order: [ [ 'language', 'ASC' ] ] as OrderItem[],
       where: {
index b545a2f8c9528f67bd6a262cb61bd9e3a72a427f..2d0ff48fb212e608fac91f4e729dd17b084e4794 100644 (file)
@@ -3,6 +3,8 @@ import { AccountModel } from '../account/account'
 import { ScopeNames as VideoScopeNames, VideoModel } from './video'
 import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos'
 import { getSort } from '../utils'
+import { MVideoChangeOwnershipFull } from '@server/typings/models/video/video-change-ownership'
+import * as Bluebird from 'bluebird'
 
 enum ScopeNames {
   WITH_ACCOUNTS = 'WITH_ACCOUNTS',
@@ -108,11 +110,11 @@ export class VideoChangeOwnershipModel extends Model<VideoChangeOwnershipModel>
 
     return Promise.all([
       VideoChangeOwnershipModel.scope(ScopeNames.WITH_ACCOUNTS).count(query),
-      VideoChangeOwnershipModel.scope([ ScopeNames.WITH_ACCOUNTS, ScopeNames.WITH_VIDEO ]).findAll(query)
+      VideoChangeOwnershipModel.scope([ ScopeNames.WITH_ACCOUNTS, ScopeNames.WITH_VIDEO ]).findAll<MVideoChangeOwnershipFull>(query)
     ]).then(([ count, rows ]) => ({ total: count, data: rows }))
   }
 
-  static load (id: number) {
+  static load (id: number): Bluebird<MVideoChangeOwnershipFull> {
     return VideoChangeOwnershipModel.scope([ ScopeNames.WITH_ACCOUNTS, ScopeNames.WITH_VIDEO ])
                                     .findByPk(id)
   }
index 6241a75a30bfffd499cede0102bd4734781cc838..79b9e7d2ba1e83190e4e3a975ff98dd873e01536 100644 (file)
@@ -33,6 +33,13 @@ import { ServerModel } from '../server/server'
 import { FindOptions, ModelIndexesOptions, Op } from 'sequelize'
 import { AvatarModel } from '../avatar/avatar'
 import { VideoPlaylistModel } from './video-playlist'
+import * as Bluebird from 'bluebird'
+import {
+  MChannelAccountDefault,
+  MChannelActor,
+  MChannelActorAccountDefault,
+  MChannelActorAccountDefaultVideos
+} from '../../typings/models/video'
 
 // FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation
 const indexes: ModelIndexesOptions[] = [
@@ -47,7 +54,7 @@ const indexes: ModelIndexesOptions[] = [
 ]
 
 export enum ScopeNames {
-  AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST',
+  FOR_API = 'FOR_API',
   WITH_ACCOUNT = 'WITH_ACCOUNT',
   WITH_ACTOR = 'WITH_ACTOR',
   WITH_VIDEOS = 'WITH_VIDEOS',
@@ -74,10 +81,10 @@ export type SummaryOptions = {
 @Scopes(() => ({
   [ScopeNames.SUMMARY]: (options: SummaryOptions = {}) => {
     const base: FindOptions = {
-      attributes: [ 'name', 'description', 'id', 'actorId' ],
+      attributes: [ 'id', 'name', 'description', 'actorId' ],
       include: [
         {
-          attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ],
+          attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ],
           model: ActorModel.unscoped(),
           required: true,
           include: [
@@ -106,7 +113,7 @@ export type SummaryOptions = {
 
     return base
   },
-  [ScopeNames.AVAILABLE_FOR_LIST]: (options: AvailableForListOptions) => {
+  [ScopeNames.FOR_API]: (options: AvailableForListOptions) => {
     // Only list local channels OR channels that are on an instance followed by actorId
     const inQueryInstanceFollow = buildServerIdsFollowedBy(options.actorId)
 
@@ -268,7 +275,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
     }
 
     const scopes = {
-      method: [ ScopeNames.AVAILABLE_FOR_LIST, { actorId } as AvailableForListOptions ]
+      method: [ ScopeNames.FOR_API, { actorId } as AvailableForListOptions ]
     }
     return VideoChannelModel
       .scope(scopes)
@@ -278,7 +285,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       })
   }
 
-  static listLocalsForSitemap (sort: string) {
+  static listLocalsForSitemap (sort: string): Bluebird<MChannelActor[]> {
     const query = {
       attributes: [ ],
       offset: 0,
@@ -331,7 +338,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
     }
 
     const scopes = {
-      method: [ ScopeNames.AVAILABLE_FOR_LIST, { actorId: options.actorId } as AvailableForListOptions ]
+      method: [ ScopeNames.FOR_API, { actorId: options.actorId } as AvailableForListOptions ]
     }
     return VideoChannelModel
       .scope(scopes)
@@ -369,13 +376,13 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       })
   }
 
-  static loadByIdAndPopulateAccount (id: number) {
+  static loadByIdAndPopulateAccount (id: number): Bluebird<MChannelActorAccountDefault> {
     return VideoChannelModel.unscoped()
       .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
       .findByPk(id)
   }
 
-  static loadByIdAndAccount (id: number, accountId: number) {
+  static loadByIdAndAccount (id: number, accountId: number): Bluebird<MChannelActorAccountDefault> {
     const query = {
       where: {
         id,
@@ -388,13 +395,13 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       .findOne(query)
   }
 
-  static loadAndPopulateAccount (id: number) {
+  static loadAndPopulateAccount (id: number): Bluebird<MChannelActorAccountDefault> {
     return VideoChannelModel.unscoped()
       .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ])
       .findByPk(id)
   }
 
-  static loadByUrlAndPopulateAccount (url: string) {
+  static loadByUrlAndPopulateAccount (url: string): Bluebird<MChannelAccountDefault> {
     const query = {
       include: [
         {
@@ -420,7 +427,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
     return VideoChannelModel.loadByNameAndHostAndPopulateAccount(name, host)
   }
 
-  static loadLocalByNameAndPopulateAccount (name: string) {
+  static loadLocalByNameAndPopulateAccount (name: string): Bluebird<MChannelActorAccountDefault> {
     const query = {
       include: [
         {
@@ -439,7 +446,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       .findOne(query)
   }
 
-  static loadByNameAndHostAndPopulateAccount (name: string, host: string) {
+  static loadByNameAndHostAndPopulateAccount (name: string, host: string): Bluebird<MChannelActorAccountDefault> {
     const query = {
       include: [
         {
@@ -464,7 +471,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
       .findOne(query)
   }
 
-  static loadAndPopulateAccountAndVideos (id: number) {
+  static loadAndPopulateAccountAndVideos (id: number): Bluebird<MChannelActorAccountDefaultVideos> {
     const options = {
       include: [
         VideoModel
index 58b75510dfde221371cfc84df0536552fee25595..c88dac1c19bb393a69e35b1012f873ec59ee10af 100644 (file)
@@ -1,36 +1,30 @@
-import {
-  AllowNull,
-  BeforeDestroy,
-  BelongsTo,
-  Column,
-  CreatedAt,
-  DataType,
-  ForeignKey,
-  Is,
-  Model,
-  Scopes,
-  Table,
-  UpdatedAt
-} from 'sequelize-typescript'
+import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
 import { ActivityTagObject } from '../../../shared/models/activitypub/objects/common-objects'
 import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object'
 import { VideoComment } from '../../../shared/models/videos/video-comment.model'
 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
 import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants'
-import { sendDeleteVideoComment } from '../../lib/activitypub/send'
 import { AccountModel } from '../account/account'
 import { ActorModel } from '../activitypub/actor'
-import { AvatarModel } from '../avatar/avatar'
-import { ServerModel } from '../server/server'
 import { buildBlockedAccountSQL, buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils'
 import { VideoModel } from './video'
 import { VideoChannelModel } from './video-channel'
 import { getServerActor } from '../../helpers/utils'
-import { UserModel } from '../account/user'
 import { actorNameAlphabet } from '../../helpers/custom-validators/activitypub/actor'
 import { regexpCapture } from '../../helpers/regexp'
 import { uniq } from 'lodash'
-import { FindOptions, literal, Op, Order, ScopeOptions, Sequelize, Transaction } from 'sequelize'
+import { FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction } from 'sequelize'
+import * as Bluebird from 'bluebird'
+import {
+  MComment,
+  MCommentId,
+  MCommentOwner,
+  MCommentOwnerReplyVideoLight,
+  MCommentOwnerVideo,
+  MCommentOwnerVideoFeed,
+  MCommentOwnerVideoReply
+} from '../../typings/models/video'
+import { MUserAccountId } from '@server/typings/models'
 
 enum ScopeNames {
   WITH_ACCOUNT = 'WITH_ACCOUNT',
@@ -68,22 +62,7 @@ enum ScopeNames {
   [ScopeNames.WITH_ACCOUNT]: {
     include: [
       {
-        model: AccountModel,
-        include: [
-          {
-            model: ActorModel,
-            include: [
-              {
-                model: ServerModel,
-                required: false
-              },
-              {
-                model: AvatarModel,
-                required: false
-              }
-            ]
-          }
-        ]
+        model: AccountModel
       }
     ]
   },
@@ -102,22 +81,12 @@ enum ScopeNames {
         required: true,
         include: [
           {
-            model: VideoChannelModel.unscoped(),
+            model: VideoChannelModel,
             required: true,
             include: [
-              {
-                model: ActorModel,
-                required: true
-              },
               {
                 model: AccountModel,
-                required: true,
-                include: [
-                  {
-                    model: ActorModel,
-                    required: true
-                  }
-                ]
+                required: true
               }
             ]
           }
@@ -212,7 +181,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
   })
   Account: AccountModel
 
-  static loadById (id: number, t?: Transaction) {
+  static loadById (id: number, t?: Transaction): Bluebird<MComment> {
     const query: FindOptions = {
       where: {
         id
@@ -224,7 +193,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
     return VideoCommentModel.findOne(query)
   }
 
-  static loadByIdAndPopulateVideoAndAccountAndReply (id: number, t?: Transaction) {
+  static loadByIdAndPopulateVideoAndAccountAndReply (id: number, t?: Transaction): Bluebird<MCommentOwnerVideoReply> {
     const query: FindOptions = {
       where: {
         id
@@ -238,7 +207,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
       .findOne(query)
   }
 
-  static loadByUrlAndPopulateAccountAndVideo (url: string, t?: Transaction) {
+  static loadByUrlAndPopulateAccountAndVideo (url: string, t?: Transaction): Bluebird<MCommentOwnerVideo> {
     const query: FindOptions = {
       where: {
         url
@@ -250,7 +219,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
     return VideoCommentModel.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEO ]).findOne(query)
   }
 
-  static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction) {
+  static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction): Bluebird<MCommentOwnerReplyVideoLight> {
     const query: FindOptions = {
       where: {
         url
@@ -273,7 +242,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
     start: number,
     count: number,
     sort: string,
-    user?: UserModel
+    user?: MUserAccountId
   }) {
     const { videoId, start, count, sort, user } = parameters
 
@@ -314,7 +283,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
   static async listThreadCommentsForApi (parameters: {
     videoId: number,
     threadId: number,
-    user?: UserModel
+    user?: MUserAccountId
   }) {
     const { videoId, threadId, user } = parameters
 
@@ -353,7 +322,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
       })
   }
 
-  static listThreadParentComments (comment: VideoCommentModel, t: Transaction, order: 'ASC' | 'DESC' = 'ASC') {
+  static listThreadParentComments (comment: MCommentId, t: Transaction, order: 'ASC' | 'DESC' = 'ASC'): Bluebird<MCommentOwner[]> {
     const query = {
       order: [ [ 'createdAt', order ] ] as Order,
       where: {
@@ -389,10 +358,10 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
       transaction: t
     }
 
-    return VideoCommentModel.findAndCountAll(query)
+    return VideoCommentModel.findAndCountAll<MComment>(query)
   }
 
-  static listForFeed (start: number, count: number, videoId?: number) {
+  static listForFeed (start: number, count: number, videoId?: number): Bluebird<MCommentOwnerVideoFeed[]> {
     const query = {
       order: [ [ 'createdAt', 'DESC' ] ] as Order,
       offset: start,
@@ -521,7 +490,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
     } as VideoComment
   }
 
-  toActivityPubObject (threadParentComments: VideoCommentModel[]): VideoCommentObject {
+  toActivityPubObject (threadParentComments: MCommentOwner[]): VideoCommentObject {
     let inReplyTo: string
     // New thread, so in AS we reply to the video
     if (this.inReplyToCommentId === null) {
index 05c4907594fbbd36c7d86e0e8a5373c3fe24a664..6304f741ce0aa272d2ad0bb2b1c76961ec5a2e35 100644 (file)
@@ -25,6 +25,7 @@ import { VideoRedundancyModel } from '../redundancy/video-redundancy'
 import { VideoStreamingPlaylistModel } from './video-streaming-playlist'
 import { FindOptions, QueryTypes, Transaction } from 'sequelize'
 import { MIMETYPES } from '../../initializers/constants'
+import { MVideoFile } from '@server/typings/models'
 
 @Table({
   tableName: 'videoFile',
@@ -166,7 +167,7 @@ export class VideoFileModel extends Model<VideoFileModel> {
     return !!MIMETYPES.AUDIO.EXT_MIMETYPE[this.extname]
   }
 
-  hasSameUniqueKeysThan (other: VideoFileModel) {
+  hasSameUniqueKeysThan (other: MVideoFile) {
     return this.fps === other.fps &&
       this.resolution === other.resolution &&
       this.videoId === other.videoId
index 284539deff6551125d3c15e9df5df6f027ee1f90..4e7eb5f0c7cbb8225ab0f92dd9ed9afcf029b5a2 100644 (file)
@@ -1,6 +1,5 @@
 import { Video, VideoDetails, VideoFile } from '../../../shared/models/videos'
 import { VideoModel } from './video'
-import { VideoFileModel } from './video-file'
 import {
   ActivityPlaylistInfohashesObject,
   ActivityPlaylistSegmentHashesObject,
@@ -17,7 +16,9 @@ import {
 } from '../../lib/activitypub'
 import { isArray } from '../../helpers/custom-validators/misc'
 import { VideoStreamingPlaylist } from '../../../shared/models/videos/video-streaming-playlist.model'
-import { VideoStreamingPlaylistModel } from './video-streaming-playlist'
+import { MVideo, MVideoAP, MVideoDetails } from '../../typings/models'
+import { MStreamingPlaylistRedundancies } from '../../typings/models/video/video-streaming-playlist'
+import { MVideoFileRedundanciesOpt } from '../../typings/models/video/video-file'
 
 export type VideoFormattingJSONOptions = {
   completeDescription?: boolean
@@ -102,7 +103,7 @@ function videoModelToFormattedJSON (video: VideoModel, options?: VideoFormatting
   return videoObject
 }
 
-function videoModelToFormattedDetailsJSON (video: VideoModel): VideoDetails {
+function videoModelToFormattedDetailsJSON (video: MVideoDetails): VideoDetails {
   const formattedJson = video.toFormattedJSON({
     additionalAttributes: {
       scheduledUpdate: true,
@@ -114,7 +115,7 @@ function videoModelToFormattedDetailsJSON (video: VideoModel): VideoDetails {
 
   const tags = video.Tags ? video.Tags.map(t => t.name) : []
 
-  const streamingPlaylists = streamingPlaylistsModelToFormattedJSON(video, video.VideoStreamingPlaylists)
+  const streamingPlaylists = streamingPlaylistsModelToFormattedJSON(video.VideoStreamingPlaylists)
 
   const detailsJson = {
     support: video.support,
@@ -142,7 +143,7 @@ function videoModelToFormattedDetailsJSON (video: VideoModel): VideoDetails {
   return Object.assign(formattedJson, detailsJson)
 }
 
-function streamingPlaylistsModelToFormattedJSON (video: VideoModel, playlists: VideoStreamingPlaylistModel[]): VideoStreamingPlaylist[] {
+function streamingPlaylistsModelToFormattedJSON (playlists: MStreamingPlaylistRedundancies[]): VideoStreamingPlaylist[] {
   if (isArray(playlists) === false) return []
 
   return playlists
@@ -161,7 +162,7 @@ function streamingPlaylistsModelToFormattedJSON (video: VideoModel, playlists: V
     })
 }
 
-function videoFilesModelToFormattedJSON (video: VideoModel, videoFiles: VideoFileModel[]): VideoFile[] {
+function videoFilesModelToFormattedJSON (video: MVideo, videoFiles: MVideoFileRedundanciesOpt[]): VideoFile[] {
   const { baseUrlHttp, baseUrlWs } = video.getBaseUrls()
 
   return videoFiles
@@ -189,7 +190,7 @@ function videoFilesModelToFormattedJSON (video: VideoModel, videoFiles: VideoFil
     })
 }
 
-function videoModelToActivityPubObject (video: VideoModel): VideoTorrentObject {
+function videoModelToActivityPubObject (video: MVideoAP): VideoTorrentObject {
   const { baseUrlHttp, baseUrlWs } = video.getBaseUrls()
   if (!video.Tags) video.Tags = []
 
index 480a671c883d059df97197b5d8d934cebfe5c430..f596eea9d259f1a256b6c1d9d14f81fb543df0d2 100644 (file)
@@ -20,6 +20,8 @@ import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../help
 import { VideoImport, VideoImportState } from '../../../shared'
 import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
 import { UserModel } from '../account/user'
+import * as Bluebird from 'bluebird'
+import { MVideoImportDefault } from '@server/typings/models/video/video-import'
 
 @DefaultScope(() => ({
   include: [
@@ -28,7 +30,11 @@ import { UserModel } from '../account/user'
       required: true
     },
     {
-      model: VideoModel.scope([ VideoModelScopeNames.WITH_ACCOUNT_DETAILS, VideoModelScopeNames.WITH_TAGS]),
+      model: VideoModel.scope([
+        VideoModelScopeNames.WITH_ACCOUNT_DETAILS,
+        VideoModelScopeNames.WITH_TAGS,
+        VideoModelScopeNames.WITH_THUMBNAILS
+      ]),
       required: false
     }
   ]
@@ -114,7 +120,7 @@ export class VideoImportModel extends Model<VideoImportModel> {
     return undefined
   }
 
-  static loadAndPopulateVideo (id: number) {
+  static loadAndPopulateVideo (id: number): Bluebird<MVideoImportDefault> {
     return VideoImportModel.findByPk(id)
   }
 
@@ -135,7 +141,7 @@ export class VideoImportModel extends Model<VideoImportModel> {
       }
     }
 
-    return VideoImportModel.findAndCountAll(query)
+    return VideoImportModel.findAndCountAll<MVideoImportDefault>(query)
                            .then(({ rows, count }) => {
                              return {
                                data: rows,
index dd7653533d25e31775b32e5435ff3e8aeaaeacee..90111316199fa103a32654f18b211dd7659c8dca 100644 (file)
@@ -25,6 +25,9 @@ import { UserModel } from '../account/user'
 import { VideoPlaylistElement, VideoPlaylistElementType } from '../../../shared/models/videos/playlist/video-playlist-element.model'
 import { AccountModel } from '../account/account'
 import { VideoPrivacy } from '../../../shared/models/videos'
+import * as Bluebird from 'bluebird'
+import { MVideoPlaylistAP, MVideoPlaylistElement, MVideoPlaylistVideoThumbnail } from '@server/typings/models/video/video-playlist-element'
+import { MUserAccountId } from '@server/typings/models'
 
 @Table({
   tableName: 'videoPlaylistElement',
@@ -116,7 +119,7 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
     count: number,
     videoPlaylistId: number,
     serverAccount: AccountModel,
-    user?: UserModel
+    user?: MUserAccountId
   }) {
     const accountIds = [ options.serverAccount.id ]
     const videoScope: (ScopeOptions | string)[] = [
@@ -162,7 +165,7 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
     ]).then(([ total, data ]) => ({ total, data }))
   }
 
-  static loadByPlaylistAndVideo (videoPlaylistId: number, videoId: number) {
+  static loadByPlaylistAndVideo (videoPlaylistId: number, videoId: number): Bluebird<MVideoPlaylistElement> {
     const query = {
       where: {
         videoPlaylistId,
@@ -173,11 +176,11 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
     return VideoPlaylistElementModel.findOne(query)
   }
 
-  static loadById (playlistElementId: number) {
+  static loadById (playlistElementId: number): Bluebird<MVideoPlaylistElement> {
     return VideoPlaylistElementModel.findByPk(playlistElementId)
   }
 
-  static loadByPlaylistAndVideoForAP (playlistId: number | string, videoId: number | string) {
+  static loadByPlaylistAndVideoForAP (playlistId: number | string, videoId: number | string): Bluebird<MVideoPlaylistAP> {
     const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId }
     const videoWhere = validator.isUUID('' + videoId) ? { uuid: videoId } : { id: videoId }
 
@@ -218,7 +221,7 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
       })
   }
 
-  static loadFirstElementWithVideoThumbnail (videoPlaylistId: number) {
+  static loadFirstElementWithVideoThumbnail (videoPlaylistId: number): Bluebird<MVideoPlaylistVideoThumbnail> {
     const query = {
       order: getSort('position'),
       where: {
index c8e97c491d1866633a3432be57c239461ce33d5d..9f1d03ac5e7f8f8744433db9cbf5d7c0f7e32499 100644 (file)
@@ -43,6 +43,14 @@ import { VideoPlaylistType } from '../../../shared/models/videos/playlist/video-
 import { ThumbnailModel } from './thumbnail'
 import { ActivityIconObject } from '../../../shared/models/activitypub/objects'
 import { FindOptions, literal, Op, ScopeOptions, Transaction, WhereOptions } from 'sequelize'
+import * as Bluebird from 'bluebird'
+import {
+  MVideoPlaylistAccountThumbnail,
+  MVideoPlaylistFull,
+  MVideoPlaylistFullSummary,
+  MVideoPlaylistIdWithElements
+} from '../../typings/models/video/video-playlist'
+import { MThumbnail } from '../../typings/models/video/thumbnail'
 
 enum ScopeNames {
   AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST',
@@ -332,7 +340,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
                              })
   }
 
-  static listPlaylistIdsOf (accountId: number, videoIds: number[]) {
+  static listPlaylistIdsOf (accountId: number, videoIds: number[]): Bluebird<MVideoPlaylistIdWithElements[]> {
     const query = {
       attributes: [ 'id' ],
       where: {
@@ -368,7 +376,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
       .then(e => !!e)
   }
 
-  static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction) {
+  static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction): Bluebird<MVideoPlaylistFullSummary> {
     const where = buildWhereIdOrUUID(id)
 
     const query = {
@@ -381,7 +389,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
       .findOne(query)
   }
 
-  static loadWithAccountAndChannel (id: number | string, transaction: Transaction) {
+  static loadWithAccountAndChannel (id: number | string, transaction: Transaction): Bluebird<MVideoPlaylistFull> {
     const where = buildWhereIdOrUUID(id)
 
     const query = {
@@ -394,7 +402,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
       .findOne(query)
   }
 
-  static loadByUrlAndPopulateAccount (url: string) {
+  static loadByUrlAndPopulateAccount (url: string): Bluebird<MVideoPlaylistAccountThumbnail> {
     const query = {
       where: {
         url
@@ -423,7 +431,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
     return VideoPlaylistModel.update({ privacy: VideoPlaylistPrivacy.PRIVATE, videoChannelId: null }, query)
   }
 
-  async setAndSaveThumbnail (thumbnail: ThumbnailModel, t: Transaction) {
+  async setAndSaveThumbnail (thumbnail: MThumbnail, t: Transaction) {
     thumbnail.videoPlaylistId = this.id
 
     this.Thumbnail = await thumbnail.save({ transaction: t })
index d8ed64557917ea907e3f6b34be801dd5d86929da..9019b401abeda0d0439cebb63673c91f7effd370 100644 (file)
@@ -8,6 +8,8 @@ import { buildLocalActorIdsIn, throwIfNotValid } from '../utils'
 import { VideoModel } from './video'
 import { VideoChannelModel } from './video-channel'
 import { Op, Transaction } from 'sequelize'
+import { MVideoShareActor, MVideoShareFull } from '../../typings/models/video'
+import { MActorDefault } from '../../typings/models'
 
 enum ScopeNames {
   FULL = 'FULL',
@@ -88,7 +90,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
   })
   Video: VideoModel
 
-  static load (actorId: number, videoId: number, t?: Transaction) {
+  static load (actorId: number, videoId: number, t?: Transaction): Bluebird<MVideoShareActor> {
     return VideoShareModel.scope(ScopeNames.WITH_ACTOR).findOne({
       where: {
         actorId,
@@ -98,7 +100,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
     })
   }
 
-  static loadByUrl (url: string, t: Transaction) {
+  static loadByUrl (url: string, t: Transaction): Bluebird<MVideoShareFull> {
     return VideoShareModel.scope(ScopeNames.FULL).findOne({
       where: {
         url
@@ -107,7 +109,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
     })
   }
 
-  static loadActorsByShare (videoId: number, t: Transaction) {
+  static loadActorsByShare (videoId: number, t: Transaction): Bluebird<MActorDefault[]> {
     const query = {
       where: {
         videoId
@@ -122,10 +124,10 @@ export class VideoShareModel extends Model<VideoShareModel> {
     }
 
     return VideoShareModel.scope(ScopeNames.FULL).findAll(query)
-      .then(res => res.map(r => r.Actor))
+      .then((res: MVideoShareFull[]) => res.map(r => r.Actor))
   }
 
-  static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Bluebird<ActorModel[]> {
+  static loadActorsWhoSharedVideosOf (actorOwnerId: number, t: Transaction): Bluebird<MActorDefault[]> {
     const query = {
       attributes: [],
       include: [
@@ -163,7 +165,7 @@ export class VideoShareModel extends Model<VideoShareModel> {
       .then(res => res.map(r => r.Actor))
   }
 
-  static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Bluebird<ActorModel[]> {
+  static loadActorsByVideoChannel (videoChannelId: number, t: Transaction): Bluebird<MActorDefault[]> {
     const query = {
       attributes: [],
       include: [
index 31dc82c541109ed56a72078928e9e9aae4b9e2f6..0ea90d28c40561a0d050ca534b042179002997b5 100644 (file)
@@ -1,16 +1,16 @@
-import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, HasMany, Is, Model, Table, UpdatedAt, DataType } from 'sequelize-typescript'
+import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
 import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos'
 import { throwIfNotValid } from '../utils'
 import { VideoModel } from './video'
 import { VideoRedundancyModel } from '../redundancy/video-redundancy'
 import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type'
 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
-import { CONSTRAINTS_FIELDS, STATIC_PATHS, P2P_MEDIA_LOADER_PEER_VERSION } from '../../initializers/constants'
-import { VideoFileModel } from './video-file'
+import { CONSTRAINTS_FIELDS, P2P_MEDIA_LOADER_PEER_VERSION, STATIC_PATHS } from '../../initializers/constants'
 import { join } from 'path'
 import { sha1 } from '../../helpers/core-utils'
 import { isArrayOf } from '../../helpers/custom-validators/misc'
-import { QueryTypes, Op } from 'sequelize'
+import { Op, QueryTypes } from 'sequelize'
+import { MStreamingPlaylist, MVideoFile } from '@server/typings/models'
 
 @Table({
   tableName: 'videoStreamingPlaylist',
@@ -91,7 +91,7 @@ export class VideoStreamingPlaylistModel extends Model<VideoStreamingPlaylistMod
               .then(results => results.length === 1)
   }
 
-  static buildP2PMediaLoaderInfoHashes (playlistUrl: string, videoFiles: VideoFileModel[]) {
+  static buildP2PMediaLoaderInfoHashes (playlistUrl: string, videoFiles: MVideoFile[]) {
     const hashes: string[] = []
 
     // https://github.com/Novage/p2p-media-loader/blob/master/p2p-media-loader-core/lib/p2p-media-manager.ts#L115
@@ -165,7 +165,7 @@ export class VideoStreamingPlaylistModel extends Model<VideoStreamingPlaylistMod
     return baseUrlHttp + STATIC_PATHS.REDUNDANCY + this.getStringType() + '/' + this.Video.uuid
   }
 
-  hasSameUniqueKeysThan (other: VideoStreamingPlaylistModel) {
+  hasSameUniqueKeysThan (other: MStreamingPlaylist) {
     return this.type === other.type &&
       this.videoId === other.videoId
   }
index b59df397d470a2ccce64866bef5ed8d5133c73c5..7b1f0bc316b698cc8403b8725079cbfa46c72a9f 100644 (file)
@@ -36,7 +36,7 @@ import {
   Table,
   UpdatedAt
 } from 'sequelize-typescript'
-import { UserRight, VideoPrivacy, VideoResolution, VideoState } from '../../../shared'
+import { UserRight, VideoPrivacy, VideoState } from '../../../shared'
 import { VideoTorrentObject } from '../../../shared/models/activitypub/objects'
 import { Video, VideoDetails, VideoFile } from '../../../shared/models/videos'
 import { VideoFilter } from '../../../shared/models/videos/video-query.type'
@@ -111,7 +111,6 @@ import {
   videoModelToFormattedJSON
 } from './video-format-utils'
 import { UserVideoHistoryModel } from '../account/user-video-history'
-import { UserModel } from '../account/user'
 import { VideoImportModel } from './video-import'
 import { VideoStreamingPlaylistModel } from './video-streaming-playlist'
 import { VideoPlaylistElementModel } from './video-playlist-element'
@@ -120,6 +119,24 @@ import { ThumbnailModel } from './thumbnail'
 import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
 import { createTorrentPromise } from '../../helpers/webtorrent'
 import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type'
+import {
+  MChannel,
+  MChannelActorAccountDefault,
+  MChannelId,
+  MUserAccountId,
+  MUserId,
+  MVideoAccountAllFiles,
+  MVideoAccountLight,
+  MVideoDetails,
+  MVideoFullLight,
+  MVideoIdThumbnail,
+  MVideoThumbnail,
+  MVideoWithAllFiles,
+  MVideoWithBlacklistThumbnailScheduled,
+  MVideoWithRights
+} from '../../typings/models'
+import { MVideoFile, MVideoFileRedundanciesOpt } from '../../typings/models/video/video-file'
+import { MThumbnail } from '../../typings/models/video/thumbnail'
 
 // FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation
 const indexes: (ModelIndexesOptions & { where?: WhereOptions })[] = [
@@ -232,8 +249,8 @@ export type AvailableForListIDsOptions = {
   videoPlaylistId?: number
 
   trendingDays?: number
-  user?: UserModel,
-  historyOfUser?: UserModel
+  user?: MUserAccountId
+  historyOfUser?: MUserId
 
   baseWhere?: WhereOptions[]
 }
@@ -634,7 +651,7 @@ export type AvailableForListIDsOptions = {
   [ ScopeNames.WITH_BLACKLISTED ]: {
     include: [
       {
-        attributes: [ 'id', 'reason' ],
+        attributes: [ 'id', 'reason', 'unfederated' ],
         model: VideoBlacklistModel,
         required: false
       }
@@ -989,18 +1006,16 @@ export class VideoModel extends Model<VideoModel> {
   VideoCaptions: VideoCaptionModel[]
 
   @BeforeDestroy
-  static async sendDelete (instance: VideoModel, options) {
+  static async sendDelete (instance: MVideoAccountLight, options) {
     if (instance.isOwned()) {
       if (!instance.VideoChannel) {
         instance.VideoChannel = await instance.$get('VideoChannel', {
           include: [
-            {
-              model: AccountModel,
-              include: [ ActorModel ]
-            }
+            ActorModel,
+            AccountModel
           ],
           transaction: options.transaction
-        }) as VideoChannelModel
+        }) as MChannelActorAccountDefault
       }
 
       return sendDeleteVideo(instance, options.transaction)
@@ -1039,7 +1054,7 @@ export class VideoModel extends Model<VideoModel> {
     return undefined
   }
 
-  static listLocal () {
+  static listLocal (): Bluebird<MVideoWithAllFiles[]> {
     const query = {
       where: {
         remote: false
@@ -1159,7 +1174,7 @@ export class VideoModel extends Model<VideoModel> {
     })
   }
 
-  static listUserVideosForApi (accountId: number, start: number, count: number, sort: string, withFiles = false) {
+  static listUserVideosForApi (accountId: number, start: number, count: number, sort: string) {
     function buildBaseQuery (): FindOptions {
       return {
         offset: start,
@@ -1192,19 +1207,12 @@ export class VideoModel extends Model<VideoModel> {
       ScopeNames.WITH_THUMBNAILS
     ]
 
-    if (withFiles === true) {
-      findQuery.include.push({
-        model: VideoFileModel.unscoped(),
-        required: true
-      })
-    }
-
     return Promise.all([
       VideoModel.count(countQuery),
       VideoModel.scope(findScopes).findAll(findQuery)
     ]).then(([ count, rows ]) => {
       return {
-        data: rows,
+        data: rows as MVideoWithBlacklistThumbnailScheduled[],
         total: count
       }
     })
@@ -1228,8 +1236,8 @@ export class VideoModel extends Model<VideoModel> {
     followerActorId?: number
     videoPlaylistId?: number,
     trendingDays?: number,
-    user?: UserModel,
-    historyOfUser?: UserModel
+    user?: MUserAccountId,
+    historyOfUser?: MUserId
   }, countVideos = true) {
     if (options.filter && options.filter === 'all-local' && !options.user.hasRight(UserRight.SEE_ALL_VIDEOS)) {
       throw new Error('Try to filter all-local but no user has not the see all videos right')
@@ -1294,7 +1302,7 @@ export class VideoModel extends Model<VideoModel> {
     tagsAllOf?: string[]
     durationMin?: number // seconds
     durationMax?: number // seconds
-    user?: UserModel,
+    user?: MUserAccountId,
     filter?: VideoFilter
   }) {
     const whereAnd = []
@@ -1387,7 +1395,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.getAvailableForApi(query, queryOptions)
   }
 
-  static load (id: number | string, t?: Transaction) {
+  static load (id: number | string, t?: Transaction): Bluebird<MVideoThumbnail> {
     const where = buildWhereIdOrUUID(id)
     const options = {
       where,
@@ -1397,7 +1405,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
   }
 
-  static loadWithRights (id: number | string, t?: Transaction) {
+  static loadWithRights (id: number | string, t?: Transaction): Bluebird<MVideoWithRights> {
     const where = buildWhereIdOrUUID(id)
     const options = {
       where,
@@ -1411,7 +1419,7 @@ export class VideoModel extends Model<VideoModel> {
     ]).findOne(options)
   }
 
-  static loadOnlyId (id: number | string, t?: Transaction) {
+  static loadOnlyId (id: number | string, t?: Transaction): Bluebird<MVideoIdThumbnail> {
     const where = buildWhereIdOrUUID(id)
 
     const options = {
@@ -1423,7 +1431,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
   }
 
-  static loadWithFiles (id: number | string, t?: Transaction, logging?: boolean) {
+  static loadWithFiles (id: number | string, t?: Transaction, logging?: boolean): Bluebird<MVideoWithAllFiles> {
     const where = buildWhereIdOrUUID(id)
 
     const query = {
@@ -1439,7 +1447,7 @@ export class VideoModel extends Model<VideoModel> {
     ]).findOne(query)
   }
 
-  static loadByUUID (uuid: string) {
+  static loadByUUID (uuid: string): Bluebird<MVideoThumbnail> {
     const options = {
       where: {
         uuid
@@ -1449,7 +1457,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(options)
   }
 
-  static loadByUrl (url: string, transaction?: Transaction) {
+  static loadByUrl (url: string, transaction?: Transaction): Bluebird<MVideoThumbnail> {
     const query: FindOptions = {
       where: {
         url
@@ -1460,7 +1468,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.scope(ScopeNames.WITH_THUMBNAILS).findOne(query)
   }
 
-  static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction) {
+  static loadByUrlAndPopulateAccount (url: string, transaction?: Transaction): Bluebird<MVideoAccountAllFiles> {
     const query: FindOptions = {
       where: {
         url
@@ -1472,11 +1480,12 @@ export class VideoModel extends Model<VideoModel> {
       ScopeNames.WITH_ACCOUNT_DETAILS,
       ScopeNames.WITH_FILES,
       ScopeNames.WITH_STREAMING_PLAYLISTS,
-      ScopeNames.WITH_THUMBNAILS
+      ScopeNames.WITH_THUMBNAILS,
+      ScopeNames.WITH_BLACKLISTED
     ]).findOne(query)
   }
 
-  static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number) {
+  static loadAndPopulateAccountAndServerAndTags (id: number | string, t?: Transaction, userId?: number): Bluebird<MVideoFullLight> {
     const where = buildWhereIdOrUUID(id)
 
     const options = {
@@ -1508,7 +1517,7 @@ export class VideoModel extends Model<VideoModel> {
     id: number | string,
     t?: Transaction,
     userId?: number
-  }) {
+  }): Bluebird<MVideoDetails> {
     const { id, t, userId } = parameters
     const where = buildWhereIdOrUUID(id)
 
@@ -1586,7 +1595,7 @@ export class VideoModel extends Model<VideoModel> {
                      .then(results => results.length === 1)
   }
 
-  static bulkUpdateSupportField (videoChannel: VideoChannelModel, t: Transaction) {
+  static bulkUpdateSupportField (videoChannel: MChannel, t: Transaction) {
     const options = {
       where: {
         channelId: videoChannel.id
@@ -1597,7 +1606,7 @@ export class VideoModel extends Model<VideoModel> {
     return VideoModel.update({ support: videoChannel.support }, options)
   }
 
-  static getAllIdsFromChannel (videoChannel: VideoChannelModel) {
+  static getAllIdsFromChannel (videoChannel: MChannelId): Bluebird<number[]> {
     const query = {
       attributes: [ 'id' ],
       where: {
@@ -1769,7 +1778,7 @@ export class VideoModel extends Model<VideoModel> {
     return this.VideoFiles.find(f => f.resolution === resolution)
   }
 
-  async addAndSaveThumbnail (thumbnail: ThumbnailModel, transaction: Transaction) {
+  async addAndSaveThumbnail (thumbnail: MThumbnail, transaction: Transaction) {
     thumbnail.videoId = this.id
 
     const savedThumbnail = await thumbnail.save({ transaction })
@@ -1782,7 +1791,7 @@ export class VideoModel extends Model<VideoModel> {
     this.Thumbnails.push(savedThumbnail)
   }
 
-  getVideoFilename (videoFile: VideoFileModel) {
+  getVideoFilename (videoFile: MVideoFile) {
     return this.uuid + '-' + videoFile.resolution + videoFile.extname
   }
 
@@ -1806,7 +1815,7 @@ export class VideoModel extends Model<VideoModel> {
     return this.Thumbnails.find(t => t.type === ThumbnailType.PREVIEW)
   }
 
-  getTorrentFileName (videoFile: VideoFileModel) {
+  getTorrentFileName (videoFile: MVideoFile) {
     const extension = '.torrent'
     return this.uuid + '-' + videoFile.resolution + extension
   }
@@ -1815,15 +1824,15 @@ export class VideoModel extends Model<VideoModel> {
     return this.remote === false
   }
 
-  getTorrentFilePath (videoFile: VideoFileModel) {
+  getTorrentFilePath (videoFile: MVideoFile) {
     return join(CONFIG.STORAGE.TORRENTS_DIR, this.getTorrentFileName(videoFile))
   }
 
-  getVideoFilePath (videoFile: VideoFileModel) {
+  getVideoFilePath (videoFile: MVideoFile) {
     return join(CONFIG.STORAGE.VIDEOS_DIR, this.getVideoFilename(videoFile))
   }
 
-  async createTorrentAndSetInfoHash (videoFile: VideoFileModel) {
+  async createTorrentAndSetInfoHash (videoFile: MVideoFile) {
     const options = {
       // Keep the extname, it's used by the client to stream the file inside a web browser
       name: `${this.name} ${videoFile.resolution}p${videoFile.extname}`,
@@ -1908,7 +1917,7 @@ export class VideoModel extends Model<VideoModel> {
     return this.VideoStreamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
   }
 
-  removeFile (videoFile: VideoFileModel, isRedundancy = false) {
+  removeFile (videoFile: MVideoFile, isRedundancy = false) {
     const baseDir = isRedundancy ? CONFIG.STORAGE.REDUNDANCY_DIR : CONFIG.STORAGE.VIDEOS_DIR
 
     const filePath = join(baseDir, this.getVideoFilename(videoFile))
@@ -1916,7 +1925,7 @@ export class VideoModel extends Model<VideoModel> {
       .catch(err => logger.warn('Cannot delete file %s.', filePath, { err }))
   }
 
-  removeTorrent (videoFile: VideoFileModel) {
+  removeTorrent (videoFile: MVideoFile) {
     const torrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, this.getTorrentFileName(videoFile))
     return remove(torrentPath)
       .catch(err => logger.warn('Cannot delete torrent %s.', torrentPath, { err }))
@@ -1957,7 +1966,7 @@ export class VideoModel extends Model<VideoModel> {
     return { baseUrlHttp, baseUrlWs }
   }
 
-  generateMagnetUri (videoFile: VideoFileModel, baseUrlHttp: string, baseUrlWs: string) {
+  generateMagnetUri (videoFile: MVideoFileRedundanciesOpt, baseUrlHttp: string, baseUrlWs: string) {
     const xs = this.getTorrentUrl(videoFile, baseUrlHttp)
     const announce = this.getTrackerUrls(baseUrlHttp, baseUrlWs)
     let urlList = [ this.getVideoFileUrl(videoFile, baseUrlHttp) ]
@@ -1980,27 +1989,27 @@ export class VideoModel extends Model<VideoModel> {
     return [ baseUrlWs + '/tracker/socket', baseUrlHttp + '/tracker/announce' ]
   }
 
-  getTorrentUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
+  getTorrentUrl (videoFile: MVideoFile, baseUrlHttp: string) {
     return baseUrlHttp + STATIC_PATHS.TORRENTS + this.getTorrentFileName(videoFile)
   }
 
-  getTorrentDownloadUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
+  getTorrentDownloadUrl (videoFile: MVideoFile, baseUrlHttp: string) {
     return baseUrlHttp + STATIC_DOWNLOAD_PATHS.TORRENTS + this.getTorrentFileName(videoFile)
   }
 
-  getVideoFileUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
+  getVideoFileUrl (videoFile: MVideoFile, baseUrlHttp: string) {
     return baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename(videoFile)
   }
 
-  getVideoRedundancyUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
+  getVideoRedundancyUrl (videoFile: MVideoFile, baseUrlHttp: string) {
     return baseUrlHttp + STATIC_PATHS.REDUNDANCY + this.getVideoFilename(videoFile)
   }
 
-  getVideoFileDownloadUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
+  getVideoFileDownloadUrl (videoFile: MVideoFile, baseUrlHttp: string) {
     return baseUrlHttp + STATIC_DOWNLOAD_PATHS.VIDEOS + this.getVideoFilename(videoFile)
   }
 
-  getBandwidthBits (videoFile: VideoFileModel) {
+  getBandwidthBits (videoFile: MVideoFile) {
     return Math.ceil((videoFile.size * 8) / this.duration)
   }
 }
index 37b2859dec301addd0f1cf1a22f5c6fa937625f4..7ed3a65b153cbf37cff0642a76d0e5c28d6faddb 100644 (file)
@@ -1,10 +1,9 @@
 import { Activity } from '../../shared/models/activitypub'
-import { ActorModel } from '../models/activitypub/actor'
-import { SignatureActorModel } from './models'
+import { MActorDefault, MActorSignature } from './models'
 
 export type APProcessorOptions<T extends Activity> = {
   activity: T
-  byActor: SignatureActorModel
-  inboxActor?: ActorModel
+  byActor: MActorSignature
+  inboxActor?: MActorDefault
   fromFetch?: boolean
 }
index f7da55ab0e8ed5e1c738f3717c5c7f69cf65f799..26009146110c0702dc36ccee4b8bc65cfc1e6cea 100644 (file)
-import { VideoChannelModel } from '../models/video/video-channel'
-import { VideoPlaylistModel } from '../models/video/video-playlist'
-import { VideoPlaylistElementModel } from '../models/video/video-playlist-element'
-import { UserModel } from '../models/account/user'
-import { VideoModel } from '../models/video/video'
-import { AccountModel } from '../models/account/account'
-import { VideoChangeOwnershipModel } from '../models/video/video-change-ownership'
-import { ActorModel } from '../models/activitypub/actor'
-import { VideoCommentModel } from '../models/video/video-comment'
-import { VideoShareModel } from '../models/video/video-share'
-import { AccountVideoRateModel } from '../models/account/account-video-rate'
-import { ActorFollowModel } from '../models/activitypub/actor-follow'
-import { ServerModel } from '../models/server/server'
-import { VideoFileModel } from '../models/video/video-file'
-import { VideoRedundancyModel } from '../models/redundancy/video-redundancy'
-import { ServerBlocklistModel } from '../models/server/server-blocklist'
-import { AccountBlocklistModel } from '../models/account/account-blocklist'
-import { VideoImportModel } from '../models/video/video-import'
-import { VideoAbuseModel } from '../models/video/video-abuse'
-import { VideoBlacklistModel } from '../models/video/video-blacklist'
-import { VideoCaptionModel } from '../models/video/video-caption'
-import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist'
 import { RegisteredPlugin } from '../lib/plugins/plugin-manager'
-import { PluginModel } from '../models/server/plugin'
-import { SignatureActorModel } from './models'
+import {
+  MAccountDefault,
+  MActorAccountChannelId,
+  MActorFollowActorsDefault,
+  MActorFollowActorsDefaultSubscription,
+  MActorFull,
+  MChannelActorAccountDefault,
+  MComment,
+  MCommentOwnerVideoReply,
+  MUserDefault,
+  MVideoAbuse,
+  MVideoBlacklist,
+  MVideoCaptionVideo,
+  MVideoFullLight,
+  MVideoIdThumbnail,
+  MVideoRedundancyVideo,
+  MVideoShareActor,
+  MVideoThumbnail,
+  MVideoWithRights
+} from './models'
+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 { MAccountVideoRateAccountVideo } from '@server/typings/models/video/video-rate'
+import { MVideoChangeOwnershipFull } from './models/video/video-change-ownership'
+import { MPlugin, MServer } from '@server/typings/models/server'
+import { MServerBlocklist } from './models/server/server-blocklist'
+import { MOAuthTokenUser } from '@server/typings/models/oauth/oauth-token'
 
 declare module 'express' {
 
   interface Response {
+
     locals: {
-      video?: VideoModel
-      videoShare?: VideoShareModel
-      videoFile?: VideoFileModel
+      videoAll?: MVideoFullLight
+      onlyVideo?: MVideoThumbnail
+      onlyVideoWithRights?: MVideoWithRights
+      videoId?: MVideoIdThumbnail
+
+      videoShare?: MVideoShareActor
+
+      videoFile?: MVideoFile
+
+      videoImport?: MVideoImportDefault
+
+      videoBlacklist?: MVideoBlacklist
+
+      videoCaption?: MVideoCaptionVideo
+
+      videoAbuse?: MVideoAbuse
 
-      videoImport?: VideoImportModel
+      videoStreamingPlaylist?: MStreamingPlaylist
 
-      videoBlacklist?: VideoBlacklistModel
+      videoChannel?: MChannelActorAccountDefault
 
-      videoCaption?: VideoCaptionModel
+      videoPlaylistFull?: MVideoPlaylistFull
+      videoPlaylistSummary?: MVideoPlaylistFullSummary
 
-      videoAbuse?: VideoAbuseModel
+      videoPlaylistElement?: MVideoPlaylistElement
 
-      videoStreamingPlaylist?: VideoStreamingPlaylistModel
+      accountVideoRate?: MAccountVideoRateAccountVideo
 
-      videoChannel?: VideoChannelModel
+      videoCommentFull?: MCommentOwnerVideoReply
+      videoCommentThread?: MComment
 
-      videoPlaylist?: VideoPlaylistModel
-      videoPlaylistElement?: VideoPlaylistElementModel
+      follow?: MActorFollowActorsDefault
+      subscription?: MActorFollowActorsDefaultSubscription
 
-      accountVideoRate?: AccountVideoRateModel
+      nextOwner?: MAccountDefault
+      videoChangeOwnership?: MVideoChangeOwnershipFull
 
-      videoComment?: VideoCommentModel
-      videoCommentThread?: VideoCommentModel
+      account?: MAccountDefault
 
-      follow?: ActorFollowModel
-      subscription?: ActorFollowModel
+      actorFull?: MActorFull
 
-      nextOwner?: AccountModel
-      videoChangeOwnership?: VideoChangeOwnershipModel
-      account?: AccountModel
-      actor?: ActorModel
-      user?: UserModel
+      user?: MUserDefault
 
-      server?: ServerModel
+      server?: MServer
 
-      videoRedundancy?: VideoRedundancyModel
+      videoRedundancy?: MVideoRedundancyVideo
 
-      accountBlock?: AccountBlocklistModel
-      serverBlock?: ServerBlocklistModel
+      accountBlock?: MAccountBlocklist
+      serverBlock?: MServerBlocklist
 
       oauth?: {
-        token: {
-          User: UserModel
-          user: UserModel
-        }
+        token: MOAuthTokenUser
       }
 
       signature?: {
-        actor: SignatureActorModel
+        actor: MActorAccountChannelId
       }
 
       authenticated?: boolean
 
       registeredPlugin?: RegisteredPlugin
 
-      plugin?: PluginModel
+      plugin?: MPlugin
     }
   }
 }
diff --git a/server/typings/models/account/account-blocklist.ts b/server/typings/models/account/account-blocklist.ts
new file mode 100644 (file)
index 0000000..6d1771d
--- /dev/null
@@ -0,0 +1,11 @@
+import { AccountBlocklistModel } from '../../../models/account/account-blocklist'
+import { PickWith } from '../../utils'
+import { MAccountDefault } from './account'
+
+export type MAccountBlocklist = Omit<AccountBlocklistModel, 'ByAccount' | 'BlockedAccount'>
+
+export type MAccountBlocklistId = Pick<AccountBlocklistModel, 'id'>
+
+export type MAccountBlocklistAccounts = MAccountBlocklist &
+  PickWith<AccountBlocklistModel, 'ByAccount', MAccountDefault> &
+  PickWith<AccountBlocklistModel, 'BlockedAccount', MAccountDefault>
diff --git a/server/typings/models/account/account.ts b/server/typings/models/account/account.ts
new file mode 100644 (file)
index 0000000..f3646d5
--- /dev/null
@@ -0,0 +1,56 @@
+import { AccountModel } from '../../../models/account/account'
+import {
+  MActor,
+  MActorAccountChannelId,
+  MActorAPI,
+  MActorAudience,
+  MActorDefault,
+  MActorDefaultLight, MActorId,
+  MActorServer,
+  MActorSummary,
+  MActorUrl
+} from './actor'
+import { PickWith } from '../../utils'
+import { MAccountBlocklistId } from './account-blocklist'
+import { MChannelDefault } from '@server/typings/models'
+
+export type MAccountId = Pick<AccountModel, 'id'>
+export type MAccountIdActor = MAccountId &
+  PickWith<AccountModel, 'Actor', MActorAccountChannelId>
+export type MAccountIdActorId = MAccountId &
+  PickWith<AccountModel, 'Actor', MActorId>
+
+export type MAccount = Omit<AccountModel, 'Actor' | 'User' | 'Application' | 'VideoChannels' | 'VideoPlaylists' |
+  'VideoComments' | 'BlockedAccounts'>
+
+// Default scope
+export type MAccountDefault = MAccount &
+  PickWith<AccountModel, 'Actor', MActorDefault>
+
+export type MAccountDefaultChannelDefault = MAccountDefault &
+  PickWith<AccountModel, 'VideoChannels', MChannelDefault[]>
+
+export type MAccountLight = MAccount &
+  PickWith<AccountModel, 'Actor', MActorDefaultLight>
+
+export type MAccountUserId = Pick<MAccount, 'userId'>
+
+export type MAccountActor = MAccount &
+  PickWith<AccountModel, 'Actor', MActor>
+export type MAccountServer = MAccountActor &
+  PickWith<AccountModel, 'Actor', MActorServer>
+
+export type MAccountActorDefault = MAccount &
+  PickWith<AccountModel, 'Actor', MActorDefault>
+
+export type MAccountSummary = Pick<MAccount, 'id' | 'name'> &
+  PickWith<AccountModel, 'Actor', MActorSummary>
+
+export type MAccountBlocks = MAccountSummary &
+  PickWith<AccountModel, 'BlockedAccounts', MAccountBlocklistId[]>
+
+export type MAccountAPI = MAccountDefault &
+  PickWith<AccountModel, 'Actor', MActorAPI>
+
+export type MAccountUrl = PickWith<AccountModel, 'Actor', MActorUrl>
+export type MAccountAudience = PickWith<AccountModel, 'Actor', MActorAudience>
diff --git a/server/typings/models/account/actor-follow.ts b/server/typings/models/account/actor-follow.ts
new file mode 100644 (file)
index 0000000..96c53d8
--- /dev/null
@@ -0,0 +1,27 @@
+import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
+import { MActor, MActorAccountChannel, MActorChannel, MActorChannelAccount, MActorDefault, MActorHost, MActorUsername } from './actor'
+import { PickWith } from '../../utils'
+
+export type MActorFollow = Omit<ActorFollowModel, 'ActorFollower' | 'ActorFollowing'>
+
+export type MActorFollowActors = MActorFollow &
+  PickWith<ActorFollowModel, 'ActorFollower', MActor> &
+  PickWith<ActorFollowModel, 'ActorFollowing', MActor>
+
+export type MActorFollowActorsDefault = MActorFollow &
+  PickWith<ActorFollowModel, 'ActorFollower', MActorDefault> &
+  PickWith<ActorFollowModel, 'ActorFollowing', MActorDefault>
+
+export type MActorFollowActorsDefaultSubscription = MActorFollow &
+  PickWith<ActorFollowModel, 'ActorFollower', MActorDefault> &
+  PickWith<ActorFollowModel, 'ActorFollowing', MActorDefault & MActorChannel>
+
+export type MActorFollowFull = MActorFollow &
+  PickWith<ActorFollowModel, 'ActorFollower', MActorAccountChannel> &
+  PickWith<ActorFollowModel, 'ActorFollowing', MActorAccountChannel>
+
+export type MActorFollowFollowingHost = MActorFollow &
+  PickWith<ActorFollowModel, 'ActorFollowing', MActorUsername & MActorHost>
+
+export type MActorFollowSubscriptions = MActorFollow &
+  PickWith<ActorFollowModel, 'ActorFollowing', MActorChannelAccount>
diff --git a/server/typings/models/account/actor.ts b/server/typings/models/account/actor.ts
new file mode 100644 (file)
index 0000000..f3e752a
--- /dev/null
@@ -0,0 +1,74 @@
+import { ActorModel } from '../../../models/activitypub/actor'
+import { PickWith } from '../../utils'
+import { MAccount, MAccountActorDefault, MAccountId, MAccountIdActor } from './account'
+import { MServerHost, MServerHostBlocks, MServer } from '../server'
+import { MAvatar } from './avatar'
+import { MChannel, MChannelAccountActor, MChannelActorAccountDefault, MChannelId, MChannelIdActor } from '../video'
+
+export type MActor = Omit<ActorModel, 'Account' | 'VideoChannel' | 'ActorFollowing' | 'Avatar' | 'ActorFollowers' | 'Server'>
+
+export type MActorUrl = Pick<MActor, 'url'>
+export type MActorId = Pick<MActor, 'id'>
+export type MActorUsername = Pick<MActor, 'preferredUsername'>
+export type MActorHost = PickWith<ActorModel, 'Server', MServerHost>
+
+export type MActorFollowersUrl = Pick<MActor, 'followersUrl'>
+export type MActorAudience = MActorUrl & MActorFollowersUrl
+
+export type MActorLight = Omit<MActor, 'privateKey' | 'privateKey'>
+
+export type MActorDefaultLight = MActorLight &
+  MActorHost &
+  PickWith<ActorModel, 'Avatar', MAvatar>
+
+export type MActorAccountId = MActor &
+  PickWith<ActorModel, 'Account', MAccountId>
+export type MActorAccountIdActor = MActor &
+  PickWith<ActorModel, 'Account', MAccountIdActor>
+
+export type MActorChannelId = MActor &
+  PickWith<ActorModel, 'VideoChannel', MChannelId>
+export type MActorChannelIdActor = MActor &
+  PickWith<ActorModel, 'VideoChannel', MChannelIdActor>
+
+export type MActorAccountChannelId = MActorAccountId & MActorChannelId
+export type MActorAccountChannelIdActor = MActorAccountIdActor & MActorChannelIdActor
+
+export type MActorAccount = MActor &
+  PickWith<ActorModel, 'Account', MAccount>
+
+export type MActorChannel = MActor &
+  PickWith<ActorModel, 'VideoChannel', MChannel>
+
+export type MActorAccountChannel = MActorAccount & MActorChannel
+
+export type MActorChannelAccount = MActor &
+  PickWith<ActorModel, 'VideoChannel', MChannelAccountActor>
+
+export type MActorServer = MActor &
+  PickWith<ActorModel, 'Server', MServer>
+
+export type MActorDefault = MActorServer &
+  PickWith<ActorModel, 'Avatar', MAvatar>
+
+export type MActorFull = MActorDefault &
+  PickWith<ActorModel, 'Account', MAccount> &
+  PickWith<ActorModel, 'VideoChannel', MChannelAccountActor>
+
+export type MActorFullActor = MActorDefault &
+  PickWith<ActorModel, 'Account', MAccountActorDefault> &
+  PickWith<ActorModel, 'VideoChannel', MChannelActorAccountDefault>
+
+export type MActorSummary = Pick<MActor, 'id' | 'preferredUsername' | 'url' | 'serverId' | 'avatarId'> &
+  MActorHost &
+  PickWith<ActorModel, 'Avatar', MAvatar>
+
+export type MActorSummaryBlocks = Omit<MActorSummary, 'Server'> &
+  PickWith<ActorModel, 'Server', MServerHostBlocks>
+
+export type MActorFollowerException = Pick<ActorModel, 'sharedInboxUrl' | 'inboxUrl'>
+
+export type MActorAPI = Omit<MActorDefault, 'publicKey' | 'privateKey' | 'inboxUrl' | 'outboxUrl' | 'sharedInboxUrl' |
+  'followersUrl' | 'followingUrl' | 'url' | 'createdAt' | 'updatedAt'>
+
+export type MActorSignature = MActorAccountChannelId
diff --git a/server/typings/models/account/avatar.ts b/server/typings/models/account/avatar.ts
new file mode 100644 (file)
index 0000000..257c48b
--- /dev/null
@@ -0,0 +1,3 @@
+import { AvatarModel } from '../../../models/avatar/avatar'
+
+export type MAvatar = AvatarModel
diff --git a/server/typings/models/account/index.d.ts b/server/typings/models/account/index.d.ts
new file mode 100644 (file)
index 0000000..513c09c
--- /dev/null
@@ -0,0 +1,5 @@
+export * from './account'
+export * from './account-blocklist'
+export * from './actor'
+export * from './actor-follow'
+export * from './avatar'
diff --git a/server/typings/models/actor-follow.ts b/server/typings/models/actor-follow.ts
deleted file mode 100644 (file)
index 952ef87..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-import { ActorFollowModel } from '../../models/activitypub/actor-follow'
-import { ActorModelOnly } from './actor'
-
-export type ActorFollowModelOnly = Omit<ActorFollowModel, 'ActorFollower' | 'ActorFollowing'>
-export type ActorFollowModelLight = ActorFollowModelOnly & {
-  ActorFollower: ActorModelOnly
-  ActorFollowing: ActorModelOnly
-}
diff --git a/server/typings/models/actor.ts b/server/typings/models/actor.ts
deleted file mode 100644 (file)
index 2656c7b..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-import { ActorModel } from '../../models/activitypub/actor'
-import { VideoChannelModel } from '../../models/video/video-channel'
-import { AccountModel } from '../../models/account/account'
-import { FunctionProperties } from '../utils'
-
-export type VideoChannelModelId = FunctionProperties<VideoChannelModel>
-export type AccountModelId = FunctionProperties<AccountModel> | Pick<AccountModel, 'id'>
-
-export type VideoChannelModelIdActor = VideoChannelModelId & Pick<VideoChannelModel, 'Actor'>
-export type AccountModelIdActor = AccountModelId & Pick<AccountModel, 'Actor'>
-
-export type ActorModelUrl = Pick<ActorModel, 'url'>
-export type ActorModelOnly = Omit<ActorModel, 'Account' | 'VideoChannel' | 'ActorFollowing' | 'Avatar' | 'ActorFollowers' | 'Server'>
-export type ActorModelId = Pick<ActorModelOnly, 'id'>
-
-export type SignatureActorModel = ActorModelOnly & {
-  VideoChannel: VideoChannelModelIdActor
-
-  Account: AccountModelIdActor
-}
-
-export type ActorFollowerException = Pick<ActorModel, 'sharedInboxUrl' | 'inboxUrl'>
index c906569654a391a591a61796957a84acea804ee1..39e82e4a8c8a76347e29b8c97382a72594d4dad6 100644 (file)
@@ -1 +1,4 @@
-export * from './actor'
+export * from './account'
+export * from './server'
+export * from './user'
+export * from './video'
diff --git a/server/typings/models/oauth/oauth-client.ts b/server/typings/models/oauth/oauth-client.ts
new file mode 100644 (file)
index 0000000..904a078
--- /dev/null
@@ -0,0 +1,3 @@
+import { OAuthClientModel } from '@server/models/oauth/oauth-client'
+
+export type MOAuthClient = Omit<OAuthClientModel, 'OAuthTokens'>
diff --git a/server/typings/models/oauth/oauth-token.ts b/server/typings/models/oauth/oauth-token.ts
new file mode 100644 (file)
index 0000000..105ea3d
--- /dev/null
@@ -0,0 +1,9 @@
+import { OAuthTokenModel } from '@server/models/oauth/oauth-token'
+import { PickWith } from '@server/typings/utils'
+import { MUserAccountUrl } from '@server/typings/models'
+
+export type MOAuthToken = Omit<OAuthTokenModel, 'User' | 'OAuthClients'>
+
+export type MOAuthTokenUser = MOAuthToken &
+  PickWith<OAuthTokenModel, 'User', MUserAccountUrl> &
+  { user?: MUserAccountUrl }
diff --git a/server/typings/models/server/index.d.ts b/server/typings/models/server/index.d.ts
new file mode 100644 (file)
index 0000000..c853795
--- /dev/null
@@ -0,0 +1,3 @@
+export * from './plugin'
+export * from './server'
+export * from './server-blocklist'
diff --git a/server/typings/models/server/plugin.ts b/server/typings/models/server/plugin.ts
new file mode 100644 (file)
index 0000000..b1e2e14
--- /dev/null
@@ -0,0 +1,3 @@
+import { PluginModel } from '@server/models/server/plugin'
+
+export type MPlugin = PluginModel
diff --git a/server/typings/models/server/server-blocklist.ts b/server/typings/models/server/server-blocklist.ts
new file mode 100644 (file)
index 0000000..38065f3
--- /dev/null
@@ -0,0 +1,9 @@
+import { ServerBlocklistModel } from '@server/models/server/server-blocklist'
+import { PickWith } from '@server/typings/utils'
+import { MAccountDefault, MServer } from '@server/typings/models'
+
+export type MServerBlocklist = Omit<ServerBlocklistModel, 'ByAccount' | 'BlockedServer'>
+
+export type MServerBlocklistAccountServer = MServerBlocklist &
+  PickWith<ServerBlocklistModel, 'ByAccount', MAccountDefault> &
+  PickWith<ServerBlocklistModel, 'BlockedServer', MServer>
diff --git a/server/typings/models/server/server.ts b/server/typings/models/server/server.ts
new file mode 100644 (file)
index 0000000..6be7bf9
--- /dev/null
@@ -0,0 +1,10 @@
+import { ServerModel } from '../../../models/server/server'
+import { PickWith } from '../../utils'
+import { MAccountBlocklistId } from '../account'
+
+export type MServer = Omit<ServerModel, 'Actors' | 'BlockedByAccounts'>
+
+export type MServerHost = Pick<MServer, 'host'>
+
+export type MServerHostBlocks = MServerHost &
+  PickWith<ServerModel, 'BlockedByAccounts', MAccountBlocklistId[]>
diff --git a/server/typings/models/user/index.d.ts b/server/typings/models/user/index.d.ts
new file mode 100644 (file)
index 0000000..e3353d0
--- /dev/null
@@ -0,0 +1,3 @@
+export * from './user'
+export * from './user-notification'
+export * from './user-video-history'
diff --git a/server/typings/models/user/user-notification-setting.ts b/server/typings/models/user/user-notification-setting.ts
new file mode 100644 (file)
index 0000000..585d30a
--- /dev/null
@@ -0,0 +1,3 @@
+import { UserNotificationSettingModel } from '@server/models/account/user-notification-setting'
+
+export type MNotificationSetting = Omit<UserNotificationSettingModel, 'User'>
diff --git a/server/typings/models/user/user-notification.ts b/server/typings/models/user/user-notification.ts
new file mode 100644 (file)
index 0000000..b872c5d
--- /dev/null
@@ -0,0 +1,69 @@
+import { UserNotificationModel } from '../../../models/account/user-notification'
+import { PickWith } from '../../utils'
+import { VideoModel } from '../../../models/video/video'
+import { ActorModel } from '../../../models/activitypub/actor'
+import { ServerModel } from '../../../models/server/server'
+import { AvatarModel } from '../../../models/avatar/avatar'
+import { VideoChannelModel } from '../../../models/video/video-channel'
+import { AccountModel } from '../../../models/account/account'
+import { VideoCommentModel } from '../../../models/video/video-comment'
+import { VideoAbuseModel } from '../../../models/video/video-abuse'
+import { VideoBlacklistModel } from '../../../models/video/video-blacklist'
+import { VideoImportModel } from '../../../models/video/video-import'
+import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
+
+export namespace UserNotificationIncludes {
+  export type VideoInclude = Pick<VideoModel, 'id' | 'uuid' | 'name'>
+  export type VideoIncludeChannel = VideoInclude &
+    PickWith<VideoModel, 'VideoChannel', VideoChannelIncludeActor>
+
+  export type ActorInclude = Pick<ActorModel, 'preferredUsername' | 'getHost'> &
+    PickWith<ActorModel, 'Avatar', Pick<AvatarModel, 'filename' | 'getStaticPath'>> &
+    PickWith<ActorModel, 'Server', Pick<ServerModel, 'host'>>
+
+  export type VideoChannelInclude = Pick<VideoChannelModel, 'id' | 'name' | 'getDisplayName'>
+  export type VideoChannelIncludeActor = VideoChannelInclude &
+    PickWith<VideoChannelModel, 'Actor', ActorInclude>
+
+  export type AccountInclude = Pick<AccountModel, 'id' | 'name' | 'getDisplayName'>
+  export type AccountIncludeActor = AccountInclude &
+    PickWith<AccountModel, 'Actor', ActorInclude>
+
+  export type VideoCommentInclude = Pick<VideoCommentModel, 'id' | 'originCommentId' | 'getThreadId'> &
+    PickWith<VideoCommentModel, 'Account', AccountIncludeActor> &
+    PickWith<VideoCommentModel, 'Video', VideoInclude>
+
+  export type VideoAbuseInclude = Pick<VideoAbuseModel, 'id'> &
+    PickWith<VideoAbuseModel, 'Video', VideoInclude>
+
+  export type VideoBlacklistInclude = Pick<VideoBlacklistModel, 'id'> &
+    PickWith<VideoAbuseModel, 'Video', VideoInclude>
+
+  export type VideoImportInclude = Pick<VideoImportModel, 'id' | 'magnetUri' | 'targetUrl' | 'torrentName'> &
+    PickWith<VideoImportModel, 'Video', VideoInclude>
+
+  export type ActorFollower = Pick<ActorModel, 'preferredUsername' | 'getHost'> &
+    PickWith<ActorModel, 'Account', AccountInclude> &
+    PickWith<ActorModel, 'Avatar', Pick<AvatarModel, 'filename' | 'getStaticPath'>> &
+    PickWith<ActorModel, 'Server', Pick<ServerModel, 'host'>>
+
+  export type ActorFollowing = Pick<ActorModel, 'preferredUsername'> &
+    PickWith<ActorModel, 'VideoChannel', VideoChannelInclude> &
+    PickWith<ActorModel, 'Account', AccountInclude>
+
+  export type ActorFollowInclude = Pick<ActorFollowModel, 'id' | 'state'> &
+    PickWith<ActorFollowModel, 'ActorFollower', ActorFollower> &
+    PickWith<ActorFollowModel, 'ActorFollowing', ActorFollowing>
+}
+
+export type UserNotificationModelOnly = Omit<UserNotificationModel, 'User' | 'Video' | 'Comment' | 'VideoAbuse' | 'VideoBlacklist' |
+  'VideoImport' | 'Account' | 'ActorFollow'>
+
+export type UserNotificationModelForApi = UserNotificationModelOnly &
+  PickWith<UserNotificationModel, 'Video', UserNotificationIncludes.VideoIncludeChannel> &
+  PickWith<UserNotificationModel, 'Comment', UserNotificationIncludes.VideoCommentInclude> &
+  PickWith<UserNotificationModel, 'VideoAbuse', UserNotificationIncludes.VideoAbuseInclude> &
+  PickWith<UserNotificationModel, 'VideoBlacklist', UserNotificationIncludes.VideoBlacklistInclude> &
+  PickWith<UserNotificationModel, 'VideoImport', UserNotificationIncludes.VideoImportInclude> &
+  PickWith<UserNotificationModel, 'ActorFollow', UserNotificationIncludes.ActorFollowInclude> &
+  PickWith<UserNotificationModel, 'Account', UserNotificationIncludes.AccountIncludeActor>
diff --git a/server/typings/models/user/user-video-history.ts b/server/typings/models/user/user-video-history.ts
new file mode 100644 (file)
index 0000000..62673ab
--- /dev/null
@@ -0,0 +1,5 @@
+import { UserVideoHistoryModel } from '../../../models/account/user-video-history'
+
+export type MUserVideoHistory = Omit<UserVideoHistoryModel, 'Video' | 'User'>
+
+export type MUserVideoHistoryTime = Pick<MUserVideoHistory, 'currentTime'>
diff --git a/server/typings/models/user/user.ts b/server/typings/models/user/user.ts
new file mode 100644 (file)
index 0000000..b91eed8
--- /dev/null
@@ -0,0 +1,32 @@
+import { UserModel } from '../../../models/account/user'
+import { PickWith } from '../../utils'
+import { MAccount, MAccountDefault, MAccountDefaultChannelDefault, MAccountId, MAccountIdActorId, MAccountUrl } from '../account'
+import { MNotificationSetting } from './user-notification-setting'
+
+export type MUser = Omit<UserModel, 'Account' | 'NotificationSetting' | 'VideoImports' | 'OAuthTokens'>
+
+export type MUserId = Pick<UserModel, 'id'>
+
+export type MUserWithNotificationSetting = MUser &
+  PickWith<UserModel, 'NotificationSetting', MNotificationSetting>
+
+export type MUserAccountDefault = MUser &
+  PickWith<UserModel, 'Account', MAccountDefault>
+
+export type MUserAccount = MUser &
+  PickWith<UserModel, 'Account', MAccount>
+
+export type MUserAccountId = MUser &
+  PickWith<UserModel, 'Account', MAccountId>
+
+export type MUserNotifSettingAccount = MUserWithNotificationSetting & MUserAccount
+
+export type MUserDefault = MUser &
+  MUserWithNotificationSetting &
+  MUserAccountDefault
+
+export type MUserChannel = MUserWithNotificationSetting &
+  PickWith<UserModel, 'Account', MAccountDefaultChannelDefault>
+
+export type MUserAccountUrl = MUser &
+  PickWith<UserModel, 'Account', MAccountUrl & MAccountIdActorId>
diff --git a/server/typings/models/video-share.ts b/server/typings/models/video-share.ts
deleted file mode 100644 (file)
index 1406749..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-import { VideoShareModel } from '../../models/video/video-share'
-
-export type VideoShareModelOnly = Omit<VideoShareModel, 'Actor' | 'Video'>
diff --git a/server/typings/models/video/index.d.ts b/server/typings/models/video/index.d.ts
new file mode 100644 (file)
index 0000000..528e9d2
--- /dev/null
@@ -0,0 +1,14 @@
+export * from './schedule-video-update'
+export * from './tag'
+export * from './thumbnail'
+export * from './video'
+export * from './video-abuse'
+export * from './video-blacklist'
+export * from './video-caption'
+export * from './video-channels'
+export * from './video-comment'
+export * from './video-file'
+export * from './video-playlist'
+export * from './video-redundancy'
+export * from './video-share'
+export * from './video-streaming-playlist'
diff --git a/server/typings/models/video/schedule-video-update.ts b/server/typings/models/video/schedule-video-update.ts
new file mode 100644 (file)
index 0000000..0697055
--- /dev/null
@@ -0,0 +1,3 @@
+import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update'
+
+export type MScheduleVideoUpdate = Omit<ScheduleVideoUpdateModel, 'Video'>
diff --git a/server/typings/models/video/tag.ts b/server/typings/models/video/tag.ts
new file mode 100644 (file)
index 0000000..64a6887
--- /dev/null
@@ -0,0 +1,3 @@
+import { TagModel } from '../../../models/video/tag'
+
+export type MTag = Omit<TagModel, 'Videos'>
diff --git a/server/typings/models/video/thumbnail.ts b/server/typings/models/video/thumbnail.ts
new file mode 100644 (file)
index 0000000..c03ba55
--- /dev/null
@@ -0,0 +1,3 @@
+import { ThumbnailModel } from '../../../models/video/thumbnail'
+
+export type MThumbnail = Omit<ThumbnailModel, 'Video' | 'VideoPlaylist'>
diff --git a/server/typings/models/video/video-abuse.ts b/server/typings/models/video/video-abuse.ts
new file mode 100644 (file)
index 0000000..1667ae5
--- /dev/null
@@ -0,0 +1,15 @@
+import { VideoAbuseModel } from '../../../models/video/video-abuse'
+import { PickWith } from '../../utils'
+import { MVideo } from './video'
+import { MAccountDefault } from '../account'
+
+export type MVideoAbuse = Omit<VideoAbuseModel, 'Account' | 'Video' | 'toActivityPubObject'>
+
+export type MVideoAbuseId = Pick<VideoAbuseModel, 'id'>
+
+export type MVideoAbuseVideo = MVideoAbuse &
+  Pick<VideoAbuseModel, 'toActivityPubObject'> &
+  PickWith<VideoAbuseModel, 'Video', MVideo>
+
+export type MVideoAbuseAccountVideo = MVideoAbuseVideo &
+  PickWith<VideoAbuseModel, 'Account', MAccountDefault>
diff --git a/server/typings/models/video/video-blacklist.ts b/server/typings/models/video/video-blacklist.ts
new file mode 100644 (file)
index 0000000..9242b35
--- /dev/null
@@ -0,0 +1,11 @@
+import { VideoBlacklistModel } from '../../../models/video/video-blacklist'
+import { PickWith } from '@server/typings/utils'
+import { MVideo } from '@server/typings/models'
+
+export type MVideoBlacklist = Omit<VideoBlacklistModel, 'Video'>
+
+export type MVideoBlacklistLight = Pick<MVideoBlacklist, 'id' | 'reason' | 'unfederated'>
+export type MVideoBlacklistUnfederated = Pick<MVideoBlacklist, 'unfederated'>
+
+export type MVideoBlacklistVideo = MVideoBlacklist &
+  PickWith<VideoBlacklistModel, 'Video', MVideo>
diff --git a/server/typings/models/video/video-caption.ts b/server/typings/models/video/video-caption.ts
new file mode 100644 (file)
index 0000000..16d8b73
--- /dev/null
@@ -0,0 +1,10 @@
+import { VideoCaptionModel } from '../../../models/video/video-caption'
+import { PickWith } from '@server/typings/utils'
+import { VideoModel } from '@server/models/video/video'
+
+export type MVideoCaption = Omit<VideoCaptionModel, 'Video'>
+
+export type MVideoCaptionLanguage = Pick<MVideoCaption, 'language'>
+
+export type MVideoCaptionVideo = MVideoCaption &
+  PickWith<VideoCaptionModel, 'Video', Pick<VideoModel, 'id' | 'remote' | 'uuid'>>
diff --git a/server/typings/models/video/video-change-ownership.ts b/server/typings/models/video/video-change-ownership.ts
new file mode 100644 (file)
index 0000000..718515e
--- /dev/null
@@ -0,0 +1,10 @@
+import { VideoChangeOwnershipModel } from '@server/models/video/video-change-ownership'
+import { PickWith } from '@server/typings/utils'
+import { MAccountDefault, MVideoWithFileThumbnail } from '@server/typings/models'
+
+export type MVideoChangeOwnership = Omit<VideoChangeOwnershipModel, 'Initiator' | 'NextOwner' | 'Video'>
+
+export type MVideoChangeOwnershipFull = MVideoChangeOwnership &
+  PickWith<VideoChangeOwnershipModel, 'Initiator', MAccountDefault> &
+  PickWith<VideoChangeOwnershipModel, 'NextOwner', MAccountDefault> &
+  PickWith<VideoChangeOwnershipModel, 'Video', MVideoWithFileThumbnail>
diff --git a/server/typings/models/video/video-channels.ts b/server/typings/models/video/video-channels.ts
new file mode 100644 (file)
index 0000000..e10bd68
--- /dev/null
@@ -0,0 +1,70 @@
+import { FunctionProperties, PickWith } from '../../utils'
+import { VideoChannelModel } from '../../../models/video/video-channel'
+import {
+  MAccountActor,
+  MAccountAPI,
+  MAccountBlocks,
+  MAccountDefault,
+  MAccountLight,
+  MAccountUserId,
+  MActor,
+  MActorAccountChannelId,
+  MActorAPI,
+  MActorDefault,
+  MActorDefaultLight, MActorLight,
+  MActorSummary
+} from '../account'
+import { MVideo } from './video'
+
+export type MChannelId = FunctionProperties<VideoChannelModel>
+export type MChannelIdActor = MChannelId &
+  PickWith<VideoChannelModel, 'Actor', MActorAccountChannelId>
+
+export type MChannel = Omit<VideoChannelModel, 'Actor' | 'Account' | 'Videos' | 'VideoPlaylists'>
+
+export type MChannelUserId = Pick<MChannel, 'accountId'> &
+  PickWith<VideoChannelModel, 'Account', MAccountUserId>
+
+// Default scope
+export type MChannelDefault = MChannel &
+  PickWith<VideoChannelModel, 'Actor', MActorDefault>
+
+export type MChannelLight = MChannel &
+  PickWith<VideoChannelModel, 'Actor', MActorDefaultLight>
+
+export type MChannelAccountLight = MChannel &
+  PickWith<VideoChannelModel, 'Actor', MActorDefaultLight> &
+  PickWith<VideoChannelModel, 'Account', MAccountLight>
+
+export type MChannelSummary = Pick<MChannel, 'id' | 'name' | 'description' | 'actorId'> &
+  PickWith<VideoChannelModel, 'Actor', MActorSummary>
+
+export type MChannelSummaryAccount = MChannelSummary &
+  PickWith<VideoChannelModel, 'Account', MAccountBlocks>
+
+export type MChannelAPI = MChannel &
+  PickWith<VideoChannelModel, 'Actor', MActorAPI> &
+  PickWith<VideoChannelModel, 'Account', MAccountAPI>
+
+export type MChannelAccountActor = MChannel &
+  PickWith<VideoChannelModel, 'Account', MAccountActor>
+export type MChannelAccountDefault = MChannelActor &
+  PickWith<VideoChannelModel, 'Account', MAccountDefault>
+
+export type MChannelVideos = MChannel &
+  PickWith<VideoChannelModel, 'Videos', MVideo[]>
+
+export type MChannelActor = MChannel &
+  PickWith<VideoChannelModel, 'Actor', MActor>
+export type MChannelActorLight = MChannel &
+  PickWith<VideoChannelModel, 'Actor', MActorLight>
+export type MChannelActorDefault = MChannel &
+  PickWith<VideoChannelModel, 'Actor', MActorDefault>
+
+export type MChannelActorAccountActor = MChannelAccountActor & MChannelActor
+
+export type MChannelActorAccountDefault = MChannel &
+  PickWith<VideoChannelModel, 'Actor', MActorDefault> &
+  PickWith<VideoChannelModel, 'Account', MAccountDefault>
+
+export type MChannelActorAccountDefaultVideos = MChannelActorAccountDefault & MChannelVideos
diff --git a/server/typings/models/video/video-comment.ts b/server/typings/models/video/video-comment.ts
new file mode 100644 (file)
index 0000000..6756138
--- /dev/null
@@ -0,0 +1,29 @@
+import { VideoCommentModel } from '../../../models/video/video-comment'
+import { PickWith } from '../../utils'
+import { MAccountDefault } from '../account'
+import { MVideoAccountDefault, MVideoAccountLight, MVideoFeed, MVideoIdUrl } from './video'
+
+export type MComment = Omit<VideoCommentModel, 'OriginVideoComment' | 'InReplyToVideoComment' | 'Video' | 'Account'>
+export type MCommentId = Pick<MComment, 'id'>
+
+export type MCommentAPI = MComment & { totalReplies: number }
+
+export type MCommentOwner = MComment &
+  PickWith<VideoCommentModel, 'Account', MAccountDefault>
+
+export type MCommentVideo = MComment &
+  PickWith<VideoCommentModel, 'Video', MVideoAccountLight>
+
+export type MCommentReply = MComment &
+  PickWith<VideoCommentModel, 'InReplyToVideoComment', MComment>
+
+export type MCommentOwnerReply = MCommentOwner & MCommentReply
+export type MCommentOwnerVideo = MCommentOwner & MCommentVideo
+export type MCommentReplyVideo = MCommentReply & MCommentVideo
+export type MCommentOwnerVideoReply = MCommentOwnerVideo & MCommentReply
+
+export type MCommentOwnerReplyVideoLight = MCommentOwnerReply &
+  PickWith<VideoCommentModel, 'Video', MVideoIdUrl>
+
+export type MCommentOwnerVideoFeed = MCommentOwner &
+  PickWith<VideoCommentModel, 'Video', MVideoFeed>
diff --git a/server/typings/models/video/video-file.ts b/server/typings/models/video/video-file.ts
new file mode 100644 (file)
index 0000000..afa659d
--- /dev/null
@@ -0,0 +1,15 @@
+import { VideoFileModel } from '../../../models/video/video-file'
+import { PickWith, PickWithOpt } from '../../utils'
+import { MVideo, MVideoUUID } from './video'
+import { MVideoRedundancyFileUrl } from './video-redundancy'
+
+export type MVideoFile = Omit<VideoFileModel, 'Video' | 'RedundancyVideos'>
+
+export type MVideoFileVideo = MVideoFile &
+  PickWith<VideoFileModel, 'Video', MVideo>
+
+export type MVideoFileVideoUUID = MVideoFile &
+  PickWith<VideoFileModel, 'Video', MVideoUUID>
+
+export type MVideoFileRedundanciesOpt = MVideoFile &
+  PickWithOpt<VideoFileModel, 'RedundancyVideos', MVideoRedundancyFileUrl[]>
diff --git a/server/typings/models/video/video-import.ts b/server/typings/models/video/video-import.ts
new file mode 100644 (file)
index 0000000..51be900
--- /dev/null
@@ -0,0 +1,15 @@
+import { VideoImportModel } from '@server/models/video/video-import'
+import { PickWith } from '@server/typings/utils'
+import { MUser, MVideo, MVideoAccountLight, MVideoTag, MVideoThumbnail, MVideoWithFile } from '@server/typings/models'
+
+export type MVideoImport = Omit<VideoImportModel, 'User' | 'Video'>
+
+export type MVideoImportDefault = MVideoImport &
+  PickWith<VideoImportModel, 'User', MUser> &
+  PickWith<VideoImportModel, 'Video', MVideoTag & MVideoAccountLight & MVideoThumbnail>
+
+export type MVideoImportDefaultFiles = MVideoImportDefault &
+  PickWith<VideoImportModel, 'Video', MVideoTag & MVideoAccountLight & MVideoThumbnail & MVideoWithFile>
+
+export type MVideoImportVideo = MVideoImport &
+  PickWith<VideoImportModel, 'Video', MVideo>
diff --git a/server/typings/models/video/video-playlist-element.ts b/server/typings/models/video/video-playlist-element.ts
new file mode 100644 (file)
index 0000000..d1b8a18
--- /dev/null
@@ -0,0 +1,15 @@
+import { VideoPlaylistElementModel } from '@server/models/video/video-playlist-element'
+import { PickWith } from '@server/typings/utils'
+import { MVideoPlaylistPrivacy, MVideoThumbnail, MVideoUrl } from '@server/typings/models'
+
+export type MVideoPlaylistElement = Omit<VideoPlaylistElementModel, 'VideoPlaylist' | 'Video'>
+export type MVideoPlaylistElementId = Pick<MVideoPlaylistElement, 'id'>
+
+export type MVideoPlaylistElementLight = Pick<MVideoPlaylistElement, 'id' | 'videoId' | 'startTimestamp' | 'stopTimestamp'>
+
+export type MVideoPlaylistVideoThumbnail = MVideoPlaylistElement &
+  PickWith<VideoPlaylistElementModel, 'Video', MVideoThumbnail>
+
+export type MVideoPlaylistAP = MVideoPlaylistElement &
+  PickWith<VideoPlaylistElementModel, 'Video', MVideoUrl> &
+  PickWith<VideoPlaylistElementModel, 'VideoPlaylist', MVideoPlaylistPrivacy>
diff --git a/server/typings/models/video/video-playlist.ts b/server/typings/models/video/video-playlist.ts
new file mode 100644 (file)
index 0000000..825b339
--- /dev/null
@@ -0,0 +1,42 @@
+import { VideoPlaylistModel } from '../../../models/video/video-playlist'
+import { PickWith } from '../../utils'
+import { MAccount, MAccountDefault, MAccountSummary } from '../account'
+import { MThumbnail } from './thumbnail'
+import { MChannelDefault, MChannelSummary } from './video-channels'
+import { MVideoPlaylistElementLight } from '@server/typings/models/video/video-playlist-element'
+
+export type MVideoPlaylist = Omit<VideoPlaylistModel, 'OwnerAccount' | 'VideoChannel' | 'VideoPlaylistElements' | 'Thumbnail'>
+export type MVideoPlaylistId = Pick<MVideoPlaylist, 'id'>
+export type MVideoPlaylistPrivacy = Pick<MVideoPlaylist, 'privacy'>
+
+export type MVideoPlaylistWithElements = MVideoPlaylist &
+  PickWith<VideoPlaylistModel, 'VideoPlaylistElements', MVideoPlaylistElementLight[]>
+export type MVideoPlaylistIdWithElements = MVideoPlaylistId & MVideoPlaylistWithElements
+
+export type MVideoPlaylistUUID = Pick<MVideoPlaylist, 'uuid'>
+
+export type MVideoPlaylistOwner = MVideoPlaylist &
+  PickWith<VideoPlaylistModel, 'OwnerAccount', MAccount>
+
+export type MVideoPlaylistOwnerDefault = MVideoPlaylist &
+  PickWith<VideoPlaylistModel, 'OwnerAccount', MAccountDefault>
+
+export type MVideoPlaylistThumbnail = MVideoPlaylist &
+  PickWith<VideoPlaylistModel, 'Thumbnail', MThumbnail>
+
+export type MVideoPlaylistAccountThumbnail = MVideoPlaylistOwnerDefault &
+  PickWith<VideoPlaylistModel, 'Thumbnail', MThumbnail>
+
+export type MVideoPlaylistAccountChannelSummary = MVideoPlaylist &
+  PickWith<VideoPlaylistModel, 'OwnerAccount', MAccountSummary> &
+  PickWith<VideoPlaylistModel, 'VideoChannel', MChannelSummary>
+
+export type MVideoPlaylistAccountChannelDefault = MVideoPlaylist &
+  PickWith<VideoPlaylistModel, 'OwnerAccount', MAccountDefault> &
+  PickWith<VideoPlaylistModel, 'VideoChannel', MChannelDefault>
+
+export type MVideoPlaylistVideosLength = MVideoPlaylist & { videosLength: number }
+
+export type MVideoPlaylistFullSummary = MVideoPlaylistAccountChannelSummary & MVideoPlaylistThumbnail
+
+export type MVideoPlaylistFull = MVideoPlaylist & MVideoPlaylistThumbnail & MVideoPlaylistAccountChannelDefault
diff --git a/server/typings/models/video/video-rate.ts b/server/typings/models/video/video-rate.ts
new file mode 100644 (file)
index 0000000..6eefe63
--- /dev/null
@@ -0,0 +1,12 @@
+import { AccountVideoRateModel } from '@server/models/account/account-video-rate'
+import { PickWith } from '@server/typings/utils'
+import { MAccountAudience, MAccountUrl, MVideo } from '..'
+
+export type MAccountVideoRate = Omit<AccountVideoRateModel, 'Video' | 'Account'>
+
+export type MAccountVideoRateAccountUrl = MAccountVideoRate &
+  PickWith<AccountVideoRateModel, 'Account', MAccountUrl>
+
+export type MAccountVideoRateAccountVideo = MAccountVideoRate &
+  PickWith<AccountVideoRateModel, 'Account', MAccountAudience> &
+  PickWith<AccountVideoRateModel, 'Video', MVideo>
diff --git a/server/typings/models/video/video-redundancy.ts b/server/typings/models/video/video-redundancy.ts
new file mode 100644 (file)
index 0000000..ec61bfb
--- /dev/null
@@ -0,0 +1,18 @@
+import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
+import { PickWith } from '@server/typings/utils'
+import { MStreamingPlaylistVideo, MVideoFile, MVideoFileVideo } from '@server/typings/models'
+
+export type MVideoRedundancy = Omit<VideoRedundancyModel, 'VideoFile' | 'VideoStreamingPlaylist' | 'Actor'>
+
+export type MVideoRedundancyFileUrl = Pick<MVideoRedundancy, 'fileUrl'>
+
+export type MVideoRedundancyFile = MVideoRedundancy &
+  PickWith<VideoRedundancyModel, 'VideoFile', MVideoFile>
+
+export type MVideoRedundancyFileVideo = MVideoRedundancy &
+  PickWith<VideoRedundancyModel, 'VideoFile', MVideoFileVideo>
+
+export type MVideoRedundancyStreamingPlaylistVideo = MVideoRedundancy &
+  PickWith<VideoRedundancyModel, 'VideoStreamingPlaylist', MStreamingPlaylistVideo>
+
+export type MVideoRedundancyVideo = MVideoRedundancyFileVideo | MVideoRedundancyStreamingPlaylistVideo
diff --git a/server/typings/models/video/video-share.ts b/server/typings/models/video/video-share.ts
new file mode 100644 (file)
index 0000000..7e8cb8b
--- /dev/null
@@ -0,0 +1,12 @@
+import { VideoShareModel } from '../../../models/video/video-share'
+import { PickWith } from '../../utils'
+import { MActorDefault } from '../account'
+import { MVideo } from './video'
+
+export type MVideoShare = Omit<VideoShareModel, 'Actor' | 'Video'>
+
+export type MVideoShareActor = MVideoShare &
+  PickWith<VideoShareModel, 'Actor', MActorDefault>
+
+export type MVideoShareFull = MVideoShareActor &
+  PickWith<VideoShareModel, 'Video', MVideo>
diff --git a/server/typings/models/video/video-streaming-playlist.ts b/server/typings/models/video/video-streaming-playlist.ts
new file mode 100644 (file)
index 0000000..5b63107
--- /dev/null
@@ -0,0 +1,12 @@
+import { VideoStreamingPlaylistModel } from '../../../models/video/video-streaming-playlist'
+import { PickWith } from '../../utils'
+import { MVideoRedundancyFileUrl } from './video-redundancy'
+import { MVideo } from '@server/typings/models'
+
+export type MStreamingPlaylist = Omit<VideoStreamingPlaylistModel, 'Video' | 'RedundancyVideos'>
+
+export type MStreamingPlaylistVideo = MStreamingPlaylist &
+  PickWith<VideoStreamingPlaylistModel, 'Video', MVideo>
+
+export type MStreamingPlaylistRedundancies = MStreamingPlaylist &
+  PickWith<VideoStreamingPlaylistModel, 'RedundancyVideos', MVideoRedundancyFileUrl[]>
diff --git a/server/typings/models/video/video.ts b/server/typings/models/video/video.ts
new file mode 100644 (file)
index 0000000..0ffd0c3
--- /dev/null
@@ -0,0 +1,103 @@
+import { VideoModel } from '../../../models/video/video'
+import { PickWith, PickWithOpt } from '../../utils'
+import { MChannelAccountLight, MChannelActor, MChannelActorAccountDefault, MChannelUserId } from './video-channels'
+import { MTag } from './tag'
+import { MVideoCaptionLanguage } from './video-caption'
+import { MStreamingPlaylist, MStreamingPlaylistRedundancies } from './video-streaming-playlist'
+import { MVideoFile, MVideoFileRedundanciesOpt } from './video-file'
+import { MThumbnail } from './thumbnail'
+import { MVideoBlacklistLight, MVideoBlacklistUnfederated } from './video-blacklist'
+import { MScheduleVideoUpdate } from './schedule-video-update'
+import { MUserVideoHistoryTime } from '../user/user-video-history'
+
+export type MVideo = Omit<VideoModel, 'VideoChannel' | 'Tags' | 'Thumbnails' | 'VideoPlaylistElements' | 'VideoAbuses' |
+  'VideoFiles' | 'VideoStreamingPlaylists' | 'VideoShares' | 'AccountVideoRates' | 'VideoComments' | 'VideoViews' | 'UserVideoHistories' |
+  'ScheduleVideoUpdate' | 'VideoBlacklist' | 'VideoImport' | 'VideoCaptions'>
+
+export type MVideoId = Pick<MVideo, 'id'>
+export type MVideoUrl = Pick<MVideo, 'url'>
+export type MVideoUUID = Pick<MVideo, 'uuid'>
+
+export type MVideoIdUrl = MVideoId & MVideoUrl
+export type MVideoFeed = Pick<MVideo, 'name' | 'uuid'>
+
+export type MVideoWithFile = MVideo &
+  PickWith<VideoModel, 'VideoFiles', MVideoFile[]>
+
+export type MVideoThumbnail = MVideo &
+  PickWith<VideoModel, 'Thumbnails', MThumbnail[]>
+export type MVideoIdThumbnail = MVideoThumbnail & MVideoId
+
+export type MVideoTag = MVideo &
+  PickWith<VideoModel, 'Tags', MTag[]>
+
+export type MVideoWithSchedule = MVideo &
+  PickWithOpt<VideoModel, 'ScheduleVideoUpdate', MScheduleVideoUpdate>
+
+export type MVideoWithFileThumbnail = MVideoWithFile & MVideoThumbnail
+
+export type MVideoUser = MVideo &
+  PickWith<VideoModel, 'VideoChannel', MChannelUserId>
+
+export type MVideoWithCaptions = MVideo &
+  PickWith<VideoModel, 'VideoCaptions', MVideoCaptionLanguage[]>
+
+export type MVideoWithBlacklistLight = MVideo &
+  PickWith<VideoModel, 'VideoBlacklist', MVideoBlacklistLight>
+
+export type MVideoAccountLight = MVideo &
+  PickWith<VideoModel, 'VideoChannel', MChannelAccountLight>
+
+export type MVideoWithRights = MVideoWithBlacklistLight & MVideoThumbnail & MVideoUser
+
+export type MVideoWithStreamingPlaylist = MVideo &
+  PickWith<VideoModel, 'VideoStreamingPlaylists', MStreamingPlaylist[]>
+
+export type MVideoWithAllFiles = MVideoWithFileThumbnail & MVideoWithStreamingPlaylist
+
+export type MVideoAccountAllFiles = MVideoWithAllFiles & MVideoAccountLight & MVideoWithBlacklistLight
+export type MVideoAccountAllFilesCaptions = MVideoAccountAllFiles & MVideoWithCaptions
+
+export type MVideoUserHistory = MVideo &
+  PickWith<VideoModel, 'UserVideoHistories', MUserVideoHistoryTime[]>
+
+export type MVideoWithBlacklistThumbnailScheduled = MVideoWithSchedule & MVideoWithBlacklistLight & MVideoWithFileThumbnail
+
+export type MVideoAccountDefault = MVideo &
+  PickWith<VideoModel, 'VideoChannel', MChannelActorAccountDefault>
+
+export type MVideoThumbnailAccountDefault = MVideoThumbnail &
+  PickWith<VideoModel, 'VideoChannel', MChannelActorAccountDefault>
+
+export type MVideoWithChannelActor = MVideo &
+  PickWith<VideoModel, 'VideoChannel', MChannelActor>
+
+export type MVideoFullLight = MVideoThumbnail &
+  MVideoWithBlacklistLight &
+  MVideoTag &
+  MVideoAccountLight &
+  MVideoUserHistory &
+  MVideoWithFile &
+  MVideoWithSchedule &
+  MVideoWithStreamingPlaylist &
+  MVideoUserHistory
+
+export type MVideoAP = MVideo &
+  MVideoTag &
+  MVideoAccountLight &
+  MVideoWithStreamingPlaylist &
+  MVideoWithCaptions &
+  PickWith<VideoModel, 'VideoBlacklist', MVideoBlacklistUnfederated> &
+  PickWith<VideoModel, 'VideoFiles', MVideoFileRedundanciesOpt[]>
+
+export type MVideoAPWithoutCaption = Omit<MVideoAP, 'VideoCaptions'>
+
+export type MVideoDetails = MVideo &
+  MVideoWithBlacklistLight &
+  MVideoTag &
+  MVideoAccountLight &
+  MVideoWithSchedule &
+  MVideoThumbnail &
+  MVideoUserHistory &
+  PickWith<VideoModel, 'VideoStreamingPlaylists', MStreamingPlaylistRedundancies[]> &
+  PickWith<VideoModel, 'VideoFiles', MVideoFileRedundanciesOpt[]>
index a86b05be2d1bf273e2bca51377809aab9c8552b8..ed0fca3d156179acdea9d1c108e698680885094f 100644 (file)
@@ -1,3 +1,15 @@
-export type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]
+export type FunctionPropertyNames<T> = {
+  [K in keyof T]: T[K] extends Function ? K : never
+}[keyof T]
 
 export type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>>
+
+export type ValueOf <T, KT extends keyof T> = T[KT]
+
+export type PickWith<T, KT extends keyof T, V> = {
+  [P in KT]: T[P] extends V ? V : never
+}
+
+export type PickWithOpt<T, KT extends keyof T, V> = {
+  [P in KT]?: T[P] extends V ? V : never
+}
index 4d2bdd6baf4f2df9168ef9888b689fdea362af8b..5ed870c5c3a74b7bdff326e54c7d53a76cdc604a 100644 (file)
       "es2016",
       "es2017"
     ],
-    "typeRoots": [ "node_modules/@types", "server/typings" ]
+    "typeRoots": [ "node_modules/@types", "server/typings" ],
+    "baseUrl": "./",
+    "paths": {
+      "@server/typings/*": [ "server/typings/*" ],
+      "@server/models/*": [ "server/models/*" ]
+    }
   },
   "exclude": [
     "server/tools/",
-    "client/node_modules",
     "node_modules",
     "dist",
     "storage",