"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.YoutubeDLWrapper = void 0;
const tslib_1 = require("tslib");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const util_1 = require("util");
const config_1 = require("../../initializers/config");
const videos_1 = require("../custom-validators/videos");
const logger_1 = require("../logger");
const utils_1 = require("../utils");
const youtube_dl_cli_1 = require("./youtube-dl-cli");
const youtube_dl_info_builder_1 = require("./youtube-dl-info-builder");
const lTags = (0, logger_1.loggerTagsFactory)('youtube-dl');
const processOptions = {
    maxBuffer: 1024 * 1024 * 30
};
class YoutubeDLWrapper {
    constructor(url, enabledResolutions, useBestFormat) {
        this.url = url;
        this.enabledResolutions = enabledResolutions;
        this.useBestFormat = useBestFormat;
    }
    getInfoForDownload(youtubeDLArgs = []) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const youtubeDL = yield youtube_dl_cli_1.YoutubeDLCLI.safeGet();
            const info = yield youtubeDL.getInfo({
                url: this.url,
                format: youtube_dl_cli_1.YoutubeDLCLI.getYoutubeDLVideoFormat(this.enabledResolutions, this.useBestFormat),
                additionalYoutubeDLArgs: youtubeDLArgs,
                processOptions
            });
            if (!info)
                throw new Error(`YoutubeDL could not get info from ${this.url}`);
            if (info.is_live === true)
                throw new Error('Cannot download a live streaming.');
            const infoBuilder = new youtube_dl_info_builder_1.YoutubeDLInfoBuilder(info);
            return infoBuilder.getInfo();
        });
    }
    getInfoForListImport(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const youtubeDL = yield youtube_dl_cli_1.YoutubeDLCLI.safeGet();
            const list = yield youtubeDL.getListInfo({
                url: this.url,
                latestVideosCount: options.latestVideosCount,
                processOptions
            });
            if (!Array.isArray(list))
                throw new Error(`YoutubeDL could not get list info from ${this.url}: ${(0, util_1.inspect)(list)}`);
            return list.map(info => info.webpage_url);
        });
    }
    getSubtitles() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const cwd = config_1.CONFIG.STORAGE.TMP_DIR;
            const youtubeDL = yield youtube_dl_cli_1.YoutubeDLCLI.safeGet();
            const files = yield youtubeDL.getSubs({ url: this.url, format: 'vtt', processOptions: { cwd } });
            if (!files)
                return [];
            logger_1.logger.debug('Get subtitles from youtube dl.', Object.assign({ url: this.url, files }, lTags()));
            const subtitles = files.reduce((acc, filename) => {
                const matched = filename.match(/\.([a-z]{2})(-[a-z]+)?\.(vtt|ttml)/i);
                if (!(matched === null || matched === void 0 ? void 0 : matched[1]))
                    return acc;
                return [
                    ...acc,
                    {
                        language: matched[1],
                        path: (0, path_1.join)(cwd, filename),
                        filename
                    }
                ];
            }, []);
            return subtitles;
        });
    }
    downloadVideo(fileExt, timeout) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const pathWithoutExtension = (0, utils_1.generateVideoImportTmpPath)(this.url, '');
            logger_1.logger.info('Importing youtubeDL video %s to %s', this.url, pathWithoutExtension, lTags());
            const youtubeDL = yield youtube_dl_cli_1.YoutubeDLCLI.safeGet();
            try {
                yield youtubeDL.download({
                    url: this.url,
                    format: youtube_dl_cli_1.YoutubeDLCLI.getYoutubeDLVideoFormat(this.enabledResolutions, this.useBestFormat),
                    output: pathWithoutExtension,
                    timeout,
                    processOptions
                });
                if (yield (0, fs_extra_1.pathExists)(pathWithoutExtension)) {
                    yield (0, fs_extra_1.move)(pathWithoutExtension, pathWithoutExtension + '.mp4');
                }
                return this.guessVideoPathWithExtension(pathWithoutExtension, fileExt);
            }
            catch (err) {
                this.guessVideoPathWithExtension(pathWithoutExtension, fileExt)
                    .then(path => {
                    logger_1.logger.debug('Error in youtube-dl import, deleting file %s.', path, Object.assign({ err }, lTags()));
                    return (0, fs_extra_1.remove)(path);
                })
                    .catch(innerErr => logger_1.logger.error('Cannot remove file in youtubeDL error.', Object.assign({ innerErr }, lTags())));
                throw err;
            }
        });
    }
    guessVideoPathWithExtension(tmpPath, sourceExt) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!(0, videos_1.isVideoFileExtnameValid)(sourceExt)) {
                throw new Error('Invalid video extension ' + sourceExt);
            }
            const extensions = [sourceExt, '.mp4', '.mkv', '.webm'];
            for (const extension of extensions) {
                const path = tmpPath + extension;
                if (yield (0, fs_extra_1.pathExists)(path))
                    return path;
            }
            const directoryContent = yield (0, fs_extra_1.readdir)((0, path_1.dirname)(tmpPath));
            throw new Error(`Cannot guess path of ${tmpPath}. Directory content: ${directoryContent.join(', ')}`);
        });
    }
}
exports.YoutubeDLWrapper = YoutubeDLWrapper;
//# sourceMappingURL=youtube-dl-wrapper.js.map