asyncMiddleware,
asyncRetryTransactionMiddleware,
authenticate,
- commonVideosFiltersValidator, optionalAuthenticate,
+ commonVideosFiltersValidator,
+ optionalAuthenticate,
paginationValidator,
setDefaultPagination,
setDefaultSort
} from '../../middlewares'
-import { VideoChannelModel } from '../../models/video/video-channel'
import { videoPlaylistsSortValidator } from '../../middlewares/validators'
import { buildNSFWFilter, createReqFiles, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
-import { CONFIG, MIMETYPES, sequelizeTypescript, THUMBNAILS_SIZE } from '../../initializers'
+import { CONFIG, MIMETYPES, sequelizeTypescript, THUMBNAILS_SIZE, VIDEO_PLAYLIST_PRIVACIES } from '../../initializers'
import { logger } from '../../helpers/logger'
import { resetSequelizeInstance } from '../../helpers/database-utils'
import { VideoPlaylistModel } from '../../models/video/video-playlist'
import {
+ commonVideoPlaylistFiltersValidator,
videoPlaylistsAddValidator,
videoPlaylistsAddVideoValidator,
videoPlaylistsDeleteValidator,
import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
import { processImage } from '../../helpers/image-utils'
import { join } from 'path'
-import { UserModel } from '../../models/account/user'
-import {
- sendCreateVideoPlaylist,
- sendDeleteVideoPlaylist,
- sendUpdateVideoPlaylist
-} from '../../lib/activitypub/send'
-import {
- getVideoPlaylistActivityPubUrl,
- getVideoPlaylistElementActivityPubUrl
-} from '../../lib/activitypub/url'
+import { sendCreateVideoPlaylist, sendDeleteVideoPlaylist, sendUpdateVideoPlaylist } from '../../lib/activitypub/send'
+import { getVideoPlaylistActivityPubUrl, getVideoPlaylistElementActivityPubUrl } from '../../lib/activitypub/url'
import { VideoPlaylistUpdate } from '../../../shared/models/videos/playlist/video-playlist-update.model'
import { VideoModel } from '../../models/video/video'
import { VideoPlaylistElementModel } from '../../models/video/video-playlist-element'
import { VideoPlaylistElementCreate } from '../../../shared/models/videos/playlist/video-playlist-element-create.model'
import { VideoPlaylistElementUpdate } from '../../../shared/models/videos/playlist/video-playlist-element-update.model'
import { copy, pathExists } from 'fs-extra'
+import { AccountModel } from '../../models/account/account'
+import { VideoPlaylistReorder } from '../../../shared/models/videos/playlist/video-playlist-reorder.model'
+import { JobQueue } from '../../lib/job-queue'
const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { thumbnailfile: CONFIG.STORAGE.TMP_DIR })
const videoPlaylistRouter = express.Router()
+videoPlaylistRouter.get('/privacies', listVideoPlaylistPrivacies)
+
videoPlaylistRouter.get('/',
paginationValidator,
videoPlaylistsSortValidator,
setDefaultSort,
setDefaultPagination,
+ commonVideoPlaylistFiltersValidator,
asyncMiddleware(listVideoPlaylists)
)
// ---------------------------------------------------------------------------
+function listVideoPlaylistPrivacies (req: express.Request, res: express.Response) {
+ res.json(VIDEO_PLAYLIST_PRIVACIES)
+}
+
async function listVideoPlaylists (req: express.Request, res: express.Response) {
const serverActor = await getServerActor()
const resultList = await VideoPlaylistModel.listForApi({
followerActorId: serverActor.id,
start: req.query.start,
count: req.query.count,
- sort: req.query.sort
+ sort: req.query.sort,
+ type: req.query.type
})
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
function getVideoPlaylist (req: express.Request, res: express.Response) {
- const videoPlaylist = res.locals.videoPlaylist as VideoPlaylistModel
+ const videoPlaylist = res.locals.videoPlaylist
+
+ if (videoPlaylist.isOutdated()) {
+ JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video-playlist', url: videoPlaylist.url } })
+ .catch(err => logger.error('Cannot create AP refresher job for playlist %s.', videoPlaylist.url, { err }))
+ }
return res.json(videoPlaylist.toFormattedJSON())
}
async function addVideoPlaylist (req: express.Request, res: express.Response) {
const videoPlaylistInfo: VideoPlaylistCreate = req.body
- const user: UserModel = res.locals.oauth.token.User
+ const user = res.locals.oauth.token.User
const videoPlaylist = new VideoPlaylistModel({
name: videoPlaylistInfo.displayName,
videoPlaylist.url = getVideoPlaylistActivityPubUrl(videoPlaylist) // We use the UUID, so set the URL after building the object
- if (videoPlaylistInfo.videoChannelId !== undefined) {
- const videoChannel = res.locals.videoChannel as VideoChannelModel
+ if (videoPlaylistInfo.videoChannelId) {
+ const videoChannel = res.locals.videoChannel
videoPlaylist.videoChannelId = videoChannel.id
videoPlaylist.VideoChannel = videoChannel
const videoPlaylistCreated: VideoPlaylistModel = await sequelizeTypescript.transaction(async t => {
const videoPlaylistCreated = await videoPlaylist.save({ transaction: t })
- videoPlaylistCreated.OwnerAccount = user.Account
+ // We need more attributes for the federation
+ videoPlaylistCreated.OwnerAccount = await AccountModel.load(user.Account.id, t)
await sendCreateVideoPlaylist(videoPlaylistCreated, t)
return videoPlaylistCreated
}
async function updateVideoPlaylist (req: express.Request, res: express.Response) {
- const videoPlaylistInstance = res.locals.videoPlaylist as VideoPlaylistModel
+ const videoPlaylistInstance = res.locals.videoPlaylist
const videoPlaylistFieldsSave = videoPlaylistInstance.toJSON()
const videoPlaylistInfoToUpdate = req.body as VideoPlaylistUpdate
const wasPrivatePlaylist = videoPlaylistInstance.privacy === VideoPlaylistPrivacy.PRIVATE
if (videoPlaylistInfoToUpdate.videoChannelId === null) {
videoPlaylistInstance.videoChannelId = null
} else {
- const videoChannel = res.locals.videoChannel as VideoChannelModel
+ const videoChannel = res.locals.videoChannel
videoPlaylistInstance.videoChannelId = videoChannel.id
+ videoPlaylistInstance.VideoChannel = videoChannel
}
}
}
async function removeVideoPlaylist (req: express.Request, res: express.Response) {
- const videoPlaylistInstance: VideoPlaylistModel = res.locals.videoPlaylist
+ const videoPlaylistInstance = res.locals.videoPlaylist
await sequelizeTypescript.transaction(async t => {
await videoPlaylistInstance.destroy({ transaction: t })
async function addVideoInPlaylist (req: express.Request, res: express.Response) {
const body: VideoPlaylistElementCreate = req.body
- const videoPlaylist: VideoPlaylistModel = res.locals.videoPlaylist
- const video: VideoModel = res.locals.video
+ const videoPlaylist = res.locals.videoPlaylist
+ const video = res.locals.video
const playlistElement: VideoPlaylistElementModel = await sequelizeTypescript.transaction(async t => {
const position = await VideoPlaylistElementModel.getNextPositionOf(videoPlaylist.id, t)
videoId: video.id
}, { transaction: t })
- // If the user did not set a thumbnail, automatically take the video thumbnail
- if (playlistElement.position === 1) {
- const playlistThumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, videoPlaylist.getThumbnailName())
-
- if (await pathExists(playlistThumbnailPath) === false) {
- const videoThumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName())
- await copy(videoThumbnailPath, playlistThumbnailPath)
- }
- }
+ videoPlaylist.changed('updatedAt', true)
+ await videoPlaylist.save({ transaction: t })
await sendUpdateVideoPlaylist(videoPlaylist, t)
return playlistElement
})
+ // If the user did not set a thumbnail, automatically take the video thumbnail
+ if (playlistElement.position === 1) {
+ const playlistThumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, videoPlaylist.getThumbnailName())
+
+ if (await pathExists(playlistThumbnailPath) === false) {
+ logger.info('Generating default thumbnail to playlist %s.', videoPlaylist.url)
+
+ const videoThumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName())
+ await copy(videoThumbnailPath, playlistThumbnailPath)
+ }
+ }
+
logger.info('Video added in playlist %s at position %d.', videoPlaylist.uuid, playlistElement.position)
return res.json({
async function updateVideoPlaylistElement (req: express.Request, res: express.Response) {
const body: VideoPlaylistElementUpdate = req.body
- const videoPlaylist: VideoPlaylistModel = res.locals.videoPlaylist
- const videoPlaylistElement: VideoPlaylistElementModel = res.locals.videoPlaylistElement
+ const videoPlaylist = res.locals.videoPlaylist
+ const videoPlaylistElement = res.locals.videoPlaylistElement
const playlistElement: VideoPlaylistElementModel = await sequelizeTypescript.transaction(async t => {
if (body.startTimestamp !== undefined) videoPlaylistElement.startTimestamp = body.startTimestamp
const element = await videoPlaylistElement.save({ transaction: t })
+ videoPlaylist.changed('updatedAt', true)
+ await videoPlaylist.save({ transaction: t })
+
await sendUpdateVideoPlaylist(videoPlaylist, t)
return element
}
async function removeVideoFromPlaylist (req: express.Request, res: express.Response) {
- const videoPlaylistElement: VideoPlaylistElementModel = res.locals.videoPlaylistElement
- const videoPlaylist: VideoPlaylistModel = res.locals.videoPlaylist
+ const videoPlaylistElement = res.locals.videoPlaylistElement
+ const videoPlaylist = res.locals.videoPlaylist
const positionToDelete = videoPlaylistElement.position
await sequelizeTypescript.transaction(async t => {
// Decrease position of the next elements
await VideoPlaylistElementModel.increasePositionOf(videoPlaylist.id, positionToDelete, null, -1, t)
+ videoPlaylist.changed('updatedAt', true)
+ await videoPlaylist.save({ transaction: t })
+
await sendUpdateVideoPlaylist(videoPlaylist, t)
logger.info('Video playlist element %d of playlist %s deleted.', videoPlaylistElement.position, videoPlaylist.uuid)
}
async function reorderVideosPlaylist (req: express.Request, res: express.Response) {
- const videoPlaylist: VideoPlaylistModel = res.locals.videoPlaylist
+ const videoPlaylist = res.locals.videoPlaylist
+ const body: VideoPlaylistReorder = req.body
- const start: number = req.body.startPosition
- const insertAfter: number = req.body.insertAfterPosition
- const reorderLength: number = req.body.reorderLength || 1
+ const start: number = body.startPosition
+ const insertAfter: number = body.insertAfterPosition
+ const reorderLength: number = body.reorderLength || 1
if (start === insertAfter) {
return res.status(204).end()
// Decrease positions of elements after the old position of our ordered elements (decrease)
await VideoPlaylistElementModel.increasePositionOf(videoPlaylist.id, oldPosition, null, -reorderLength, t)
+ videoPlaylist.changed('updatedAt', true)
+ await videoPlaylist.save({ transaction: t })
+
await sendUpdateVideoPlaylist(videoPlaylist, t)
})
}
async function getVideoPlaylistVideos (req: express.Request, res: express.Response) {
- const videoPlaylistInstance: VideoPlaylistModel = res.locals.videoPlaylist
+ const videoPlaylistInstance = res.locals.videoPlaylist
const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined
const resultList = await VideoModel.listForApi({
user: res.locals.oauth ? res.locals.oauth.token.User : undefined
})
- return res.json(getFormattedObjects(resultList.data, resultList.total))
+ const additionalAttributes = { playlistInfo: true }
+ return res.json(getFormattedObjects(resultList.data, resultList.total, { additionalAttributes }))
}