rdio_api 0.1.0
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.
- data/.gitignore +11 -0
- data/Gemfile +4 -0
- data/Guardfile +20 -0
- data/README.md +115 -0
- data/Rakefile +10 -0
- data/lib/rdio_api/api.rb +81 -0
- data/lib/rdio_api/client.rb +48 -0
- data/lib/rdio_api/version.rb +3 -0
- data/lib/rdio_api.rb +14 -0
- data/rdio_api.gemspec +30 -0
- data/spec/fixtures/addFriend.json +4 -0
- data/spec/fixtures/addToCollection.json +4 -0
- data/spec/fixtures/addToPlaylist.json +4 -0
- data/spec/fixtures/createPlaylist.json +19 -0
- data/spec/fixtures/currentUser.json +14 -0
- data/spec/fixtures/deletePlaylist.json +4 -0
- data/spec/fixtures/findUser.json +14 -0
- data/spec/fixtures/get.json +16 -0
- data/spec/fixtures/getActivityStream.json +18 -0
- data/spec/fixtures/getAlbumsForArtist.json +917 -0
- data/spec/fixtures/getAlbumsForArtistInCollection.json +82 -0
- data/spec/fixtures/getAlbumsInCollection.json +1184 -0
- data/spec/fixtures/getArtistsInCollection.json +37 -0
- data/spec/fixtures/getHeavyRotation.json +394 -0
- data/spec/fixtures/getNewReleases.json +796 -0
- data/spec/fixtures/getObjectFromShortCode.json +33 -0
- data/spec/fixtures/getObjectFromUrl.json +16 -0
- data/spec/fixtures/getPlaybackToken.json +4 -0
- data/spec/fixtures/getPlaylists.json +25 -0
- data/spec/fixtures/getTopCharts.json +181 -0
- data/spec/fixtures/getTracksForAlbumInCollection.json +440 -0
- data/spec/fixtures/getTracksForArtist.json +295 -0
- data/spec/fixtures/getTracksForArtistInCollection.json +34 -0
- data/spec/fixtures/getTracksInCollection.json +121 -0
- data/spec/fixtures/removeFriend.json +4 -0
- data/spec/fixtures/removeFromCollection.json +4 -0
- data/spec/fixtures/removeFromPlaylist.json +4 -0
- data/spec/fixtures/search.json +523 -0
- data/spec/fixtures/searchSuggestions.json +117 -0
- data/spec/fixtures/setAvailableOffline.json +4 -0
- data/spec/fixtures/setPlaylistCollaborating.json +4 -0
- data/spec/fixtures/setPlaylistCollaborationMode.json +4 -0
- data/spec/fixtures/setPlaylistFields.json +4 -0
- data/spec/fixtures/setPlaylistOrder.json +4 -0
- data/spec/fixtures/userFollowers.json +27 -0
- data/spec/fixtures/userFollowing.json +27 -0
- data/spec/helper.rb +26 -0
- data/spec/rdio_api/activity_spec.rb +59 -0
- data/spec/rdio_api/catalog_spec.rb +77 -0
- data/spec/rdio_api/client_spec.rb +18 -0
- data/spec/rdio_api/collection_spec.rb +127 -0
- data/spec/rdio_api/core_spec.rb +59 -0
- data/spec/rdio_api/playback_spec.rb +22 -0
- data/spec/rdio_api/playlists_spec.rb +122 -0
- data/spec/rdio_api/social_spec.rb +92 -0
- metadata +273 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :version => 2 do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^spec/.+_spec\.rb$})
|
11
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
12
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
13
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
14
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
15
|
+
watch('spec/spec_helper.rb') { "spec" }
|
16
|
+
watch('config/routes.rb') { "spec/routing" }
|
17
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
18
|
+
# Capybara request specs
|
19
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
20
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
Rdio
|
2
|
+
====================
|
3
|
+
Ruby wrapper for the [Rdio](http://rdio.com) API. Inspired from [Linkedin gem](https://github.com/pengwynn/linkedin) & [Twitter gem](https://github.com/jnunemaker/twitter).
|
4
|
+
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
gem install rdio_api
|
9
|
+
|
10
|
+
|
11
|
+
Usage
|
12
|
+
-----
|
13
|
+
|
14
|
+
Register for developer keys at [http://developer.rdio.com/](http://developer.rdio.com/).
|
15
|
+
|
16
|
+
All the methods are exactly as in the [API docs](http://developer.rdio.com/docs/read/rest/Methods), camel cased and all the endpoints are also exactly the same.
|
17
|
+
|
18
|
+
OAuth flow is not part of this gem. Recommend using [OmniAuth](https://github.com/intridea/omniauth). Also check Rdio [OAuth documentation](http://developer.rdio.com/docs/read/rest/oauth).
|
19
|
+
|
20
|
+
|
21
|
+
Usage Examples
|
22
|
+
--------------
|
23
|
+
require "rubygems"
|
24
|
+
require "rdio_api"
|
25
|
+
|
26
|
+
# Initialize a new Rdio client
|
27
|
+
client = RdioApi.new(:consumer_key => CONSUMER_KEY, :consumer_secret => CONSUMER_SECRET)
|
28
|
+
|
29
|
+
# Get songs in heavy rotation
|
30
|
+
client.getHeavyRotation(:type => "albums")
|
31
|
+
|
32
|
+
# Get top playlists
|
33
|
+
client.getTopCharts(:type => "Playlist")
|
34
|
+
|
35
|
+
# Search for a query and and pass in the type
|
36
|
+
client.search(:query => "michael giacchino", :types => "album")
|
37
|
+
|
38
|
+
# Get activity stream of a user
|
39
|
+
client.getActivityStream(:user => "s12345", :scope => "user")
|
40
|
+
|
41
|
+
# Find a user by email address
|
42
|
+
client.findUser(:email => "email@example.com")
|
43
|
+
|
44
|
+
# Methods that act on behalf of a user require an access token, OmniAuth is best for this
|
45
|
+
|
46
|
+
# Access token can be set at initialization
|
47
|
+
client = RdioApi.new(:consumer_key => CONSUMER_KEY,
|
48
|
+
:consumer_secret => CONSUMER_SECRET,
|
49
|
+
:access_token => ACCESS_TOKEN)
|
50
|
+
|
51
|
+
# Access token can also be set at the clien't access_token instance variable
|
52
|
+
client.access_token = ACCESS_TOKEN
|
53
|
+
|
54
|
+
# Get info about the current user
|
55
|
+
client.currentUser
|
56
|
+
|
57
|
+
# Add a friend
|
58
|
+
client.addFriend(:user => "s12345")
|
59
|
+
|
60
|
+
# Create a Playlist
|
61
|
+
client.createPlaylist(:name => "RubyGem",
|
62
|
+
:description => "Testing",
|
63
|
+
:tracks => "t1945474, t3483614")
|
64
|
+
|
65
|
+
Available Methods
|
66
|
+
-----------------
|
67
|
+
|
68
|
+
# Unauthenticated methods, which only require registering for developer keys
|
69
|
+
client.get
|
70
|
+
client.getAlbumsForArtist
|
71
|
+
client.getTracksForArtist
|
72
|
+
client.search
|
73
|
+
client.searchSuggestions
|
74
|
+
client.getAlbumsForArtistInCollection
|
75
|
+
client.getAlbumsInCollection
|
76
|
+
client.getArtistsInCollection
|
77
|
+
client.getTracksForAlbumInCollection
|
78
|
+
client.getTracksForArtistInCollection
|
79
|
+
client.getTracksInCollection
|
80
|
+
client.findUser
|
81
|
+
client.userFollowers
|
82
|
+
client.userFollowing
|
83
|
+
client.getActivityStream
|
84
|
+
client.getHeavyRotation
|
85
|
+
client.getNewReleases
|
86
|
+
client.getTopCharts
|
87
|
+
client.getPlaybackToken
|
88
|
+
|
89
|
+
# Authenticated methods, which require an access token , obtained with user permission
|
90
|
+
client.getObjectFromShortCode
|
91
|
+
client.getObjectFromUrl
|
92
|
+
client.addToCollection
|
93
|
+
client.removeFromCollection
|
94
|
+
client.setAvailableOffline
|
95
|
+
client.addToPlaylist
|
96
|
+
client.createPlaylist
|
97
|
+
client.deletePlaylist
|
98
|
+
client.getPlaylists
|
99
|
+
client.removeFromPlaylist
|
100
|
+
client.setPlaylistCollaborating
|
101
|
+
client.setPlaylistCollaborationMode
|
102
|
+
client.setPlaylistFields
|
103
|
+
client.setPlaylistOrder
|
104
|
+
client.addFriend
|
105
|
+
client.currentUser
|
106
|
+
client.removeFriend
|
107
|
+
|
108
|
+
TODO
|
109
|
+
----
|
110
|
+
* Explore moving methods from camel case to snake case and update tests accordingly
|
111
|
+
* OAuth flow
|
112
|
+
* More tests for methods and for each endpoints
|
113
|
+
* Test and Support multiple Rubies
|
114
|
+
|
115
|
+
|
data/Rakefile
ADDED
data/lib/rdio_api/api.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
require 'hashie'
|
3
|
+
|
4
|
+
module RdioApi
|
5
|
+
|
6
|
+
module Api
|
7
|
+
|
8
|
+
def method_missing(method_sym, *arguments)
|
9
|
+
if UNAUTHENTICATED.include?(method_sym)
|
10
|
+
unauthenticated_request(method_sym, *arguments)
|
11
|
+
elsif AUTHENTICATED.include?(method_sym)
|
12
|
+
authenticated_request(method_sym, *arguments)
|
13
|
+
else
|
14
|
+
raise NoMethodError.new("Undefined method '#{method_sym}' for #{self}")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def respond_to?(method)
|
19
|
+
AUTHENTICATED.include?(method.to_sym) || UNAUTHENTICATED.include?(method.to_sym) ? true : false
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def unauthenticated_request(method_sym, *arguments)
|
25
|
+
response = unauthenticated_connection.post do |request|
|
26
|
+
request.body = {:method => method_sym.to_s}.merge!(Hash[*arguments.flatten])
|
27
|
+
end
|
28
|
+
response.body.result
|
29
|
+
end
|
30
|
+
|
31
|
+
def authenticated_request(method_sym, *arguments)
|
32
|
+
if authenticated_connection
|
33
|
+
response = MultiJson.decode(authenticated_connection.post(api_url,
|
34
|
+
{:method => method_sym.to_s}.merge!(Hash[*arguments.flatten])).body)['result']
|
35
|
+
response.is_a?(Hash) ? Hashie::Mash.new(response) : response
|
36
|
+
else
|
37
|
+
"Set access token at initialization or the client's access_token instance variable"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
UNAUTHENTICATED = [
|
42
|
+
:get,
|
43
|
+
:getAlbumsForArtist,
|
44
|
+
:getTracksForArtist,
|
45
|
+
:search,
|
46
|
+
:searchSuggestions,
|
47
|
+
:getAlbumsForArtistInCollection,
|
48
|
+
:getAlbumsInCollection,
|
49
|
+
:getArtistsInCollection,
|
50
|
+
:getTracksForAlbumInCollection,
|
51
|
+
:getTracksForArtistInCollection,
|
52
|
+
:getTracksInCollection,
|
53
|
+
:findUser,
|
54
|
+
:userFollowers,
|
55
|
+
:userFollowing,
|
56
|
+
:getActivityStream,
|
57
|
+
:getHeavyRotation,
|
58
|
+
:getNewReleases,
|
59
|
+
:getTopCharts,
|
60
|
+
:getPlaybackToken]
|
61
|
+
|
62
|
+
AUTHENTICATED = [
|
63
|
+
:getObjectFromShortCode,
|
64
|
+
:getObjectFromUrl,
|
65
|
+
:addToCollection,
|
66
|
+
:removeFromCollection,
|
67
|
+
:setAvailableOffline,
|
68
|
+
:addToPlaylist,
|
69
|
+
:createPlaylist,
|
70
|
+
:deletePlaylist,
|
71
|
+
:getPlaylists,
|
72
|
+
:removeFromPlaylist,
|
73
|
+
:setPlaylistCollaborating,
|
74
|
+
:setPlaylistCollaborationMode,
|
75
|
+
:setPlaylistFields,
|
76
|
+
:setPlaylistOrder,
|
77
|
+
:addFriend,
|
78
|
+
:currentUser,
|
79
|
+
:removeFriend]
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module RdioApi
|
2
|
+
|
3
|
+
class Client
|
4
|
+
|
5
|
+
include Api
|
6
|
+
|
7
|
+
attr_reader :consumer_key, :consumer_secret
|
8
|
+
attr_accessor :access_token
|
9
|
+
|
10
|
+
# Initialize the client for API request. A consumer key and consumer secret are required.
|
11
|
+
# Requests on behalf of the user require access_token (oauth token)
|
12
|
+
|
13
|
+
def initialize(options={})
|
14
|
+
@consumer_key = options[:consumer_key]
|
15
|
+
@consumer_secret = options[:consumer_secret]
|
16
|
+
@access_token = options[:access_token]
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Set up the connection to use for all requests based on the options from intialization.
|
22
|
+
|
23
|
+
def unauthenticated_connection
|
24
|
+
params = {}
|
25
|
+
params[:consumer_key] = @consumer_key
|
26
|
+
params[:consumer_secret] = @consumer_secret
|
27
|
+
@connection ||= Faraday.new(:url => api_url) do |builder|
|
28
|
+
builder.use Faraday::Request::OAuth, params
|
29
|
+
builder.use Faraday::Request::UrlEncoded
|
30
|
+
builder.use Faraday::Response::Mashify
|
31
|
+
builder.use Faraday::Response::ParseJson
|
32
|
+
builder.adapter Faraday.default_adapter
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Sets the access token to make authenticated calls
|
37
|
+
|
38
|
+
def authenticated_connection
|
39
|
+
@access_token
|
40
|
+
end
|
41
|
+
|
42
|
+
# Base URL for api requests
|
43
|
+
|
44
|
+
def api_url
|
45
|
+
("http://api.rdio.com/1/").freeze
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/rdio_api.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rdio_api/version"
|
2
|
+
require 'faraday'
|
3
|
+
require 'faraday_middleware'
|
4
|
+
|
5
|
+
require 'rdio_api/api'
|
6
|
+
require 'rdio_api/client'
|
7
|
+
|
8
|
+
module RdioApi
|
9
|
+
|
10
|
+
# RdioApi::Client.new alias
|
11
|
+
def self.new(options={})
|
12
|
+
RdioApi::Client.new(options)
|
13
|
+
end
|
14
|
+
end
|
data/rdio_api.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rdio_api/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rdio_api"
|
7
|
+
s.version = RdioApi::VERSION
|
8
|
+
s.authors = ["Anil"]
|
9
|
+
s.homepage = "http://github.com/anilv/rdio_api"
|
10
|
+
s.summary = %q{A Ruby wrapper for the Rdio API}
|
11
|
+
s.description = %q{A Ruby wrapper for the Rdio API}
|
12
|
+
|
13
|
+
s.add_development_dependency 'rake', '~> 0.9'
|
14
|
+
s.add_development_dependency 'rspec', '~> 2.6'
|
15
|
+
s.add_development_dependency 'webmock', '~>1.6'
|
16
|
+
s.add_development_dependency 'oauth', '~>0.4.5'
|
17
|
+
s.add_development_dependency 'rb-fsevent'
|
18
|
+
s.add_development_dependency 'guard-rspec'
|
19
|
+
|
20
|
+
s.add_runtime_dependency 'faraday', '~> 0.6.1'
|
21
|
+
s.add_runtime_dependency 'faraday_middleware', '~> 0.6.5'
|
22
|
+
s.add_runtime_dependency 'hashie', '~> 1.0.0'
|
23
|
+
s.add_runtime_dependency 'multi_json', '~> 1.0.3'
|
24
|
+
s.add_runtime_dependency 'simple_oauth', '~> 0.1.5'
|
25
|
+
|
26
|
+
s.files = `git ls-files`.split("\n")
|
27
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
28
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
29
|
+
s.require_paths = ["lib"]
|
30
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"status" :"ok",
|
3
|
+
"result" : {
|
4
|
+
"ownerKey": "s27093",
|
5
|
+
"name": "RubyGem",
|
6
|
+
"baseIcon": "album/f/4/8/000000000002784f/square-200.jpg",
|
7
|
+
"ownerIcon": "user/no-user-image-square.jpg",
|
8
|
+
"owner": "Anil V",
|
9
|
+
"lastUpdated": 1312411563.0,
|
10
|
+
"shortUrl": "http://rd.io/x/QDaXL0BSKw",
|
11
|
+
"length": 2,
|
12
|
+
"url": "/people/anilv/playlists/200057/RubyGem/",
|
13
|
+
"key": "p200057",
|
14
|
+
"ownerUrl": "/people/anilv/",
|
15
|
+
"embedUrl": "http://rd.io/e/QDaXL0BSKw",
|
16
|
+
"type": "p",
|
17
|
+
"icon": "http://m.rdio.com/_is/?aid=284243,161871&w=200&h=200"
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
{
|
2
|
+
"status" :"ok",
|
3
|
+
"result" : {
|
4
|
+
"firstName": "Anil",
|
5
|
+
"baseIcon": "user/no-user-image-square.jpg",
|
6
|
+
"gender": "m",
|
7
|
+
"url": "/people/anilv/",
|
8
|
+
"key": "s27093",
|
9
|
+
"lastName": "V",
|
10
|
+
"libraryVersion": 110,
|
11
|
+
"type": "s",
|
12
|
+
"icon": "http://media.rd.io/user/no-user-image-square.jpg"
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
{
|
2
|
+
"status" :"ok",
|
3
|
+
"result" : {
|
4
|
+
"firstName": "Anil",
|
5
|
+
"baseIcon": "user/no-user-image-square.jpg",
|
6
|
+
"gender": "m",
|
7
|
+
"url": "/people/anilv/",
|
8
|
+
"key": "s27093",
|
9
|
+
"lastName": "V",
|
10
|
+
"libraryVersion": 110,
|
11
|
+
"type": "s",
|
12
|
+
"icon": "http://media.rd.io/user/no-user-image-square.jpg"
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"status" :"ok",
|
3
|
+
"result" : {
|
4
|
+
"r13700" : {
|
5
|
+
"name" : "John Williams",
|
6
|
+
"hasRadio" : false,
|
7
|
+
"baseIcon" : "artist/4/8/5/0000000000003584/square-200.jpg",
|
8
|
+
"shortUrl" : "http://rd.io/x/Qi132w",
|
9
|
+
"length" : 2075,
|
10
|
+
"url" : "/artist/John_Williams/",
|
11
|
+
"key" : "r13700",
|
12
|
+
"type" : "r",
|
13
|
+
"icon" : "http://media.rd.io/artist/4/8/5/0000000000003584/square-200.jpg"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
{
|
2
|
+
"status" :"ok",
|
3
|
+
"result" : {
|
4
|
+
"last_id": 0,
|
5
|
+
"user": {
|
6
|
+
"firstName": "Anil",
|
7
|
+
"baseIcon": "user/no-user-image-square.jpg",
|
8
|
+
"gender": "m",
|
9
|
+
"url": "/people/anilv/",
|
10
|
+
"key": "s27093",
|
11
|
+
"lastName": "V",
|
12
|
+
"libraryVersion": 110,
|
13
|
+
"type": "s",
|
14
|
+
"icon": "http://media.rd.io/user/no-user-image-square.jpg"
|
15
|
+
},
|
16
|
+
"updates": []
|
17
|
+
}
|
18
|
+
}
|