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