-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Christiaan Maks
committed
May 28, 2016
0 parents
commit 53da694
Showing
7 changed files
with
333 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Logs | ||
logs | ||
*.log | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directory | ||
# Deployed apps should consider commenting this line out: | ||
# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git | ||
node_modules | ||
spotify_appkey.key | ||
downloads | ||
config.json | ||
|
||
.DS_Store |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# spotijay-lib | ||
|
||
Download tracks from Spotify in 320kbps. | ||
|
||
# Installation | ||
|
||
1. `npm install` | ||
1. Install [libspotify](https://developer.spotify.com/technologies/libspotify/) | ||
1. Install following libraries: lame sox eye3D | ||
- Ubuntu/Debian: `sudo apt-get install lame sox eyed3` | ||
- Arch: `yaourt -S libspotify python2-eyed3 lame sox` | ||
- OSX: `brew install homebrew/binary/libspotify lame sox eyeD3` | ||
1. Copy your [appkey](https://developer.spotify.com/my-account/keys) in the root of the dir that uses this library (or specify another path, its the `__dirname` below that points to the appkey dir) | ||
|
||
# Usage | ||
|
||
```js | ||
if (args.playlist) { | ||
Spotijay(args.username, args.password, __dirname, function(err, spotify) { | ||
spotify.downloadPlaylistByUrl(args.playlist, args.dir, errorCallback) | ||
}) | ||
} else if (args.track) { | ||
Spotijay(args.username, args.password, __dirname, function(err, spotify) { | ||
spotify.getTrackByUrl(args.track, args.dir, errorCallback) | ||
}) | ||
} | ||
``` | ||
|
||
For more see [Spotijay](https://github.com/Christilut/Spotijay) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
var sp = require('libspotify') | ||
var path = require('path') | ||
|
||
module.exports = function(username, password, dir, cb) { | ||
var session = new sp.Session({ | ||
applicationKey: path.join(dir, 'spotify_appkey.key') | ||
}) | ||
|
||
var downloadTrack = require('./lib/download_track') | ||
var downloadPlaylist = require('./lib/download_playlist') | ||
var getTrackByUrl = require('./lib/get_track') | ||
|
||
session.login(username, password) | ||
|
||
session.once('login', function(err) { | ||
|
||
cb(null, { | ||
downloadTrack: downloadTrack(session), | ||
downloadPlaylistByUrl: downloadPlaylist(session), | ||
getTrackByUrl: getTrackByUrl(session) | ||
}) | ||
}) | ||
|
||
session.on('error', function(err) { | ||
cb(err) | ||
session.close() | ||
process.exit() | ||
}) | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
var async = require('async') | ||
var sp = require('libspotify') | ||
|
||
module.exports = function(session) { | ||
var downloadTrack = require(__dirname + '/download_track')(session) | ||
|
||
function downloadPlaylist(url, path, callback) { | ||
var args = arguments | ||
var playlist = sp.Playlist.getFromUrl(url) | ||
|
||
console.log('Getting playlist contents from Spotify...') | ||
|
||
playlist.whenReady(function() { | ||
playlist.getTracks(function(tracks) { | ||
var left = tracks.length | ||
|
||
if (left) { | ||
async.mapSeries(tracks, function(track, callback) { | ||
console.log('Tracks left: ' + left) | ||
left-- | ||
downloadTrack(track, path, callback) | ||
|
||
}, function(err) { | ||
if (err) { | ||
callback(err) | ||
} else { | ||
console.log('Downloaded all tracks') | ||
setTimeout(function() { | ||
downloadPlaylist.apply(downloadPlaylist, args) | ||
}, 60 * 1000) | ||
} | ||
}) | ||
|
||
} else { | ||
console.log('There are no tracks on this playlist') | ||
setTimeout(function() { | ||
downloadPlaylist.apply(downloadPlaylist, args) | ||
}, 60 * 1000) | ||
} | ||
}) | ||
}) | ||
} | ||
|
||
return downloadPlaylist | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
var async = require('async') | ||
var crypto = require('crypto') | ||
var exec = require('child_process').exec | ||
var fs = require('fs') | ||
var punycode = require('punycode') | ||
|
||
module.exports = function(session) { | ||
return function(track, path, callback) { | ||
var tracktitle = track.artist.name + ' - ' + track.title | ||
|
||
if (track.availability === 'UNAVAILABLE') { | ||
console.log('Track unavavailabe, skipping: ' + tracktitle) | ||
return callback(null) | ||
} | ||
|
||
var player = session.getPlayer() | ||
|
||
// var destiny = path + '/' + track.artist.name + '/' + track.album.name + '/' + track.name | ||
var destiny = path + '/' + tracktitle | ||
|
||
var hashedName = crypto.createHash('sha1').update( | ||
tracktitle | ||
).digest('hex') | ||
|
||
//getting a hash cuz eyeD3 is a motherfucker with special chars. | ||
var destinyHash = path + '/' + hashedName | ||
|
||
// skip if already exists | ||
if (fs.existsSync(destiny + '.mp3')) { | ||
console.log('File already exists, skipping: ' + tracktitle + '.mp3') | ||
return callback(null) | ||
} | ||
|
||
console.log('Downloading: ' + tracktitle) | ||
|
||
if (!fs.existsSync(path)) fs.mkdirSync(path) | ||
var ws = fs.createWriteStream(destinyHash + '.raw') | ||
|
||
player.load(track) | ||
player.play() | ||
player.pipe(ws) | ||
|
||
player.once('track-end', function() { | ||
player.stop() | ||
ws.end() | ||
|
||
async.waterfall([ | ||
|
||
function(callback) { | ||
console.log('Converting raw file to wav') | ||
exec('sox ' + [ | ||
'-r', 44100, | ||
'-b', 16, | ||
'-L', | ||
'-c', 2, | ||
'-e', 'signed-integer', | ||
'-t', 'raw', | ||
'"' + destinyHash + '.raw"', | ||
'"' + destinyHash + '.wav"' | ||
].join(' '), function(err) { | ||
callback(err) | ||
}) | ||
}, | ||
function(callback) { | ||
console.log('Converting wav file to mp3 at 320kbps') | ||
exec('lame ' + [ | ||
'--preset', 'insane', | ||
'-b', 320, | ||
'-h', | ||
'"' + destinyHash + '.wav"', | ||
'"' + destinyHash + '.mp3"' | ||
].join(' '), function(err) { | ||
callback(err) | ||
}) | ||
}, | ||
function(callback) { | ||
track.album.coverImage(function(err, buffer) { | ||
if (err) { | ||
return callback(null, false) | ||
} | ||
fs.writeFile(destinyHash + '.png', buffer, function(err) { | ||
callback(null, true) | ||
}) | ||
}) | ||
}, | ||
function(cover, callback) { | ||
console.log('Adding id3 tags') | ||
|
||
var coverCmd = ['--add-image', '"' + destinyHash + '.png:FRONT_COVER"'] | ||
|
||
var args = [ | ||
'-t', '"' + punycode.toASCII(track.title) + '"', | ||
'-a', '"' + punycode.toASCII(track.artist.name) + '"', | ||
'-A', '"' + punycode.toASCII(track.album.name) + '"', | ||
'-Y', '"' + track.album.year + '"', | ||
'"' + destinyHash + '.mp3"' | ||
] | ||
|
||
// Adds the command to add a ilustration to the file | ||
if (cover) | ||
args = coverCmd.concat(args) | ||
|
||
var cmd = 'eyeD3 ' + args.join(' ') | ||
|
||
exec(cmd, function(err) { | ||
callback(err, cover) | ||
}) | ||
|
||
}, | ||
function(cover, callback) { | ||
// if (config.copy) | ||
// exec('cp ' + destinyHash + '.mp3 ' + config.copy + '/' + destinyHash + '.mp3', function(err) { | ||
// console.log(err) | ||
// }) | ||
// if (config.itunes) | ||
// exec('open -a "itunes" ' + destinyHash + '.mp3 ', function(err) { | ||
// console.log(err) | ||
// }) | ||
|
||
// cleanup | ||
fs.unlinkSync(destinyHash + '.raw') | ||
fs.unlinkSync(destinyHash + '.wav') | ||
fs.unlinkSync(destinyHash + '.png') // use flag? some may want it as cover.png or something | ||
|
||
fs.renameSync(destinyHash + '.mp3', destiny + '.mp3') | ||
|
||
// if (cover) { | ||
// fs.renameSync(destinyHash + '.png', path + '/' + track.artist.name + ' - ' + track.title + '.png') | ||
// } | ||
callback() | ||
} | ||
|
||
], function(err) { | ||
console.log('Finished: ' + tracktitle) | ||
ws.end() | ||
player.removeAllListeners('error') | ||
delete player, ws | ||
callback(err) | ||
}) | ||
|
||
}) | ||
|
||
player.on('error', function(err) { | ||
ws.end() | ||
callback(err) | ||
}) | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
var async = require('async') | ||
var sp = require('libspotify') | ||
|
||
var downloadTrack = require(__dirname + '/download_track') | ||
|
||
module.exports = function(session) { | ||
return function(url, path, callback) { | ||
var track = sp.Track.getFromUrl(url) | ||
|
||
track.on('ready', function() { | ||
downloadTrack(session)(track, path, callback) | ||
}) | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"name": "spotijay-lib", | ||
"description": "Spotify downloader library", | ||
"version": "0.1.0", | ||
"keywords": [ | ||
"spotify", | ||
"spotijay", | ||
"download" | ||
], | ||
"author": { | ||
"name": "Alejandro Perezpayá", | ||
"email": "[email protected]", | ||
"url": "http://perezpaya.net" | ||
}, | ||
"contributors": [ | ||
{ | ||
"name": "Alejandro Perezpayá", | ||
"email": "[email protected]", | ||
"url": "http://perezpaya.net" | ||
}, | ||
{ | ||
"name": "Luis Iván Cuende", | ||
"email": "[email protected]", | ||
"url": "http://luisivan.net" | ||
}, | ||
{ | ||
"name": "Christiaan Maks" | ||
} | ||
], | ||
"main": "index.js", | ||
"engines": { | ||
"node": ">= 0.10.x" | ||
}, | ||
"dependencies": { | ||
"async": "~0.9.0", | ||
"libspotify": "~0.2.2" | ||
} | ||
} |