Created
November 27, 2011 14:29
-
-
Save adammw/1397625 to your computer and use it in GitHub Desktop.
SoundCloud CLI Downloader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* CLI Tool to download streamable songs from SoundCloud API | |
* Requires Node.js, Flow-JS and cli libraries | |
*/ | |
var cli = require('cli').enable('status'), | |
fs = require('fs'), | |
flow = require('flow'), | |
path = require('path'), | |
SC = require('./node-soundcloud.js'); | |
SC.initialize({ | |
client_id: "00000000000000000000000000000000" // Replace this with your client ID | |
}); | |
cli.parse({ | |
tag: ['t', 'Restrict to tag', 'string', null], | |
outdir: ['D', 'Directory to download files to', 'dir', '.'], | |
max: ['n', 'Number of files to download', 'num', 10] | |
}); | |
cli.main(function(args, options) { | |
cli.debug("Downloading track listing"); | |
flow.exec( | |
function() { | |
// Get the track listing | |
SC.get('/tracks', {limit: options.max, filter: 'streamable', order: 'hotness', tags: options.tag}, this); | |
}, | |
function(tracks, error) { | |
if (error) { | |
cli.fatal(error.message); | |
} | |
// Download each track sequentially | |
flow.serialForEach(tracks, | |
function(track) { | |
cli.info("Downloading \"" + track.title + "\" by " + track.user.username); | |
cli.debug("Stream url is: " + track.stream_url); | |
var outpath = path.join(options.outdir, (track.user.username + " - " + track.title + ".mp3").replace(/[\/\\:]/g,'')); | |
var nextTrack = this; | |
flow.exec( | |
function() { | |
// Check if the file has already been downloaded (already exists) | |
path.exists(outpath, this); | |
}, | |
function(exists) { | |
// If it exists, get the file size and do a HEAD request on the file to be downloaded | |
if (exists) { | |
fs.stat(outpath, this.MULTI()); | |
SC.stream(track.stream_url, this.MULTI(), 'HEAD'); | |
} else { | |
return this(); | |
} | |
}, | |
function(args) { | |
// If we have the stats and response, check if the file sizes match | |
if (args && args.length == 2 && args[0].length >= 2 && args[1].length >= 1) { | |
var stats = args[0][1]; | |
var res = args[1][0]; | |
if (args.length == 2 && res.headers['content-length'] && stats.size && stats.size >= res.headers['content-length']) { | |
cli.info("Track already downloaded fully, skipping..."); | |
return nextTrack(); | |
} | |
} | |
// Otherwise, download the track | |
SC.stream(track.stream_url, this); | |
}, | |
function(res) { | |
var callback = this; | |
var file = fs.createWriteStream(outpath); | |
res.pipe(file); | |
if (res.headers['content-length']) { | |
res.on('data', function(chunk) { | |
cli.progress(file.bytesWritten / res.headers['content-length']); | |
}); | |
} | |
res.on('end', function() { | |
cli.progress(1) | |
cli.ok('Download Complete!'); | |
callback(); | |
}); | |
}, | |
nextTrack | |
); | |
} | |
); | |
} | |
); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var http = require('http'), | |
querystring = require('querystring'), | |
url = require('url'); | |
const SOUNDCLOUD_HOST = 'api.soundcloud.com'; | |
const SOUNDCLOUD_PORT = 80; | |
var SC = module.exports = {}; | |
SC.initialize = function(options) { | |
SC._config = options; | |
}; | |
SC.get = function(path, params, callback) { | |
var httpopts = (typeof path == "string") ? url.parse(path, true) : path; | |
if (typeof params == "function") { | |
callback = params; | |
params = {}; | |
} | |
for (var i in params) { | |
httpopts.query[i] = params[i]; | |
} | |
httpopts.query.client_id = SC._config.client_id; | |
httpopts.host = SOUNDCLOUD_HOST; | |
httpopts.port = SOUNDCLOUD_PORT; | |
httpopts.path = httpopts.pathname + ".json?" + querystring.stringify(httpopts.query); | |
var req = http.get(httpopts, function(res) { | |
var buffer = ""; | |
res.on('data', function(chunk) { | |
buffer += chunk; | |
}); | |
res.on('end', function() { | |
try { | |
var data = JSON.parse(buffer); | |
callback.call(data, data, null); | |
} catch (e) { | |
callback.call(null, null, e); | |
} | |
}); | |
}); | |
req.on('error', function(e) { | |
callback.call(null, null, e); | |
}); | |
}; | |
SC.stream = function(stream_url, callback, method) { | |
var httpopts = (typeof stream_url == "string") ? url.parse(stream_url, true) : stream_url; | |
httpopts.query.client_id = SC._config.client_id; | |
httpopts.path = httpopts.pathname + "?" + querystring.stringify(httpopts.query); | |
httpopts.method = method || "GET"; | |
(function request(httpopts) { | |
var req = http.get(httpopts, function(res) { | |
if (res.headers.location) { | |
httpopts = url.parse(res.headers.location); | |
httpopts.method = method || "GET"; | |
request(httpopts); | |
} else { | |
callback.call(res, res, null); | |
} | |
}); | |
req.on('error', function(e) { | |
callback.call(null, null, e); | |
}); | |
})(httpopts); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* If you want to download in parallel without the flow library, try: | |
for (var i in tracks) { | |
var track = tracks[i]; | |
var totalsize = 0; | |
var byteswritten = 0; | |
SC.stream(track.stream_url, function(res) { | |
if (res.headers['content-length'] && path.existsSync(outpath) && path.statSync(outpath).size >= res.headers['content-length']) { | |
cli.info("Track already downloaded fully, skipping..."); | |
// Note that we can't really stop the download - we are wasting the data by ignoring it | |
} else { | |
var file = fs.createWriteStream(outpath); | |
res.pipe(file); | |
if (res.headers['content-length']) { | |
totalsize += parseInt(res.headers['content-length']); | |
var lastbyteswritten = 0; | |
var lastdelta = 0; | |
res.on('data', function(chunk) { | |
lastdelta = (file.bytesWritten - lastbyteswritten); | |
byteswritten += lastdelta; | |
cli.progress(byteswritten / totalsize); | |
}); | |
file.on('drain', function() { // needed because of the pause/resume done by pipe - data events done twice | |
byteswritten -= lastdelta; | |
}); | |
} | |
} | |
}); | |
} | |
*/ |
i am searching for some cli command to download a soundcloud song , can i use it for that? and if yes, how to do that?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Could ya please update the gist a little bit?