grooveshark 0.1.1

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.
@@ -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
+