aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/activitypub/playlist.ts14
-rw-r--r--server/lib/activitypub/video-comments.ts3
-rw-r--r--server/lib/activitypub/videos.ts34
-rw-r--r--server/lib/files-cache/abstract-video-static-file-cache.ts18
-rw-r--r--server/lib/files-cache/videos-caption-cache.ts9
-rw-r--r--server/lib/files-cache/videos-preview-cache.ts6
-rw-r--r--server/lib/job-queue/handlers/video-import.ts20
-rw-r--r--server/lib/oauth-model.ts2
-rw-r--r--server/lib/thumbnail.ts26
9 files changed, 63 insertions, 69 deletions
diff --git a/server/lib/activitypub/playlist.ts b/server/lib/activitypub/playlist.ts
index 721c19603..36a91faec 100644
--- a/server/lib/activitypub/playlist.ts
+++ b/server/lib/activitypub/playlist.ts
@@ -16,7 +16,8 @@ import { VideoPlaylistElementModel } from '../../models/video/video-playlist-ele
16import { VideoModel } from '../../models/video/video' 16import { VideoModel } from '../../models/video/video'
17import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' 17import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
18import { sequelizeTypescript } from '../../initializers/database' 18import { sequelizeTypescript } from '../../initializers/database'
19import { createPlaylistThumbnailFromUrl } from '../thumbnail' 19import { createPlaylistMiniatureFromUrl } from '../thumbnail'
20import { FilteredModelAttributes } from '../../typings/sequelize'
20 21
21function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: AccountModel, to: string[]) { 22function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: AccountModel, to: string[]) {
22 const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPlaylistPrivacy.PUBLIC : VideoPlaylistPrivacy.UNLISTED 23 const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPlaylistPrivacy.PUBLIC : VideoPlaylistPrivacy.UNLISTED
@@ -86,8 +87,7 @@ async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAc
86 } 87 }
87 } 88 }
88 89
89 // FIXME: sequelize typings 90 const [ playlist ] = await VideoPlaylistModel.upsert<VideoPlaylistModel>(playlistAttributes, { returning: true })
90 const [ playlist ] = (await VideoPlaylistModel.upsert<VideoPlaylistModel>(playlistAttributes, { returning: true }) as any)
91 91
92 let accItems: string[] = [] 92 let accItems: string[] = []
93 await crawlCollectionPage<string>(playlistObject.id, items => { 93 await crawlCollectionPage<string>(playlistObject.id, items => {
@@ -100,10 +100,8 @@ async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAc
100 100
101 if (playlistObject.icon) { 101 if (playlistObject.icon) {
102 try { 102 try {
103 const thumbnailModel = await createPlaylistThumbnailFromUrl(playlistObject.icon.url, refreshedPlaylist) 103 const thumbnailModel = await createPlaylistMiniatureFromUrl(playlistObject.icon.url, refreshedPlaylist)
104 thumbnailModel.videoPlaylistId = refreshedPlaylist.id 104 await refreshedPlaylist.setAndSaveThumbnail(thumbnailModel, undefined)
105
106 refreshedPlaylist.setThumbnail(await thumbnailModel.save())
107 } catch (err) { 105 } catch (err) {
108 logger.warn('Cannot generate thumbnail of %s.', playlistObject.id, { err }) 106 logger.warn('Cannot generate thumbnail of %s.', playlistObject.id, { err })
109 } 107 }
@@ -156,7 +154,7 @@ export {
156// --------------------------------------------------------------------------- 154// ---------------------------------------------------------------------------
157 155
158async function resetVideoPlaylistElements (elementUrls: string[], playlist: VideoPlaylistModel) { 156async function resetVideoPlaylistElements (elementUrls: string[], playlist: VideoPlaylistModel) {
159 const elementsToCreate: object[] = [] // FIXME: sequelize typings 157 const elementsToCreate: FilteredModelAttributes<VideoPlaylistElementModel>[] = []
160 158
161 await Bluebird.map(elementUrls, async elementUrl => { 159 await Bluebird.map(elementUrls, async elementUrl => {
162 try { 160 try {
diff --git a/server/lib/activitypub/video-comments.ts b/server/lib/activitypub/video-comments.ts
index cb67bf9a4..18f44d50e 100644
--- a/server/lib/activitypub/video-comments.ts
+++ b/server/lib/activitypub/video-comments.ts
@@ -73,8 +73,7 @@ async function addVideoComment (videoInstance: VideoModel, commentUrl: string) {
73 const entry = await videoCommentActivityObjectToDBAttributes(videoInstance, actor, body) 73 const entry = await videoCommentActivityObjectToDBAttributes(videoInstance, actor, body)
74 if (!entry) return { created: false } 74 if (!entry) return { created: false }
75 75
76 // FIXME: sequelize typings 76 const [ comment, created ] = await VideoCommentModel.upsert<VideoCommentModel>(entry, { returning: true })
77 const [ comment, created ] = (await VideoCommentModel.upsert<VideoCommentModel>(entry, { returning: true }) as any)
78 comment.Account = actor.Account 77 comment.Account = actor.Account
79 comment.Video = videoInstance 78 comment.Video = videoInstance
80 79
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index 5a56942a9..63bb07ec1 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -49,10 +49,11 @@ import { AccountVideoRateModel } from '../../models/account/account-video-rate'
49import { VideoShareModel } from '../../models/video/video-share' 49import { VideoShareModel } from '../../models/video/video-share'
50import { VideoCommentModel } from '../../models/video/video-comment' 50import { VideoCommentModel } from '../../models/video/video-comment'
51import { sequelizeTypescript } from '../../initializers/database' 51import { sequelizeTypescript } from '../../initializers/database'
52import { createPlaceholderThumbnail, createVideoThumbnailFromUrl } from '../thumbnail' 52import { createPlaceholderThumbnail, createVideoMiniatureFromUrl } from '../thumbnail'
53import { ThumbnailModel } from '../../models/video/thumbnail' 53import { ThumbnailModel } from '../../models/video/thumbnail'
54import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' 54import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
55import { join } from 'path' 55import { join } from 'path'
56import { FilteredModelAttributes } from '../../typings/sequelize'
56 57
57async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) { 58async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) {
58 // If the video is not private and is published, we federate it 59 // If the video is not private and is published, we federate it
@@ -247,7 +248,7 @@ async function updateVideoFromAP (options: {
247 let thumbnailModel: ThumbnailModel 248 let thumbnailModel: ThumbnailModel
248 249
249 try { 250 try {
250 thumbnailModel = await createVideoThumbnailFromUrl(options.videoObject.icon.url, options.video, ThumbnailType.THUMBNAIL) 251 thumbnailModel = await createVideoMiniatureFromUrl(options.videoObject.icon.url, options.video, ThumbnailType.MINIATURE)
251 } catch (err) { 252 } catch (err) {
252 logger.warn('Cannot generate thumbnail of %s.', options.videoObject.id, { err }) 253 logger.warn('Cannot generate thumbnail of %s.', options.videoObject.id, { err })
253 } 254 }
@@ -288,16 +289,12 @@ async function updateVideoFromAP (options: {
288 289
289 await options.video.save(sequelizeOptions) 290 await options.video.save(sequelizeOptions)
290 291
291 if (thumbnailModel) { 292 if (thumbnailModel) if (thumbnailModel) await options.video.addAndSaveThumbnail(thumbnailModel, t)
292 thumbnailModel.videoId = options.video.id
293 options.video.addThumbnail(await thumbnailModel.save({ transaction: t }))
294 }
295 293
296 // FIXME: use icon URL instead 294 // FIXME: use icon URL instead
297 const previewUrl = buildRemoteBaseUrl(options.video, join(STATIC_PATHS.PREVIEWS, options.video.getPreview().filename)) 295 const previewUrl = buildRemoteBaseUrl(options.video, join(STATIC_PATHS.PREVIEWS, options.video.getPreview().filename))
298 const previewModel = createPlaceholderThumbnail(previewUrl, options.video, ThumbnailType.PREVIEW, PREVIEWS_SIZE) 296 const previewModel = createPlaceholderThumbnail(previewUrl, options.video, ThumbnailType.PREVIEW, PREVIEWS_SIZE)
299 297 await options.video.addAndSaveThumbnail(previewModel, t)
300 options.video.addThumbnail(await previewModel.save({ transaction: t }))
301 298
302 { 299 {
303 const videoFileAttributes = videoFileActivityUrlToDBAttributes(options.video, options.videoObject) 300 const videoFileAttributes = videoFileActivityUrlToDBAttributes(options.video, options.videoObject)
@@ -311,7 +308,7 @@ async function updateVideoFromAP (options: {
311 308
312 // Update or add other one 309 // Update or add other one
313 const upsertTasks = videoFileAttributes.map(a => { 310 const upsertTasks = videoFileAttributes.map(a => {
314 return (VideoFileModel.upsert<VideoFileModel>(a, { returning: true, transaction: t }) as any) // FIXME: sequelize typings 311 return VideoFileModel.upsert<VideoFileModel>(a, { returning: true, transaction: t })
315 .then(([ file ]) => file) 312 .then(([ file ]) => file)
316 }) 313 })
317 314
@@ -334,8 +331,7 @@ async function updateVideoFromAP (options: {
334 331
335 // Update or add other one 332 // Update or add other one
336 const upsertTasks = streamingPlaylistAttributes.map(a => { 333 const upsertTasks = streamingPlaylistAttributes.map(a => {
337 // FIXME: sequelize typings 334 return VideoStreamingPlaylistModel.upsert<VideoStreamingPlaylistModel>(a, { returning: true, transaction: t })
338 return (VideoStreamingPlaylistModel.upsert<VideoStreamingPlaylistModel>(a, { returning: true, transaction: t }) as any)
339 .then(([ streamingPlaylist ]) => streamingPlaylist) 335 .then(([ streamingPlaylist ]) => streamingPlaylist)
340 }) 336 })
341 337
@@ -464,7 +460,7 @@ async function createVideo (videoObject: VideoTorrentObject, channelActor: Actor
464 const videoData = await videoActivityObjectToDBAttributes(channelActor.VideoChannel, videoObject, videoObject.to) 460 const videoData = await videoActivityObjectToDBAttributes(channelActor.VideoChannel, videoObject, videoObject.to)
465 const video = VideoModel.build(videoData) 461 const video = VideoModel.build(videoData)
466 462
467 const promiseThumbnail = createVideoThumbnailFromUrl(videoObject.icon.url, video, ThumbnailType.THUMBNAIL) 463 const promiseThumbnail = createVideoMiniatureFromUrl(videoObject.icon.url, video, ThumbnailType.MINIATURE)
468 464
469 let thumbnailModel: ThumbnailModel 465 let thumbnailModel: ThumbnailModel
470 if (waitThumbnail === true) { 466 if (waitThumbnail === true) {
@@ -477,18 +473,12 @@ async function createVideo (videoObject: VideoTorrentObject, channelActor: Actor
477 const videoCreated = await video.save(sequelizeOptions) 473 const videoCreated = await video.save(sequelizeOptions)
478 videoCreated.VideoChannel = channelActor.VideoChannel 474 videoCreated.VideoChannel = channelActor.VideoChannel
479 475
480 if (thumbnailModel) { 476 if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t)
481 thumbnailModel.videoId = videoCreated.id
482
483 videoCreated.addThumbnail(await thumbnailModel.save({ transaction: t }))
484 }
485 477
486 // FIXME: use icon URL instead 478 // FIXME: use icon URL instead
487 const previewUrl = buildRemoteBaseUrl(videoCreated, join(STATIC_PATHS.PREVIEWS, video.generatePreviewName())) 479 const previewUrl = buildRemoteBaseUrl(videoCreated, join(STATIC_PATHS.PREVIEWS, video.generatePreviewName()))
488 const previewModel = createPlaceholderThumbnail(previewUrl, video, ThumbnailType.PREVIEW, PREVIEWS_SIZE) 480 const previewModel = createPlaceholderThumbnail(previewUrl, video, ThumbnailType.PREVIEW, PREVIEWS_SIZE)
489 previewModel.videoId = videoCreated.id 481 if (thumbnailModel) await videoCreated.addAndSaveThumbnail(previewModel, t)
490
491 videoCreated.addThumbnail(await previewModel.save({ transaction: t }))
492 482
493 // Process files 483 // Process files
494 const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoCreated, videoObject) 484 const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoCreated, videoObject)
@@ -594,7 +584,7 @@ function videoFileActivityUrlToDBAttributes (video: VideoModel, videoObject: Vid
594 throw new Error('Cannot find video files for ' + video.url) 584 throw new Error('Cannot find video files for ' + video.url)
595 } 585 }
596 586
597 const attributes: object[] = [] // FIXME: add typings 587 const attributes: FilteredModelAttributes<VideoFileModel>[] = []
598 for (const fileUrl of fileUrls) { 588 for (const fileUrl of fileUrls) {
599 // Fetch associated magnet uri 589 // Fetch associated magnet uri
600 const magnet = videoObject.url.find(u => { 590 const magnet = videoObject.url.find(u => {
@@ -629,7 +619,7 @@ function streamingPlaylistActivityUrlToDBAttributes (video: VideoModel, videoObj
629 const playlistUrls = videoObject.url.filter(u => isAPStreamingPlaylistUrlObject(u)) as ActivityPlaylistUrlObject[] 619 const playlistUrls = videoObject.url.filter(u => isAPStreamingPlaylistUrlObject(u)) as ActivityPlaylistUrlObject[]
630 if (playlistUrls.length === 0) return [] 620 if (playlistUrls.length === 0) return []
631 621
632 const attributes: object[] = [] // FIXME: add typings 622 const attributes: FilteredModelAttributes<VideoStreamingPlaylistModel>[] = []
633 for (const playlistUrlObject of playlistUrls) { 623 for (const playlistUrlObject of playlistUrls) {
634 const segmentsSha256UrlObject = playlistUrlObject.tag 624 const segmentsSha256UrlObject = playlistUrlObject.tag
635 .find(t => { 625 .find(t => {
diff --git a/server/lib/files-cache/abstract-video-static-file-cache.ts b/server/lib/files-cache/abstract-video-static-file-cache.ts
index 61837e0f8..84ed74c98 100644
--- a/server/lib/files-cache/abstract-video-static-file-cache.ts
+++ b/server/lib/files-cache/abstract-video-static-file-cache.ts
@@ -4,24 +4,28 @@ import { VideoModel } from '../../models/video/video'
4import { fetchRemoteVideoStaticFile } from '../activitypub' 4import { fetchRemoteVideoStaticFile } from '../activitypub'
5import * as memoizee from 'memoizee' 5import * as memoizee from 'memoizee'
6 6
7type GetFilePathResult = { isOwned: boolean, path: string } | undefined
8
7export abstract class AbstractVideoStaticFileCache <T> { 9export abstract class AbstractVideoStaticFileCache <T> {
8 10
9 getFilePath: (params: T) => Promise<string> 11 getFilePath: (params: T) => Promise<GetFilePathResult>
10 12
11 abstract getFilePathImpl (params: T): Promise<string> 13 abstract getFilePathImpl (params: T): Promise<GetFilePathResult>
12 14
13 // Load and save the remote file, then return the local path from filesystem 15 // Load and save the remote file, then return the local path from filesystem
14 protected abstract loadRemoteFile (key: string): Promise<string> 16 protected abstract loadRemoteFile (key: string): Promise<GetFilePathResult>
15 17
16 init (max: number, maxAge: number) { 18 init (max: number, maxAge: number) {
17 this.getFilePath = memoizee(this.getFilePathImpl, { 19 this.getFilePath = memoizee(this.getFilePathImpl, {
18 maxAge, 20 maxAge,
19 max, 21 max,
20 promise: true, 22 promise: true,
21 dispose: (value: string) => { 23 dispose: (result: GetFilePathResult) => {
22 remove(value) 24 if (result.isOwned !== true) {
23 .then(() => logger.debug('%s evicted from %s', value, this.constructor.name)) 25 remove(result.path)
24 .catch(err => logger.error('Cannot remove %s from cache %s.', value, this.constructor.name, { err })) 26 .then(() => logger.debug('%s removed from %s', result.path, this.constructor.name))
27 .catch(err => logger.error('Cannot remove %s from cache %s.', result.path, this.constructor.name, { err }))
28 }
25 } 29 }
26 }) 30 })
27 } 31 }
diff --git a/server/lib/files-cache/videos-caption-cache.ts b/server/lib/files-cache/videos-caption-cache.ts
index d4a0a3345..305e39c35 100644
--- a/server/lib/files-cache/videos-caption-cache.ts
+++ b/server/lib/files-cache/videos-caption-cache.ts
@@ -4,6 +4,7 @@ import { VideoModel } from '../../models/video/video'
4import { VideoCaptionModel } from '../../models/video/video-caption' 4import { VideoCaptionModel } from '../../models/video/video-caption'
5import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' 5import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache'
6import { CONFIG } from '../../initializers/config' 6import { CONFIG } from '../../initializers/config'
7import { logger } from '../../helpers/logger'
7 8
8type GetPathParam = { videoId: string, language: string } 9type GetPathParam = { videoId: string, language: string }
9 10
@@ -24,13 +25,15 @@ class VideosCaptionCache extends AbstractVideoStaticFileCache <GetPathParam> {
24 const videoCaption = await VideoCaptionModel.loadByVideoIdAndLanguage(params.videoId, params.language) 25 const videoCaption = await VideoCaptionModel.loadByVideoIdAndLanguage(params.videoId, params.language)
25 if (!videoCaption) return undefined 26 if (!videoCaption) return undefined
26 27
27 if (videoCaption.isOwned()) return join(CONFIG.STORAGE.CAPTIONS_DIR, videoCaption.getCaptionName()) 28 if (videoCaption.isOwned()) return { isOwned: true, path: join(CONFIG.STORAGE.CAPTIONS_DIR, videoCaption.getCaptionName()) }
28 29
29 const key = params.videoId + VideosCaptionCache.KEY_DELIMITER + params.language 30 const key = params.videoId + VideosCaptionCache.KEY_DELIMITER + params.language
30 return this.loadRemoteFile(key) 31 return this.loadRemoteFile(key)
31 } 32 }
32 33
33 protected async loadRemoteFile (key: string) { 34 protected async loadRemoteFile (key: string) {
35 logger.debug('Loading remote caption file %s.', key)
36
34 const [ videoId, language ] = key.split(VideosCaptionCache.KEY_DELIMITER) 37 const [ videoId, language ] = key.split(VideosCaptionCache.KEY_DELIMITER)
35 38
36 const videoCaption = await VideoCaptionModel.loadByVideoIdAndLanguage(videoId, language) 39 const videoCaption = await VideoCaptionModel.loadByVideoIdAndLanguage(videoId, language)
@@ -46,7 +49,9 @@ class VideosCaptionCache extends AbstractVideoStaticFileCache <GetPathParam> {
46 const remoteStaticPath = videoCaption.getCaptionStaticPath() 49 const remoteStaticPath = videoCaption.getCaptionStaticPath()
47 const destPath = join(FILES_CACHE.VIDEO_CAPTIONS.DIRECTORY, videoCaption.getCaptionName()) 50 const destPath = join(FILES_CACHE.VIDEO_CAPTIONS.DIRECTORY, videoCaption.getCaptionName())
48 51
49 return this.saveRemoteVideoFileAndReturnPath(video, remoteStaticPath, destPath) 52 const path = await this.saveRemoteVideoFileAndReturnPath(video, remoteStaticPath, destPath)
53
54 return { isOwned: false, path }
50 } 55 }
51} 56}
52 57
diff --git a/server/lib/files-cache/videos-preview-cache.ts b/server/lib/files-cache/videos-preview-cache.ts
index fc0d92c78..c117ae426 100644
--- a/server/lib/files-cache/videos-preview-cache.ts
+++ b/server/lib/files-cache/videos-preview-cache.ts
@@ -20,7 +20,7 @@ class VideosPreviewCache extends AbstractVideoStaticFileCache <string> {
20 const video = await VideoModel.loadByUUIDWithFile(videoUUID) 20 const video = await VideoModel.loadByUUIDWithFile(videoUUID)
21 if (!video) return undefined 21 if (!video) return undefined
22 22
23 if (video.isOwned()) return join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreview().filename) 23 if (video.isOwned()) return { isOwned: true, path: join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreview().filename) }
24 24
25 return this.loadRemoteFile(videoUUID) 25 return this.loadRemoteFile(videoUUID)
26 } 26 }
@@ -35,7 +35,9 @@ class VideosPreviewCache extends AbstractVideoStaticFileCache <string> {
35 const remoteStaticPath = join(STATIC_PATHS.PREVIEWS, video.getPreview().filename) 35 const remoteStaticPath = join(STATIC_PATHS.PREVIEWS, video.getPreview().filename)
36 const destPath = join(FILES_CACHE.PREVIEWS.DIRECTORY, video.getPreview().filename) 36 const destPath = join(FILES_CACHE.PREVIEWS.DIRECTORY, video.getPreview().filename)
37 37
38 return this.saveRemoteVideoFileAndReturnPath(video, remoteStaticPath, destPath) 38 const path = await this.saveRemoteVideoFileAndReturnPath(video, remoteStaticPath, destPath)
39
40 return { isOwned: false, path }
39 } 41 }
40} 42}
41 43
diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts
index 3fa0dd65d..1650916a6 100644
--- a/server/lib/job-queue/handlers/video-import.ts
+++ b/server/lib/job-queue/handlers/video-import.ts
@@ -18,7 +18,7 @@ import { Notifier } from '../../notifier'
18import { CONFIG } from '../../../initializers/config' 18import { CONFIG } from '../../../initializers/config'
19import { sequelizeTypescript } from '../../../initializers/database' 19import { sequelizeTypescript } from '../../../initializers/database'
20import { ThumbnailModel } from '../../../models/video/thumbnail' 20import { ThumbnailModel } from '../../../models/video/thumbnail'
21import { createVideoThumbnailFromUrl, generateVideoThumbnail } from '../../thumbnail' 21import { createVideoMiniatureFromUrl, generateVideoMiniature } from '../../thumbnail'
22import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' 22import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
23 23
24type VideoImportYoutubeDLPayload = { 24type VideoImportYoutubeDLPayload = {
@@ -150,17 +150,17 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
150 // Process thumbnail 150 // Process thumbnail
151 let thumbnailModel: ThumbnailModel 151 let thumbnailModel: ThumbnailModel
152 if (options.downloadThumbnail && options.thumbnailUrl) { 152 if (options.downloadThumbnail && options.thumbnailUrl) {
153 thumbnailModel = await createVideoThumbnailFromUrl(options.thumbnailUrl, videoImport.Video, ThumbnailType.THUMBNAIL) 153 thumbnailModel = await createVideoMiniatureFromUrl(options.thumbnailUrl, videoImport.Video, ThumbnailType.MINIATURE)
154 } else if (options.generateThumbnail || options.downloadThumbnail) { 154 } else if (options.generateThumbnail || options.downloadThumbnail) {
155 thumbnailModel = await generateVideoThumbnail(videoImport.Video, videoFile, ThumbnailType.THUMBNAIL) 155 thumbnailModel = await generateVideoMiniature(videoImport.Video, videoFile, ThumbnailType.MINIATURE)
156 } 156 }
157 157
158 // Process preview 158 // Process preview
159 let previewModel: ThumbnailModel 159 let previewModel: ThumbnailModel
160 if (options.downloadPreview && options.thumbnailUrl) { 160 if (options.downloadPreview && options.thumbnailUrl) {
161 previewModel = await createVideoThumbnailFromUrl(options.thumbnailUrl, videoImport.Video, ThumbnailType.PREVIEW) 161 previewModel = await createVideoMiniatureFromUrl(options.thumbnailUrl, videoImport.Video, ThumbnailType.PREVIEW)
162 } else if (options.generatePreview || options.downloadPreview) { 162 } else if (options.generatePreview || options.downloadPreview) {
163 previewModel = await generateVideoThumbnail(videoImport.Video, videoFile, ThumbnailType.PREVIEW) 163 previewModel = await generateVideoMiniature(videoImport.Video, videoFile, ThumbnailType.PREVIEW)
164 } 164 }
165 165
166 // Create torrent 166 // Create torrent
@@ -180,14 +180,8 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
180 video.state = CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED 180 video.state = CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED
181 await video.save({ transaction: t }) 181 await video.save({ transaction: t })
182 182
183 if (thumbnailModel) { 183 if (thumbnailModel) await video.addAndSaveThumbnail(thumbnailModel, t)
184 thumbnailModel.videoId = video.id 184 if (previewModel) await video.addAndSaveThumbnail(previewModel, t)
185 video.addThumbnail(await thumbnailModel.save({ transaction: t }))
186 }
187 if (previewModel) {
188 previewModel.videoId = video.id
189 video.addThumbnail(await previewModel.save({ transaction: t }))
190 }
191 185
192 // Now we can federate the video (reload from database, we need more attributes) 186 // Now we can federate the video (reload from database, we need more attributes)
193 const videoForFederation = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t) 187 const videoForFederation = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t)
diff --git a/server/lib/oauth-model.ts b/server/lib/oauth-model.ts
index eb0e63bc8..45ac3e7c4 100644
--- a/server/lib/oauth-model.ts
+++ b/server/lib/oauth-model.ts
@@ -39,6 +39,8 @@ function clearCacheByToken (token: string) {
39function getAccessToken (bearerToken: string) { 39function getAccessToken (bearerToken: string) {
40 logger.debug('Getting access token (bearerToken: ' + bearerToken + ').') 40 logger.debug('Getting access token (bearerToken: ' + bearerToken + ').')
41 41
42 if (!bearerToken) return Bluebird.resolve(undefined)
43
42 if (accessTokenCache[bearerToken] !== undefined) return Bluebird.resolve(accessTokenCache[bearerToken]) 44 if (accessTokenCache[bearerToken] !== undefined) return Bluebird.resolve(accessTokenCache[bearerToken])
43 45
44 return OAuthTokenModel.getByTokenAndPopulateUser(bearerToken) 46 return OAuthTokenModel.getByTokenAndPopulateUser(bearerToken)
diff --git a/server/lib/thumbnail.ts b/server/lib/thumbnail.ts
index 344c28566..8ad82ee80 100644
--- a/server/lib/thumbnail.ts
+++ b/server/lib/thumbnail.ts
@@ -12,37 +12,37 @@ import { VideoPlaylistModel } from '../models/video/video-playlist'
12 12
13type ImageSize = { height: number, width: number } 13type ImageSize = { height: number, width: number }
14 14
15function createPlaylistThumbnailFromExisting (inputPath: string, playlist: VideoPlaylistModel, keepOriginal = false, size?: ImageSize) { 15function createPlaylistMiniatureFromExisting (inputPath: string, playlist: VideoPlaylistModel, keepOriginal = false, size?: ImageSize) {
16 const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size) 16 const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size)
17 const type = ThumbnailType.THUMBNAIL 17 const type = ThumbnailType.MINIATURE
18 18
19 const thumbnailCreator = () => processImage({ path: inputPath }, outputPath, { width, height }, keepOriginal) 19 const thumbnailCreator = () => processImage({ path: inputPath }, outputPath, { width, height }, keepOriginal)
20 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail }) 20 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail })
21} 21}
22 22
23function createPlaylistThumbnailFromUrl (url: string, playlist: VideoPlaylistModel, size?: ImageSize) { 23function createPlaylistMiniatureFromUrl (url: string, playlist: VideoPlaylistModel, size?: ImageSize) {
24 const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size) 24 const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromPlaylist(playlist, size)
25 const type = ThumbnailType.THUMBNAIL 25 const type = ThumbnailType.MINIATURE
26 26
27 const thumbnailCreator = () => downloadImage(url, basePath, filename, { width, height }) 27 const thumbnailCreator = () => downloadImage(url, basePath, filename, { width, height })
28 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, url }) 28 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, url })
29} 29}
30 30
31function createVideoThumbnailFromUrl (url: string, video: VideoModel, type: ThumbnailType, size?: ImageSize) { 31function createVideoMiniatureFromUrl (url: string, video: VideoModel, type: ThumbnailType, size?: ImageSize) {
32 const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) 32 const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
33 const thumbnailCreator = () => downloadImage(url, basePath, filename, { width, height }) 33 const thumbnailCreator = () => downloadImage(url, basePath, filename, { width, height })
34 34
35 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, url }) 35 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail, url })
36} 36}
37 37
38function createVideoThumbnailFromExisting (inputPath: string, video: VideoModel, type: ThumbnailType, size?: ImageSize) { 38function createVideoMiniatureFromExisting (inputPath: string, video: VideoModel, type: ThumbnailType, size?: ImageSize) {
39 const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) 39 const { filename, outputPath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size)
40 const thumbnailCreator = () => processImage({ path: inputPath }, outputPath, { width, height }) 40 const thumbnailCreator = () => processImage({ path: inputPath }, outputPath, { width, height })
41 41
42 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail }) 42 return createThumbnailFromFunction({ thumbnailCreator, filename, height, width, type, existingThumbnail })
43} 43}
44 44
45function generateVideoThumbnail (video: VideoModel, videoFile: VideoFileModel, type: ThumbnailType) { 45function generateVideoMiniature (video: VideoModel, videoFile: VideoFileModel, type: ThumbnailType) {
46 const input = video.getVideoFilePath(videoFile) 46 const input = video.getVideoFilePath(videoFile)
47 47
48 const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type) 48 const { filename, basePath, height, width, existingThumbnail } = buildMetadataFromVideo(video, type)
@@ -68,12 +68,12 @@ function createPlaceholderThumbnail (url: string, video: VideoModel, type: Thumb
68// --------------------------------------------------------------------------- 68// ---------------------------------------------------------------------------
69 69
70export { 70export {
71 generateVideoThumbnail, 71 generateVideoMiniature,
72 createVideoThumbnailFromUrl, 72 createVideoMiniatureFromUrl,
73 createVideoThumbnailFromExisting, 73 createVideoMiniatureFromExisting,
74 createPlaceholderThumbnail, 74 createPlaceholderThumbnail,
75 createPlaylistThumbnailFromUrl, 75 createPlaylistMiniatureFromUrl,
76 createPlaylistThumbnailFromExisting 76 createPlaylistMiniatureFromExisting
77} 77}
78 78
79function buildMetadataFromPlaylist (playlist: VideoPlaylistModel, size: ImageSize) { 79function buildMetadataFromPlaylist (playlist: VideoPlaylistModel, size: ImageSize) {
@@ -95,7 +95,7 @@ function buildMetadataFromVideo (video: VideoModel, type: ThumbnailType, size?:
95 ? video.Thumbnails.find(t => t.type === type) 95 ? video.Thumbnails.find(t => t.type === type)
96 : undefined 96 : undefined
97 97
98 if (type === ThumbnailType.THUMBNAIL) { 98 if (type === ThumbnailType.MINIATURE) {
99 const filename = video.generateThumbnailName() 99 const filename = video.generateThumbnailName()
100 const basePath = CONFIG.STORAGE.THUMBNAILS_DIR 100 const basePath = CONFIG.STORAGE.THUMBNAILS_DIR
101 101