-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
executable file
·118 lines (92 loc) · 3.31 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env node
'use strict'
const Promise = require('bluebird')
const logSymbols = require('log-symbols')
const PlexAPI = require('@hyperlink/plex-api')
const JSONPath = require('JSONPath')
const path = require('path')
const fs = Promise.promisifyAll(require('fs'))
const humanize = require('humanize')
const chalk = require('chalk')
const elegantSpinner = require('elegant-spinner')
const logUpdate = require('log-update')
const frame = elegantSpinner()
const os = require('os')
const CONFIG_PATH = os.homedir() + '/.plex-tv-cleanup-config'
try {
var config = require(CONFIG_PATH)
} catch (e) {
console.error(
logSymbols.error,
'Please create',
chalk.green(CONFIG_PATH + '.json'),
'with your configuration. See https://github.com/hyperlink/plex-tv-cleanup/blob/master/README.md#installation'
)
process.exit(1)
}
if (config.plex.homeUser) {
console.warn(`${logSymbols.warning} homeUser has been renamed to managedUser please update your config.`)
config.plex.managedUser = config.plex.homeUser
}
const dnd = config.dnd
const client = new PlexAPI({
...config.plex,
options: {
identifier: 'plex-tv-cleanup',
product: 'Plex TV Cleanup'
}
})
let spinnerIntervalId = null
function startSpinner () {
spinnerIntervalId = setInterval(() => logUpdate(frame()), 50)
}
function stopSpinner () {
clearInterval(spinnerIntervalId)
logUpdate('')
}
const dryRun = process.argv.slice(2).some(arg => arg === '--dry-run')
async function getWatchedShows (section) {
console.log(`TV URI : ${section}`)
const allShows = path.join(section, 'allLeaves')
const viewed = ep => ep.viewCount
const allEpisodes = await client.find(allShows)
const viewedEpisodes = allEpisodes.filter(viewed)
return JSONPath({ json: viewedEpisodes, path: '$..file', resultType: 'parent' }).filter(ep => !ignore(ep.file))
}
(async function () {
if (dryRun) {
console.log(logSymbols.info, 'Dry Run')
}
const tvSections = (await client.find('/library/sections', { type: 'show' })).map(section => section.uri)
if (tvSections.length === 0) {
throw new Error('No TV sections were found.')
}
const filesToDelete = [].concat.apply([], await Promise.map(tvSections, getWatchedShows))
filesToDelete.forEach(ep =>
console.log(' %s %s | %s', logSymbols.info, path.basename(ep.file), chalk.green(humanize.filesize(ep.size)))
)
const totalBytes = filesToDelete.reduce((prev, ep) => prev + ep.size, 0)
const totalEpisodes = filesToDelete.length
startSpinner()
if (!dryRun) {
try {
await Promise.map(filesToDelete, ep => fs.unlinkAsync(decodeURIComponent(ep.file)), { concurrency: 10 })
await Promise.map(tvSections, televisionSection => client.perform(path.join(televisionSection, 'refresh')))
} catch (err) {
console.error('Delete failed', err)
}
}
stopSpinner()
displaySummary()
function displaySummary () {
const wouldBe = dryRun ? chalk.yellow(' (would be)') : ''
console.log('%s Total%s deleted: %d episodes', logSymbols.success, wouldBe, totalEpisodes)
console.log('%s Space%s recovered: %s', logSymbols.success, wouldBe, chalk.green(humanize.filesize(totalBytes)))
}
})().catch(error => console.error(error))
function ignore (filepath) {
if (dnd == null) {
return false
}
return dnd.some(show => ~filepath.toLowerCase().indexOf(show.toLowerCase()))
}