"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.feedsRouter = void 0;
const tslib_1 = require("tslib");
const express_1 = tslib_1.__importDefault(require("express"));
const path_1 = require("path");
const feed_1 = require("@peertube/feed");
const markdown_1 = require("../helpers/markdown");
const application_1 = require("../models/application/application");
const video_format_utils_1 = require("../models/video/formatter/video-format-utils");
const express_utils_1 = require("../helpers/express-utils");
const config_1 = require("../initializers/config");
const constants_1 = require("../initializers/constants");
const middlewares_1 = require("../middlewares");
const cache_1 = require("../middlewares/cache/cache");
const video_1 = require("../models/video/video");
const video_comment_1 = require("../models/video/video-comment");
const feedsRouter = express_1.default.Router();
exports.feedsRouter = feedsRouter;
const cacheRoute = (0, cache_1.cacheRouteFactory)({
    headerBlacklist: ['Content-Type']
});
feedsRouter.get('/feeds/video-comments.:format', middlewares_1.feedsFormatValidator, middlewares_1.setFeedFormatContentType, cacheRoute(constants_1.ROUTE_CACHE_LIFETIME.FEEDS), (0, middlewares_1.asyncMiddleware)(middlewares_1.videoFeedsValidator), (0, middlewares_1.asyncMiddleware)(middlewares_1.videoCommentsFeedsValidator), (0, middlewares_1.asyncMiddleware)(generateVideoCommentsFeed));
feedsRouter.get('/feeds/videos.:format', middlewares_1.videosSortValidator, middlewares_1.setDefaultVideosSort, middlewares_1.feedsFormatValidator, middlewares_1.setFeedFormatContentType, cacheRoute(constants_1.ROUTE_CACHE_LIFETIME.FEEDS), middlewares_1.commonVideosFiltersValidator, (0, middlewares_1.asyncMiddleware)(middlewares_1.videoFeedsValidator), (0, middlewares_1.asyncMiddleware)(generateVideoFeed));
feedsRouter.get('/feeds/subscriptions.:format', middlewares_1.videosSortValidator, middlewares_1.setDefaultVideosSort, middlewares_1.feedsFormatValidator, middlewares_1.setFeedFormatContentType, cacheRoute(constants_1.ROUTE_CACHE_LIFETIME.FEEDS), middlewares_1.commonVideosFiltersValidator, (0, middlewares_1.asyncMiddleware)(middlewares_1.videoSubscriptionFeedsValidator), (0, middlewares_1.asyncMiddleware)(generateVideoFeedForSubscriptions));
function generateVideoCommentsFeed(req, res) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const start = 0;
        const video = res.locals.videoAll;
        const account = res.locals.account;
        const videoChannel = res.locals.videoChannel;
        const comments = yield video_comment_1.VideoCommentModel.listForFeed({
            start,
            count: config_1.CONFIG.FEEDS.COMMENTS.COUNT,
            videoId: video ? video.id : undefined,
            accountId: account ? account.id : undefined,
            videoChannelId: videoChannel ? videoChannel.id : undefined
        });
        const { name, description, imageUrl } = buildFeedMetadata({ video, account, videoChannel });
        const feed = initFeed({
            name,
            description,
            imageUrl,
            resourceType: 'video-comments',
            queryString: new URL(constants_1.WEBSERVER.URL + req.originalUrl).search
        });
        for (const comment of comments) {
            const localLink = constants_1.WEBSERVER.URL + comment.getCommentStaticPath();
            let title = comment.Video.name;
            const author = [];
            if (comment.Account) {
                title += ` - ${comment.Account.getDisplayName()}`;
                author.push({
                    name: comment.Account.getDisplayName(),
                    link: comment.Account.Actor.url
                });
            }
            feed.addItem({
                title,
                id: localLink,
                link: localLink,
                content: (0, markdown_1.toSafeHtml)(comment.text),
                author,
                date: comment.createdAt
            });
        }
        return sendFeed(feed, req, res);
    });
}
function generateVideoFeed(req, res) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const start = 0;
        const account = res.locals.account;
        const videoChannel = res.locals.videoChannel;
        const nsfw = (0, express_utils_1.buildNSFWFilter)(res, req.query.nsfw);
        const { name, description, imageUrl } = buildFeedMetadata({ videoChannel, account });
        const feed = initFeed({
            name,
            description,
            imageUrl,
            resourceType: 'videos',
            queryString: new URL(constants_1.WEBSERVER.URL + req.url).search
        });
        const options = {
            accountId: account ? account.id : null,
            videoChannelId: videoChannel ? videoChannel.id : null
        };
        const server = yield (0, application_1.getServerActor)();
        const { data } = yield video_1.VideoModel.listForApi(Object.assign({ start, count: config_1.CONFIG.FEEDS.VIDEOS.COUNT, sort: req.query.sort, displayOnlyForFollower: {
                actorId: server.id,
                orLocalVideos: true
            }, nsfw, isLocal: req.query.isLocal, include: req.query.include | 8, hasFiles: true, countVideos: false }, options));
        addVideosToFeed(feed, data);
        return sendFeed(feed, req, res);
    });
}
function generateVideoFeedForSubscriptions(req, res) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const start = 0;
        const account = res.locals.account;
        const nsfw = (0, express_utils_1.buildNSFWFilter)(res, req.query.nsfw);
        const { name, description, imageUrl } = buildFeedMetadata({ account });
        const feed = initFeed({
            name,
            description,
            imageUrl,
            resourceType: 'videos',
            queryString: new URL(constants_1.WEBSERVER.URL + req.url).search
        });
        const { data } = yield video_1.VideoModel.listForApi({
            start,
            count: config_1.CONFIG.FEEDS.VIDEOS.COUNT,
            sort: req.query.sort,
            nsfw,
            isLocal: req.query.isLocal,
            hasFiles: true,
            include: req.query.include | 8,
            countVideos: false,
            displayOnlyForFollower: {
                actorId: res.locals.user.Account.Actor.id,
                orLocalVideos: false
            },
            user: res.locals.user
        });
        addVideosToFeed(feed, data);
        return sendFeed(feed, req, res);
    });
}
function initFeed(parameters) {
    const webserverUrl = constants_1.WEBSERVER.URL;
    const { name, description, resourceType, queryString, imageUrl } = parameters;
    return new feed_1.Feed({
        title: name,
        description: (0, markdown_1.mdToOneLinePlainText)(description),
        id: webserverUrl,
        link: webserverUrl,
        image: imageUrl,
        favicon: webserverUrl + '/client/assets/images/favicon.png',
        copyright: `All rights reserved, unless otherwise specified in the terms specified at ${webserverUrl}/about` +
            ` and potential licenses granted by each content's rightholder.`,
        generator: `Toraifōsu`,
        feedLinks: {
            json: `${webserverUrl}/feeds/${resourceType}.json${queryString}`,
            atom: `${webserverUrl}/feeds/${resourceType}.atom${queryString}`,
            rss: `${webserverUrl}/feeds/${resourceType}.xml${queryString}`
        },
        author: {
            name: 'Instance admin of ' + config_1.CONFIG.INSTANCE.NAME,
            email: config_1.CONFIG.ADMIN.EMAIL,
            link: `${webserverUrl}/about`
        }
    });
}
function addVideosToFeed(feed, videos) {
    for (const video of videos) {
        const formattedVideoFiles = video.getFormattedVideoFilesJSON(false);
        const torrents = formattedVideoFiles.map(videoFile => ({
            title: video.name,
            url: videoFile.torrentUrl,
            size_in_bytes: videoFile.size
        }));
        const videoFiles = formattedVideoFiles.map(videoFile => {
            const result = {
                type: constants_1.MIMETYPES.VIDEO.EXT_MIMETYPE[(0, path_1.extname)(videoFile.fileUrl)],
                medium: 'video',
                height: videoFile.resolution.id,
                fileSize: videoFile.size,
                url: videoFile.fileUrl,
                framerate: videoFile.fps,
                duration: video.duration
            };
            if (video.language)
                Object.assign(result, { lang: video.language });
            return result;
        });
        const categories = [];
        if (video.category) {
            categories.push({
                value: video.category,
                label: (0, video_format_utils_1.getCategoryLabel)(video.category)
            });
        }
        const localLink = constants_1.WEBSERVER.URL + video.getWatchStaticPath();
        feed.addItem({
            title: video.name,
            id: localLink,
            link: localLink,
            description: (0, markdown_1.mdToOneLinePlainText)(video.getTruncatedDescription()),
            content: (0, markdown_1.toSafeHtml)(video.description),
            author: [
                {
                    name: video.VideoChannel.Account.getDisplayName(),
                    link: video.VideoChannel.Account.Actor.url
                }
            ],
            date: video.publishedAt,
            nsfw: video.nsfw,
            torrents,
            video: videoFiles.length !== 0
                ? {
                    url: videoFiles[0].url,
                    length: videoFiles[0].fileSize,
                    type: videoFiles[0].type
                }
                : undefined,
            videos: videoFiles,
            embed: {
                url: constants_1.WEBSERVER.URL + video.getEmbedStaticPath(),
                allowFullscreen: true
            },
            player: {
                url: constants_1.WEBSERVER.URL + video.getWatchStaticPath()
            },
            categories,
            community: {
                statistics: {
                    views: video.views
                }
            },
            thumbnails: [
                {
                    url: constants_1.WEBSERVER.URL + video.getPreviewStaticPath(),
                    height: constants_1.PREVIEWS_SIZE.height,
                    width: constants_1.PREVIEWS_SIZE.width
                }
            ]
        });
    }
}
function sendFeed(feed, req, res) {
    const format = req.params.format;
    if (format === 'atom' || format === 'atom1') {
        return res.send(feed.atom1()).end();
    }
    if (format === 'json' || format === 'json1') {
        return res.send(feed.json1()).end();
    }
    if (format === 'rss' || format === 'rss2') {
        return res.send(feed.rss2()).end();
    }
    if (req.query.format === 'atom' || req.query.format === 'atom1') {
        return res.send(feed.atom1()).end();
    }
    return res.send(feed.rss2()).end();
}
function buildFeedMetadata(options) {
    const { video, videoChannel, account } = options;
    let imageUrl = constants_1.WEBSERVER.URL + '/client/assets/images/icons/icon-96x96.png';
    let name;
    let description;
    if (videoChannel) {
        name = videoChannel.getDisplayName();
        description = videoChannel.description;
        if (videoChannel.Actor.hasImage(1)) {
            imageUrl = constants_1.WEBSERVER.URL + videoChannel.Actor.Avatars[0].getStaticPath();
        }
    }
    else if (account) {
        name = account.getDisplayName();
        description = account.description;
        if (account.Actor.hasImage(1)) {
            imageUrl = constants_1.WEBSERVER.URL + account.Actor.Avatars[0].getStaticPath();
        }
    }
    else if (video) {
        name = video.name;
        description = video.description;
    }
    else {
        name = config_1.CONFIG.INSTANCE.NAME;
        description = config_1.CONFIG.INSTANCE.DESCRIPTION;
    }
    return { name, description, imageUrl };
}
//# sourceMappingURL=feeds.js.map