Class: Grooveshark::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/grooveshark/client.rb

Overview

Client class

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params = {}) ⇒ Client

Returns a new instance of Client.



8
9
10
11
12
# File 'lib/grooveshark/client.rb', line 8

def initialize(params = {})
  @ttl = params[:ttl] || 120 # 2 minutes
  @uuid = UUID.new.generate.upcase
  token_data
end

Instance Attribute Details

#comm_tokenObject

Returns the value of attribute comm_token.



5
6
7
# File 'lib/grooveshark/client.rb', line 5

def comm_token
  @comm_token
end

#comm_token_ttlObject (readonly)

Returns the value of attribute comm_token_ttl.



6
7
8
# File 'lib/grooveshark/client.rb', line 6

def comm_token_ttl
  @comm_token_ttl
end

#countryObject (readonly)

Returns the value of attribute country.



6
7
8
# File 'lib/grooveshark/client.rb', line 6

def country
  @country
end

#sessionObject

Returns the value of attribute session.



5
6
7
# File 'lib/grooveshark/client.rb', line 5

def session
  @session
end

#userObject (readonly)

Returns the value of attribute user.



6
7
8
# File 'lib/grooveshark/client.rb', line 6

def user
  @user
end

Instance Method Details

#body(method, params) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/grooveshark/client.rb', line 153

def body(method, params)
  body = {
    'header' => {
      'client' => 'mobileshark',
      'clientRevision' => '20120830',
      'country' => @country,
      'privacy' => 0,
      'session' => @session,
      'uuid' => @uuid
    },
    'method' => method,
    'parameters' => params
  }
  body['header']['token'] = create_token(method) if @comm_token
  body
end

#create_token(method) ⇒ Object

Sign method



140
141
142
143
144
145
146
# File 'lib/grooveshark/client.rb', line 140

def create_token(method)
  rnd = get_random_hex_chars(6)
  salt = 'gooeyFlubber'
  plain = [method, @comm_token, salt, rnd].join(':')
  hash = Digest::SHA1.hexdigest(plain)
  "#{rnd}#{hash}"
end

#get_random_hex_chars(length) ⇒ Object



148
149
150
151
# File 'lib/grooveshark/client.rb', line 148

def get_random_hex_chars(length)
  chars = ('a'..'f').to_a | (0..9).to_a
  (0...length).map { chars[rand(chars.length)] }.join
end

#get_song_url(song) ⇒ Object

Get song stream



115
116
117
# File 'lib/grooveshark/client.rb', line 115

def get_song_url(song)
  get_song_url_by_id(song.id)
end

#get_song_url_by_id(id) ⇒ Object

Get song stream url by ID



109
110
111
112
# File 'lib/grooveshark/client.rb', line 109

def get_song_url_by_id(id)
  resp = get_stream_auth_by_songid(id)
  "http://#{resp['ip']}/stream.php?streamKey=#{resp['stream_key']}"
end

#get_stream_auth(song) ⇒ Object

Get stream authentication for song object



104
105
106
# File 'lib/grooveshark/client.rb', line 104

def get_stream_auth(song)
  get_stream_auth_by_songid(song.id)
end

#get_stream_auth_by_songid(song_id) ⇒ Object

Get stream authentication by song ID



89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/grooveshark/client.rb', line 89

def get_stream_auth_by_songid(song_id)
  result = request('getStreamKeyFromSongIDEx',
                   'type' => 0,
                   'prefetch' => false,
                   'songID' => song_id,
                   'country' => @country,
                   'mobile' => false)
  if result == []
    fail GeneralError, 'No data for this song. ' \
         'Maybe Grooveshark banned your IP.'
  end
  result
end

#get_user_by_id(id) ⇒ Object

Find user by ID



26
27
28
29
# File 'lib/grooveshark/client.rb', line 26

def get_user_by_id(id)
  resp = request('getUserByID', userID: id)['user']
  resp['user_id'].nil? ? nil : User.new(self, resp)
end

#get_user_by_username(name) ⇒ Object

Find user by username



32
33
34
35
# File 'lib/grooveshark/client.rb', line 32

def get_user_by_username(name)
  resp = request('getUserByUsername', username: name)['user']
  resp['user_id'].nil? ? nil : User.new(self, resp)
end

#login(user, password) ⇒ Object

Authenticate user



15
16
17
18
19
20
21
22
23
# File 'lib/grooveshark/client.rb', line 15

def (user, password)
  data = request('authenticateUser',
                 { username: user, password: password },
                 true)
  @user = User.new(self, data)
  fail InvalidAuthentication, 'Wrong username or password!' if @user.id == 0

  @user
end

Get popular songs type => daily, monthly



47
48
49
50
# File 'lib/grooveshark/client.rb', line 47

def popular_songs(type = 'daily')
  fail ArgumentError, 'Invalid type' unless %w(daily monthly).include?(type)
  request('popularGetSongs', type: type)['songs'].map { |s| Song.new(s) }
end

#recent_usersObject

Get recently active users



38
39
40
41
42
43
# File 'lib/grooveshark/client.rb', line 38

def recent_users
  request('getRecentlyActiveUsers', {})['users']
    .map do |u|
    User.new(self, u)
  end
end

#refresh_tokenObject

Refresh communications token on ttl



194
195
196
# File 'lib/grooveshark/client.rb', line 194

def refresh_token
  token_data if Time.now.to_i - @comm_token_ttl > @ttl
end

#request(method, params = {}, secure = false) ⇒ Object

Perform API request



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/grooveshark/client.rb', line 171

def request(method, params = {}, secure = false)
  refresh_token if @comm_token

  url = "#{secure ? 'https' : 'http'}://grooveshark.com/more.php?#{method}"
  begin
    data = RestClient.post(url,
                           body(method, params).to_json,
                           'Content-Type' => 'application/json')
  rescue StandardError => ex
    raise GeneralError, ex.message
  end

  data = JSON.parse(data)
  data = data.normalize if data.is_a?(Hash)

  if data.key?('fault')
    fail ApiError, data['fault']
  else
    data['result']
  end
end

#search(type, query) ⇒ Object

Perform search request for query



67
68
69
70
71
72
73
74
75
76
# File 'lib/grooveshark/client.rb', line 67

def search(type, query)
  results = []
  search = request('getResultsFromSearch', type: type, query: query)
  results = search['result'].map do |data|
    next Song.new data if type == 'Songs'
    next Playlist.new(self, data) if type == 'Playlists'
    data
  end if search.key?('result')
  results
end

#search_songs(query) ⇒ Object

Perform songs search request for query



79
80
81
# File 'lib/grooveshark/client.rb', line 79

def search_songs(query)
  search('Songs', query)
end

#search_songs_pure(query) ⇒ Object

Return raw response for songs search request



84
85
86
# File 'lib/grooveshark/client.rb', line 84

def search_songs_pure(query)
  request('getSearchResultsEx', type: 'Songs', query: query)
end

#token_dataObject



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/grooveshark/client.rb', line 119

def token_data
  response = RestClient.get('http://grooveshark.com')

  preload_regex = /gsPreloadAjax\(\{url: '\/preload.php\?(.*)&hash=' \+ clientPage\}\)/ # rubocop:disable Metrics/LineLength
  preload_id = response.to_s.scan(preload_regex).flatten.first
  preload_url = "http://grooveshark.com/preload.php?#{preload_id}" \
                '&getCommunicationToken=1&hash=%2F'
  preload_response = RestClient.get(preload_url)

  token_data_json = preload_response.to_s
                    .scan(/window.tokenData = (.*);/).flatten.first
  fail GeneralError, 'token data not found' unless token_data_json
  token_data = JSON.parse(token_data_json)
  @comm_token = token_data['getCommunicationToken']
  @comm_token_ttl = Time.now.to_i
  config = token_data['getGSConfig']
  @country = config['country']
  @session = config['sessionID']
end

#top_broadcasts(count = 10) ⇒ Object

Get top broadcasts count => specifies how many broadcasts to get



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/grooveshark/client.rb', line 54

def top_broadcasts(count = 10)
  top_broadcasts = []
  request('getTopBroadcastsCombined').each do |key, _val|
    broadcast_id = key.split(':')[1]
    top_broadcasts.push(Broadcast.new(self, broadcast_id))
    count -= 1
    break if count == 0
  end

  top_broadcasts
end