]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Add script that prunes storage files
authorChocobozzz <me@florianbigard.com>
Tue, 29 May 2018 09:11:52 +0000 (11:11 +0200)
committerChocobozzz <me@florianbigard.com>
Tue, 29 May 2018 09:11:52 +0000 (11:11 +0200)
package.json
scripts/prune-storage.ts [new file with mode: 0755]

index 5d8cbd23d573c28eb83a3f852b7e8f86580ca26b..c4ee202e19d729c0c7c892bb221c84e617524429 100644 (file)
@@ -40,6 +40,7 @@
     "help": "scripty",
     "generate-api-doc": "scripty",
     "parse-log": "node ./dist/scripts/parse-log.js",
+    "prune-storage": "node ./dist/scripts/prune-storage.js",
     "postinstall": "cd client && yarn install --pure-lockfile",
     "tsc": "tsc",
     "spectacle-docs": "node_modules/spectacle-docs/bin/spectacle.js",
diff --git a/scripts/prune-storage.ts b/scripts/prune-storage.ts
new file mode 100755 (executable)
index 0000000..1973725
--- /dev/null
@@ -0,0 +1,96 @@
+import * as prompt from 'prompt'
+import { createReadStream } from 'fs'
+import { join } from 'path'
+import { createInterface } from 'readline'
+import { readdirPromise, unlinkPromise } from '../server/helpers/core-utils'
+import { CONFIG } from '../server/initializers/constants'
+import { VideoModel } from '../server/models/video/video'
+import { initDatabaseModels } from '../server/initializers'
+
+run()
+  .then(() => process.exit(0))
+  .catch(err => {
+    console.error(err)
+    process.exit(-1)
+  })
+
+async function run () {
+  await initDatabaseModels(true)
+
+  const storageToPrune = [
+    CONFIG.STORAGE.VIDEOS_DIR,
+    CONFIG.STORAGE.PREVIEWS_DIR,
+    CONFIG.STORAGE.THUMBNAILS_DIR,
+    CONFIG.STORAGE.TORRENTS_DIR
+  ]
+
+  let toDelete: string[] = []
+  for (const directory of storageToPrune) {
+    toDelete = toDelete.concat(await pruneDirectory(directory))
+  }
+
+  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 = await askConfirmation()
+  if (res === true) {
+    console.log('Processing delete...\n')
+
+    for (const path of toDelete) {
+      await unlinkPromise(path)
+    }
+
+    console.log('Done!')
+  } else {
+    console.log('Exiting without deleting files.')
+  }
+}
+
+async function pruneDirectory (directory: string) {
+  const files = await readdirPromise(directory)
+
+  const toDelete: string[] = []
+  for (const file of files) {
+    const uuid = getUUIDFromFilename(file)
+    let video: VideoModel
+
+    if (uuid) video = await VideoModel.loadByUUID(uuid)
+
+    if (!uuid || !video) toDelete.push(join(directory, file))
+  }
+
+  return toDelete
+}
+
+function getUUIDFromFilename (filename: string) {
+  const regex = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
+  const result = filename.match(regex)
+
+  if (!result || Array.isArray(result) === false) return null
+
+  return result[0]
+}
+
+async function askConfirmation () {
+  return new Promise((res, rej) => {
+    prompt.start()
+    const schema = {
+      properties: {
+        confirm: {
+          type: 'string',
+          description: 'Are you sure you want to delete these files? Please check carefully',
+          default: 'n',
+          required: true
+        }
+      }
+    }
+    prompt.get(schema, function (err, result) {
+      if (err) return rej(err)
+      return res(result.confirm && result.confirm.match(/y/) !== null)
+    })
+  })
+}