grooveshark 0.2.11 → 0.2.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/.rspec +2 -2
- data/.rubocop.yml +6 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -1
- data/README.md +5 -3
- data/Rakefile +11 -4
- data/grooveshark.gemspec +24 -17
- data/lib/grooveshark/broadcast.rb +5 -3
- data/lib/grooveshark/client.rb +67 -46
- data/lib/grooveshark/errors.rb +11 -4
- data/lib/grooveshark/playlist.rb +24 -20
- data/lib/grooveshark/song.rb +17 -15
- data/lib/grooveshark/user.rb +43 -27
- data/lib/grooveshark/utils.rb +14 -12
- data/lib/grooveshark/version.rb +2 -1
- data/spec/grooveshark/broadcast_spec.rb +41 -0
- data/spec/grooveshark/client_spec.rb +80 -0
- data/spec/grooveshark/errors_spec.rb +15 -0
- data/spec/grooveshark/playlist_spec.rb +98 -0
- data/spec/grooveshark/song_spec.rb +43 -0
- data/spec/grooveshark/user_spec.rb +233 -0
- data/spec/grooveshark/utils_spec.rb +38 -0
- data/spec/helper.rb +7 -2
- metadata +105 -39
- data/spec/broadcast_spec.rb +0 -39
- data/spec/client_spec.rb +0 -85
- data/spec/utils_spec.rb +0 -35
data/lib/grooveshark/song.rb
CHANGED
@@ -1,25 +1,27 @@
|
|
1
|
+
# Grooveshark module
|
1
2
|
module Grooveshark
|
3
|
+
# Song class
|
2
4
|
class Song
|
3
5
|
attr_reader :data
|
4
6
|
attr_reader :id, :artist_id, :album_id
|
5
7
|
attr_reader :name, :artist, :album, :track, :year
|
6
8
|
attr_reader :duration, :artwork, :playcount
|
7
9
|
|
8
|
-
def initialize(data=nil)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
10
|
+
def initialize(data = nil)
|
11
|
+
return if data.nil?
|
12
|
+
|
13
|
+
@data = data
|
14
|
+
@id = data['song_id']
|
15
|
+
@name = data['song_name'] || data['name']
|
16
|
+
@artist = data['artist_name']
|
17
|
+
@artist_id = data['artist_id']
|
18
|
+
@album = data['album_name']
|
19
|
+
@album_id = data['album_id']
|
20
|
+
@track = data['track_num']
|
21
|
+
@duration = data['estimate_duration']
|
22
|
+
@artwork = data['cover_art_filename']
|
23
|
+
@playcount = data['song_plays']
|
24
|
+
@year = data['year']
|
23
25
|
end
|
24
26
|
|
25
27
|
# Presentable format
|
data/lib/grooveshark/user.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
+
# Grooveshark module
|
1
2
|
module Grooveshark
|
3
|
+
# User class
|
2
4
|
class User
|
3
|
-
attr_reader :id, :
|
5
|
+
attr_reader :id, :name, :email, :premium, :data
|
4
6
|
attr_reader :city, :country, :sex
|
5
7
|
attr_reader :playlists, :favorites
|
6
8
|
|
7
9
|
# Init user account object
|
8
|
-
def initialize(client, data=nil)
|
10
|
+
def initialize(client, data = nil)
|
9
11
|
if data
|
10
12
|
@data = data
|
11
13
|
@id = data['user_id']
|
12
|
-
@
|
14
|
+
@name = data['f_name']
|
13
15
|
@premium = data['is_premium']
|
14
16
|
@email = data['email']
|
15
17
|
@city = data['city']
|
@@ -25,9 +27,11 @@ module Grooveshark
|
|
25
27
|
end
|
26
28
|
|
27
29
|
# Get user activity for the date (COMES AS RAW RESPONSE)
|
28
|
-
def feed(date=nil)
|
30
|
+
def feed(date = nil)
|
29
31
|
date = Time.now if date.nil?
|
30
|
-
@client.request('getProcessedUserFeedData',
|
32
|
+
@client.request('getProcessedUserFeedData',
|
33
|
+
userID: @id,
|
34
|
+
day: date.strftime('%Y%m%d'))
|
31
35
|
end
|
32
36
|
|
33
37
|
# --------------------------------------------------------------------------
|
@@ -35,26 +39,35 @@ module Grooveshark
|
|
35
39
|
# --------------------------------------------------------------------------
|
36
40
|
|
37
41
|
# Fetch songs from library
|
38
|
-
def library(page=0)
|
39
|
-
|
40
|
-
resp
|
42
|
+
def library(page = 0)
|
43
|
+
songs = []
|
44
|
+
resp = @client.request('userGetSongsInLibrary',
|
45
|
+
userID: @id,
|
46
|
+
page: page.to_s)
|
47
|
+
songs = resp['songs'].map do |song|
|
48
|
+
Song.new song
|
49
|
+
end if resp.key?('songs')
|
50
|
+
songs
|
41
51
|
end
|
42
52
|
|
43
53
|
# Add songs to user's library
|
44
|
-
def library_add(songs=[])
|
45
|
-
@client.request('userAddSongsToLibrary',
|
54
|
+
def library_add(songs = [])
|
55
|
+
@client.request('userAddSongsToLibrary', songs: songs.map(&:to_hash))
|
46
56
|
end
|
47
57
|
|
48
58
|
# Remove song from user library
|
49
59
|
def library_remove(song)
|
50
|
-
|
51
|
-
req = {:
|
60
|
+
fail ArgumentError, 'Song object required' unless song.is_a?(Song)
|
61
|
+
req = { userID: @id,
|
62
|
+
songID: song.id,
|
63
|
+
albumID: song.album_id,
|
64
|
+
artistID: song.artist_id }
|
52
65
|
@client.request('userRemoveSongFromLibrary', req)
|
53
66
|
end
|
54
67
|
|
55
68
|
# Get library modification time
|
56
69
|
def library_ts_modified
|
57
|
-
@client.request('userGetLibraryTSModified',
|
70
|
+
@client.request('userGetLibraryTSModified', userID: @id)
|
58
71
|
end
|
59
72
|
|
60
73
|
# --------------------------------------------------------------------------
|
@@ -64,8 +77,10 @@ module Grooveshark
|
|
64
77
|
# Fetch user playlists
|
65
78
|
def playlists
|
66
79
|
return @playlists if @playlists
|
67
|
-
results = @client.request('userGetPlaylists', :
|
68
|
-
@playlists = results['playlists'].map
|
80
|
+
results = @client.request('userGetPlaylists', userID: @id)
|
81
|
+
@playlists = results['playlists'].map do |list|
|
82
|
+
Playlist.new(@client, list, @id)
|
83
|
+
end
|
69
84
|
end
|
70
85
|
|
71
86
|
# Get playlist by ID
|
@@ -74,15 +89,16 @@ module Grooveshark
|
|
74
89
|
result.nil? ? nil : result.first
|
75
90
|
end
|
76
91
|
|
77
|
-
|
92
|
+
alias_method :playlist, :get_playlist
|
78
93
|
|
79
94
|
# Create new user playlist
|
80
|
-
def create_playlist(name, description='', songs=[])
|
81
|
-
@client.request('createPlaylist',
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
95
|
+
def create_playlist(name, description = '', songs = [])
|
96
|
+
@client.request('createPlaylist',
|
97
|
+
'playlistName' => name,
|
98
|
+
'playlistAbout' => description,
|
99
|
+
'songIDs' => songs.map do |s|
|
100
|
+
s.is_a?(Song) ? s.id : s.to_s
|
101
|
+
end)
|
86
102
|
end
|
87
103
|
|
88
104
|
# --------------------------------------------------------------------------
|
@@ -92,20 +108,20 @@ module Grooveshark
|
|
92
108
|
# Get user favorites
|
93
109
|
def favorites
|
94
110
|
return @favorites if @favorites
|
95
|
-
resp = @client.request('getFavorites', :
|
111
|
+
resp = @client.request('getFavorites', ofWhat: 'Songs', userID: @id)
|
96
112
|
@favorites = resp.map { |s| Song.new(s) }
|
97
113
|
end
|
98
114
|
|
99
115
|
# Add song to favorites
|
100
116
|
def add_favorite(song)
|
101
|
-
song_id = song.
|
102
|
-
@client.request('favorite',
|
117
|
+
song_id = song.is_a?(Song) ? song.id : song
|
118
|
+
@client.request('favorite', what: 'Song', ID: song_id)
|
103
119
|
end
|
104
120
|
|
105
121
|
# Remove song from favorites
|
106
122
|
def remove_favorite(song)
|
107
|
-
song_id = song.
|
108
|
-
@client.request('unfavorite',
|
123
|
+
song_id = song.is_a?(Song) ? song.id : song
|
124
|
+
@client.request('unfavorite', what: 'Song', ID: song_id)
|
109
125
|
end
|
110
126
|
end
|
111
127
|
end
|
data/lib/grooveshark/utils.rb
CHANGED
@@ -1,26 +1,28 @@
|
|
1
|
+
# String class
|
1
2
|
class String
|
2
3
|
def normalize_attribute
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
gsub(/^.*::/, '')
|
5
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
6
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
7
|
+
.downcase
|
7
8
|
end
|
8
9
|
end
|
9
10
|
|
11
|
+
# Hash class
|
10
12
|
class Hash
|
11
13
|
def normalize
|
12
14
|
h = {}
|
13
|
-
|
15
|
+
each_pair do |k, v|
|
14
16
|
attr = k.to_s.normalize_attribute
|
15
17
|
case v
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
when Hash
|
19
|
+
h[attr] = v.normalize
|
20
|
+
when Array
|
21
|
+
h[attr] = v.map { |o| o.is_a?(Hash) ? o.normalize : o }
|
22
|
+
else
|
23
|
+
h[attr] = v
|
22
24
|
end
|
23
25
|
end
|
24
26
|
h
|
25
27
|
end
|
26
|
-
end
|
28
|
+
end
|
data/lib/grooveshark/version.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
require 'grooveshark'
|
4
|
+
|
5
|
+
describe Grooveshark::Broadcast do
|
6
|
+
let(:client) { Grooveshark::Client.new }
|
7
|
+
|
8
|
+
describe 'search' do
|
9
|
+
let(:result) { client.top_broadcasts(10) }
|
10
|
+
|
11
|
+
it 'returns an array' do
|
12
|
+
expect(result).to be_an Array
|
13
|
+
expect(result.size).to eq 10
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'includes brodcasts' do
|
17
|
+
all = result.all? { |item| item.is_a?(Grooveshark::Broadcast) }
|
18
|
+
expect(all).to be_truthy
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'broadcast' do
|
23
|
+
let(:broadcast) { client.top_broadcasts.first }
|
24
|
+
|
25
|
+
it 'has a valid id' do
|
26
|
+
expect(broadcast.id).to match(/^[abcdef\d]{24}$/i)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#active_song' do
|
30
|
+
it 'is a song instance' do
|
31
|
+
expect(broadcast.active_song).to be_a Grooveshark::Song
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#next_song' do
|
36
|
+
it 'is a song instance' do
|
37
|
+
expect(broadcast.active_song).to be_a Grooveshark::Song
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
require 'grooveshark'
|
4
|
+
|
5
|
+
describe 'Client' do
|
6
|
+
context 'initialization' do
|
7
|
+
it 'should have a valid session' do
|
8
|
+
@gs = Grooveshark::Client.new
|
9
|
+
expect(@gs.session).to_not be_nil
|
10
|
+
expect(@gs.session).to match(/^[abcdef\d]{32}$/i)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should have a valid country' do
|
14
|
+
gs = Grooveshark::Client.new
|
15
|
+
expect(gs.country).to be_a Hash
|
16
|
+
expect(gs.country.size).to eq(11)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have a valid token' do
|
20
|
+
@gs = Grooveshark::Client.new
|
21
|
+
expect(@gs.comm_token).to_not be_nil
|
22
|
+
expect(@gs.comm_token).to match(/^[abcdef\d]{40}$/i)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'authentication' do
|
27
|
+
it 'should raise InvalidAuthentication error for invalid credentials' do
|
28
|
+
@gs = Grooveshark::Client.new
|
29
|
+
expect { @gs.login('invlid_user_name', 'invalid_password') }
|
30
|
+
.to raise_error Grooveshark::InvalidAuthentication
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should obtain a new communication token on TTL expiration' do
|
34
|
+
@gs = Grooveshark::Client.new(ttl: 1)
|
35
|
+
@tokens = []
|
36
|
+
|
37
|
+
3.times do
|
38
|
+
@gs.search_songs('Muse')
|
39
|
+
@tokens << @gs.comm_token
|
40
|
+
sleep 3
|
41
|
+
end
|
42
|
+
|
43
|
+
@tokens.uniq!
|
44
|
+
expect(@tokens.size).to eq(3)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'search' do
|
49
|
+
before(:all) do
|
50
|
+
@gs = Grooveshark::Client.new
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should return empty songs collection' do
|
54
|
+
songs = @gs.search_songs('@@@@@%%%%%%%@%@%%@')
|
55
|
+
expect(songs).to be_a Array
|
56
|
+
expect(songs.size).to eq(0)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should return songs collection' do
|
60
|
+
songs = @gs.search_songs('Nirvana')
|
61
|
+
expect(songs).to be_a Array
|
62
|
+
expect(songs.first).to be_a(Grooveshark::Song)
|
63
|
+
expect(songs.size).to_not eq(0)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should return playlist' do
|
67
|
+
playlists = @gs.search('Playlists', 'CruciAGoT')
|
68
|
+
expect(playlists).to be_a(Array)
|
69
|
+
expect(playlists.first).to be_a(Grooveshark::Playlist)
|
70
|
+
expect(playlists.size).to_not eq(0)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should return result' do
|
74
|
+
artists = @gs.search('Artists', 'Nirvana')
|
75
|
+
expect(artists).to be_a(Array)
|
76
|
+
expect(artists.first).to be_a(Hash)
|
77
|
+
expect(artists.size).to_not eq(0)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
require 'grooveshark'
|
4
|
+
|
5
|
+
describe 'Errors' do
|
6
|
+
it 'should test ApiError' do
|
7
|
+
fault = {
|
8
|
+
'code' => '25',
|
9
|
+
'message' => 'Something went wrong'
|
10
|
+
}
|
11
|
+
|
12
|
+
error = Grooveshark::ApiError.new(fault)
|
13
|
+
expect(error.to_s).to eq('25 - Something went wrong')
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
require 'grooveshark'
|
4
|
+
|
5
|
+
describe 'Playlist' do
|
6
|
+
it 'should initialize without data' do
|
7
|
+
expect(Grooveshark::Playlist.new(double).id).to be_nil
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should initialize with data' do
|
11
|
+
playlist = Grooveshark::Playlist
|
12
|
+
.new(double,
|
13
|
+
'playlist_id' => '1',
|
14
|
+
'name' => 'something',
|
15
|
+
'about' => 'me',
|
16
|
+
'picture' => 'ruby.jpg',
|
17
|
+
'user_id' => '2',
|
18
|
+
'user_name' => 'PierreRambaud')
|
19
|
+
expect(playlist.id).to eq('1')
|
20
|
+
expect(playlist.name).to eq('something')
|
21
|
+
expect(playlist.about).to eq('me')
|
22
|
+
expect(playlist.picture).to eq('ruby.jpg')
|
23
|
+
expect(playlist.user_id).to eq('2')
|
24
|
+
expect(playlist.username).to eq('PierreRambaud')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should initiliaze without data and user_id' do
|
28
|
+
playlist = Grooveshark::Playlist.new(double, nil, '2')
|
29
|
+
expect(playlist.id).to be_nil
|
30
|
+
expect(playlist.user_id).to be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should initiliaze with data and user_id' do
|
34
|
+
playlist = Grooveshark::Playlist
|
35
|
+
.new(double, { 'playlist_id' => '1' }, '2')
|
36
|
+
expect(playlist.id).to eq('1')
|
37
|
+
expect(playlist.user_id).to eq('2')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "shouldn't load songs if playlist isn't found" do
|
41
|
+
client = double
|
42
|
+
allow(client).to receive(:request)
|
43
|
+
.with('getPlaylistByID', playlistID: nil).and_return({})
|
44
|
+
expect(Grooveshark::Playlist.new(client).load_songs).to eq([])
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should load songs if playlist is found' do
|
48
|
+
client = double
|
49
|
+
allow(client).to receive(:request)
|
50
|
+
.with('getPlaylistByID', playlistID: nil)
|
51
|
+
.and_return('songs' => ['song_id' => '42',
|
52
|
+
'name' => 'End of days',
|
53
|
+
'artist_name' => 'Vinnie Paz'])
|
54
|
+
songs = Grooveshark::Playlist.new(client).load_songs
|
55
|
+
expect(songs.first).to be_a(Grooveshark::Song)
|
56
|
+
expect(songs.first.to_s).to eq('42 - End of days - Vinnie Paz')
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should rename playlist' do
|
60
|
+
client = double
|
61
|
+
allow(client).to receive(:request)
|
62
|
+
.with('renamePlaylist', playlistID: '2', playlistName: 'GoT')
|
63
|
+
.and_return(true)
|
64
|
+
|
65
|
+
allow(client).to receive(:request)
|
66
|
+
.with('setPlaylistAbout', playlistID: '2', about: 'Description')
|
67
|
+
.and_return(true)
|
68
|
+
|
69
|
+
playlist = Grooveshark::Playlist.new(client, 'playlist_id' => '2')
|
70
|
+
expect(playlist.rename('GoT', 'Description')).to eq(true)
|
71
|
+
expect(playlist.name).to eq('GoT')
|
72
|
+
expect(playlist.about).to eq('Description')
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should return false when rename playlist failed' do
|
76
|
+
client = double
|
77
|
+
allow(client).to receive(:request)
|
78
|
+
.with('renamePlaylist', playlistID: '2', playlistName: 'GoT')
|
79
|
+
.and_raise(ArgumentError)
|
80
|
+
|
81
|
+
playlist = Grooveshark::Playlist.new(client, 'playlist_id' => '2')
|
82
|
+
expect(playlist.rename('GoT', 'Description')).to eq(false)
|
83
|
+
expect(playlist.name).to be_nil
|
84
|
+
expect(playlist.about).to be_nil
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should delete playlist' do
|
88
|
+
client = double
|
89
|
+
allow(client).to receive(:request)
|
90
|
+
.with('deletePlaylist', playlistID: '2', name: 'GoT')
|
91
|
+
.and_return(true)
|
92
|
+
|
93
|
+
playlist = Grooveshark::Playlist.new(client,
|
94
|
+
'playlist_id' => '2',
|
95
|
+
'name' => 'GoT')
|
96
|
+
expect(playlist.delete).to eq(true)
|
97
|
+
end
|
98
|
+
end
|