diff --git a/package.json b/package.json index 97ca8a3..d7208d7 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "redis": "^3.0.2", "request": "^2.88.2", "request-promise-native": "^1.0.8", + "sanitize-filename": "^1.6.3", "socket.io": "^2.3.0", "sqlite": "^4.0.9", "sqlite3": "^4.2.0", diff --git a/src/common/async.js b/src/common/async.js index c8dd5a2..c04dc09 100644 --- a/src/common/async.js +++ b/src/common/async.js @@ -1,9 +1,7 @@ -import {exec} from 'child_process' +import { exec } from 'child_process' import path from 'path' import fs from 'fs-extra' -import url from 'url' import os from 'os' -import qs from 'querystring' const supportedMetadata = ['album', 'genre', 'title', 'artist', 'year', 'track'] @@ -41,7 +39,7 @@ function filewalker (dir, done) { } async function insertDB (db, track) { - let ensure = await db.get('SELECT * FROM Track WHERE title=? AND artist=? AND album=?', track.title, track.artist, track.album || '') + const ensure = await db.get('SELECT * FROM Track WHERE title=? AND artist=? AND album=?', track.title, track.artist, track.album || '') if (ensure) { return null } @@ -54,13 +52,15 @@ async function insertDB (db, track) { } async function updateDB (db, id, meta) { - let sanit = [] - for (let key in meta) { + const ref = [] + const vals = [] + for (const key in meta) { if (supportedMetadata.indexOf(key) === -1) continue - let val = meta[key] - sanit.push(key + '="' + val + '"') + const val = meta[key] + ref.push(key + ' = ?') + vals.push(val) } - await db.run('UPDATE Track SET ' + sanit.join(',') + ' WHERE id = ?', id) + await db.run('UPDATE Track SET ' + ref.join(',') + ' WHERE id = ?', [...vals, id]) return meta } @@ -77,7 +77,7 @@ function promiseExec (cmd, opts) { return new Promise((resolve, reject) => { exec(cmd, opts, function (err, stdout, stderr) { if (err) return reject(err) - resolve({stdout, stderr}) + resolve({ stdout, stderr }) }) }) } @@ -90,8 +90,8 @@ function askAsync (rl, q) { function copyAsync (fsrc, fdst) { return new Promise((resolve, reject) => { - let source = fs.createReadStream(path.resolve(fsrc)) - let dest = fs.createWriteStream(path.resolve(fdst)) + const source = fs.createReadStream(path.resolve(fsrc)) + const dest = fs.createWriteStream(path.resolve(fdst)) source.pipe(dest) source.on('end', resolve) @@ -100,13 +100,13 @@ function copyAsync (fsrc, fdst) { } async function getInfos (file) { - let formatData = await promiseExec(`ffprobe -i "${file}" -show_entries format -v quiet -of json`) + const formatData = await promiseExec(`ffprobe -i "${file}" -show_entries format -v quiet -of json`) let parsed = JSON.parse(formatData.stdout) if (!parsed || !parsed.format || !parsed.format.duration) throw new Error('Failed to parse metadata!') parsed = parsed.format - let data = { + const data = { file, duration: parseFloat(parsed.duration) } @@ -114,7 +114,7 @@ async function getInfos (file) { if (Math.floor(data.duration) === 0) throw new Error('Invalid file type!') if (parsed.tags) { - for (let k in parsed.tags) { + for (const k in parsed.tags) { let tagtype = k.toLowerCase() let value = parsed.tags[k] @@ -132,7 +132,7 @@ async function getInfos (file) { } if (!data.title) { - let parsed = path.parse(file) + const parsed = path.parse(file) data.title = parsed.name } @@ -140,12 +140,12 @@ async function getInfos (file) { } async function setMetadata (file, meta, source, cleanup = false) { - if (!meta || !meta['title'] || meta.title === '') throw new Error('Invalid metadata provided') - let sanit = [] - let dbq = {} + if (!meta || !meta.title || meta.title === '') throw new Error('Invalid metadata provided') + const sanit = [] + const dbq = {} for (let key in meta) { if (supportedMetadata.indexOf(key) === -1) continue - let val = meta[key] + const val = meta[key] if ((key === 'artist' || key === 'title') && (!val || val === '')) continue dbq[key] = val if (key === 'year') key = 'date' @@ -155,7 +155,7 @@ async function setMetadata (file, meta, source, cleanup = false) { if (!sanit.length) throw new Error('Invalid metadata provided') if (!source) { - let p = path.parse(file) + const p = path.parse(file) source = path.join(os.tmpdir(), '.retmp' + p.ext) cleanup = true await copyAsync(file, source) @@ -171,5 +171,14 @@ async function setMetadata (file, meta, source, cleanup = false) { return { file, dbq } } -export default { getFiles, promiseExec, askAsync, insertDB, updateDB, - copyAsync, getInfos, setMetadata, supportedMetadata } +export default { + getFiles, + promiseExec, + askAsync, + insertDB, + updateDB, + copyAsync, + getInfos, + setMetadata, + supportedMetadata +} diff --git a/src/download.js b/src/download.js index 2feb0cf..025ccb9 100644 --- a/src/download.js +++ b/src/download.js @@ -2,6 +2,7 @@ import readline from 'readline' import path from 'path' +import sanitize from 'sanitize-filename' import asn from './common/async' import dl from './common/download' @@ -47,6 +48,7 @@ async function download (furl) { filename = fileAnsw } + filename = sanitize(filename) const fn = path.join(musicdir, filename) await asn.setMetadata(fn, clean, file.source, true) diff --git a/src/external.js b/src/external.js index 6a545fa..38acb39 100644 --- a/src/external.js +++ b/src/external.js @@ -1,4 +1,5 @@ import path from 'path' +import sanitize from 'sanitize-filename' import asn from './common/async' import dl from './common/download' import { dbPromise } from './database' @@ -16,7 +17,8 @@ async function downloadLocally (id) { const info = await getTrackMetaReal(id) if (!info) throw new Error('No track with this ID in external list.') const file = await dl.fetchVideo(info) - const filename = info.artist + ' - ' + info.title + '.mp3' + let filename = info.artist + ' - ' + info.title + '.mp3' + filename = sanitize(filename) info.file = path.join(values.directory, filename) await asn.promiseExec(`ffmpeg -i "${file.source}" -metadata artist="${info.artist}" -metadata title="${info.title}" -codec copy "${info.file}"`) await fs.unlink(file.source)