1
0
Fork 0

Add ability to a video multiple times in a playlist

This commit is contained in:
Chocobozzz 2020-08-17 16:39:32 +02:00 committed by Chocobozzz
parent b75410b87d
commit 371906639e
7 changed files with 53 additions and 40 deletions

View file

@ -159,7 +159,7 @@ activityPubClientRouter.get('/video-playlists/:playlistId',
asyncMiddleware(videoPlaylistsGetValidator('all')), asyncMiddleware(videoPlaylistsGetValidator('all')),
asyncMiddleware(videoPlaylistController) asyncMiddleware(videoPlaylistController)
) )
activityPubClientRouter.get('/video-playlists/:playlistId/:videoId', activityPubClientRouter.get('/video-playlists/:playlistId/videos/:playlistElementId',
executeIfActivityPub, executeIfActivityPub,
asyncMiddleware(videoPlaylistElementAPGetValidator), asyncMiddleware(videoPlaylistElementAPGetValidator),
videoPlaylistElementController videoPlaylistElementController

View file

@ -297,7 +297,6 @@ async function addVideoInPlaylist (req: express.Request, res: express.Response)
const position = await VideoPlaylistElementModel.getNextPositionOf(videoPlaylist.id, t) const position = await VideoPlaylistElementModel.getNextPositionOf(videoPlaylist.id, t)
const playlistElement = await VideoPlaylistElementModel.create({ const playlistElement = await VideoPlaylistElementModel.create({
url: getVideoPlaylistElementActivityPubUrl(videoPlaylist, video),
position, position,
startTimestamp: body.startTimestamp || null, startTimestamp: body.startTimestamp || null,
stopTimestamp: body.stopTimestamp || null, stopTimestamp: body.stopTimestamp || null,
@ -305,6 +304,9 @@ async function addVideoInPlaylist (req: express.Request, res: express.Response)
videoId: video.id videoId: video.id
}, { transaction: t }) }, { transaction: t })
playlistElement.url = getVideoPlaylistElementActivityPubUrl(videoPlaylist, playlistElement)
await playlistElement.save({ transaction: t })
videoPlaylist.changed('updatedAt', true) videoPlaylist.changed('updatedAt', true)
await videoPlaylist.save({ transaction: t }) await videoPlaylist.save({ transaction: t })

View file

@ -8,7 +8,8 @@ import {
MVideoId, MVideoId,
MVideoUrl, MVideoUrl,
MVideoUUID, MVideoUUID,
MAbuseId MAbuseId,
MVideoPlaylistElement
} from '../../types/models' } from '../../types/models'
import { MVideoPlaylist, MVideoPlaylistUUID } from '../../types/models/video/video-playlist' import { MVideoPlaylist, MVideoPlaylistUUID } from '../../types/models/video/video-playlist'
import { MVideoFileVideoUUID } from '../../types/models/video/video-file' import { MVideoFileVideoUUID } from '../../types/models/video/video-file'
@ -22,8 +23,8 @@ function getVideoPlaylistActivityPubUrl (videoPlaylist: MVideoPlaylist) {
return WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid return WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid
} }
function getVideoPlaylistElementActivityPubUrl (videoPlaylist: MVideoPlaylistUUID, video: MVideoUUID) { function getVideoPlaylistElementActivityPubUrl (videoPlaylist: MVideoPlaylistUUID, videoPlaylistElement: MVideoPlaylistElement) {
return WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid + '/' + video.uuid return WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid + '/videos/' + videoPlaylistElement.id
} }
function getVideoCacheFileActivityPubUrl (videoFile: MVideoFileVideoUUID) { function getVideoCacheFileActivityPubUrl (videoFile: MVideoFileVideoUUID) {

View file

@ -199,16 +199,6 @@ const videoPlaylistsAddVideoValidator = [
if (!await doesVideoExist(req.body.videoId, res, 'only-video')) return if (!await doesVideoExist(req.body.videoId, res, 'only-video')) return
const videoPlaylist = getPlaylist(res) const videoPlaylist = getPlaylist(res)
const video = res.locals.onlyVideo
const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndVideo(videoPlaylist.id, video.id)
if (videoPlaylistElement) {
res.status(409)
.json({ error: 'This video in this playlist already exists' })
.end()
return
}
if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, videoPlaylist, UserRight.UPDATE_ANY_VIDEO_PLAYLIST, res)) { if (!checkUserCanManageVideoPlaylist(res.locals.oauth.token.User, videoPlaylist, UserRight.UPDATE_ANY_VIDEO_PLAYLIST, res)) {
return return
@ -258,15 +248,18 @@ const videoPlaylistsUpdateOrRemoveVideoValidator = [
const videoPlaylistElementAPGetValidator = [ const videoPlaylistElementAPGetValidator = [
param('playlistId') param('playlistId')
.custom(isIdOrUUIDValid).withMessage('Should have a valid playlist id/uuid'), .custom(isIdOrUUIDValid).withMessage('Should have a valid playlist id/uuid'),
param('videoId') param('playlistElementId')
.custom(isIdOrUUIDValid).withMessage('Should have an video id/uuid'), .custom(isIdValid).withMessage('Should have an playlist element id'),
async (req: express.Request, res: express.Response, next: express.NextFunction) => { async (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking videoPlaylistElementAPGetValidator parameters', { parameters: req.params }) logger.debug('Checking videoPlaylistElementAPGetValidator parameters', { parameters: req.params })
if (areValidationErrors(req, res)) return if (areValidationErrors(req, res)) return
const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndVideoForAP(req.params.playlistId, req.params.videoId) const playlistElementId = parseInt(req.params.playlistElementId + '', 10)
const playlistId = req.params.playlistId
const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndElementIdForAP(playlistId, playlistElementId)
if (!videoPlaylistElement) { if (!videoPlaylistElement) {
res.status(404) res.status(404)
.json({ error: 'Video playlist element not found' }) .json({ error: 'Video playlist element not found' })

View file

@ -43,10 +43,6 @@ import { MUserAccountId } from '@server/types/models'
{ {
fields: [ 'videoId' ] fields: [ 'videoId' ]
}, },
{
fields: [ 'videoPlaylistId', 'videoId' ],
unique: true
},
{ {
fields: [ 'url' ], fields: [ 'url' ],
unique: true unique: true
@ -60,8 +56,8 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
@UpdatedAt @UpdatedAt
updatedAt: Date updatedAt: Date
@AllowNull(false) @AllowNull(true)
@Is('VideoPlaylistUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) @Is('VideoPlaylistUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url', true))
@Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_PLAYLISTS.URL.max)) @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_PLAYLISTS.URL.max))
url: string url: string
@ -185,12 +181,11 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
return VideoPlaylistElementModel.findByPk(playlistElementId) return VideoPlaylistElementModel.findByPk(playlistElementId)
} }
static loadByPlaylistAndVideoForAP ( static loadByPlaylistAndElementIdForAP (
playlistId: number | string, playlistId: number | string,
videoId: number | string playlistElementId: number
): Bluebird<MVideoPlaylistElementVideoUrlPlaylistPrivacy> { ): Bluebird<MVideoPlaylistElementVideoUrlPlaylistPrivacy> {
const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId } const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId }
const videoWhere = validator.isUUID('' + videoId) ? { uuid: videoId } : { id: videoId }
const query = { const query = {
include: [ include: [
@ -201,10 +196,12 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
}, },
{ {
attributes: [ 'url' ], attributes: [ 'url' ],
model: VideoModel.unscoped(), model: VideoModel.unscoped()
where: videoWhere
} }
] ],
where: {
id: playlistElementId
}
} }
return VideoPlaylistElementModel.findOne(query) return VideoPlaylistElementModel.findOne(query)

View file

@ -346,11 +346,6 @@ describe('Test video playlists API validator', function () {
const res = await addVideoInPlaylist(params) const res = await addVideoInPlaylist(params)
playlistElementId = res.body.videoPlaylistElement.id playlistElementId = res.body.videoPlaylistElement.id
}) })
it('Should fail if the video was already added in the playlist', async function () {
const params = getBase({}, { expectedStatus: 409 })
await addVideoInPlaylist(params)
})
}) })
describe('When updating an element in a playlist', function () { describe('When updating an element in a playlist', function () {

View file

@ -552,6 +552,9 @@ describe('Test video playlists', function () {
{ {
const res = await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 5 }) const res = await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 5 })
playlistElementNSFW = res.body.videoPlaylistElement.id playlistElementNSFW = res.body.videoPlaylistElement.id
await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 4 })
await addVideo({ videoId: nsfwVideoServer1 })
} }
await waitJobs(servers) await waitJobs(servers)
@ -563,10 +566,10 @@ describe('Test video playlists', function () {
for (const server of servers) { for (const server of servers) {
const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10) const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
expect(res.body.total).to.equal(6) expect(res.body.total).to.equal(8)
const videoElements: VideoPlaylistElement[] = res.body.data const videoElements: VideoPlaylistElement[] = res.body.data
expect(videoElements).to.have.lengthOf(6) expect(videoElements).to.have.lengthOf(8)
expect(videoElements[0].video.name).to.equal('video 0 server 1') expect(videoElements[0].video.name).to.equal('video 0 server 1')
expect(videoElements[0].position).to.equal(1) expect(videoElements[0].position).to.equal(1)
@ -598,6 +601,16 @@ describe('Test video playlists', function () {
expect(videoElements[5].startTimestamp).to.equal(5) expect(videoElements[5].startTimestamp).to.equal(5)
expect(videoElements[5].stopTimestamp).to.be.null expect(videoElements[5].stopTimestamp).to.be.null
expect(videoElements[6].video.name).to.equal('NSFW video')
expect(videoElements[6].position).to.equal(7)
expect(videoElements[6].startTimestamp).to.equal(4)
expect(videoElements[6].stopTimestamp).to.be.null
expect(videoElements[7].video.name).to.equal('NSFW video')
expect(videoElements[7].position).to.equal(8)
expect(videoElements[7].startTimestamp).to.be.null
expect(videoElements[7].stopTimestamp).to.be.null
const res3 = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 2) const res3 = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 2)
expect(res3.body.data).to.have.lengthOf(2) expect(res3.body.data).to.have.lengthOf(2)
} }
@ -807,6 +820,8 @@ describe('Test video playlists', function () {
'video 1 server 3', 'video 1 server 3',
'video 3 server 1', 'video 3 server 1',
'video 4 server 1', 'video 4 server 1',
'NSFW video',
'NSFW video',
'NSFW video' 'NSFW video'
]) ])
} }
@ -836,6 +851,8 @@ describe('Test video playlists', function () {
'video 2 server 3', 'video 2 server 3',
'video 1 server 3', 'video 1 server 3',
'video 4 server 1', 'video 4 server 1',
'NSFW video',
'NSFW video',
'NSFW video' 'NSFW video'
]) ])
} }
@ -865,7 +882,9 @@ describe('Test video playlists', function () {
'video 2 server 3', 'video 2 server 3',
'NSFW video', 'NSFW video',
'video 1 server 3', 'video 1 server 3',
'video 4 server 1' 'video 4 server 1',
'NSFW video',
'NSFW video'
]) ])
for (let i = 1; i <= elements.length; i++) { for (let i = 1; i <= elements.length; i++) {
@ -1023,10 +1042,10 @@ describe('Test video playlists', function () {
for (const server of servers) { for (const server of servers) {
const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10) const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
expect(res.body.total).to.equal(4) expect(res.body.total).to.equal(6)
const elements: VideoPlaylistElement[] = res.body.data const elements: VideoPlaylistElement[] = res.body.data
expect(elements).to.have.lengthOf(4) expect(elements).to.have.lengthOf(6)
expect(elements[0].video.name).to.equal('video 0 server 1') expect(elements[0].video.name).to.equal('video 0 server 1')
expect(elements[0].position).to.equal(1) expect(elements[0].position).to.equal(1)
@ -1039,6 +1058,12 @@ describe('Test video playlists', function () {
expect(elements[3].video.name).to.equal('video 4 server 1') expect(elements[3].video.name).to.equal('video 4 server 1')
expect(elements[3].position).to.equal(4) expect(elements[3].position).to.equal(4)
expect(elements[4].video.name).to.equal('NSFW video')
expect(elements[4].position).to.equal(5)
expect(elements[5].video.name).to.equal('NSFW video')
expect(elements[5].position).to.equal(6)
} }
}) })