From 418d092afa81e2c8fe8ac6838fc4b5eb0af6a782 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 26 Feb 2019 10:55:40 +0100 Subject: Playlist server API --- shared/utils/videos/video-playlists.ts | 198 +++++++++++++++++++---- shared/utils/videos/video-streaming-playlists.ts | 51 ++++++ shared/utils/videos/videos.ts | 25 ++- 3 files changed, 241 insertions(+), 33 deletions(-) create mode 100644 shared/utils/videos/video-streaming-playlists.ts (limited to 'shared/utils') diff --git a/shared/utils/videos/video-playlists.ts b/shared/utils/videos/video-playlists.ts index eb25011cb..5186d9c4f 100644 --- a/shared/utils/videos/video-playlists.ts +++ b/shared/utils/videos/video-playlists.ts @@ -1,51 +1,185 @@ -import { makeRawRequest } from '../requests/requests' -import { sha256 } from '../../../server/helpers/core-utils' -import { VideoStreamingPlaylist } from '../../models/videos/video-streaming-playlist.model' -import { expect } from 'chai' +import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests' +import { VideoPlaylistCreate } from '../../models/videos/playlist/video-playlist-create.model' +import { omit } from 'lodash' +import { VideoPlaylistUpdate } from '../../models/videos/playlist/video-playlist-update.model' +import { VideoPlaylistElementCreate } from '../../models/videos/playlist/video-playlist-element-create.model' +import { VideoPlaylistElementUpdate } from '../../models/videos/playlist/video-playlist-element-update.model' -function getPlaylist (url: string, statusCodeExpected = 200) { - return makeRawRequest(url, statusCodeExpected) +function getVideoPlaylistsList (url: string, start: number, count: number, sort?: string) { + const path = '/api/v1/video-playlists' + + const query = { + start, + count, + sort + } + + return makeGetRequest({ + url, + path, + query + }) } -function getSegment (url: string, statusCodeExpected = 200, range?: string) { - return makeRawRequest(url, statusCodeExpected, range) +function getVideoPlaylist (url: string, playlistId: number | string, statusCodeExpected = 200) { + const path = '/api/v1/video-playlists/' + playlistId + + return makeGetRequest({ + url, + path, + statusCodeExpected + }) } -function getSegmentSha256 (url: string, statusCodeExpected = 200) { - return makeRawRequest(url, statusCodeExpected) +function deleteVideoPlaylist (url: string, token: string, playlistId: number | string, statusCodeExpected = 200) { + const path = '/api/v1/video-playlists/' + playlistId + + return makeDeleteRequest({ + url, + path, + token, + statusCodeExpected + }) } -async function checkSegmentHash ( - baseUrlPlaylist: string, - baseUrlSegment: string, - videoUUID: string, - resolution: number, - hlsPlaylist: VideoStreamingPlaylist -) { - const res = await getPlaylist(`${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8`) - const playlist = res.text +function createVideoPlaylist (options: { + url: string, + token: string, + playlistAttrs: VideoPlaylistCreate, + expectedStatus: number +}) { + const path = '/api/v1/video-playlists/' + + const fields = omit(options.playlistAttrs, 'thumbnailfile') - const videoName = `${videoUUID}-${resolution}-fragmented.mp4` + const attaches = options.playlistAttrs.thumbnailfile + ? { thumbnailfile: options.playlistAttrs.thumbnailfile } + : {} - const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist) + return makeUploadRequest({ + method: 'POST', + url: options.url, + path, + token: options.token, + fields, + attaches, + statusCodeExpected: options.expectedStatus + }) +} - const length = parseInt(matches[1], 10) - const offset = parseInt(matches[2], 10) - const range = `${offset}-${offset + length - 1}` +function updateVideoPlaylist (options: { + url: string, + token: string, + playlistAttrs: VideoPlaylistUpdate, + expectedStatus: number +}) { + const path = '/api/v1/video-playlists/' - const res2 = await getSegment(`${baseUrlSegment}/${videoUUID}/${videoName}`, 206, `bytes=${range}`) + const fields = omit(options.playlistAttrs, 'thumbnailfile') - const resSha = await getSegmentSha256(hlsPlaylist.segmentsSha256Url) + const attaches = options.playlistAttrs.thumbnailfile + ? { thumbnailfile: options.playlistAttrs.thumbnailfile } + : {} - const sha256Server = resSha.body[ videoName ][range] - expect(sha256(res2.body)).to.equal(sha256Server) + return makeUploadRequest({ + method: 'PUT', + url: options.url, + path, + token: options.token, + fields, + attaches, + statusCodeExpected: options.expectedStatus + }) +} + +function addVideoInPlaylist (options: { + url: string, + token: string, + playlistId: number | string, + elementAttrs: VideoPlaylistElementCreate + expectedStatus: number +}) { + const path = '/api/v1/video-playlists/' + options.playlistId + '/videos' + + return makePostBodyRequest({ + url: options.url, + path, + token: options.token, + fields: options.elementAttrs, + statusCodeExpected: options.expectedStatus + }) +} + +function updateVideoPlaylistElement (options: { + url: string, + token: string, + playlistId: number | string, + videoId: number | string, + elementAttrs: VideoPlaylistElementUpdate, + expectedStatus: number +}) { + const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.videoId + + return makePutBodyRequest({ + url: options.url, + path, + token: options.token, + fields: options.elementAttrs, + statusCodeExpected: options.expectedStatus + }) +} + +function removeVideoFromPlaylist (options: { + url: string, + token: string, + playlistId: number | string, + videoId: number | string, + expectedStatus: number +}) { + const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.videoId + + return makeDeleteRequest({ + url: options.url, + path, + token: options.token, + statusCodeExpected: options.expectedStatus + }) +} + +function reorderVideosPlaylist (options: { + url: string, + token: string, + playlistId: number | string, + elementAttrs: { + startPosition: number, + insertAfter: number, + reorderLength?: number + }, + expectedStatus: number +}) { + const path = '/api/v1/video-playlists/' + options.playlistId + '/videos' + + return makePutBodyRequest({ + url: options.url, + path, + token: options.token, + fields: options.elementAttrs, + statusCodeExpected: options.expectedStatus + }) } // --------------------------------------------------------------------------- export { - getPlaylist, - getSegment, - getSegmentSha256, - checkSegmentHash + getVideoPlaylistsList, + getVideoPlaylist, + + createVideoPlaylist, + updateVideoPlaylist, + deleteVideoPlaylist, + + addVideoInPlaylist, + removeVideoFromPlaylist, + + reorderVideosPlaylist } diff --git a/shared/utils/videos/video-streaming-playlists.ts b/shared/utils/videos/video-streaming-playlists.ts new file mode 100644 index 000000000..eb25011cb --- /dev/null +++ b/shared/utils/videos/video-streaming-playlists.ts @@ -0,0 +1,51 @@ +import { makeRawRequest } from '../requests/requests' +import { sha256 } from '../../../server/helpers/core-utils' +import { VideoStreamingPlaylist } from '../../models/videos/video-streaming-playlist.model' +import { expect } from 'chai' + +function getPlaylist (url: string, statusCodeExpected = 200) { + return makeRawRequest(url, statusCodeExpected) +} + +function getSegment (url: string, statusCodeExpected = 200, range?: string) { + return makeRawRequest(url, statusCodeExpected, range) +} + +function getSegmentSha256 (url: string, statusCodeExpected = 200) { + return makeRawRequest(url, statusCodeExpected) +} + +async function checkSegmentHash ( + baseUrlPlaylist: string, + baseUrlSegment: string, + videoUUID: string, + resolution: number, + hlsPlaylist: VideoStreamingPlaylist +) { + const res = await getPlaylist(`${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8`) + const playlist = res.text + + const videoName = `${videoUUID}-${resolution}-fragmented.mp4` + + const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist) + + const length = parseInt(matches[1], 10) + const offset = parseInt(matches[2], 10) + const range = `${offset}-${offset + length - 1}` + + const res2 = await getSegment(`${baseUrlSegment}/${videoUUID}/${videoName}`, 206, `bytes=${range}`) + + const resSha = await getSegmentSha256(hlsPlaylist.segmentsSha256Url) + + const sha256Server = resSha.body[ videoName ][range] + expect(sha256(res2.body)).to.equal(sha256Server) +} + +// --------------------------------------------------------------------------- + +export { + getPlaylist, + getSegment, + getSegmentSha256, + checkSegmentHash +} diff --git a/shared/utils/videos/videos.ts b/shared/utils/videos/videos.ts index b3d24bc53..2c09f0086 100644 --- a/shared/utils/videos/videos.ts +++ b/shared/utils/videos/videos.ts @@ -223,6 +223,28 @@ function getVideoChannelVideos ( }) } +function getPlaylistVideos ( + url: string, + accessToken: string, + playlistId: number | string, + start: number, + count: number, + query: { nsfw?: boolean } = {} +) { + const path = '/api/v1/video-playlists/' + playlistId + '/videos' + + return makeGetRequest({ + url, + path, + query: immutableAssign(query, { + start, + count + }), + token: accessToken, + statusCodeExpected: 200 + }) +} + function getVideosListPagination (url: string, start: number, count: number, sort?: string) { const path = '/api/v1/videos' @@ -601,5 +623,6 @@ export { parseTorrentVideo, getLocalVideos, completeVideoCheck, - checkVideoFilesWereRemoved + checkVideoFilesWereRemoved, + getPlaylistVideos } -- cgit v1.2.3