rdio_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +11 -0
  2. data/Gemfile +4 -0
  3. data/Guardfile +20 -0
  4. data/README.md +115 -0
  5. data/Rakefile +10 -0
  6. data/lib/rdio_api/api.rb +81 -0
  7. data/lib/rdio_api/client.rb +48 -0
  8. data/lib/rdio_api/version.rb +3 -0
  9. data/lib/rdio_api.rb +14 -0
  10. data/rdio_api.gemspec +30 -0
  11. data/spec/fixtures/addFriend.json +4 -0
  12. data/spec/fixtures/addToCollection.json +4 -0
  13. data/spec/fixtures/addToPlaylist.json +4 -0
  14. data/spec/fixtures/createPlaylist.json +19 -0
  15. data/spec/fixtures/currentUser.json +14 -0
  16. data/spec/fixtures/deletePlaylist.json +4 -0
  17. data/spec/fixtures/findUser.json +14 -0
  18. data/spec/fixtures/get.json +16 -0
  19. data/spec/fixtures/getActivityStream.json +18 -0
  20. data/spec/fixtures/getAlbumsForArtist.json +917 -0
  21. data/spec/fixtures/getAlbumsForArtistInCollection.json +82 -0
  22. data/spec/fixtures/getAlbumsInCollection.json +1184 -0
  23. data/spec/fixtures/getArtistsInCollection.json +37 -0
  24. data/spec/fixtures/getHeavyRotation.json +394 -0
  25. data/spec/fixtures/getNewReleases.json +796 -0
  26. data/spec/fixtures/getObjectFromShortCode.json +33 -0
  27. data/spec/fixtures/getObjectFromUrl.json +16 -0
  28. data/spec/fixtures/getPlaybackToken.json +4 -0
  29. data/spec/fixtures/getPlaylists.json +25 -0
  30. data/spec/fixtures/getTopCharts.json +181 -0
  31. data/spec/fixtures/getTracksForAlbumInCollection.json +440 -0
  32. data/spec/fixtures/getTracksForArtist.json +295 -0
  33. data/spec/fixtures/getTracksForArtistInCollection.json +34 -0
  34. data/spec/fixtures/getTracksInCollection.json +121 -0
  35. data/spec/fixtures/removeFriend.json +4 -0
  36. data/spec/fixtures/removeFromCollection.json +4 -0
  37. data/spec/fixtures/removeFromPlaylist.json +4 -0
  38. data/spec/fixtures/search.json +523 -0
  39. data/spec/fixtures/searchSuggestions.json +117 -0
  40. data/spec/fixtures/setAvailableOffline.json +4 -0
  41. data/spec/fixtures/setPlaylistCollaborating.json +4 -0
  42. data/spec/fixtures/setPlaylistCollaborationMode.json +4 -0
  43. data/spec/fixtures/setPlaylistFields.json +4 -0
  44. data/spec/fixtures/setPlaylistOrder.json +4 -0
  45. data/spec/fixtures/userFollowers.json +27 -0
  46. data/spec/fixtures/userFollowing.json +27 -0
  47. data/spec/helper.rb +26 -0
  48. data/spec/rdio_api/activity_spec.rb +59 -0
  49. data/spec/rdio_api/catalog_spec.rb +77 -0
  50. data/spec/rdio_api/client_spec.rb +18 -0
  51. data/spec/rdio_api/collection_spec.rb +127 -0
  52. data/spec/rdio_api/core_spec.rb +59 -0
  53. data/spec/rdio_api/playback_spec.rb +22 -0
  54. data/spec/rdio_api/playlists_spec.rb +122 -0
  55. data/spec/rdio_api/social_spec.rb +92 -0
  56. metadata +273 -0
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ *.gem
2
+ *.rbc
3
+ .DS_Store
4
+ .bundle
5
+ .rvmrc
6
+ .yardoc
7
+ Gemfile.lock
8
+ coverage/*
9
+ doc/*
10
+ log/*
11
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rdio_api.gemspec
4
+ gemspec
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
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :test => :spec
10
+ task :default => :spec
@@ -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
@@ -0,0 +1,3 @@
1
+ module RdioApi
2
+ VERSION = "0.1.0"
3
+ 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,4 @@
1
+ {
2
+ "status" :"ok",
3
+ "result" : "true"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "status" :"ok",
3
+ "result" : "true"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "status" :"ok",
3
+ "result" : "true"
4
+ }
@@ -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,4 @@
1
+ {
2
+ "status" :"ok",
3
+ "result" : "true"
4
+ }
@@ -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
+ }