spotify-to-mp3 0.4.2 → 0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rspec +1 -0
- data/README.md +7 -2
- data/bin/spotify-to-mp3 +2 -2
- data/lib/spotify_to_mp3.rb +10 -52
- data/lib/spotify_to_mp3/app.rb +35 -0
- data/lib/spotify_to_mp3/app/file_track_ids.rb +21 -0
- data/lib/spotify_to_mp3/dependency_injection.rb +15 -0
- data/lib/spotify_to_mp3/grooveshark.rb +18 -0
- data/lib/spotify_to_mp3/grooveshark/track.rb +19 -0
- data/lib/spotify_to_mp3/spotify.rb +13 -0
- data/lib/spotify_to_mp3/spotify/track.rb +12 -0
- data/lib/spotify_to_mp3/track.rb +14 -0
- data/lib/spotify_to_mp3/track_id_resolver.rb +26 -0
- data/spec/app/file_track_ids_spec.rb +32 -0
- data/spec/grooveshark_spec.rb +23 -0
- data/spec/spotify_spec.rb +41 -0
- data/spec/track_id_resolver_spec.rb +24 -0
- data/spotify-to-mp3.gemspec +14 -14
- metadata +18 -7
- data/lib/spotify_to_mp3/services.rb +0 -40
- data/lib/spotify_to_mp3/songs.rb +0 -65
- data/lib/spotify_to_mp3/sources.rb +0 -43
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color --format nested
|
data/README.md
CHANGED
@@ -42,6 +42,10 @@ Make sure you have rubygems installed and configured:
|
|
42
42
|
|
43
43
|
## Changelog
|
44
44
|
|
45
|
+
2012-08-20
|
46
|
+
|
47
|
+
- Set filename artist and title from Grooveshark
|
48
|
+
|
45
49
|
2012-01-11
|
46
50
|
|
47
51
|
- Touch already downloaded songs. This way songs no more in the download list can be spotted easily.
|
@@ -57,7 +61,8 @@ Make sure you have rubygems installed and configured:
|
|
57
61
|
## TODO
|
58
62
|
|
59
63
|
- Consider multiple artists songs
|
60
|
-
- Distinguish internal errors from user errors
|
61
64
|
- Filter Grooveshark results by artist, title and length
|
62
|
-
- Split code in multiple files
|
63
65
|
- It seems Grooveshark API fails after hundreds of calls
|
66
|
+
- Accept tracks from stdin (instead of from a file)
|
67
|
+
- Test downloads
|
68
|
+
- Test App class
|
data/bin/spotify-to-mp3
CHANGED
data/lib/spotify_to_mp3.rb
CHANGED
@@ -1,58 +1,16 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'grooveshark'
|
3
2
|
require 'open-uri'
|
4
3
|
require 'colorize'
|
5
4
|
require 'rest-client'
|
6
5
|
require 'fileutils'
|
6
|
+
require 'cgi'
|
7
7
|
|
8
|
-
require 'spotify_to_mp3/
|
9
|
-
require 'spotify_to_mp3/
|
10
|
-
require 'spotify_to_mp3/
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@context = {
|
18
|
-
:grooveshark => Grooveshark.new,
|
19
|
-
:spotify => Spotify.new
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
def run
|
24
|
-
begin
|
25
|
-
file = ARGV.first
|
26
|
-
raise "No songs file specified. Usage: #{$0} file" if file.nil?
|
27
|
-
|
28
|
-
File.open(file).each_line{|song_id|
|
29
|
-
song_id.strip!
|
30
|
-
next if song_id.empty?
|
31
|
-
begin
|
32
|
-
song = UnresolvedSong.new(@context, song_id)
|
33
|
-
print "Resolving \"#{song}\" "
|
34
|
-
song = song.resolve
|
35
|
-
print "-> Searching \"#{song}\" on Grooveshark "
|
36
|
-
song = song.from_grooveshark
|
37
|
-
print "-> Downloading \"#{song}\" "
|
38
|
-
if File.exists? song.filename
|
39
|
-
FileUtils.touch song.filename # To know about songs no longer in download list
|
40
|
-
puts "Already exists, skipping".green
|
41
|
-
else
|
42
|
-
begin
|
43
|
-
song.download
|
44
|
-
puts "Done".green
|
45
|
-
rescue Exception => exception
|
46
|
-
puts exception.message.red
|
47
|
-
end
|
48
|
-
end
|
49
|
-
rescue
|
50
|
-
puts "#{$!}".red
|
51
|
-
end
|
52
|
-
}
|
53
|
-
rescue
|
54
|
-
puts "#{$!}".red
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
8
|
+
require 'spotify_to_mp3/app'
|
9
|
+
require 'spotify_to_mp3/app/file_track_ids'
|
10
|
+
require 'spotify_to_mp3/dependency_injection'
|
11
|
+
require 'spotify_to_mp3/spotify'
|
12
|
+
require 'spotify_to_mp3/spotify/track'
|
13
|
+
require 'spotify_to_mp3/track_id_resolver'
|
14
|
+
require 'spotify_to_mp3/track'
|
15
|
+
require 'spotify_to_mp3/grooveshark'
|
16
|
+
require 'spotify_to_mp3/grooveshark/track'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module SpotifyToMp3
|
2
|
+
class App
|
3
|
+
def initialize(track_id_resolver, grooveshark)
|
4
|
+
@track_id_resolver = track_id_resolver
|
5
|
+
@grooveshark = grooveshark
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
file = ARGV.first or raise "No songs file specified. Usage: #{$0} file"
|
10
|
+
FileTrackIds.new(file).each do |track_id|
|
11
|
+
begin
|
12
|
+
puts "Resolving \"#{track_id}\" ".blue
|
13
|
+
track = @track_id_resolver.resolve(track_id)
|
14
|
+
|
15
|
+
puts "Searching \"#{track}\" on Grooveshark ".blue
|
16
|
+
grooveshark_track = @grooveshark.get_track(track.grooveshark_query)
|
17
|
+
|
18
|
+
puts "Downloading \"#{grooveshark_track}\" ".blue
|
19
|
+
if File.exists? grooveshark_track.filename
|
20
|
+
FileUtils.touch grooveshark_track.filename # To know about songs no longer in download list
|
21
|
+
puts "Already exists, skipping".green
|
22
|
+
else
|
23
|
+
@grooveshark.download(grooveshark_track)
|
24
|
+
puts "Done".green
|
25
|
+
end
|
26
|
+
rescue Exception => exception # For some reason without the "Exception" it is ignored
|
27
|
+
puts exception.message.red
|
28
|
+
# Continue with the next track
|
29
|
+
end
|
30
|
+
end
|
31
|
+
rescue
|
32
|
+
puts "#{$!}".red
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SpotifyToMp3
|
2
|
+
class App
|
3
|
+
class FileTrackIds
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(file)
|
7
|
+
@file = file
|
8
|
+
end
|
9
|
+
|
10
|
+
def each
|
11
|
+
File.open(@file) do |file|
|
12
|
+
file.each do |track_id|
|
13
|
+
track_id.strip!
|
14
|
+
next if track_id.empty?
|
15
|
+
yield track_id
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module SpotifyToMp3
|
2
|
+
class DependencyInjection
|
3
|
+
def track_id_resolver
|
4
|
+
@track_id_resolver ||= TrackIdResolver.new(Spotify.new)
|
5
|
+
end
|
6
|
+
|
7
|
+
def grooveshark
|
8
|
+
@grooveshark ||= Grooveshark.new(::Grooveshark::Client.new)
|
9
|
+
end
|
10
|
+
|
11
|
+
def app
|
12
|
+
@app ||= App.new(track_id_resolver, grooveshark)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SpotifyToMp3
|
2
|
+
class Grooveshark
|
3
|
+
def initialize(client)
|
4
|
+
@client = client
|
5
|
+
end
|
6
|
+
|
7
|
+
def get_track(query)
|
8
|
+
client_track = @client.search_songs(query).first or raise "Track not found"
|
9
|
+
Track.new(client_track)
|
10
|
+
end
|
11
|
+
|
12
|
+
def download(track)
|
13
|
+
url = @client.get_song_url(track.client_track)
|
14
|
+
file = RestClient::Request.execute(:method => :post, :url => url, :raw_response => true).file
|
15
|
+
FileUtils.mv(file.path, track.filename)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SpotifyToMp3
|
2
|
+
class Grooveshark
|
3
|
+
class Track
|
4
|
+
attr_reader :client_track
|
5
|
+
|
6
|
+
def initialize(client_track)
|
7
|
+
@client_track = client_track
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
"#{@client_track.artist} - #{@client_track.name}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def filename
|
15
|
+
"#{self}.mp3".tr('/', '-') # / is not allowed in file names
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SpotifyToMp3
|
2
|
+
class Spotify
|
3
|
+
def get_track(uri)
|
4
|
+
content = open('http://ws.spotify.com/lookup/1/.json?uri=' + CGI.escape(uri))
|
5
|
+
json = JSON.parse(content.string)
|
6
|
+
Track.new(json)
|
7
|
+
end
|
8
|
+
|
9
|
+
def resolvable_uri?(uri)
|
10
|
+
uri.start_with?('http://open.spotify.com/track/', 'spotify:track:')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module SpotifyToMp3
|
2
|
+
class Track
|
3
|
+
attr_reader :grooveshark_query
|
4
|
+
|
5
|
+
def initialize(description, grooveshark_query = nil)
|
6
|
+
@description = description
|
7
|
+
@grooveshark_query = grooveshark_query || @description
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
@description
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SpotifyToMp3
|
2
|
+
class TrackIdResolver
|
3
|
+
def initialize(spotify)
|
4
|
+
@spotify = spotify
|
5
|
+
end
|
6
|
+
|
7
|
+
def resolve(track_id)
|
8
|
+
resolve_spotify_track(track_id) || resolve_plain_track(track_id)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def resolve_spotify_track(id)
|
14
|
+
if @spotify.resolvable_uri?(id)
|
15
|
+
spotify_track = @spotify.get_track(id)
|
16
|
+
description = "#{spotify_track.artist} - #{spotify_track.name}"
|
17
|
+
grooveshark_query = "artist:\"#{spotify_track.artist}\" title:\"#{spotify_track.name}\""
|
18
|
+
Track.new(description, grooveshark_query)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def resolve_plain_track(id)
|
23
|
+
Track.new(id)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spotify_to_mp3'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module SpotifyToMp3
|
5
|
+
describe App::FileTrackIds do
|
6
|
+
it "reads lines" do
|
7
|
+
open_test_file("1\n2\n3") do |ids|
|
8
|
+
ids.count.should == 3
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "trims spaces" do
|
13
|
+
open_test_file(" 1 ") do |ids|
|
14
|
+
ids.each do |id| id.should == "1" end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "ignores empty lines" do
|
19
|
+
open_test_file("1\n\n2\n") do |ids|
|
20
|
+
ids.count.should == 2
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def open_test_file(content)
|
25
|
+
Tempfile.open('tracks') do |file|
|
26
|
+
file.write(content)
|
27
|
+
file.rewind
|
28
|
+
yield App::FileTrackIds.new(file)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spotify_to_mp3'
|
2
|
+
|
3
|
+
module SpotifyToMp3
|
4
|
+
describe Grooveshark do
|
5
|
+
context "#get_track" do
|
6
|
+
before(:each) do
|
7
|
+
@grooveshark = DependencyInjection.new.grooveshark
|
8
|
+
end
|
9
|
+
|
10
|
+
it "finds by plain query" do
|
11
|
+
@grooveshark.get_track("Cake - I Will Survive").should be
|
12
|
+
end
|
13
|
+
|
14
|
+
it "finds by artist and title" do
|
15
|
+
@grooveshark.get_track('artist:"Cake" title:"I Will Survive"').should be
|
16
|
+
end
|
17
|
+
|
18
|
+
it "fails with nonexistent tracks" do
|
19
|
+
expect { @grooveshark.get_track('XXXXXXXXXXXXXXX') }.to raise_error
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spotify_to_mp3'
|
2
|
+
|
3
|
+
module SpotifyToMp3
|
4
|
+
describe Spotify do
|
5
|
+
before(:each) do
|
6
|
+
@spotify = SpotifyToMp3::Spotify.new
|
7
|
+
end
|
8
|
+
|
9
|
+
context '#get_track' do
|
10
|
+
it "resolves HTTP URLs" do
|
11
|
+
track = @spotify.get_track('http://open.spotify.com/track/0qgiFuYhYuwtFXEwYakddE')
|
12
|
+
track.name.should == "I Will Survive"
|
13
|
+
track.artist.should == "Cake"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "resolves Spotify URIs" do
|
17
|
+
track = @spotify.get_track('spotify:track:0qgiFuYhYuwtFXEwYakddE')
|
18
|
+
track.name.should == "I Will Survive"
|
19
|
+
track.artist.should == "Cake"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "fails on nonexistent URI" do
|
23
|
+
expect { @spotify.get_track('spotify:track:not-found') }.to raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "#resolvable_uri?" do
|
28
|
+
it "accepts HTTP URLs" do
|
29
|
+
@spotify.resolvable_uri?('http://open.spotify.com/track/0qgiFuYhYuwtFXEwYakddE').should be_true
|
30
|
+
end
|
31
|
+
|
32
|
+
it "accepts Spotify URIs" do
|
33
|
+
@spotify.resolvable_uri?('spotify:track:0qgiFuYhYuwtFXEwYakddE').should be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "refuses other URIs" do
|
37
|
+
@spotify.resolvable_uri?('123').should be_false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spotify_to_mp3'
|
2
|
+
|
3
|
+
module SpotifyToMp3
|
4
|
+
describe TrackIdResolver do
|
5
|
+
before(:each) do
|
6
|
+
@resolver = DependencyInjection.new.track_id_resolver
|
7
|
+
end
|
8
|
+
|
9
|
+
it "resolves Spotify HTTP URLs" do
|
10
|
+
track = @resolver.resolve('http://open.spotify.com/track/0qgiFuYhYuwtFXEwYakddE')
|
11
|
+
track.to_s.should == "Cake - I Will Survive"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "resolves Spotify URIs" do
|
15
|
+
track = @resolver.resolve('spotify:track:0qgiFuYhYuwtFXEwYakddE')
|
16
|
+
track.to_s.should == "Cake - I Will Survive"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "resolves track titles" do
|
20
|
+
track = @resolver.resolve('Cake - I Will Survive')
|
21
|
+
track.to_s.should == "Cake - I Will Survive"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spotify-to-mp3.gemspec
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
Gem::Specification.new do |
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = 'spotify-to-mp3'
|
3
|
+
gem.summary = 'Spotify to MP3'
|
4
|
+
gem.description = 'Download Spotify tracks as MP3 files from Grooveshark'
|
5
|
+
gem.version = '0.5'
|
6
|
+
gem.author = 'Francesc Rosàs'
|
7
|
+
gem.email = 'francescrosasbosque@gmail.com'
|
8
|
+
gem.homepage = 'https://github.com/frosas/spotify-to-mp3'
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
gem.add_dependency 'grooveshark'
|
11
|
+
gem.add_dependency 'colorize'
|
12
|
+
gem.add_dependency 'rest-client'
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
gem.files = `git ls-files`.split("\n")
|
15
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
gem.require_paths = ['lib']
|
17
17
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spotify-to-mp3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.5'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: grooveshark
|
@@ -59,28 +59,39 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
-
description: Download MP3 files
|
62
|
+
description: Download Spotify tracks as MP3 files from Grooveshark
|
63
63
|
email: francescrosasbosque@gmail.com
|
64
64
|
executables:
|
65
65
|
- spotify-to-mp3
|
66
66
|
extensions: []
|
67
67
|
extra_rdoc_files: []
|
68
68
|
files:
|
69
|
+
- .rspec
|
69
70
|
- Gemfile
|
70
71
|
- Gemfile.lock
|
71
72
|
- README.md
|
72
73
|
- bin/spotify-to-mp3
|
73
74
|
- lib/spotify_to_mp3.rb
|
74
|
-
- lib/spotify_to_mp3/
|
75
|
-
- lib/spotify_to_mp3/
|
76
|
-
- lib/spotify_to_mp3/
|
75
|
+
- lib/spotify_to_mp3/app.rb
|
76
|
+
- lib/spotify_to_mp3/app/file_track_ids.rb
|
77
|
+
- lib/spotify_to_mp3/dependency_injection.rb
|
78
|
+
- lib/spotify_to_mp3/grooveshark.rb
|
79
|
+
- lib/spotify_to_mp3/grooveshark/track.rb
|
80
|
+
- lib/spotify_to_mp3/spotify.rb
|
81
|
+
- lib/spotify_to_mp3/spotify/track.rb
|
82
|
+
- lib/spotify_to_mp3/track.rb
|
83
|
+
- lib/spotify_to_mp3/track_id_resolver.rb
|
84
|
+
- spec/app/file_track_ids_spec.rb
|
85
|
+
- spec/grooveshark_spec.rb
|
86
|
+
- spec/spotify_spec.rb
|
87
|
+
- spec/track_id_resolver_spec.rb
|
77
88
|
- spotify-to-mp3.gemspec
|
78
89
|
homepage: https://github.com/frosas/spotify-to-mp3
|
79
90
|
licenses: []
|
80
91
|
post_install_message:
|
81
92
|
rdoc_options: []
|
82
93
|
require_paths:
|
83
|
-
-
|
94
|
+
- lib
|
84
95
|
required_ruby_version: !ruby/object:Gem::Requirement
|
85
96
|
none: false
|
86
97
|
requirements:
|
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
|
3
|
-
module SpotifyToMp3
|
4
|
-
|
5
|
-
class Grooveshark
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@client = ::Grooveshark::Client.new
|
9
|
-
end
|
10
|
-
|
11
|
-
def song_url(song)
|
12
|
-
@client.get_song_url(song)
|
13
|
-
end
|
14
|
-
|
15
|
-
def song(query)
|
16
|
-
song = @client.search_songs(query).first
|
17
|
-
raise "Song not found" if song.nil?
|
18
|
-
song
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class Spotify
|
23
|
-
|
24
|
-
def track(uri)
|
25
|
-
content = open('http://ws.spotify.com/lookup/1/.json?uri=' + CGI.escape(uri))
|
26
|
-
json = JSON.parse(content.string)
|
27
|
-
Track.new(json)
|
28
|
-
end
|
29
|
-
|
30
|
-
class Track
|
31
|
-
|
32
|
-
attr_reader :name, :artist
|
33
|
-
|
34
|
-
def initialize(json)
|
35
|
-
@name = json['track']['name']
|
36
|
-
@artist = json['track']['artists'].first['name']
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
data/lib/spotify_to_mp3/songs.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
class UnresolvedSong
|
2
|
-
|
3
|
-
def initialize(context, id)
|
4
|
-
@context = context
|
5
|
-
@id = id
|
6
|
-
end
|
7
|
-
|
8
|
-
def resolve
|
9
|
-
if @id.start_with?('http://open.spotify.com/track/', 'spotify:track:')
|
10
|
-
track = @context[:spotify].track(@id)
|
11
|
-
source = SpotifySource.new(@context, track)
|
12
|
-
else
|
13
|
-
source = PlainSource.new(@context, @id)
|
14
|
-
end
|
15
|
-
ResolvedSong.new(@context, source)
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_s
|
19
|
-
@id
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class ResolvedSong
|
24
|
-
|
25
|
-
def initialize(context, source)
|
26
|
-
@context = context
|
27
|
-
@source = source
|
28
|
-
end
|
29
|
-
|
30
|
-
def from_grooveshark
|
31
|
-
GroovesharkSong.new(@context, @source.grooveshark_query)
|
32
|
-
end
|
33
|
-
|
34
|
-
def to_s
|
35
|
-
"#{@source}"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class GroovesharkSong
|
40
|
-
|
41
|
-
def initialize(context, query)
|
42
|
-
@context = context
|
43
|
-
@raw_grooveshark_song = @context[:grooveshark].song(query)
|
44
|
-
end
|
45
|
-
|
46
|
-
def download
|
47
|
-
download_url(@context[:grooveshark].song_url(@raw_grooveshark_song))
|
48
|
-
end
|
49
|
-
|
50
|
-
def to_s
|
51
|
-
"#{@raw_grooveshark_song.artist} - #{@raw_grooveshark_song.name}"
|
52
|
-
end
|
53
|
-
|
54
|
-
def filename
|
55
|
-
name = "#{@raw_grooveshark_song.artist} - #{@raw_grooveshark_song.name}.mp3"
|
56
|
-
name.tr('/', '-') # / is not allowed in file names
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def download_url(url)
|
62
|
-
file = RestClient::Request.execute(:method => :post, :url => url, :raw_response => true).file
|
63
|
-
FileUtils.mv(file.path, filename)
|
64
|
-
end
|
65
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
class Source
|
2
|
-
|
3
|
-
def grooveshark_query
|
4
|
-
raise "Not implemented"
|
5
|
-
end
|
6
|
-
|
7
|
-
def to_s
|
8
|
-
raise "Not implemented"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class SpotifySource < Source
|
13
|
-
|
14
|
-
def initialize(context, track)
|
15
|
-
@context = context
|
16
|
-
@track = track
|
17
|
-
end
|
18
|
-
|
19
|
-
def grooveshark_query
|
20
|
-
"artist:\"#{@track.artist}\" title:\"#{@track.name}\""
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_s
|
24
|
-
"#{@track.artist} - #{@track.name}"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class PlainSource < Source
|
29
|
-
|
30
|
-
attr_reader :grooveshark_query, :to_s
|
31
|
-
|
32
|
-
def initialize(context, id)
|
33
|
-
parts = id.split(' - ', 2)
|
34
|
-
if parts.length < 2
|
35
|
-
@grooveshark_query = id
|
36
|
-
@to_s = id
|
37
|
-
else
|
38
|
-
artist, name = parts
|
39
|
-
@grooveshark_query = "artist:\"#{artist}\" title:\"#{name}\""
|
40
|
-
@to_s = "#{artist} - #{name}"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|