"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const bluebird_1 = require("bluebird");
const fs_extra_1 = require("fs-extra");
const lodash_1 = require("lodash");
const path_1 = require("path");
const prompt_1 = require("prompt");
const constants_1 = require("../server/initializers/constants");
const video_file_1 = require("../server/models/video/video-file");
const video_streaming_playlist_1 = require("../server/models/video/video-streaming-playlist");
const utils_1 = require("../server/helpers/utils");
const config_1 = require("../server/initializers/config");
const database_1 = require("../server/initializers/database");
const actor_image_1 = require("../server/models/actor/actor-image");
const video_redundancy_1 = require("../server/models/redundancy/video-redundancy");
const thumbnail_1 = require("../server/models/video/thumbnail");
const video_1 = require("../server/models/video/video");
run()
    .then(() => process.exit(0))
    .catch(err => {
    console.error(err);
    process.exit(-1);
});
function run() {
    return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
        const dirs = (0, lodash_1.values)(config_1.CONFIG.STORAGE);
        if ((0, lodash_1.uniq)(dirs).length !== dirs.length) {
            console.error('Cannot prune storage because you put multiple storage keys in the same directory.');
            process.exit(0);
        }
        yield (0, database_1.initDatabaseModels)(true);
        let toDelete = [];
        console.log('Detecting files to remove, it could take a while...');
        toDelete = toDelete.concat(yield pruneDirectory(config_1.CONFIG.STORAGE.VIDEOS_DIR, doesWebTorrentFileExist()), yield pruneDirectory(constants_1.HLS_STREAMING_PLAYLIST_DIRECTORY, doesHLSPlaylistExist()), yield pruneDirectory(config_1.CONFIG.STORAGE.TORRENTS_DIR, doesTorrentFileExist()), yield pruneDirectory(config_1.CONFIG.STORAGE.REDUNDANCY_DIR, doesRedundancyExist), yield pruneDirectory(config_1.CONFIG.STORAGE.PREVIEWS_DIR, doesThumbnailExist(true, 2)), yield pruneDirectory(config_1.CONFIG.STORAGE.THUMBNAILS_DIR, doesThumbnailExist(false, 1)), yield pruneDirectory(config_1.CONFIG.STORAGE.ACTOR_IMAGES, doesActorImageExist));
        const tmpFiles = yield (0, fs_extra_1.readdir)(config_1.CONFIG.STORAGE.TMP_DIR);
        toDelete = toDelete.concat(tmpFiles.map(t => (0, path_1.join)(config_1.CONFIG.STORAGE.TMP_DIR, t)));
        if (toDelete.length === 0) {
            console.log('No files to delete.');
            return;
        }
        console.log('Will delete %d files:\n\n%s\n\n', toDelete.length, toDelete.join('\n'));
        const res = yield askConfirmation();
        if (res === true) {
            console.log('Processing delete...\n');
            for (const path of toDelete) {
                yield (0, fs_extra_1.remove)(path);
            }
            console.log('Done!');
        }
        else {
            console.log('Exiting without deleting files.');
        }
    });
}
function pruneDirectory(directory, existFun) {
    return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
        const files = yield (0, fs_extra_1.readdir)(directory);
        const toDelete = [];
        yield (0, bluebird_1.map)(files, (file) => (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
            const filePath = (0, path_1.join)(directory, file);
            if ((yield existFun(filePath)) !== true) {
                toDelete.push(filePath);
            }
        }), { concurrency: 20 });
        return toDelete;
    });
}
function doesWebTorrentFileExist() {
    return (filePath) => video_file_1.VideoFileModel.doesOwnedWebTorrentVideoFileExist((0, path_1.basename)(filePath));
}
function doesHLSPlaylistExist() {
    return (hlsPath) => video_streaming_playlist_1.VideoStreamingPlaylistModel.doesOwnedHLSPlaylistExist((0, path_1.basename)(hlsPath));
}
function doesTorrentFileExist() {
    return (filePath) => video_file_1.VideoFileModel.doesOwnedTorrentFileExist((0, path_1.basename)(filePath));
}
function doesThumbnailExist(keepOnlyOwned, type) {
    return (filePath) => (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
        const thumbnail = yield thumbnail_1.ThumbnailModel.loadByFilename((0, path_1.basename)(filePath), type);
        if (!thumbnail)
            return false;
        if (keepOnlyOwned) {
            const video = yield video_1.VideoModel.load(thumbnail.videoId);
            if (video.isOwned() === false)
                return false;
        }
        return true;
    });
}
function doesActorImageExist(filePath) {
    return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
        const image = yield actor_image_1.ActorImageModel.loadByName((0, path_1.basename)(filePath));
        return !!image;
    });
}
function doesRedundancyExist(filePath) {
    return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
        const isPlaylist = (yield (0, fs_extra_1.stat)(filePath)).isDirectory();
        if (isPlaylist) {
            if (filePath === constants_1.HLS_REDUNDANCY_DIRECTORY)
                return true;
            const uuid = (0, utils_1.getUUIDFromFilename)(filePath);
            const video = yield video_1.VideoModel.loadWithFiles(uuid);
            if (!video)
                return false;
            const p = video.getHLSPlaylist();
            if (!p)
                return false;
            const redundancy = yield video_redundancy_1.VideoRedundancyModel.loadLocalByStreamingPlaylistId(p.id);
            return !!redundancy;
        }
        const file = yield video_file_1.VideoFileModel.loadByFilename((0, path_1.basename)(filePath));
        if (!file)
            return false;
        const redundancy = yield video_redundancy_1.VideoRedundancyModel.loadLocalByFileId(file.id);
        return !!redundancy;
    });
}
function askConfirmation() {
    return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
        return new Promise((res, rej) => {
            (0, prompt_1.start)();
            const schema = {
                properties: {
                    confirm: {
                        type: 'string',
                        description: 'These following unused files can be deleted, but please check your backups first (bugs happen).' +
                            ' Notice PeerTube must have been stopped when your ran this script.' +
                            ' Can we delete these files?',
                        default: 'n',
                        required: true
                    }
                }
            };
            (0, prompt_1.get)(schema, function (err, result) {
                var _a;
                if (err)
                    return rej(err);
                return res(((_a = result.confirm) === null || _a === void 0 ? void 0 : _a.match(/y/)) !== null);
            });
        });
    });
}
//# sourceMappingURL=prune-storage.js.map