1
0
Fork 0

Fix updating hls infohash on privacy update

This commit is contained in:
Chocobozzz 2024-07-31 09:26:54 +02:00
parent 44919a8d57
commit 22e9d9a1fe
No known key found for this signature in database
GPG key ID: 583A612D890159BE
4 changed files with 49 additions and 39 deletions

View file

@ -1,7 +1,5 @@
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import { expect } from 'chai'
import { basename } from 'path'
import { getAllFiles, getHLS } from '@peertube/peertube-core-utils' import { getAllFiles, getHLS } from '@peertube/peertube-core-utils'
import { HttpStatusCode, LiveVideo, VideoDetails, VideoPrivacy } from '@peertube/peertube-models' import { HttpStatusCode, LiveVideo, VideoDetails, VideoPrivacy } from '@peertube/peertube-models'
import { areScalewayObjectStorageTestsDisabled } from '@peertube/peertube-node-utils' import { areScalewayObjectStorageTestsDisabled } from '@peertube/peertube-node-utils'
@ -20,7 +18,9 @@ import {
} from '@peertube/peertube-server-commands' } from '@peertube/peertube-server-commands'
import { expectStartWith } from '@tests/shared/checks.js' import { expectStartWith } from '@tests/shared/checks.js'
import { SQLCommand } from '@tests/shared/sql-command.js' import { SQLCommand } from '@tests/shared/sql-command.js'
import { checkVideoFileTokenReinjection } from '@tests/shared/streaming-playlists.js' import { checkPlaylistInfohash, checkVideoFileTokenReinjection } from '@tests/shared/streaming-playlists.js'
import { expect } from 'chai'
import { basename } from 'path'
function extractFilenameFromUrl (url: string) { function extractFilenameFromUrl (url: string) {
const parts = basename(url).split(':') const parts = basename(url).split(':')
@ -74,6 +74,8 @@ describe('Object storage for video static file privacy', function () {
await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
} }
await checkPlaylistInfohash({ video, files: hls.files, sqlCommand })
} }
} }

View file

@ -1,11 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import bytes from 'bytes'
import { expect } from 'chai'
import { stat } from 'fs/promises'
import merge from 'lodash-es/merge.js'
import { HttpStatusCode, VideoDetails } from '@peertube/peertube-models' import { HttpStatusCode, VideoDetails } from '@peertube/peertube-models'
import { areMockObjectStorageTestsDisabled, sha1 } from '@peertube/peertube-node-utils' import { areMockObjectStorageTestsDisabled } from '@peertube/peertube-node-utils'
import { import {
cleanupTests, cleanupTests,
createMultipleServers, createMultipleServers,
@ -18,12 +14,17 @@ import {
setAccessTokensToServers, setAccessTokensToServers,
waitJobs waitJobs
} from '@peertube/peertube-server-commands' } from '@peertube/peertube-server-commands'
import { expectStartWith, expectLogDoesNotContain } from '@tests/shared/checks.js' import { expectLogDoesNotContain, expectStartWith } from '@tests/shared/checks.js'
import { checkTmpIsEmpty } from '@tests/shared/directories.js' import { checkTmpIsEmpty } from '@tests/shared/directories.js'
import { generateHighBitrateVideo } from '@tests/shared/generate.js' import { generateHighBitrateVideo } from '@tests/shared/generate.js'
import { MockObjectStorageProxy } from '@tests/shared/mock-servers/mock-object-storage.js' import { MockObjectStorageProxy } from '@tests/shared/mock-servers/mock-object-storage.js'
import { SQLCommand } from '@tests/shared/sql-command.js' import { SQLCommand } from '@tests/shared/sql-command.js'
import { checkPlaylistInfohash } from '@tests/shared/streaming-playlists.js'
import { checkWebTorrentWorks } from '@tests/shared/webtorrent.js' import { checkWebTorrentWorks } from '@tests/shared/webtorrent.js'
import bytes from 'bytes'
import { expect } from 'chai'
import { stat } from 'fs/promises'
import merge from 'lodash-es/merge.js'
async function checkFiles (options: { async function checkFiles (options: {
server: PeerTubeServer server: PeerTubeServer
@ -91,7 +92,6 @@ async function checkFiles (options: {
const resSha = await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) const resSha = await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
expect(JSON.stringify(resSha.body)).to.not.throw expect(JSON.stringify(resSha.body)).to.not.throw
let i = 0
for (const file of hls.files) { for (const file of hls.files) {
expectStartWith(file.fileUrl, start) expectStartWith(file.fileUrl, start)
@ -100,15 +100,10 @@ async function checkFiles (options: {
expectStartWith(location, start) expectStartWith(location, start)
await makeRawRequest({ url: location, expectedStatus: HttpStatusCode.OK_200 }) await makeRawRequest({ url: location, expectedStatus: HttpStatusCode.OK_200 })
}
if (originServer.internalServerNumber === server.internalServerNumber) { if (originServer.internalServerNumber === server.internalServerNumber) {
const infohash = sha1(`${2 + hls.playlistUrl}+V${i}`) await checkPlaylistInfohash({ video, files: hls.files, sqlCommand: originSQLCommand })
const dbInfohashes = await originSQLCommand.getPlaylistInfohash(hls.id)
expect(dbInfohashes).to.include(infohash)
}
i++
} }
} }

View file

@ -1,22 +1,24 @@
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import { expect } from 'chai' import { getHLS, removeFragmentedMP4Ext, uuidRegex } from '@peertube/peertube-core-utils'
import { basename, dirname, join } from 'path'
import { removeFragmentedMP4Ext, uuidRegex } from '@peertube/peertube-core-utils'
import { import {
HttpStatusCode, HttpStatusCode,
VideoDetails,
VideoPrivacy, VideoPrivacy,
VideoResolution, VideoResolution,
VideoStreamingPlaylist, VideoStreamingPlaylist,
VideoStreamingPlaylistType VideoStreamingPlaylistType
} from '@peertube/peertube-models' } from '@peertube/peertube-models'
import { sha256 } from '@peertube/peertube-node-utils' import { sha1, sha256 } from '@peertube/peertube-node-utils'
import { makeRawRequest, PeerTubeServer } from '@peertube/peertube-server-commands' import { makeRawRequest, PeerTubeServer } from '@peertube/peertube-server-commands'
import { expect } from 'chai'
import { basename, dirname, join } from 'path'
import { expectStartWith } from './checks.js' import { expectStartWith } from './checks.js'
import { SQLCommand } from './sql-command.js'
import { hlsInfohashExist } from './tracker.js' import { hlsInfohashExist } from './tracker.js'
import { checkWebTorrentWorks } from './webtorrent.js' import { checkWebTorrentWorks } from './webtorrent.js'
async function checkSegmentHash (options: { export async function checkSegmentHash (options: {
server: PeerTubeServer server: PeerTubeServer
baseUrlPlaylist: string baseUrlPlaylist: string
baseUrlSegment: string baseUrlSegment: string
@ -49,9 +51,7 @@ async function checkSegmentHash (options: {
expect(sha256(segmentBody)).to.equal(shaBody[videoName][range], `Invalid sha256 result for ${videoName} range ${range}`) expect(sha256(segmentBody)).to.equal(shaBody[videoName][range], `Invalid sha256 result for ${videoName} range ${range}`)
} }
// --------------------------------------------------------------------------- export async function checkLiveSegmentHash (options: {
async function checkLiveSegmentHash (options: {
server: PeerTubeServer server: PeerTubeServer
baseUrlSegment: string baseUrlSegment: string
videoUUID: string videoUUID: string
@ -68,9 +68,25 @@ async function checkLiveSegmentHash (options: {
expect(sha256(segmentBody)).to.equal(shaBody[segmentName]) expect(sha256(segmentBody)).to.equal(shaBody[segmentName])
} }
export async function checkPlaylistInfohash (options: {
video: VideoDetails
sqlCommand: SQLCommand
files: unknown[]
}) {
const { sqlCommand, video, files } = options
const hls = getHLS(video)
for (let i = 0; i < files.length; i++) {
const infohash = sha1(`${2 + hls.playlistUrl}+V${i}`)
const dbInfohashes = await sqlCommand.getPlaylistInfohash(hls.id)
expect(dbInfohashes).to.include(infohash)
}
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function checkResolutionsInMasterPlaylist (options: { export async function checkResolutionsInMasterPlaylist (options: {
server: PeerTubeServer server: PeerTubeServer
playlistUrl: string playlistUrl: string
resolutions: number[] resolutions: number[]
@ -98,7 +114,7 @@ async function checkResolutionsInMasterPlaylist (options: {
expect(playlistsLength).to.have.lengthOf(resolutions.length) expect(playlistsLength).to.have.lengthOf(resolutions.length)
} }
async function completeCheckHlsPlaylist (options: { export async function completeCheckHlsPlaylist (options: {
servers: PeerTubeServer[] servers: PeerTubeServer[]
videoUUID: string videoUUID: string
hlsOnly: boolean hlsOnly: boolean
@ -255,7 +271,7 @@ async function completeCheckHlsPlaylist (options: {
} }
} }
async function checkVideoFileTokenReinjection (options: { export async function checkVideoFileTokenReinjection (options: {
server: PeerTubeServer server: PeerTubeServer
videoUUID: string videoUUID: string
videoFileToken: string videoFileToken: string
@ -295,16 +311,7 @@ async function checkVideoFileTokenReinjection (options: {
} }
} }
function extractResolutionPlaylistUrls (masterPath: string, masterContent: string) { export function extractResolutionPlaylistUrls (masterPath: string, masterContent: string) {
return masterContent.match(/^([^.]+\.m3u8.*)/mg) return masterContent.match(/^([^.]+\.m3u8.*)/mg)
.map(filename => join(dirname(masterPath), filename)) .map(filename => join(dirname(masterPath), filename))
} }
export {
checkSegmentHash,
checkLiveSegmentHash,
checkResolutionsInMasterPlaylist,
completeCheckHlsPlaylist,
extractResolutionPlaylistUrls,
checkVideoFileTokenReinjection
}

View file

@ -125,6 +125,12 @@ export async function addVideoJobsAfterUpdate (options: {
const jobs: CreateJobArgument[] = [] const jobs: CreateJobArgument[] = []
const filePathChanged = await moveFilesIfPrivacyChanged(video, oldPrivacy) const filePathChanged = await moveFilesIfPrivacyChanged(video, oldPrivacy)
const hls = video.getHLSPlaylist()
if (filePathChanged && hls) {
hls.assignP2PMediaLoaderInfoHashes(video, hls.VideoFiles)
await hls.save()
}
if (!video.isLive && (nameChanged || filePathChanged)) { if (!video.isLive && (nameChanged || filePathChanged)) {
for (const file of (video.VideoFiles || [])) { for (const file of (video.VideoFiles || [])) {