"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStreamRouter = void 0;
const pump_1 = __importDefault(require("pump"));
const range_parser_1 = __importDefault(require("range-parser"));
const common_stuff_1 = require("common-stuff");
const torrent_client_1 = require("../services/torrent-client");
const helpers_1 = require("../helpers");
const openapi_1 = require("../helpers/openapi");
function getStreamRouter({ config }, client) {
    const encodeToken = config.security.streamApi.key || config.security.apiKey;
    const parseParams = (params) => {
        if (encodeToken) {
            if (params.file || params.fileIndex || params.fileType) {
                throw new common_stuff_1.HttpError(common_stuff_1.HttpStatusCodes.BAD_REQUEST, `All parameters should be encoded with JWT`);
            }
            const data = helpers_1.verifyJwtToken(params.torrent, encodeToken, config.security.streamApi.maxAge);
            if (!data) {
                throw new common_stuff_1.HttpError(common_stuff_1.HttpStatusCodes.FORBIDDEN, 'Incorrect JWT encoding');
            }
            return data;
        }
        return params;
    };
    return [
        openapi_1.createRoute('getStream', async (req, res) => {
            const { torrent: link, ...params } = parseParams({
                torrent: req.params.torrent,
                ...req.query,
            });
            const torrent = await client.addTorrent(link);
            const file = torrent_client_1.filterFiles(torrent.files, params)[0];
            if (!file) {
                throw new common_stuff_1.HttpError(common_stuff_1.HttpStatusCodes.NOT_FOUND);
            }
            res.setHeader('Accept-Ranges', 'bytes');
            res.attachment(file.name);
            req.connection.setTimeout(3600000);
            const parsedRange = req.headers.range
                ? range_parser_1.default(file.length, req.headers.range)
                : undefined;
            const range = parsedRange instanceof Array ? parsedRange[0] : undefined;
            if (range) {
                res.statusCode = 206;
                res.setHeader('Content-Length', range.end - range.start + 1);
                res.setHeader('Content-Range', 'bytes ' + range.start + '-' + range.end + '/' + file.length);
            }
            else {
                res.setHeader('Content-Length', file.length);
            }
            if (req.method === 'HEAD') {
                return res.end();
            }
            return pump_1.default(file.createReadStream(range), res, () => {
                file.stop();
            });
        }),
        openapi_1.createRoute('getStream2', async (req, res) => {
            const { torrent, ...query } = req.query;
            return res.redirect(openapi_1.getRouteUrl('getStream', { torrent }, query), 301);
        }),
        openapi_1.createRoute('getPlaylist', async (req, res) => {
            const domain = req.protocol + '://' + req.get('host');
            const { torrent: link, ...params } = parseParams({
                torrent: req.params.torrent,
                ...req.query,
            });
            const torrent = await client.addTorrent(link);
            const files = torrent_client_1.filterFiles(torrent.files, params).filter((v) => v.type.includes('video') || v.type.includes('audio'));
            req.connection.setTimeout(10000);
            res.attachment(torrent.name + `.m3u`);
            return res.send([
                '#EXTM3U',
                ...files.flatMap((f) => [
                    `#EXTINF:-1,${f.name}`,
                    `${domain}${helpers_1.getSteamUrl(link, f.path, encodeToken)}`,
                ]),
            ].join('\n'));
        }),
        openapi_1.createRoute('getPlaylist2', async (req, res) => {
            const { torrent, ...query } = req.query;
            return res.redirect(openapi_1.getRouteUrl('getPlaylist', { torrent }, query), 301);
        }),
    ];
}
exports.getStreamRouter = getStreamRouter;
