"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkVideoFileTokenReinjection = exports.extractResolutionPlaylistUrls = exports.completeCheckHlsPlaylist = exports.checkResolutionsInMasterPlaylist = exports.checkLiveSegmentHash = exports.checkSegmentHash = void 0;
const tslib_1 = require("tslib");
const chai_1 = require("chai");
const path_1 = require("path");
const core_utils_1 = require("../../../shared/core-utils");
const extra_utils_1 = require("../../../shared/extra-utils");
const server_commands_1 = require("../../../shared/server-commands");
const checks_1 = require("./checks");
const tracker_1 = require("./tracker");
function checkSegmentHash(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { server, baseUrlPlaylist, baseUrlSegment, resolution, hlsPlaylist } = options;
        const command = server.streamingPlaylists;
        const file = hlsPlaylist.files.find(f => f.resolution.id === resolution);
        const videoName = (0, path_1.basename)(file.fileUrl);
        const playlist = yield command.get({ url: `${baseUrlPlaylist}/${(0, core_utils_1.removeFragmentedMP4Ext)(videoName)}.m3u8` });
        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 segmentBody = yield command.getFragmentedSegment({
            url: `${baseUrlSegment}/${videoName}`,
            expectedStatus: 206,
            range: `bytes=${range}`
        });
        const shaBody = yield command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url });
        (0, chai_1.expect)((0, extra_utils_1.sha256)(segmentBody)).to.equal(shaBody[videoName][range]);
    });
}
exports.checkSegmentHash = checkSegmentHash;
function checkLiveSegmentHash(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { server, baseUrlSegment, videoUUID, segmentName, hlsPlaylist } = options;
        const command = server.streamingPlaylists;
        const segmentBody = yield command.getFragmentedSegment({ url: `${baseUrlSegment}/${videoUUID}/${segmentName}` });
        const shaBody = yield command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url });
        (0, chai_1.expect)((0, extra_utils_1.sha256)(segmentBody)).to.equal(shaBody[segmentName]);
    });
}
exports.checkLiveSegmentHash = checkLiveSegmentHash;
function checkResolutionsInMasterPlaylist(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { server, playlistUrl, resolutions, withRetry = false, transcoded = true } = options;
        const masterPlaylist = yield server.streamingPlaylists.get({ url: playlistUrl, withRetry });
        for (const resolution of resolutions) {
            const reg = transcoded
                ? new RegExp('#EXT-X-STREAM-INF:BANDWIDTH=\\d+,RESOLUTION=\\d+x' + resolution + ',(FRAME-RATE=\\d+,)?CODECS="avc1.64001f,mp4a.40.2"')
                : new RegExp('#EXT-X-STREAM-INF:BANDWIDTH=\\d+,RESOLUTION=\\d+x' + resolution + '');
            (0, chai_1.expect)(masterPlaylist).to.match(reg);
        }
        const playlistsLength = masterPlaylist.split('\n').filter(line => line.startsWith('#EXT-X-STREAM-INF:BANDWIDTH='));
        (0, chai_1.expect)(playlistsLength).to.have.lengthOf(resolutions.length);
    });
}
exports.checkResolutionsInMasterPlaylist = checkResolutionsInMasterPlaylist;
function completeCheckHlsPlaylist(options) {
    var _a;
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { videoUUID, hlsOnly, objectStorageBaseUrl } = options;
        const resolutions = (_a = options.resolutions) !== null && _a !== void 0 ? _a : [240, 360, 480, 720];
        for (const server of options.servers) {
            const videoDetails = yield server.videos.get({ id: videoUUID });
            const baseUrl = `http://${videoDetails.account.host}`;
            (0, chai_1.expect)(videoDetails.streamingPlaylists).to.have.lengthOf(1);
            const hlsPlaylist = videoDetails.streamingPlaylists.find(p => p.type === 1);
            (0, chai_1.expect)(hlsPlaylist).to.not.be.undefined;
            const hlsFiles = hlsPlaylist.files;
            (0, chai_1.expect)(hlsFiles).to.have.lengthOf(resolutions.length);
            if (hlsOnly)
                (0, chai_1.expect)(videoDetails.files).to.have.lengthOf(0);
            else
                (0, chai_1.expect)(videoDetails.files).to.have.lengthOf(resolutions.length);
            for (const resolution of resolutions) {
                const file = hlsFiles.find(f => f.resolution.id === resolution);
                (0, chai_1.expect)(file).to.not.be.undefined;
                (0, chai_1.expect)(file.magnetUri).to.have.lengthOf.above(2);
                (0, chai_1.expect)(file.torrentUrl).to.match(new RegExp(`${server.url}/lazy-static/torrents/${core_utils_1.uuidRegex}-${file.resolution.id}-hls.torrent`));
                if (objectStorageBaseUrl) {
                    (0, checks_1.expectStartWith)(file.fileUrl, objectStorageBaseUrl);
                }
                else {
                    (0, chai_1.expect)(file.fileUrl).to.match(new RegExp(`${baseUrl}/static/streaming-playlists/hls/${videoDetails.uuid}/${core_utils_1.uuidRegex}-${file.resolution.id}-fragmented.mp4`));
                }
                (0, chai_1.expect)(file.resolution.label).to.equal(resolution + 'p');
                yield (0, server_commands_1.makeRawRequest)({ url: file.torrentUrl, expectedStatus: 200 });
                yield (0, server_commands_1.makeRawRequest)({ url: file.fileUrl, expectedStatus: 200 });
                const torrent = yield (0, server_commands_1.webtorrentAdd)(file.magnetUri, true);
                (0, chai_1.expect)(torrent.files).to.be.an('array');
                (0, chai_1.expect)(torrent.files.length).to.equal(1);
                (0, chai_1.expect)(torrent.files[0].path).to.exist.and.to.not.equal('');
            }
            {
                yield checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions });
                const masterPlaylist = yield server.streamingPlaylists.get({ url: hlsPlaylist.playlistUrl });
                let i = 0;
                for (const resolution of resolutions) {
                    (0, chai_1.expect)(masterPlaylist).to.contain(`${resolution}.m3u8`);
                    (0, chai_1.expect)(masterPlaylist).to.contain(`${resolution}.m3u8`);
                    const url = 'http://' + videoDetails.account.host;
                    yield (0, tracker_1.hlsInfohashExist)(url, hlsPlaylist.playlistUrl, i);
                    i++;
                }
            }
            {
                for (const resolution of resolutions) {
                    const file = hlsFiles.find(f => f.resolution.id === resolution);
                    const playlistName = (0, core_utils_1.removeFragmentedMP4Ext)((0, path_1.basename)(file.fileUrl)) + '.m3u8';
                    const url = objectStorageBaseUrl
                        ? `${objectStorageBaseUrl}hls/${videoUUID}/${playlistName}`
                        : `${baseUrl}/static/streaming-playlists/hls/${videoUUID}/${playlistName}`;
                    const subPlaylist = yield server.streamingPlaylists.get({ url });
                    (0, chai_1.expect)(subPlaylist).to.match(new RegExp(`${core_utils_1.uuidRegex}-${resolution}-fragmented.mp4`));
                    (0, chai_1.expect)(subPlaylist).to.contain((0, path_1.basename)(file.fileUrl));
                }
            }
            {
                const baseUrlAndPath = objectStorageBaseUrl
                    ? objectStorageBaseUrl + 'hls/' + videoUUID
                    : baseUrl + '/static/streaming-playlists/hls/' + videoUUID;
                for (const resolution of resolutions) {
                    yield checkSegmentHash({
                        server,
                        baseUrlPlaylist: baseUrlAndPath,
                        baseUrlSegment: baseUrlAndPath,
                        resolution,
                        hlsPlaylist
                    });
                }
            }
        }
    });
}
exports.completeCheckHlsPlaylist = completeCheckHlsPlaylist;
function checkVideoFileTokenReinjection(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { server, resolutions, videoFileToken, videoUUID, isLive } = options;
        const video = yield server.videos.getWithToken({ id: videoUUID });
        const hls = video.streamingPlaylists[0];
        const query = { videoFileToken, reinjectVideoFileToken: 'true' };
        const { text } = yield (0, server_commands_1.makeRawRequest)({ url: hls.playlistUrl, query, expectedStatus: 200 });
        for (let i = 0; i < resolutions.length; i++) {
            const resolution = resolutions[i];
            const suffix = isLive
                ? i
                : `-${resolution}`;
            (0, chai_1.expect)(text).to.contain(`${suffix}.m3u8?videoFileToken=${videoFileToken}`);
        }
        const resolutionPlaylists = extractResolutionPlaylistUrls(hls.playlistUrl, text);
        (0, chai_1.expect)(resolutionPlaylists).to.have.lengthOf(resolutions.length);
        for (const url of resolutionPlaylists) {
            const { text } = yield (0, server_commands_1.makeRawRequest)({ url, query, expectedStatus: 200 });
            const extension = isLive
                ? '.ts'
                : '.mp4';
            (0, chai_1.expect)(text).to.contain(`${extension}?videoFileToken=${videoFileToken}`);
        }
    });
}
exports.checkVideoFileTokenReinjection = checkVideoFileTokenReinjection;
function extractResolutionPlaylistUrls(masterPath, masterContent) {
    return masterContent.match(/^([^.]+\.m3u8.*)/mg)
        .map(filename => (0, path_1.join)((0, path_1.dirname)(masterPath), filename));
}
exports.extractResolutionPlaylistUrls = extractResolutionPlaylistUrls;
//# sourceMappingURL=streaming-playlists.js.map