From 6751f38ee365aa46bf53de0f9a09b91309bed377 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Sun, 27 Jan 2019 00:35:09 +0200 Subject: [PATCH] track download from web interface --- src/common/download.js | 2 +- src/lastfm.js | 49 +++++++++++++++++++++++++++++++++++++++--- src/server.js | 8 ++++++- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/common/download.js b/src/common/download.js index cefd1d7..c8d6393 100644 --- a/src/common/download.js +++ b/src/common/download.js @@ -58,7 +58,7 @@ function getVideoInfo (arg) { function fetchVideo (data) { return new Promise((resolve, reject) => { let tempName = path.join(process.cwd(), `/tmp.yt.${data.id}.mp3`) - ffmpeg(data.url) + ffmpeg(data.url || data.file) .audioCodec('libmp3lame') .format('mp3') .on('error', reject) diff --git a/src/lastfm.js b/src/lastfm.js index e637e4b..22a45c8 100644 --- a/src/lastfm.js +++ b/src/lastfm.js @@ -1,11 +1,15 @@ import path from 'path' -import as from './common/async' +import asn from './common/async' import dl from './common/download' import crypto from 'crypto' +const fs = require('fs').promises const values = require(path.join(process.cwd(), 'values.json')) let externalTracks = {} +let downloadQueue = [] +let downloading = false +let dbPromise function createHash (data) { return crypto @@ -15,6 +19,21 @@ function createHash (data) { .substr(0, 8) } +async function downloadLocally (id) { + let info = await getTrackMetaReal(id) + if (!info) throw new Error('No track with this ID in external list.') + let file = await dl.fetchVideo(info) + let filename = info.artist + ' - ' + info.title + '.mp3' + 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) + let db = await dbPromise + let ins = await asn.insertDB(db, info) + if (!ins) { + throw new Error('A track of this description already exists in the database.') + } +} + async function getTrackMetaReal (id) { if (!id || !externalTracks[id]) return null let trdata = externalTracks[id] @@ -40,7 +59,7 @@ async function search (track, limit = 30) { let data try { - data = await as.GET(`http://ws.audioscrobbler.com/2.0/?method=track.search&track=${track}&api_key=${values.lastfm}&format=json&limit=${limit}`) + data = await asn.GET(`http://ws.audioscrobbler.com/2.0/?method=track.search&track=${track}&api_key=${values.lastfm}&format=json&limit=${limit}`) data = JSON.parse(data) if (!data.results || !data.results.trackmatches || !data.results.trackmatches.track) { @@ -74,4 +93,28 @@ async function search (track, limit = 30) { return final } -export default {search, getTrackMetaReal} +// Download thread +let dltd = null +function invokeDownload (add) { + if (add) downloadQueue.push(add) + if (dltd) return + dltd = setTimeout(function (argument) { + dltd = null + if (downloading) return invokeDownload() + if (!downloadQueue.length) return + downloading = true + downloadLocally(downloadQueue.shift()).then(() => { + downloading = false + if (downloadQueue.length) invokeDownload() + }).catch((e) => { + console.error(e) + downloading = false + if (downloadQueue.length) invokeDownload() + }) + }, 2 * 1000) +} + +export default function (db) { + dbPromise = db + return { search, getTrackMetaReal, invokeDownload } +} diff --git a/src/server.js b/src/server.js index 2c61bd5..55f192f 100644 --- a/src/server.js +++ b/src/server.js @@ -6,7 +6,7 @@ import http from 'http' import https from 'https' import ffmpeg from 'fluent-ffmpeg' -import lastfm from './lastfm' +import lfmda from './lastfm' import remote from './remote-control' require('express-async-errors') @@ -24,6 +24,8 @@ const port = process.env.PORT || 3000 const dev = process.env.NODE_ENV === 'development' const server = http.createServer(app) +const lastfm = lfmda(dbPromise) + if (dev) { const morgan = require('morgan') app.use(morgan('dev')) @@ -192,6 +194,10 @@ router.get('/serve/by-id/:id', async (req, res, next) => { if (!track) { track = await lastfm.getTrackMetaReal(id) if (!track) return next(new Error('404 file not found')) + if (dl) { + lastfm.invokeDownload(id) + return res.end('

OK

') + } return ffmpeg(track.file) .audioCodec('libmp3lame') .format('mp3')