grooveshark 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ require 'digest'
2
+ require 'json'
3
+ require 'rest-client'
4
+
5
+ require 'grooveshark/errors'
6
+ require 'grooveshark/request'
7
+ require 'grooveshark/client'
8
+ require 'grooveshark/user'
9
+ require 'grooveshark/playlist'
10
+ require 'grooveshark/song'
@@ -0,0 +1,84 @@
1
+ module Grooveshark
2
+ class Client
3
+ include Grooveshark::Request
4
+
5
+ attr_accessor :session, :comm_token
6
+ attr_reader :user
7
+
8
+ def initialize(session=nil)
9
+ @session = session || get_session
10
+ get_comm_token
11
+ end
12
+
13
+ # Obtain new session from Grooveshark
14
+ def get_session
15
+ resp = RestClient.get('http://listen.grooveshark.com')
16
+ resp.headers[:set_cookie].to_s.scan(/PHPSESSID=([a-z\d]{32});/i).flatten.first
17
+ end
18
+
19
+ # Get communication token
20
+ def get_comm_token
21
+ puts "Grooveshark::Client.get_comm_token"
22
+ @comm_token = nil # so that it doesn't send a token
23
+ @comm_token = request('getCommunicationToken', {:secretKey => Digest::MD5.hexdigest(@session)}, true)
24
+ end
25
+
26
+ # Sign method
27
+ def create_token(method)
28
+ rnd = rand(256**3).to_s(16).rjust(6, '0')
29
+ plain = [method, @comm_token, 'quitStealinMahShit', rnd].join(':')
30
+ hash = Digest::SHA1.hexdigest(plain)
31
+ "#{rnd}#{hash}"
32
+ end
33
+
34
+ # Authenticate user
35
+ def login(user, password)
36
+ data = request('authenticateUser', {:username => user, :password => password}, true)
37
+ @user = User.new(self, data)
38
+ raise InvalidAuthentication, 'Wrong username or password!' if @user.id == 0
39
+ return @user
40
+ end
41
+
42
+ # Perform search request for query
43
+ def search(type, query)
44
+ results = request('getSearchResults', {:type => type, :query => query})
45
+ results.map { |song| Song.new song }
46
+ end
47
+
48
+ # Perform songs search request for query
49
+ def search_songs(query)
50
+ search('Songs', query)
51
+ end
52
+
53
+ # Return raw response for songs search request
54
+ def search_songs_pure(query)
55
+ request('getSearchResultsEx', {:type => 'Songs', :query => query})
56
+ end
57
+
58
+ # Get stream authentication by song ID
59
+ def get_stream_auth_by_songid(song_id)
60
+ request('getStreamKeyFromSongIDEx', {
61
+ 'songID' => song_id,
62
+ 'prefetch' => false,
63
+ 'mobile' => false,
64
+ 'country' => COUNTRY
65
+ })
66
+ end
67
+
68
+ # Get stream authentication for song object
69
+ def get_stream_auth(song)
70
+ get_stream_auth_by_songid(song.id)
71
+ end
72
+
73
+ # Get song stream url by ID
74
+ def get_song_url_by_id(id)
75
+ resp = get_stream_auth_by_songid(id)
76
+ "http://#{resp['ip']}/stream.php?streamKey=#{resp['streamKey']}"
77
+ end
78
+
79
+ # Get song stream
80
+ def get_song_url(song)
81
+ get_song_url_by_id(song.id)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,4 @@
1
+ module Grooveshark
2
+ class InvalidAuthentication < Exception ; end
3
+ class GeneralError < Exception ; end
4
+ end
@@ -0,0 +1,44 @@
1
+ module Grooveshark
2
+ class Playlist
3
+ attr_reader :id, :user_id
4
+ attr_reader :name, :about, :picture, :username
5
+ attr_reader :songs
6
+
7
+ def initialize(client, data=nil, user_id=nil)
8
+ @client = client
9
+ @songs = []
10
+
11
+ if data
12
+ @id = data['PlaylistID']
13
+ @name = data['Name']
14
+ @about = data['About']
15
+ @picture = data['Picture']
16
+ @user_id = data['UserID'] || user_id
17
+ @username = data['Username']
18
+ end
19
+ end
20
+
21
+ # Fetch playlist songs
22
+ def load_songs
23
+ @songs = @client.request('playlistGetSongs', :playlistID => @id)['Songs']
24
+ @songs.map! { |s| Song.new(s) }
25
+ end
26
+
27
+ # Rename playlist
28
+ def rename(name, description)
29
+ begin
30
+ @client.request('renamePlaylist', :playlistID => @id, :playlistName => name)
31
+ @client.request('setPlaylistAbout', :playlistID => @id, :about => description)
32
+ @name = name ; @about = description
33
+ return true
34
+ rescue
35
+ return false
36
+ end
37
+ end
38
+
39
+ # Delete existing playlist
40
+ def delete
41
+ @client.request('deletePlaylist', {:playlistID => @id, :name => @name})
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,46 @@
1
+ module Grooveshark
2
+ module Request
3
+ API_BASE = 'cowbell.grooveshark.com'
4
+ UUID = 'E2AB1A59-C6B7-480E-992A-55DE1699D7F8'
5
+ CLIENT = 'htmlshark'
6
+ CLIENT_REV = '20101012.37'
7
+ COUNTRY = {"CC2" => "0","IPR" => "1","CC1" => "0","ID" => "1","CC4" => "0","CC3" => "0"}
8
+
9
+ # Client overrides for different methods
10
+ METHOD_CLIENTS = {
11
+ 'getStreamKeyFromSongIDEx' => 'jsqueue'
12
+ }
13
+
14
+ # Perform API request
15
+ def request(method, params, secure=false)
16
+ agent = METHOD_CLIENTS.key?(method) ? METHOD_CLIENTS[method] : CLIENT
17
+ url = "#{secure ? 'https' : 'http'}://#{API_BASE}/more.php?#{method}"
18
+ body = {
19
+ 'header' => {
20
+ 'session' => @session,
21
+ 'uuid' => UUID,
22
+ 'client' => agent,
23
+ 'clientRevision' => CLIENT_REV,
24
+ 'country' => COUNTRY
25
+ },
26
+ 'method' => method,
27
+ 'parameters' => params
28
+ }
29
+ body['header']['token'] = create_token(method) if @comm_token
30
+
31
+ begin
32
+ data = RestClient.post(
33
+ url, body.to_json,
34
+ :content_type => :json,
35
+ :accept => :json,
36
+ :cookie => "PHPSESSID=#{@session}"
37
+ )
38
+ rescue Exception => ex
39
+ raise GeneralError # Need define error handling
40
+ end
41
+
42
+ data = JSON.parse(data)
43
+ return data['result'] unless data['fault']
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,40 @@
1
+ module Grooveshark
2
+ class Song
3
+ attr_reader :data
4
+ attr_reader :id, :artist_id, :album_id
5
+ attr_reader :name, :artist, :album, :track
6
+ attr_reader :duraion, :artwork, :playcount
7
+
8
+ def initialize(data=nil)
9
+ unless data.nil?
10
+ @data = data
11
+ @id = data['SongID']
12
+ @name = data['SongName'] || data['Name']
13
+ @artist = data['ArtistName']
14
+ @artist_id = data['ArtistID']
15
+ @album = data['AlbumName']
16
+ @album_id = data['AlbumID']
17
+ @track = data['TrackNum']
18
+ @duration = data['EstimateDuration']
19
+ @artwork = data['CoverArtFilename']
20
+ @playcount = data['SongPlays']
21
+ end
22
+ end
23
+
24
+ def to_s
25
+ [@id, @name, @artist].join(' - ')
26
+ end
27
+
28
+ def to_hash
29
+ {
30
+ 'songID' => @id,
31
+ 'songName' => @name,
32
+ 'artistName' => @artist,
33
+ 'artistID' => @artist_id,
34
+ 'albumName' => @album,
35
+ 'albumID' => @album_id,
36
+ 'track' => @track
37
+ }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,87 @@
1
+ module Grooveshark
2
+ class User
3
+ attr_reader :id, :username, :premium, :data
4
+ attr_reader :playlists, :favorites
5
+
6
+ # Init user account object
7
+ def initialize(client, data=nil)
8
+ if data
9
+ @data = data
10
+ @id = data['userID']
11
+ @username = data['username']
12
+ @premium = data['isPremium']
13
+ end
14
+ @client = client
15
+ end
16
+
17
+ # --------------------------------------------------------------------------
18
+ # User Library
19
+ # --------------------------------------------------------------------------
20
+
21
+ # Fetch songs from library
22
+ def library(page=0)
23
+ resp = @client.request('userGetSongsInLibrary', {:userID => @id, :page => page.to_s})['Songs']
24
+ resp.map { |s| Song.new(s) }
25
+ end
26
+
27
+ # Add songs to user library (DOES NOT WORK FOR SOME REASON)
28
+ def library_add(songs=[])
29
+ @client.request('userAddSongsToLibrary', {:songs => songs.map { |s| s.to_hash }})
30
+ end
31
+
32
+ # Remove song from user library
33
+ def library_remove(song)
34
+ song_id = song.kind_of?(Song) ? song.id : song.to_s
35
+ @client.request('userRemoveSongFromLibrary', {:userID => @id, :songID => song_id})
36
+ end
37
+
38
+ # --------------------------------------------------------------------------
39
+ # User Playlists
40
+ # --------------------------------------------------------------------------
41
+
42
+ # Fetch user playlists
43
+ def playlists
44
+ return @playlists if @playlists
45
+ results = @client.request('userGetPlaylists', :userID => @id)
46
+ @playlists = results['Playlists'].map { |list| Playlist.new(@client, list, @id) }
47
+ end
48
+
49
+ # Get playlist by ID
50
+ def get_playlist(id)
51
+ result = playlists.select { |p| p.id == id }
52
+ result.nil? ? nil : result.first
53
+ end
54
+
55
+ # Create new user playlist
56
+ def create_playlist(name, description='', songs=[])
57
+ @client.request('createPlaylist', {
58
+ 'playlistName' => name,
59
+ 'playlistAbout' => description,
60
+ 'songIDs' => songs.map { |s| s.kind_of?(Song) ? s.id : s.to_s }
61
+ })
62
+ end
63
+
64
+ # --------------------------------------------------------------------------
65
+ # User Favorites
66
+ # --------------------------------------------------------------------------
67
+
68
+ # Get user favorites
69
+ def favorites
70
+ return @favorites if @favorites
71
+ resp = @client.request('getFavorites', :ofWhat => 'Songs', :userID => @id)
72
+ @favorites = resp.map { |s| Song.new(s) }
73
+ end
74
+
75
+ # Add song to favorites
76
+ def add_favorite(song)
77
+ song_id = song.kind_of?(Song) ? song.id : song
78
+ @client.request('favorite', {:what => 'Song', :ID => song_id})
79
+ end
80
+
81
+ # Remove song from favorites
82
+ def remove_favorite(song)
83
+ song_id = song.kind_of?(Song) ? song.id : song
84
+ @client.request('unfavorite', {:what => 'Song', :ID => song_id})
85
+ end
86
+ end
87
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grooveshark
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Dan Sosedoff
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-08 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 11
30
+ segments:
31
+ - 1
32
+ - 4
33
+ - 6
34
+ version: 1.4.6
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rest-client
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 1
46
+ segments:
47
+ - 1
48
+ - 5
49
+ - 1
50
+ version: 1.5.1
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Unofficial ruby library for consuming the Grooveshark API.
54
+ email: dan.sosedoff@gmail.com
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files: []
60
+
61
+ files:
62
+ - lib/grooveshark.rb
63
+ - lib/grooveshark/client.rb
64
+ - lib/grooveshark/errors.rb
65
+ - lib/grooveshark/playlist.rb
66
+ - lib/grooveshark/request.rb
67
+ - lib/grooveshark/song.rb
68
+ - lib/grooveshark/user.rb
69
+ has_rdoc: true
70
+ homepage: http://github.com/sosedoff/grooveshark
71
+ licenses: []
72
+
73
+ post_install_message:
74
+ rdoc_options: []
75
+
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ requirements: []
97
+
98
+ rubyforge_project:
99
+ rubygems_version: 1.4.1
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Grooveshark API
103
+ test_files: []
104
+