diff options
-rw-r--r-- | crawl-recursive.js | 22 | ||||
-rw-r--r-- | package.json | 3 | ||||
-rw-r--r-- | src/loop-play.js | 4 | ||||
-rw-r--r-- | src/play.js | 35 | ||||
-rw-r--r-- | src/playlist-utils.js | 56 | ||||
-rw-r--r-- | src/process-argv.js | 2 | ||||
-rw-r--r-- | src/promisify-process.js | 5 | ||||
-rw-r--r-- | todo.txt | 2 | ||||
-rw-r--r-- | yarn.lock | 9 |
9 files changed, 82 insertions, 56 deletions
diff --git a/crawl-recursive.js b/crawl-recursive.js index d3b0127..d53f7d1 100644 --- a/crawl-recursive.js +++ b/crawl-recursive.js @@ -3,6 +3,7 @@ const MAX_DOWNLOAD_ATTEMPTS = 5 const fetch = require('node-fetch') +const $ = require('cheerio') function crawl(absURL, attempts = 0) { // Recursively crawls a given URL, following every link to a deeper path and @@ -21,33 +22,34 @@ function crawl(absURL, attempts = 0) { if (href.endsWith('/')) { // It's a directory! - if (verbose) console.log('[Dir] ' + absURL + href) + if (verbose) console.log("[Dir] " + absURL + href) return crawl(absURL + href) .then(res => [title, res]) } else { // It's a file! - if (verbose) console.log('[File] ' + absURL + href) + if (verbose) console.log("[File] " + absURL + href) return Promise.resolve([title, absURL + href]) } })) }), err => { - console.error('Failed to download: ' + absURL) + console.warn("Failed to download: " + absURL) if (attempts < MAX_DOWNLOAD_ATTEMPTS) { - console.error( - 'Trying again. Attempt ' + (attempts + 1) + - '/' + MAX_DOWNLOAD_ATTEMPTS + '...' + console.warn( + "Trying again. Attempt " + (attempts + 1) + + "/" + MAX_DOWNLOAD_ATTEMPTS + "..." ) + return crawl(absURL, attempts + 1) } else { console.error( - 'We\'ve hit the download attempt limit (' + - MAX_DOWNLOAD_ATTEMPTS + '). Giving up on ' + - 'this path.' + "We've hit the download attempt limit (" + + MAX_DOWNLOAD_ATTEMPTS + "). Giving up on this path." ) + throw 'FAILED_DOWNLOAD' } } @@ -72,7 +74,7 @@ function getHTMLLinks(text) { } if (process.argv.length === 2) { - console.log('Usage: crawl-recursive http://example.com/example/path') + console.log("Usage: crawl-recursive http://example.com/example/path") } else { let url = process.argv[2] diff --git a/package.json b/package.json index 4af34d5..5efd88e 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,7 @@ { + "name": "http-music", + "version": "0.0.1", + "main": "src/play.js", "dependencies": { "cheerio": "^1.0.0-rc.1", "node-fetch": "^1.7.0", diff --git a/src/loop-play.js b/src/loop-play.js index e59fbc2..48b5790 100644 --- a/src/loop-play.js +++ b/src/loop-play.js @@ -37,8 +37,8 @@ module.exports = async function loopPlay(fn) { try { await convert('./.temp-track', wavFile) } catch(err) { - console.warn('Failed to convert ' + title) - console.warn('Selecting a new track\n') + console.warn("Failed to convert " + title) + console.warn("Selecting a new track\n") return await downloadNext() } diff --git a/src/play.js b/src/play.js index 9b9a5cf..5e3e04b 100644 --- a/src/play.js +++ b/src/play.js @@ -8,7 +8,7 @@ const processArgv = require('./process-argv') const pickers = require('./pickers') const { - filterPlaylistByPathString, ignoreGroupByPathString, getPlaylistTreeString + filterPlaylistByPathString, removeGroupByPathString, getPlaylistTreeString } = require('./playlist-utils') const readFile = promisify(fs.readFile) @@ -56,7 +56,7 @@ readFile('./playlist.json', 'utf-8') // Keeps a group by loading it from the source playlist into the // active playlist. This is usually useful after clearing the // active playlist; it can also be used to keep a subgroup when - // you've ignored an entire parent group, e.g. `-i foo -k foo/baz`. + // you've removed an entire parent group, e.g. `-r foo -k foo/baz`. const pathString = util.nextArg() const group = filterPlaylistByPathString(sourcePlaylist, pathString) @@ -65,16 +65,17 @@ readFile('./playlist.json', 'utf-8') 'k': util => util.alias('-keep'), - '-ignore': function(util) { - // --ignore <groupPath> (alias: -i) + '-remove': function(util) { + // --remove <groupPath> (alias: -r, -x) // Filters the playlist so that the given path is removed. const pathString = util.nextArg() - console.log('Ignoring path: ' + pathString) - ignoreGroupByPathString(curPlaylist, pathString) + console.log("Ignoring path: " + pathString) + removeGroupByPathString(curPlaylist, pathString) }, - 'i': util => util.alias('-ignore'), + 'r': util => util.alias('-remove'), + 'x': util => util.alias('-remove'), '-list-groups': function(util) { // --list-groups (alias: -l, --list) @@ -127,13 +128,6 @@ readFile('./playlist.json', 'utf-8') 'np': util => util.alias('-no-play'), - '-debug-list': function(util) { - // --debug-list - // Prints out the JSON representation of the active playlist. - - console.log(JSON.stringify(curPlaylist, null, 2)) - }, - '-picker': function(util) { // --picker <shuffle|ordered> // Selects the mode that the song to play is picked. @@ -141,19 +135,26 @@ readFile('./playlist.json', 'utf-8') // playlist. pickerType = util.nextArg() + }, + + '-debug-list': function(util) { + // --debug-list + // Prints out the JSON representation of the active playlist. + + console.log(JSON.stringify(curPlaylist, null, 2)) } }) if (willPlay || (willPlay === null && shouldPlay)) { let picker if (pickerType === 'shuffle') { - console.log('Using shuffle picker') + console.log("Using shuffle picker.") picker = pickers.makeShufflePlaylistPicker(curPlaylist) } else if (pickerType === 'ordered') { - console.log('Using ordered picker') + console.log("Using ordered picker.") picker = pickers.makeOrderedPlaylistPicker(curPlaylist) } else { - console.error('Invalid picker type: ' + pickerType) + console.error("Invalid picker type: " + pickerType) } return loopPlay(picker) diff --git a/src/playlist-utils.js b/src/playlist-utils.js index 5266f1a..f65e247 100644 --- a/src/playlist-utils.js +++ b/src/playlist-utils.js @@ -5,9 +5,10 @@ function flattenPlaylist(playlist) { // levels in the playlist tree and returns them as a single-level array of // tracks. - const groups = playlist.filter(x => Array.isArray(x[1])) - const nonGroups = playlist.filter(x => x[1] && !(Array.isArray(x[1]))) - return groups.map(g => flattenPlaylist(g[1])) + const groups = playlist.filter(x => isGroup(x)) + const nonGroups = playlist.filter(x => !isGroup(x)) + + return groups.map(g => flattenPlaylist(getGroupContents(g))) .reduce((a, b) => a.concat(b), nonGroups) } @@ -25,13 +26,15 @@ function filterPlaylistByPath(playlist, pathParts) { let cur = pathParts[0] - const match = playlist.find(g => g[0] === cur || g[0] === cur + '/') + const match = playlist.find(group => { + const title = getGroupTitle(group) + return title === cur || title === cur + '/' + }) if (match) { - const groupContents = match[1] if (pathParts.length > 1) { const rest = pathParts.slice(1) - return filterPlaylistByPath(groupContents, rest) + return filterPlaylistByPath(getGroupContents(match), rest) } else { return match } @@ -58,7 +61,7 @@ function removeGroupByPath(playlist, pathParts) { if (parentPath.length === 0) { parent = playlist } else { - parent = filterPlaylistByPath(playlist, pathParts.slice(0, -1)) + parent = getGroupContents(filterPlaylistByPath(playlist, parentPath)) } const index = parent.indexOf(groupToRemove) @@ -67,31 +70,32 @@ function removeGroupByPath(playlist, pathParts) { parent.splice(index, 1) } else { console.error( - 'Group ' + pathParts.join('/') + ' doesn\'t exist, so we can\'t ' + - 'explicitly ignore it.' + `Group ${pathParts.join('/')} doesn't exist, so we can't explicitly ` + + "ignore it." ) } } function getPlaylistTreeString(playlist, showTracks = false) { function recursive(group) { - const groups = group.filter(x => Array.isArray(x[1])) - const nonGroups = group.filter(x => x[1] && !(Array.isArray(x[1]))) + const groups = group.filter(x => isGroup(x)) + const nonGroups = group.filter(x => !isGroup(x)) - const childrenString = groups.map(g => { - const groupString = recursive(g[1]) + const childrenString = groups.map(group => { + const title = getGroupTitle(group) + const groupString = recursive(getGroupContents(group)) if (groupString) { const indented = groupString.split('\n').map(l => '| ' + l).join('\n') - return '\n' + g[0] + '\n' + indented + return '\n' + title + '\n' + indented } else { - return g[0] + return title } }).join('\n') - let trackString = '' + let tracksString = '' if (showTracks) { - trackString = nonGroups.map(g => g[0]).join('\n') + tracksString = nonGroups.map(g => getGroupTitle(g)).join('\n') } if (tracksString && childrenString) { @@ -113,9 +117,23 @@ function parsePathString(pathString) { return pathParts } +function getGroupTitle(group) { + return group[0] +} + +function getGroupContents(group) { + return group[1] +} + +function isGroup(array) { + return Array.isArray(array[1]) +} + module.exports = { flattenPlaylist, filterPlaylistByPathString, filterPlaylistByPath, - ignoreGroupByPathString, ignoreGroupByPath, - parsePathString + removeGroupByPathString, removeGroupByPath, + getPlaylistTreeString, + parsePathString, + getGroupTitle, getGroupContents } diff --git a/src/process-argv.js b/src/process-argv.js index d5f86f9..201f927 100644 --- a/src/process-argv.js +++ b/src/process-argv.js @@ -34,7 +34,7 @@ module.exports = async function processArgv(argv, handlers) { } }) } else { - console.warn('Option not understood: ' + opt) + console.warn("Option not understood: " + opt) } } diff --git a/src/promisify-process.js b/src/promisify-process.js index ca49b31..ef8d0c6 100644 --- a/src/promisify-process.js +++ b/src/promisify-process.js @@ -2,7 +2,8 @@ module.exports = function promisifyProcess(proc, showLogging = true) { // Takes a process (from child_process) and returns a promise that resolves - // when the process exits. + // when the process exits (or rejects with a warning, if the exit code is + // non-zero). return new Promise((resolve, reject) => { if (showLogging) { @@ -14,7 +15,7 @@ module.exports = function promisifyProcess(proc, showLogging = true) { if (code === 0) { resolve() } else { - console.error('Process failed!', proc.spawnargs) + console.error("Process failed!", proc.spawnargs) reject(code) } }) diff --git a/todo.txt b/todo.txt index cf984fc..3c62c68 100644 --- a/todo.txt +++ b/todo.txt @@ -67,3 +67,5 @@ TODO: Play-in-order track picker. TODO: Volume controls. Who knows how to do this? It might have to be an argument passed to `play`. Being able to change the volume while it's playing would be nice, but I'm not sure if that's really possible. + +TODO: Tempfiles, maybe? diff --git a/yarn.lock b/yarn.lock index 4f46d69..c18f89b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,7 +1,5 @@ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 - - "@types/node@^6.0.46": version "6.0.73" resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.73.tgz#85dc4bb6f125377c75ddd2519a1eeb63f0a4ed70" @@ -42,14 +40,14 @@ css-what@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" -dom-serializer@0, dom-serializer@~0.1.0: +dom-serializer@~0.1.0, dom-serializer@0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" dependencies: domelementtype "~1.1.1" entities "~1.1.1" -domelementtype@1, domelementtype@^1.3.0: +domelementtype@^1.3.0, domelementtype@1: version "1.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" @@ -63,7 +61,7 @@ domhandler@^2.3.0: dependencies: domelementtype "1" -domutils@1.5.1, domutils@^1.5.1: +domutils@^1.5.1, domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" dependencies: @@ -175,3 +173,4 @@ utf8-byte-length@^1.0.1: util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + |