sanitize filenames and update function

This commit is contained in:
Evert Prants 2020-09-26 09:46:08 +03:00
parent 710f1a5e48
commit 2abf4506b3
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
4 changed files with 38 additions and 24 deletions

View File

@ -25,6 +25,7 @@
"redis": "^3.0.2", "redis": "^3.0.2",
"request": "^2.88.2", "request": "^2.88.2",
"request-promise-native": "^1.0.8", "request-promise-native": "^1.0.8",
"sanitize-filename": "^1.6.3",
"socket.io": "^2.3.0", "socket.io": "^2.3.0",
"sqlite": "^4.0.9", "sqlite": "^4.0.9",
"sqlite3": "^4.2.0", "sqlite3": "^4.2.0",

View File

@ -1,9 +1,7 @@
import {exec} from 'child_process' import { exec } from 'child_process'
import path from 'path' import path from 'path'
import fs from 'fs-extra' import fs from 'fs-extra'
import url from 'url'
import os from 'os' import os from 'os'
import qs from 'querystring'
const supportedMetadata = ['album', 'genre', 'title', 'artist', 'year', 'track'] const supportedMetadata = ['album', 'genre', 'title', 'artist', 'year', 'track']
@ -41,7 +39,7 @@ function filewalker (dir, done) {
} }
async function insertDB (db, track) { 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) { if (ensure) {
return null return null
} }
@ -54,13 +52,15 @@ async function insertDB (db, track) {
} }
async function updateDB (db, id, meta) { async function updateDB (db, id, meta) {
let sanit = [] const ref = []
for (let key in meta) { const vals = []
for (const key in meta) {
if (supportedMetadata.indexOf(key) === -1) continue if (supportedMetadata.indexOf(key) === -1) continue
let val = meta[key] const val = meta[key]
sanit.push(key + '="' + val + '"') 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 return meta
} }
@ -77,7 +77,7 @@ function promiseExec (cmd, opts) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
exec(cmd, opts, function (err, stdout, stderr) { exec(cmd, opts, function (err, stdout, stderr) {
if (err) return reject(err) if (err) return reject(err)
resolve({stdout, stderr}) resolve({ stdout, stderr })
}) })
}) })
} }
@ -90,8 +90,8 @@ function askAsync (rl, q) {
function copyAsync (fsrc, fdst) { function copyAsync (fsrc, fdst) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let source = fs.createReadStream(path.resolve(fsrc)) const source = fs.createReadStream(path.resolve(fsrc))
let dest = fs.createWriteStream(path.resolve(fdst)) const dest = fs.createWriteStream(path.resolve(fdst))
source.pipe(dest) source.pipe(dest)
source.on('end', resolve) source.on('end', resolve)
@ -100,13 +100,13 @@ function copyAsync (fsrc, fdst) {
} }
async function getInfos (file) { 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) let parsed = JSON.parse(formatData.stdout)
if (!parsed || !parsed.format || !parsed.format.duration) throw new Error('Failed to parse metadata!') if (!parsed || !parsed.format || !parsed.format.duration) throw new Error('Failed to parse metadata!')
parsed = parsed.format parsed = parsed.format
let data = { const data = {
file, file,
duration: parseFloat(parsed.duration) 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 (Math.floor(data.duration) === 0) throw new Error('Invalid file type!')
if (parsed.tags) { if (parsed.tags) {
for (let k in parsed.tags) { for (const k in parsed.tags) {
let tagtype = k.toLowerCase() let tagtype = k.toLowerCase()
let value = parsed.tags[k] let value = parsed.tags[k]
@ -132,7 +132,7 @@ async function getInfos (file) {
} }
if (!data.title) { if (!data.title) {
let parsed = path.parse(file) const parsed = path.parse(file)
data.title = parsed.name data.title = parsed.name
} }
@ -140,12 +140,12 @@ async function getInfos (file) {
} }
async function setMetadata (file, meta, source, cleanup = false) { async function setMetadata (file, meta, source, cleanup = false) {
if (!meta || !meta['title'] || meta.title === '') throw new Error('Invalid metadata provided') if (!meta || !meta.title || meta.title === '') throw new Error('Invalid metadata provided')
let sanit = [] const sanit = []
let dbq = {} const dbq = {}
for (let key in meta) { for (let key in meta) {
if (supportedMetadata.indexOf(key) === -1) continue if (supportedMetadata.indexOf(key) === -1) continue
let val = meta[key] const val = meta[key]
if ((key === 'artist' || key === 'title') && (!val || val === '')) continue if ((key === 'artist' || key === 'title') && (!val || val === '')) continue
dbq[key] = val dbq[key] = val
if (key === 'year') key = 'date' 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 (!sanit.length) throw new Error('Invalid metadata provided')
if (!source) { if (!source) {
let p = path.parse(file) const p = path.parse(file)
source = path.join(os.tmpdir(), '.retmp' + p.ext) source = path.join(os.tmpdir(), '.retmp' + p.ext)
cleanup = true cleanup = true
await copyAsync(file, source) await copyAsync(file, source)
@ -171,5 +171,14 @@ async function setMetadata (file, meta, source, cleanup = false) {
return { file, dbq } return { file, dbq }
} }
export default { getFiles, promiseExec, askAsync, insertDB, updateDB, export default {
copyAsync, getInfos, setMetadata, supportedMetadata } getFiles,
promiseExec,
askAsync,
insertDB,
updateDB,
copyAsync,
getInfos,
setMetadata,
supportedMetadata
}

View File

@ -2,6 +2,7 @@
import readline from 'readline' import readline from 'readline'
import path from 'path' import path from 'path'
import sanitize from 'sanitize-filename'
import asn from './common/async' import asn from './common/async'
import dl from './common/download' import dl from './common/download'
@ -47,6 +48,7 @@ async function download (furl) {
filename = fileAnsw filename = fileAnsw
} }
filename = sanitize(filename)
const fn = path.join(musicdir, filename) const fn = path.join(musicdir, filename)
await asn.setMetadata(fn, clean, file.source, true) await asn.setMetadata(fn, clean, file.source, true)

View File

@ -1,4 +1,5 @@
import path from 'path' import path from 'path'
import sanitize from 'sanitize-filename'
import asn from './common/async' import asn from './common/async'
import dl from './common/download' import dl from './common/download'
import { dbPromise } from './database' import { dbPromise } from './database'
@ -16,7 +17,8 @@ async function downloadLocally (id) {
const info = await getTrackMetaReal(id) const info = await getTrackMetaReal(id)
if (!info) throw new Error('No track with this ID in external list.') if (!info) throw new Error('No track with this ID in external list.')
const file = await dl.fetchVideo(info) 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) 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 asn.promiseExec(`ffmpeg -i "${file.source}" -metadata artist="${info.artist}" -metadata title="${info.title}" -codec copy "${info.file}"`)
await fs.unlink(file.source) await fs.unlink(file.source)