"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateRouter = void 0;
const tslib_1 = require("tslib");
const express_1 = tslib_1.__importDefault(require("express"));
const share_1 = require("../../../lib/activitypub/share");
const video_1 = require("../../../lib/video");
const video_privacy_1 = require("../../../lib/video-privacy");
const doc_1 = require("../../../middlewares/doc");
const audit_logger_1 = require("../../../helpers/audit-logger");
const database_utils_1 = require("../../../helpers/database-utils");
const express_utils_1 = require("../../../helpers/express-utils");
const logger_1 = require("../../../helpers/logger");
const constants_1 = require("../../../initializers/constants");
const database_1 = require("../../../initializers/database");
const hooks_1 = require("../../../lib/plugins/hooks");
const video_blacklist_1 = require("../../../lib/video-blacklist");
const middlewares_1 = require("../../../middlewares");
const schedule_video_update_1 = require("../../../models/video/schedule-video-update");
const video_2 = require("../../../models/video/video");
const video_path_manager_1 = require("../../../lib/video-path-manager");
const core_utils_1 = require("../../../../shared/core-utils");
const lTags = (0, logger_1.loggerTagsFactory)('api', 'video');
const auditLogger = (0, audit_logger_1.auditLoggerFactory)('videos');
const updateRouter = express_1.default.Router();
exports.updateRouter = updateRouter;
const reqVideoFileUpdate = (0, express_utils_1.createReqFiles)(['thumbnailfile', 'previewfile'], constants_1.MIMETYPES.IMAGE.MIMETYPE_EXT);
updateRouter.put('/:id', (0, doc_1.openapiOperationDoc)({ operationId: 'putVideo' }), middlewares_1.authenticate, reqVideoFileUpdate, (0, middlewares_1.asyncMiddleware)(middlewares_1.videosUpdateValidator), (0, middlewares_1.asyncRetryTransactionMiddleware)(updateVideo));
function updateVideo(req, res) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const videoFromReq = res.locals.videoAll;
        const videoFieldsSave = videoFromReq.toJSON();
        const oldVideoAuditView = new audit_logger_1.VideoAuditView(videoFromReq.toFormattedDetailsJSON());
        const videoInfoToUpdate = req.body;
        const hadPrivacyForFederation = videoFromReq.hasPrivacyForFederation();
        const oldPrivacy = videoFromReq.privacy;
        const [thumbnailModel, previewModel] = yield (0, video_1.buildVideoThumbnailsFromReq)({
            video: videoFromReq,
            files: req.files,
            fallback: () => Promise.resolve(undefined),
            automaticallyGenerated: false
        });
        const videoFileLockReleaser = yield video_path_manager_1.VideoPathManager.Instance.lockFiles(videoFromReq.uuid);
        try {
            const { videoInstanceUpdated, isNewVideo } = yield database_1.sequelizeTypescript.transaction((t) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                const video = yield video_2.VideoModel.loadFull(videoFromReq.id, t);
                const oldVideoChannel = video.VideoChannel;
                const keysToUpdate = [
                    'name',
                    'category',
                    'licence',
                    'language',
                    'nsfw',
                    'waitTranscoding',
                    'support',
                    'description',
                    'commentsEnabled',
                    'downloadEnabled'
                ];
                for (const key of keysToUpdate) {
                    if (videoInfoToUpdate[key] !== undefined)
                        video.set(key, videoInfoToUpdate[key]);
                }
                if (videoInfoToUpdate.originallyPublishedAt !== undefined && videoInfoToUpdate.originallyPublishedAt !== null) {
                    video.originallyPublishedAt = new Date(videoInfoToUpdate.originallyPublishedAt);
                }
                let isNewVideo = false;
                if (videoInfoToUpdate.privacy !== undefined) {
                    isNewVideo = yield updateVideoPrivacy({ videoInstance: video, videoInfoToUpdate, hadPrivacyForFederation, transaction: t });
                }
                if (!video.changed()) {
                    yield video.setAsRefreshed(t);
                }
                const videoInstanceUpdated = yield video.save({ transaction: t });
                if (thumbnailModel)
                    yield videoInstanceUpdated.addAndSaveThumbnail(thumbnailModel, t);
                if (previewModel)
                    yield videoInstanceUpdated.addAndSaveThumbnail(previewModel, t);
                if (videoInfoToUpdate.tags !== undefined) {
                    yield (0, video_1.setVideoTags)({ video: videoInstanceUpdated, tags: videoInfoToUpdate.tags, transaction: t });
                }
                if (res.locals.videoChannel && videoInstanceUpdated.channelId !== res.locals.videoChannel.id) {
                    yield videoInstanceUpdated.$set('VideoChannel', res.locals.videoChannel, { transaction: t });
                    videoInstanceUpdated.VideoChannel = res.locals.videoChannel;
                    if (hadPrivacyForFederation === true) {
                        yield (0, share_1.changeVideoChannelShare)(videoInstanceUpdated, oldVideoChannel, t);
                    }
                }
                yield updateSchedule(videoInstanceUpdated, videoInfoToUpdate, t);
                yield (0, video_blacklist_1.autoBlacklistVideoIfNeeded)({
                    video: videoInstanceUpdated,
                    user: res.locals.oauth.token.User,
                    isRemote: false,
                    isNew: false,
                    transaction: t
                });
                auditLogger.update((0, audit_logger_1.getAuditIdFromRes)(res), new audit_logger_1.VideoAuditView(videoInstanceUpdated.toFormattedDetailsJSON()), oldVideoAuditView);
                logger_1.logger.info('Video with name %s and uuid %s updated.', video.name, video.uuid, lTags(video.uuid));
                return { videoInstanceUpdated, isNewVideo };
            }));
            hooks_1.Hooks.runAction('action:api.video.updated', { video: videoInstanceUpdated, body: req.body, req, res });
            yield (0, video_1.addVideoJobsAfterUpdate)({
                video: videoInstanceUpdated,
                nameChanged: !!videoInfoToUpdate.name,
                oldPrivacy,
                isNewVideo
            });
        }
        catch (err) {
            (0, database_utils_1.resetSequelizeInstance)(videoFromReq, videoFieldsSave);
            throw err;
        }
        finally {
            videoFileLockReleaser();
        }
        return res.type('json')
            .status(204)
            .end();
    });
}
function updateVideoPrivacy(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { videoInstance, videoInfoToUpdate, hadPrivacyForFederation, transaction } = options;
        const isNewVideo = videoInstance.isNewVideo(videoInfoToUpdate.privacy);
        const newPrivacy = (0, core_utils_1.forceNumber)(videoInfoToUpdate.privacy);
        (0, video_privacy_1.setVideoPrivacy)(videoInstance, newPrivacy);
        if (hadPrivacyForFederation && !videoInstance.hasPrivacyForFederation()) {
            yield video_2.VideoModel.sendDelete(videoInstance, { transaction });
        }
        return isNewVideo;
    });
}
function updateSchedule(videoInstance, videoInfoToUpdate, transaction) {
    if (videoInfoToUpdate.scheduleUpdate) {
        return schedule_video_update_1.ScheduleVideoUpdateModel.upsert({
            videoId: videoInstance.id,
            updateAt: new Date(videoInfoToUpdate.scheduleUpdate.updateAt),
            privacy: videoInfoToUpdate.scheduleUpdate.privacy || null
        }, { transaction });
    }
    else if (videoInfoToUpdate.scheduleUpdate === null) {
        return schedule_video_update_1.ScheduleVideoUpdateModel.deleteByVideoId(videoInstance.id, transaction);
    }
}
//# sourceMappingURL=update.js.map