grooveshark 0.2.7 → 0.2.8

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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ M2I1MWRjYjA2NTQyNzY4OTBmN2UwN2NjZGI4YmEwNjlmNDNhZGM4OA==
5
+ data.tar.gz: !binary |-
6
+ ZjU4YzQzNmU0MmM1NGY3Y2U3ZTY5YTFjYzljZWI5YjFlYWM3MmQwYw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NjQ3MjlkMGI3ODNhNjk2NGNmNjEzYjFjZDkxNjdkMDE1ZmEzZDFlNjRiNjlk
10
+ OTZiNGViOTIwOWY0YmQ4OGNmMjdmZGJkOTJhY2I5M2U2ZGRkYjQzNTQ2MDI4
11
+ ODE5MmFmMWY3YzhkZWJlYjQ0YTBmMDBkYzJkOGM5ZjIxMTA1MjM=
12
+ data.tar.gz: !binary |-
13
+ NGY3MjZlNzQ1ZTkzYzAyYjc2MjAyNjM2MjYxMjgyNGVmNmVlZDBhNDNiN2Qx
14
+ YWI0MDBkMDM3YmJkMmMwZDRjMjAzNTM5NDc4YjAwMGZkNzJjMzBjMGFmODhi
15
+ MDVlNTBkZmYyZTIwOTQ2NjlhMzEzMDBiZTNjNDg3ZTE2OWRjNjg=
data/Gemfile CHANGED
@@ -1,2 +1,2 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
  gemspec
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2011-2013 Dan Sosedoff.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/grooveshark.gemspec CHANGED
@@ -15,8 +15,8 @@ Gem::Specification.new do |s|
15
15
  s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
16
16
  s.require_paths = ['lib']
17
17
 
18
- s.add_development_dependency 'rspec', '~> 2.6'
19
- s.add_development_dependency 'rake', '~> 0.9'
18
+ s.add_development_dependency 'rspec', '~> 2.12'
19
+ s.add_development_dependency 'rake', '~> 10.0'
20
20
 
21
21
  s.add_runtime_dependency 'json', '>= 1.4.6'
22
22
  s.add_runtime_dependency 'rest-client', '>= 1.5.1'
data/lib/grooveshark.rb CHANGED
@@ -5,7 +5,6 @@ require 'uuid'
5
5
 
6
6
  require 'grooveshark/utils'
7
7
  require 'grooveshark/errors'
8
- require 'grooveshark/request'
9
8
  require 'grooveshark/client'
10
9
  require 'grooveshark/user'
11
10
  require 'grooveshark/playlist'
@@ -1,50 +1,15 @@
1
1
  module Grooveshark
2
2
  class Client
3
- include Grooveshark::Request
4
-
5
3
  attr_accessor :session, :comm_token
6
4
  attr_reader :user, :comm_token_ttl, :country
7
5
 
8
- def initialize(session=nil)
6
+ def initialize(params = {})
7
+ @ttl = params[:ttl] || 120 # 2 minutes
9
8
  @session, @country = get_session_and_country
10
9
  @uuid = UUID.new.generate.upcase
11
10
  get_comm_token
12
11
  end
13
12
 
14
- protected
15
-
16
- def get_session_and_country
17
- response = RestClient.get('http://grooveshark.com')
18
- session = response.headers[:set_cookie].to_s.scan(/PHPSESSID=([a-z\d]{32});/i).flatten.first
19
- config_json = response.to_s.scan(/window.gsConfig = (\{.*?\});/).flatten.first
20
- raise GeneralError, "gsConfig not found" if not config_json
21
- config = JSON.parse(config_json)
22
- [session, config['country']]
23
- end
24
-
25
- # Get communication token
26
- def get_comm_token
27
- @comm_token = nil # request() uses it
28
- @comm_token = request('getCommunicationToken', {:secretKey => Digest::MD5.hexdigest(@session)}, true)
29
- @comm_token_ttl = Time.now.to_i
30
- end
31
-
32
- # Sign method
33
- def create_token(method)
34
- rnd = get_random_hex_chars(6)
35
- salt = get_method_salt(method)
36
- plain = [method, @comm_token, salt, rnd].join(':')
37
- hash = Digest::SHA1.hexdigest(plain)
38
- "#{rnd}#{hash}"
39
- end
40
-
41
- def get_random_hex_chars(length)
42
- chars = ('a'..'f').to_a | (0..9).to_a
43
- (0...length).map { chars[rand(chars.length)] }.join
44
- end
45
-
46
- public
47
-
48
13
  # Authenticate user
49
14
  def login(user, password)
50
15
  data = request('authenticateUser', {:username => user, :password => password}, true)
@@ -124,10 +89,78 @@ module Grooveshark
124
89
  get_song_url_by_id(song.id)
125
90
  end
126
91
 
92
+ protected
93
+
94
+ def get_session_and_country
95
+ response = RestClient.get('http://grooveshark.com')
96
+ session = response.headers[:set_cookie].to_s.scan(/PHPSESSID=([a-z\d]{32});/i).flatten.first
97
+ config_json = response.to_s.scan(/window.gsConfig = (\{.*?\});/).flatten.first
98
+ raise GeneralError, "gsConfig not found" if not config_json
99
+ config = JSON.parse(config_json)
100
+ [session, config['country']]
101
+ end
102
+
103
+ # Get communication token
104
+ def get_comm_token
105
+ @comm_token = nil # request() uses it
106
+ @comm_token = request('getCommunicationToken', {:secretKey => Digest::MD5.hexdigest(@session)}, true)
107
+ @comm_token_ttl = Time.now.to_i
108
+ end
109
+
110
+ # Sign method
111
+ def create_token(method)
112
+ rnd = get_random_hex_chars(6)
113
+ salt = 'gooeyFlubber'
114
+ plain = [method, @comm_token, salt, rnd].join(':')
115
+ hash = Digest::SHA1.hexdigest(plain)
116
+ "#{rnd}#{hash}"
117
+ end
118
+
119
+ def get_random_hex_chars(length)
120
+ chars = ('a'..'f').to_a | (0..9).to_a
121
+ (0...length).map { chars[rand(chars.length)] }.join
122
+ end
123
+
127
124
  private
128
125
 
129
- def get_method_salt(method)
130
- get_method_client(method) == 'jsqueue' ? 'closeButNoCigar' : 'breakfastBurritos'
126
+ # Perform API request
127
+ def request(method, params={}, secure=false)
128
+ refresh_token if @comm_token
129
+
130
+ url = "#{secure ? 'https' : 'http'}://grooveshark.com/more.php?#{method}"
131
+ body = {
132
+ 'header' => {
133
+ 'client' => 'mobileshark',
134
+ 'clientRevision' => '20120830',
135
+ 'country' => @country,
136
+ 'privacy' => 0,
137
+ 'session' => @session,
138
+ 'uuid' => @uuid
139
+ },
140
+ 'method' => method,
141
+ 'parameters' => params
142
+ }
143
+ body['header']['token'] = create_token(method) if @comm_token
144
+
145
+ begin
146
+ data = RestClient.post(url, body.to_json, {'Content-Type' => 'application/json'})
147
+ rescue Exception => ex
148
+ raise GeneralError, ex.message
149
+ end
150
+
151
+ data = JSON.parse(data)
152
+ data = data.normalize if data.kind_of?(Hash)
153
+
154
+ if data.key?('fault')
155
+ raise ApiError.new(data['fault'])
156
+ else
157
+ data['result']
158
+ end
159
+ end
160
+
161
+ # Refresh communications token on ttl
162
+ def refresh_token
163
+ get_comm_token if Time.now.to_i - @comm_token_ttl > @ttl
131
164
  end
132
165
  end
133
166
  end
@@ -1,3 +1,3 @@
1
1
  module Grooveshark
2
- VERSION = '0.2.7'
2
+ VERSION = '0.2.8'
3
3
  end
data/spec/client_spec.rb CHANGED
@@ -26,6 +26,20 @@ describe 'Client' do
26
26
  @gs = Grooveshark::Client.new
27
27
  lambda { @gs.login('invlid_user_name', 'invalid_password') }.should raise_error Grooveshark::InvalidAuthentication
28
28
  end
29
+
30
+ it 'should obtain a new communication token on TTL expiration' do
31
+ @gs = Grooveshark::Client.new(:ttl => 1)
32
+ @tokens = []
33
+
34
+ 3.times do |i|
35
+ @gs.search_songs('Muse')
36
+ @tokens << @gs.comm_token
37
+ sleep 3
38
+ end
39
+
40
+ @tokens.uniq!
41
+ @tokens.size.should == 3
42
+ end
29
43
  end
30
44
 
31
45
  context 'search' do
@@ -49,7 +63,7 @@ describe 'Client' do
49
63
  context 'download' do
50
64
  it 'should download without being banned' do
51
65
  gs = Grooveshark::Client.new
52
- ten_minutes_later = Time.new + 15 * 60 # Usually IP is banned after about 10 minutes
66
+ ten_minutes_later = Time.new + 15 * 60 # Usually IP is banned after about 15 minutes
53
67
  while Time.new < ten_minutes_later do
54
68
  # Try with a short song (this one is about a minute long)
55
69
  song = gs.search_songs("Alan Reeves The Chase").first
metadata CHANGED
@@ -1,52 +1,46 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grooveshark
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
5
- prerelease:
4
+ version: 0.2.8
6
5
  platform: ruby
7
6
  authors:
8
7
  - Dan Sosedoff
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-01-05 00:00:00.000000000 Z
11
+ date: 2013-06-10 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rspec
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
21
- version: '2.6'
19
+ version: '2.12'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
29
- version: '2.6'
26
+ version: '2.12'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
37
- version: '0.9'
33
+ version: '10.0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
45
- version: '0.9'
40
+ version: '10.0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: json
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ! '>='
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ! '>='
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: rest-client
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ! '>='
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ! '>='
76
67
  - !ruby/object:Gem::Version
@@ -78,7 +69,6 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: uuid
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - ~>
84
74
  - !ruby/object:Gem::Version
@@ -86,7 +76,6 @@ dependencies:
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - ~>
92
81
  - !ruby/object:Gem::Version
@@ -100,6 +89,7 @@ files:
100
89
  - .gitignore
101
90
  - .rspec
102
91
  - Gemfile
92
+ - LICENSE
103
93
  - README.rdoc
104
94
  - Rakefile
105
95
  - grooveshark.gemspec
@@ -107,47 +97,38 @@ files:
107
97
  - lib/grooveshark/client.rb
108
98
  - lib/grooveshark/errors.rb
109
99
  - lib/grooveshark/playlist.rb
110
- - lib/grooveshark/request.rb
111
100
  - lib/grooveshark/song.rb
112
101
  - lib/grooveshark/user.rb
113
102
  - lib/grooveshark/utils.rb
114
103
  - lib/grooveshark/version.rb
115
104
  - spec/client_spec.rb
116
105
  - spec/helper.rb
117
- - spec/request_spec.rb
118
106
  - spec/utils_spec.rb
119
107
  homepage: http://github.com/sosedoff/grooveshark
120
108
  licenses: []
109
+ metadata: {}
121
110
  post_install_message:
122
111
  rdoc_options: []
123
112
  require_paths:
124
113
  - lib
125
114
  required_ruby_version: !ruby/object:Gem::Requirement
126
- none: false
127
115
  requirements:
128
116
  - - ! '>='
129
117
  - !ruby/object:Gem::Version
130
118
  version: '0'
131
- segments:
132
- - 0
133
- hash: 504227010873878309
134
119
  required_rubygems_version: !ruby/object:Gem::Requirement
135
- none: false
136
120
  requirements:
137
121
  - - ! '>='
138
122
  - !ruby/object:Gem::Version
139
123
  version: '0'
140
- segments:
141
- - 0
142
- hash: 504227010873878309
143
124
  requirements: []
144
125
  rubyforge_project:
145
- rubygems_version: 1.8.23
126
+ rubygems_version: 2.0.3
146
127
  signing_key:
147
- specification_version: 3
128
+ specification_version: 4
148
129
  summary: Grooveshark API
149
130
  test_files:
150
131
  - spec/client_spec.rb
151
132
  - spec/helper.rb
152
- - spec/request_spec.rb
153
133
  - spec/utils_spec.rb
134
+ has_rdoc:
@@ -1,63 +0,0 @@
1
- module Grooveshark
2
- module Request
3
- TOKEN_TTL = 120 # 2 minutes
4
-
5
- # Perform API request
6
- def request(method, params={}, secure=false)
7
- refresh_token if @comm_token
8
-
9
- url = "#{secure ? 'https' : 'http'}://grooveshark.com/more.php?#{method}"
10
- body = {
11
- 'header' => {
12
- 'client' => get_method_client(method),
13
- 'clientRevision' => get_method_client_revision(method),
14
- 'country' => @country,
15
- 'privacy' => 0,
16
- 'session' => @session,
17
- 'uuid' => @uuid
18
- },
19
- 'method' => method,
20
- 'parameters' => params
21
- }
22
- body['header']['token'] = create_token(method) if @comm_token
23
-
24
- begin
25
- data = RestClient.post(url, body.to_json, {'Content-Type' => 'application/json'})
26
- rescue Exception => ex
27
- raise GeneralError, ex.message
28
- end
29
-
30
- data = JSON.parse(data)
31
- data = data.normalize if data.kind_of?(Hash)
32
-
33
- if data.key?('fault')
34
- raise ApiError.new(data['fault'])
35
- else
36
- data['result']
37
- end
38
- end
39
-
40
- # Refresh communications token on ttl
41
- def refresh_token
42
- get_comm_token if Time.now.to_i - @comm_token_ttl > TOKEN_TTL
43
- end
44
-
45
- private
46
-
47
- def get_method_client(method)
48
- jsqueue_methods = [
49
- 'getStreamKeyFromSongIDEx',
50
- 'addSongsToQueue',
51
- 'markSongDownloadedEx',
52
- 'markStreamKeyOver30Seconds',
53
- 'markSongQueueSongPlayed',
54
- 'markSongComplete'
55
- ]
56
- jsqueue_methods.include?(method) ? 'jsqueue' : 'htmlshark'
57
- end
58
-
59
- def get_method_client_revision(method)
60
- get_method_client(method) == 'jsqueue' ? '20120312.02' : '20120312'
61
- end
62
- end
63
- end
data/spec/request_spec.rb DELETED
@@ -1,25 +0,0 @@
1
- require File.expand_path("./helper", File.dirname(__FILE__))
2
-
3
- describe 'Request' do
4
- module Grooveshark
5
- module Request
6
- # Override default ttl for tests
7
- remove_const :TOKEN_TTL # Avoid the "already initialized constant" warning
8
- TOKEN_TTL = 1
9
- end
10
- end
11
-
12
- # it 'should obtain a new communication token on TTL expiration' do
13
- # @gs = Grooveshark::Client.new
14
- # @tokens = []
15
- #
16
- # 3.times do |i|
17
- # @gs.search_songs('Muse')
18
- # @tokens << @gs.comm_token
19
- # sleep 3
20
- # end
21
- #
22
- # @tokens.uniq!
23
- # @tokens.size.should == 3
24
- # end
25
- end