'use strict'; const inquirer = require('inquirer'); const logger = require('./logger')(__filename); const knex = require('./knex'); const argv = require('./argv'); const { updateSceneSearch } = require('./update-search'); const { flushOrphanedMedia } = require('./media'); function curateRelease(release, withMedia = false, withPoster = true) { if (!release) { return null; } return { id: release.id, ...(release.relevance && { relevance: release.relevance }), entryId: release.entry_id, shootId: release.shoot_id, title: release.title, url: release.url, date: release.date, description: release.description, duration: release.duration, entity: release.entity && { id: release.entity.id, name: release.entity.name, slug: release.entity.slug, parent: release.parent && { id: release.parent.id, name: release.parent.name, slug: release.parent.slug, }, }, actors: (release.actors || []).map((actor) => ({ id: actor.id, name: actor.name, slug: actor.slug, gender: actor.gender, entityId: actor.entity_id, aliasFor: actor.alias_for, })), tags: (release.tags || []).map((tag) => ({ id: tag.id, name: tag.name, slug: tag.slug, })), chapters: (release.chapters || []).map((chapter) => ({ id: chapter.id, index: chapter.index, time: chapter.time, duration: chapter.duration, title: chapter.title, description: chapter.description, })), ...((withMedia || withPoster) && { poster: release.poster ? { id: release.poster.id, path: release.poster.path, thumbnail: release.poster.thumbnail, width: release.poster.width, height: release.poster.height, size: release.poster.size, } : null, }), ...(withMedia && { photos: (release.photos || []).map((photo) => ({ id: photo.id, path: photo.path, thumbnail: release.poster.thumbnail, width: photo.width, height: photo.height, size: photo.size, })), trailer: release.trailer ? { id: release.trailer.id, path: release.trailer.path, } : null, }), createdAt: release.created_at, }; } async function deleteScenes(sceneIds) { if (sceneIds.length === 0) { return 0; } // there can be too many scene IDs for where in, causing a stack depth error const deleteCount = await knex('releases') .whereRaw('id = ANY(:sceneIds)', { sceneIds }) .delete(); await updateSceneSearch(sceneIds); logger.info(`Removed ${deleteCount}/${sceneIds.length} scenes`); return deleteCount; } async function deleteMovies(movieIds) { if (movieIds.length === 0) { return 0; } await knex('movies_scenes') .whereIn('movie_id', movieIds) .delete(); const deleteCount = await knex('movies') .whereIn('id', movieIds) .delete(); logger.info(`Removed ${deleteCount}/${movieIds.length} movies`); return deleteCount; } async function deleteSeries(serieIds) { if (serieIds.length === 0) { return 0; } await knex('series_scenes') .whereIn('serie_id', serieIds) .delete(); const deleteCount = await knex('series') .whereIn('id', serieIds) .delete(); logger.info(`Removed ${deleteCount}/${serieIds.length} series`); return deleteCount; } async function flushScenes() { const sceneIds = await knex('releases') .select('id') .modify((builder) => { if (argv.flushAfter) { builder.where('effective_date', '>=', argv.flushAfter); } if (argv.flushBefore) { builder.where('effective_date', '<=', argv.flushBefore); } }) .pluck('id'); const confirmed = await inquirer.prompt([{ type: 'confirm', name: 'flushScenes', message: `You are about to remove ${sceneIds.length} scenes. Are you sure?`, default: false, }]); if (!confirmed.flushScenes) { logger.warn('Confirmation rejected, not flushing scenes'); return; } const deleteCount = await deleteScenes(sceneIds); if (argv.flushOrphanedMedia !== false) { await flushOrphanedMedia(); } logger.info(`Removed ${deleteCount}/${sceneIds.length} scenes`); } async function flushMovies() { const movieIds = await knex('movies').select('id').pluck('id'); const confirmed = await inquirer.prompt([{ type: 'confirm', name: 'flushMovies', message: `You are about to remove ${movieIds.length} movies. Are you sure?`, default: false, }]); if (!confirmed.flushMovies) { logger.warn('Confirmation rejected, not flushing movies'); return; } const deleteCount = await deleteMovies(movieIds); if (argv.flushOrphanedMedia !== false) { await flushOrphanedMedia(); } logger.info(`Removed ${deleteCount}/${movieIds.length} movies`); } async function flushSeries() { const serieIds = await knex('series').select('id').pluck('id'); const confirmed = await inquirer.prompt([{ type: 'confirm', name: 'flushSeries', message: `You are about to remove ${serieIds.length} series. Are you sure?`, default: false, }]); if (!confirmed.flushSeries) { logger.warn('Confirmation rejected, not flushing series'); return; } const deleteCount = await deleteSeries(serieIds); if (argv.flushOrphanedMedia !== false) { await flushOrphanedMedia(); } logger.info(`Removed ${deleteCount}/${serieIds.length} series`); } async function flushBatches(batchIds) { const [sceneIds, movieIds] = await Promise.all([ knex('releases') .select('releases.id') .whereIn('created_batch_id', batchIds) .modify((builder) => { if (argv.flushAfter) { builder.where('effective_date', '>=', argv.flushAfter); } if (argv.flushBefore) { builder.where('effective_date', '<=', argv.flushBefore); } }) .pluck('releases.id'), knex('movies').whereIn('created_batch_id', batchIds) .select('movies.id') .whereIn('created_batch_id', batchIds) .modify((builder) => { if (argv.flushAfter) { builder.where('effective_date', '>=', argv.flushAfter); } if (argv.flushBefore) { builder.where('effective_date', '<=', argv.flushBefore); } }) .pluck('movies.id'), ]); const confirmed = await inquirer.prompt([{ type: 'confirm', name: 'flushBatches', message: `You are about to remove ${sceneIds.length} scenes and ${movieIds.length} movies from batches ${batchIds}. Are you sure?`, default: false, }]); if (!confirmed.flushBatches) { logger.warn(`Confirmation rejected, not flushing scenes or movies for batches ${batchIds}`); return; } const [deletedScenesCount, deletedMoviesCount] = await Promise.all([ deleteScenes(sceneIds), deleteMovies(movieIds), ]); logger.info(`Removed ${deletedScenesCount} scenes and ${deletedMoviesCount} movies for batches ${batchIds}`); if (argv.flushOrphanedMedia !== false) { await flushOrphanedMedia(); } } module.exports = { curateRelease, flushBatches, flushMovies, flushSeries, flushScenes, deleteScenes, deleteMovies, deleteSeries, };