jberkel-spotify-api 0.0.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.
- data/.gitignore +1 -0
 - data/LICENSE +24 -0
 - data/README.md +91 -0
 - data/Rakefile +33 -0
 - data/VERSION.yml +4 -0
 - data/bin/spotify-api-server +25 -0
 - data/examples/create_playlist.rb +24 -0
 - data/examples/list_playlists.rb +16 -0
 - data/examples/search.rb +16 -0
 - data/lib/jars/jotify.jar +0 -0
 - data/lib/jotify.rb +109 -0
 - data/lib/jotify/api.rb +114 -0
 - data/lib/jotify/media.rb +99 -0
 - data/spec/api_spec.rb +179 -0
 - data/spec/integration_spec.rb +33 -0
 - data/spec/jotify_spec.rb +32 -0
 - data/spec/media_spec.rb +77 -0
 - data/spec/spec_helper.rb +11 -0
 - data/spotify-api.gemspec +76 -0
 - metadata +119 -0
 
    
        data/.gitignore
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            pkg
         
     | 
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2009, Jan Berkel
         
     | 
| 
      
 2 
     | 
    
         
            +
            All rights reserved.
         
     | 
| 
      
 3 
     | 
    
         
            +
             
         
     | 
| 
      
 4 
     | 
    
         
            +
            Redistribution and use in source and binary forms, with or without
         
     | 
| 
      
 5 
     | 
    
         
            +
            modification, are permitted provided that the following conditions are met:
         
     | 
| 
      
 6 
     | 
    
         
            +
                * Redistributions of source code must retain the above copyright
         
     | 
| 
      
 7 
     | 
    
         
            +
                  notice, this list of conditions and the following disclaimer.
         
     | 
| 
      
 8 
     | 
    
         
            +
                * Redistributions in binary form must reproduce the above copyright
         
     | 
| 
      
 9 
     | 
    
         
            +
                  notice, this list of conditions and the following disclaimer in the
         
     | 
| 
      
 10 
     | 
    
         
            +
                  documentation and/or other materials provided with the distribution.
         
     | 
| 
      
 11 
     | 
    
         
            +
                * Neither the name of spotify-api nor the
         
     | 
| 
      
 12 
     | 
    
         
            +
                  names of its contributors may be used to endorse or promote products
         
     | 
| 
      
 13 
     | 
    
         
            +
                  derived from this software without specific prior written permission.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
         
     | 
| 
      
 15 
     | 
    
         
            +
            THIS SOFTWARE IS PROVIDED BY Jan Berkel 'AS IS'' AND ANY
         
     | 
| 
      
 16 
     | 
    
         
            +
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
         
     | 
| 
      
 17 
     | 
    
         
            +
            WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
         
     | 
| 
      
 18 
     | 
    
         
            +
            DISCLAIMED. IN NO EVENT SHALL David R. MacIver BE LIABLE FOR ANY
         
     | 
| 
      
 19 
     | 
    
         
            +
            DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
         
     | 
| 
      
 20 
     | 
    
         
            +
            (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
         
     | 
| 
      
 21 
     | 
    
         
            +
            LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
         
     | 
| 
      
 22 
     | 
    
         
            +
            ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
         
     | 
| 
      
 23 
     | 
    
         
            +
            (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
         
     | 
| 
      
 24 
     | 
    
         
            +
            SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,91 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            # Spotify-API
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            I got tired of waiting for Spotify to release their API (if they release it), so decided to roll my own based on the awesome
         
     | 
| 
      
 5 
     | 
    
         
            +
            work done by [#hack.se](http://despotify.se) (despotify) and Felix Bruns who created a Java port of despotify called 
         
     | 
| 
      
 6 
     | 
    
         
            +
            [jotify](http://jotify.felixbruns.de/). Add JRuby, Sinatra and some glue to the mix and you (almost) have an API.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            *Important*: in order to use this API you'll need a premium spotify account! This API is as unofficial as it gets and *NOT* supported
         
     | 
| 
      
 9 
     | 
    
         
            +
            by Spotify in any way.
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            At the moment the following features are implemented:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            * searching 							[GET /(albums|tracks|artists)?name=Foo]
         
     | 
| 
      
 14 
     | 
    
         
            +
            * list user's playlists 	[GET /playlists]
         
     | 
| 
      
 15 
     | 
    
         
            +
            * get shared playlist			[GET /playlist/id]
         
     | 
| 
      
 16 
     | 
    
         
            +
            * create new playlist   	[POST /playlists]
         
     | 
| 
      
 17 
     | 
    
         
            +
            * add tracks to playlist  [PUT	/playlists/id]
         
     | 
| 
      
 18 
     | 
    
         
            +
            	
         
     | 
| 
      
 19 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            Prerequisites: *Java 6+*, JRuby 1.3.x.
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            		$ jruby -S gem install jberkel-spotify-api --source http://gems.github.com
         
     | 
| 
      
 24 
     | 
    
         
            +
            		$ jruby -S spotify-api-server --account login:password
         
     | 
| 
      
 25 
     | 
    
         
            +
            		== Sinatra/0.9.4 has taken the stage on 3000 for development with backup from WEBrick
         
     | 
| 
      
 26 
     | 
    
         
            +
            		[2009-08-04 01:21:03] INFO  WEBrick 1.3.1
         
     | 
| 
      
 27 
     | 
    
         
            +
            		[2009-08-04 01:21:03] INFO  ruby 1.8.6 (2009-07-24) [java]
         
     | 
| 
      
 28 
     | 
    
         
            +
            		[2009-08-04 01:21:03] INFO  WEBrick::HTTPServer#start: pid=12162 port=3000
         
     | 
| 
      
 29 
     | 
    
         
            +
            	
         
     | 
| 
      
 30 
     | 
    
         
            +
            		$ curl http://localhost:3000/playlists | jsonpretty
         
     | 
| 
      
 31 
     | 
    
         
            +
            		{
         
     | 
| 
      
 32 
     | 
    
         
            +
            		  "result": {
         
     | 
| 
      
 33 
     | 
    
         
            +
            		    "playlists": [
         
     | 
| 
      
 34 
     | 
    
         
            +
            		      {
         
     | 
| 
      
 35 
     | 
    
         
            +
            		        "name": "my shiny playlist",
         
     | 
| 
      
 36 
     | 
    
         
            +
            		        "author": "jberkel",
         
     | 
| 
      
 37 
     | 
    
         
            +
            		        "url": "http:\/\/open.spotify.com\/user\/jberkel\/playlist\/5EXLGE7HPVPjvlxPmIfrDe",
         
     | 
| 
      
 38 
     | 
    
         
            +
            		        "revision": 2,
         
     | 
| 
      
 39 
     | 
    
         
            +
            		        "id": "b9fe3dcf88945d146ef18117faa61ab4",
         
     | 
| 
      
 40 
     | 
    
         
            +
            		        "tracks": [
         
     | 
| 
      
 41 
     | 
    
         
            +
            		          {
         
     | 
| 
      
 42 
     | 
    
         
            +
            		            "artist": "Elmore Judd",
         
     | 
| 
      
 43 
     | 
    
         
            +
            		            "title": "Disco In 4 Pieces",
         
     | 
| 
      
 44 
     | 
    
         
            +
            		            "url": "http:\/\/open.spotify.com\/track\/1VaucR6Bsks5Q9bYBsXvuF",
         
     | 
| 
      
 45 
     | 
    
         
            +
            		            "id": "3f2752a98dd947c5855278a88159d7b1",
         
     | 
| 
      
 46 
     | 
    
         
            +
            		            "album": "Insect Funk",
         
     | 
| 
      
 47 
     | 
    
         
            +
            		            "popularity": 0.325379997491837
         
     | 
| 
      
 48 
     | 
    
         
            +
            		          },
         
     | 
| 
      
 49 
     | 
    
         
            +
            		          {
         
     | 
| 
      
 50 
     | 
    
         
            +
            		            "artist": "40winks",
         
     | 
| 
      
 51 
     | 
    
         
            +
            		            "title": "Goodmorning (intro)",
         
     | 
| 
      
 52 
     | 
    
         
            +
            		            "url": "http:\/\/open.spotify.com\/track\/6qHiOf1BFCQIzAjJsRbMfY",
         
     | 
| 
      
 53 
     | 
    
         
            +
            		            "id": "d34a3a6daeed4f93983068e4e8c26cd6",
         
     | 
| 
      
 54 
     | 
    
         
            +
            		            "album": "Sound Puzzle",
         
     | 
| 
      
 55 
     | 
    
         
            +
            		            "popularity": 0.170609995722771
         
     | 
| 
      
 56 
     | 
    
         
            +
            		          }
         
     | 
| 
      
 57 
     | 
    
         
            +
            		        ],
         
     | 
| 
      
 58 
     | 
    
         
            +
            		        "collaborative": false
         
     | 
| 
      
 59 
     | 
    
         
            +
            		      }
         
     | 
| 
      
 60 
     | 
    
         
            +
            		    ]
         
     | 
| 
      
 61 
     | 
    
         
            +
            		  },
         
     | 
| 
      
 62 
     | 
    
         
            +
            		  "status": "OK"
         
     | 
| 
      
 63 
     | 
    
         
            +
            		}
         
     | 
| 
      
 64 
     | 
    
         
            +
            		
         
     | 
| 
      
 65 
     | 
    
         
            +
            See examples directory for usage.
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            ## Credits
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            Contains code from the jotify project:
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            Copyright (c) 2009, Felix Bruns <felixbruns@web.de>
         
     | 
| 
      
 72 
     | 
    
         
            +
            All rights reserved.
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            Redistribution and use in source and binary forms, with or without
         
     | 
| 
      
 75 
     | 
    
         
            +
            modification, are permitted provided that the following conditions are met:
         
     | 
| 
      
 76 
     | 
    
         
            +
            	 * Redistributions of source code must retain the above copyright
         
     | 
| 
      
 77 
     | 
    
         
            +
            	   notice, this list of conditions and the following disclaimer.
         
     | 
| 
      
 78 
     | 
    
         
            +
            	 * Redistributions in binary form must reproduce the above copyright
         
     | 
| 
      
 79 
     | 
    
         
            +
            	   notice, this list of conditions and the following disclaimer in the
         
     | 
| 
      
 80 
     | 
    
         
            +
            	   documentation and/or other materials provided with the distribution.
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY
         
     | 
| 
      
 83 
     | 
    
         
            +
            EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
         
     | 
| 
      
 84 
     | 
    
         
            +
            WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
         
     | 
| 
      
 85 
     | 
    
         
            +
            DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
         
     | 
| 
      
 86 
     | 
    
         
            +
            DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
         
     | 
| 
      
 87 
     | 
    
         
            +
            (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
         
     | 
| 
      
 88 
     | 
    
         
            +
            LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
         
     | 
| 
      
 89 
     | 
    
         
            +
            ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
         
     | 
| 
      
 90 
     | 
    
         
            +
            (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
         
     | 
| 
      
 91 
     | 
    
         
            +
            SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rake/testtask'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'spec/rake/spectask'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            begin
         
     | 
| 
      
 6 
     | 
    
         
            +
              require 'jeweler'
         
     | 
| 
      
 7 
     | 
    
         
            +
              Jeweler::Tasks.new do |gem|
         
     | 
| 
      
 8 
     | 
    
         
            +
                gem.name = "spotify-api"
         
     | 
| 
      
 9 
     | 
    
         
            +
                gem.summary = "an api for spotify, based on jotify"
         
     | 
| 
      
 10 
     | 
    
         
            +
                gem.email = "jan.berkel@gmail.com"
         
     | 
| 
      
 11 
     | 
    
         
            +
                gem.homepage = "http://github.com/jberkel/spotify-api"
         
     | 
| 
      
 12 
     | 
    
         
            +
                gem.description = "an api for spotify, based on jotify"
         
     | 
| 
      
 13 
     | 
    
         
            +
                gem.authors = ["Jan Berkel"]
         
     | 
| 
      
 14 
     | 
    
         
            +
                gem.add_dependency "rack"
         
     | 
| 
      
 15 
     | 
    
         
            +
                gem.add_dependency "rack-test"
         
     | 
| 
      
 16 
     | 
    
         
            +
                gem.add_dependency "sinatra"
         
     | 
| 
      
 17 
     | 
    
         
            +
                gem.add_dependency "json-jruby"    
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 20 
     | 
    
         
            +
              puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            Spec::Rake::SpecTask.new do |t|
         
     | 
| 
      
 24 
     | 
    
         
            +
              t.rcov = false
         
     | 
| 
      
 25 
     | 
    
         
            +
              t.spec_files = FileList["spec/**/*_spec.rb"].delete_if { |f| f =~ /integration/ }
         
     | 
| 
      
 26 
     | 
    
         
            +
              t.libs << "./lib"
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            Spec::Rake::SpecTask.new(:integration) do |t|
         
     | 
| 
      
 30 
     | 
    
         
            +
              t.rcov = false
         
     | 
| 
      
 31 
     | 
    
         
            +
              t.spec_files = FileList["spec/**/*_spec.rb"].select { |f| f =~ /integration/ }
         
     | 
| 
      
 32 
     | 
    
         
            +
              t.libs << "./lib"
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
    
        data/VERSION.yml
    ADDED
    
    
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env jruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'jotify'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'jotify/api'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            DEFAULT_PORT = port = 3000
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            def usage
         
     | 
| 
      
 11 
     | 
    
         
            +
              STDERR.puts "#{File.basename($0)} [-p <port>] [--account <login>:<password>]"
         
     | 
| 
      
 12 
     | 
    
         
            +
              exit(1)
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            case ARGV.shift
         
     | 
| 
      
 16 
     | 
    
         
            +
              when '-p', '--port': port = ARGV.shift
         
     | 
| 
      
 17 
     | 
    
         
            +
              when '--account':
         
     | 
| 
      
 18 
     | 
    
         
            +
                login, password = ARGV.shift.to_s.split(':')
         
     | 
| 
      
 19 
     | 
    
         
            +
                raise ArgumentError, "you need to specify both login and password!" unless login and password
         
     | 
| 
      
 20 
     | 
    
         
            +
                Jotify.credentials = { :username=>login, :password=>password }
         
     | 
| 
      
 21 
     | 
    
         
            +
              when '-h', '--help': usage
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            #Sinatra::Application.set :environment, :production
         
     | 
| 
      
 25 
     | 
    
         
            +
            Sinatra::Application.run! :port=> (port || DEFAULT_PORT).to_i
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rest_client'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'pp'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            puts "creating a new playlist"
         
     | 
| 
      
 9 
     | 
    
         
            +
            resp = RestClient.post 'http://localhost:3000/playlists', :name=>'my shiny playlist'
         
     | 
| 
      
 10 
     | 
    
         
            +
            if resp.code == 201
         
     | 
| 
      
 11 
     | 
    
         
            +
              location = resp.headers[:location]
         
     | 
| 
      
 12 
     | 
    
         
            +
              puts "201 created (#{location})"
         
     | 
| 
      
 13 
     | 
    
         
            +
              spotify_id = location[location.rindex('/')+1..-1] 
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
              puts "adding some tracks to it"
         
     | 
| 
      
 16 
     | 
    
         
            +
              resp = RestClient.put "http://localhost:3000/playlists/#{spotify_id}", { 
         
     | 
| 
      
 17 
     | 
    
         
            +
                "tracks" => [ {'id'=>'6qHiOf1BFCQIzAjJsRbMfY'}, {'id'=>'1VaucR6Bsks5Q9bYBsXvuF'} ] 
         
     | 
| 
      
 18 
     | 
    
         
            +
              }.to_json
         
     | 
| 
      
 19 
     | 
    
         
            +
              puts resp
         
     | 
| 
      
 20 
     | 
    
         
            +
            else
         
     | 
| 
      
 21 
     | 
    
         
            +
              raise resp.to_s
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
              
         
     | 
| 
      
 24 
     | 
    
         
            +
              
         
     | 
| 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rest_client'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'pp'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            puts "getting all playlists"
         
     | 
| 
      
 9 
     | 
    
         
            +
            resp = RestClient.get 'http://localhost:3000/playlists'
         
     | 
| 
      
 10 
     | 
    
         
            +
            playlists = JSON.parse(resp)
         
     | 
| 
      
 11 
     | 
    
         
            +
            pp playlists
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            playlists['result']['playlists'].each do |p|
         
     | 
| 
      
 14 
     | 
    
         
            +
              puts "retrieving details for playlist #{p['name']}:"
         
     | 
| 
      
 15 
     | 
    
         
            +
              pp JSON.parse(RestClient.get "http://localhost:3000/playlists/#{p['id']}")
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/search.rb
    ADDED
    
    | 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rest_client'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'pp'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            puts "searching for album: Moon Safari"
         
     | 
| 
      
 9 
     | 
    
         
            +
            pp JSON.parse(RestClient.get('http://localhost:3000/albums?name=Moon+Safari'))
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            puts "searching for track: The End"
         
     | 
| 
      
 12 
     | 
    
         
            +
            pp JSON.parse(RestClient.get('http://localhost:3000/tracks?name=The+End'))
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            puts "searching for artist: The Doors"
         
     | 
| 
      
 15 
     | 
    
         
            +
            pp JSON.parse(RestClient.get('http://localhost:3000/artists?name=The+Doors'))
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
    
        data/lib/jars/jotify.jar
    ADDED
    
    | 
         Binary file 
     | 
    
        data/lib/jotify.rb
    ADDED
    
    | 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'java'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.expand_path(File.dirname(__FILE__) + '/jars/jotify.jar')
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            class Jotify          
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              module Media    
         
     | 
| 
      
 7 
     | 
    
         
            +
                import 'de.felixbruns.jotify.media.Playlist'
         
     | 
| 
      
 8 
     | 
    
         
            +
                import 'de.felixbruns.jotify.media.PlaylistContainer'    
         
     | 
| 
      
 9 
     | 
    
         
            +
                import 'de.felixbruns.jotify.media.Result'
         
     | 
| 
      
 10 
     | 
    
         
            +
                import 'de.felixbruns.jotify.media.Track'
         
     | 
| 
      
 11 
     | 
    
         
            +
                import 'de.felixbruns.jotify.media.Artist'
         
     | 
| 
      
 12 
     | 
    
         
            +
                import 'de.felixbruns.jotify.media.Album'
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
              import 'de.felixbruns.jotify.gui.util.JotifyPreferences'
         
     | 
| 
      
 16 
     | 
    
         
            +
              import 'de.felixbruns.jotify.util.SpotifyURI'
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              ByPopularity = Proc.new { |a,b| b.popularity <=> a.popularity }
         
     | 
| 
      
 19 
     | 
    
         
            +
              
         
     | 
| 
      
 20 
     | 
    
         
            +
              [:close, :search].each do |m|
         
     | 
| 
      
 21 
     | 
    
         
            +
                define_method(m) do |*args|
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @jotify.send(m, *args)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def initialize(jotify_impl=Java::DeFelixbrunsJotify::JotifyPool.new(4))
         
     | 
| 
      
 27 
     | 
    
         
            +
                @jotify  = jotify_impl
         
     | 
| 
      
 28 
     | 
    
         
            +
                
         
     | 
| 
      
 29 
     | 
    
         
            +
                credentials = Jotify.credentials
         
     | 
| 
      
 30 
     | 
    
         
            +
                @jotify.login(credentials[:username], credentials[:password])
         
     | 
| 
      
 31 
     | 
    
         
            +
                
         
     | 
| 
      
 32 
     | 
    
         
            +
                at_exit do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @jotify.close 
         
     | 
| 
      
 35 
     | 
    
         
            +
                  rescue Exception => e
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                if block_given?
         
     | 
| 
      
 40 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 41 
     | 
    
         
            +
                    yield self
         
     | 
| 
      
 42 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 43 
     | 
    
         
            +
                    close
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              def playlists
         
     | 
| 
      
 49 
     | 
    
         
            +
                @jotify.playlists.map { |p| playlist(p.getId()) }
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              def playlist(id)
         
     | 
| 
      
 53 
     | 
    
         
            +
                playlist = @jotify.playlist(Jotify.resolve_id(id))
         
     | 
| 
      
 54 
     | 
    
         
            +
                unless playlist.tracks.empty?
         
     | 
| 
      
 55 
     | 
    
         
            +
                 res = @jotify.browse(playlist.tracks)
         
     | 
| 
      
 56 
     | 
    
         
            +
                 res.tracks.each_with_index do |t,i|
         
     | 
| 
      
 57 
     | 
    
         
            +
                   playlist.tracks.set(i, t)
         
     | 
| 
      
 58 
     | 
    
         
            +
                 end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
                playlist
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
               
         
     | 
| 
      
 63 
     | 
    
         
            +
              def create_playlist(name, collaborative=false)
         
     | 
| 
      
 64 
     | 
    
         
            +
                playlist = @jotify.playlistCreate(name, collaborative)
         
     | 
| 
      
 65 
     | 
    
         
            +
                return nil unless playlist
         
     | 
| 
      
 66 
     | 
    
         
            +
                add_playlist(playlist)
         
     | 
| 
      
 67 
     | 
    
         
            +
                playlist
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
                
         
     | 
| 
      
 70 
     | 
    
         
            +
              def add_playlist(id)
         
     | 
| 
      
 71 
     | 
    
         
            +
                @jotify.playlistsAddPlaylist(@jotify.playlists, id.is_a?(Media::Playlist) ? id : playlist(id))
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
                 
         
     | 
| 
      
 74 
     | 
    
         
            +
              def add_tracks_to_playlist(playlist, track_ids)
         
     | 
| 
      
 75 
     | 
    
         
            +
                tracks = Java::JavaUtil::ArrayList.new
         
     | 
| 
      
 76 
     | 
    
         
            +
                track_ids.each { |id| tracks.add(Media::Track.new(Jotify.resolve_id(id))) }
         
     | 
| 
      
 77 
     | 
    
         
            +
                @jotify.playlistAddTracks(playlist, tracks, 0)    
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
              
         
     | 
| 
      
 80 
     | 
    
         
            +
              def self.resolve_id(id)
         
     | 
| 
      
 81 
     | 
    
         
            +
                case id
         
     | 
| 
      
 82 
     | 
    
         
            +
                  when /\Ahttp:\/\/open\.spotify\.com/: SpotifyURI.to_hex(id[id.rindex('/')+1..-1])
         
     | 
| 
      
 83 
     | 
    
         
            +
                  when /spotify:/: SpotifyURI.to_hex(id[id.rindex(':')+1..-1])
         
     | 
| 
      
 84 
     | 
    
         
            +
                  when /\A[0-9a-f]{32}\Z/: id
         
     | 
| 
      
 85 
     | 
    
         
            +
                  when /\A[a-zA-Z0-9]{22}\Z/: SpotifyURI.to_hex(id)
         
     | 
| 
      
 86 
     | 
    
         
            +
                else 
         
     | 
| 
      
 87 
     | 
    
         
            +
                  raise "invalid id: #{id}"
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
               
         
     | 
| 
      
 91 
     | 
    
         
            +
              def self.credentials
         
     | 
| 
      
 92 
     | 
    
         
            +
                prefs = JotifyPreferences.getInstance()
         
     | 
| 
      
 93 
     | 
    
         
            +
                prefs.load()
         
     | 
| 
      
 94 
     | 
    
         
            +
                { 
         
     | 
| 
      
 95 
     | 
    
         
            +
                 :username => prefs.getString("login.username"),
         
     | 
| 
      
 96 
     | 
    
         
            +
                 :password => prefs.getString("login.password")
         
     | 
| 
      
 97 
     | 
    
         
            +
                }       
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
               
         
     | 
| 
      
 100 
     | 
    
         
            +
              def self.credentials=(creds)
         
     | 
| 
      
 101 
     | 
    
         
            +
                prefs = JotifyPreferences.getInstance()
         
     | 
| 
      
 102 
     | 
    
         
            +
                prefs.load()
         
     | 
| 
      
 103 
     | 
    
         
            +
                prefs.setString("login.username", creds[:username])
         
     | 
| 
      
 104 
     | 
    
         
            +
                prefs.setString("login.password", creds[:password])
         
     | 
| 
      
 105 
     | 
    
         
            +
                prefs.save() or raise "could not save login details"
         
     | 
| 
      
 106 
     | 
    
         
            +
              end
         
     | 
| 
      
 107 
     | 
    
         
            +
            end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            require File.expand_path(File.dirname(__FILE__) + '/jotify/media')
         
     | 
    
        data/lib/jotify/api.rb
    ADDED
    
    | 
         @@ -0,0 +1,114 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env jruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'sinatra/base'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require File.expand_path(File.dirname(__FILE__) + '/../jotify') unless defined?(Jotify)
         
     | 
| 
      
 6 
     | 
    
         
            +
              
         
     | 
| 
      
 7 
     | 
    
         
            +
            class Sinatra::Application
         
     | 
| 
      
 8 
     | 
    
         
            +
              Lock = Mutex.new
         
     | 
| 
      
 9 
     | 
    
         
            +
              
         
     | 
| 
      
 10 
     | 
    
         
            +
              def jotify
         
     | 
| 
      
 11 
     | 
    
         
            +
                Lock.synchronize do
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @@jotify ||= Jotify.new
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
              
         
     | 
| 
      
 16 
     | 
    
         
            +
              def query(what, p=what) 
         
     | 
| 
      
 17 
     | 
    
         
            +
                params[p] ? "#{what}:" + params[p] : '' 
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            Sinatra::Application.error ArgumentError do
         
     | 
| 
      
 22 
     | 
    
         
            +
              content_type :json
         
     | 
| 
      
 23 
     | 
    
         
            +
              {
         
     | 
| 
      
 24 
     | 
    
         
            +
                'status' => 'ERROR',
         
     | 
| 
      
 25 
     | 
    
         
            +
                'message' => request.env['sinatra.error'].message
         
     | 
| 
      
 26 
     | 
    
         
            +
              }.to_json
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
      
 28 
     | 
    
         
            +
              
         
     | 
| 
      
 29 
     | 
    
         
            +
            Sinatra::Application.get('/tracks') do
         
     | 
| 
      
 30 
     | 
    
         
            +
              content_type :json
         
     | 
| 
      
 31 
     | 
    
         
            +
              raise ArgumentError, "need name" unless params[:name]
         
     | 
| 
      
 32 
     | 
    
         
            +
              
         
     | 
| 
      
 33 
     | 
    
         
            +
              res = jotify.search([query(:track, :name), query(:artist), query(:album)].join(' '))
         
     | 
| 
      
 34 
     | 
    
         
            +
              {
         
     | 
| 
      
 35 
     | 
    
         
            +
                'status'=>'OK', 
         
     | 
| 
      
 36 
     | 
    
         
            +
                'result'=> res.tracks.map { |t| t.to_h }
         
     | 
| 
      
 37 
     | 
    
         
            +
              }.to_json
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            Sinatra::Application.get('/albums') do
         
     | 
| 
      
 41 
     | 
    
         
            +
              content_type :json
         
     | 
| 
      
 42 
     | 
    
         
            +
              raise ArgumentError, "need name" unless params[:name]
         
     | 
| 
      
 43 
     | 
    
         
            +
                
         
     | 
| 
      
 44 
     | 
    
         
            +
              res = jotify.search([query(:album, :name), query(:artist)].join(' ') )
         
     | 
| 
      
 45 
     | 
    
         
            +
              {
         
     | 
| 
      
 46 
     | 
    
         
            +
                'status'=>'OK', 
         
     | 
| 
      
 47 
     | 
    
         
            +
                'result'=> res.albums.map { |a| a.to_h }
         
     | 
| 
      
 48 
     | 
    
         
            +
              }.to_json
         
     | 
| 
      
 49 
     | 
    
         
            +
            end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            Sinatra::Application.get('/artists') do
         
     | 
| 
      
 52 
     | 
    
         
            +
              content_type :json
         
     | 
| 
      
 53 
     | 
    
         
            +
              raise ArgumentError, "need name" unless params[:name]
         
     | 
| 
      
 54 
     | 
    
         
            +
              
         
     | 
| 
      
 55 
     | 
    
         
            +
              res = jotify.search(query(:artist, :name))
         
     | 
| 
      
 56 
     | 
    
         
            +
              {
         
     | 
| 
      
 57 
     | 
    
         
            +
                'status'=>'OK', 
         
     | 
| 
      
 58 
     | 
    
         
            +
                'result'=> res.artists.map { |a| a.to_h }
         
     | 
| 
      
 59 
     | 
    
         
            +
              }.to_json
         
     | 
| 
      
 60 
     | 
    
         
            +
            end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            Sinatra::Application.get('/playlists') do
         
     | 
| 
      
 63 
     | 
    
         
            +
              content_type :json
         
     | 
| 
      
 64 
     | 
    
         
            +
              #playlists = jotify.playlists
         
     | 
| 
      
 65 
     | 
    
         
            +
              {
         
     | 
| 
      
 66 
     | 
    
         
            +
                'status'=>'OK',
         
     | 
| 
      
 67 
     | 
    
         
            +
                'result'=> { 'playlists' => jotify.playlists.map { |p| p.to_h } }
         
     | 
| 
      
 68 
     | 
    
         
            +
              }.to_json
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            Sinatra::Application.get('/playlists/:id') do
         
     | 
| 
      
 72 
     | 
    
         
            +
              content_type :json  
         
     | 
| 
      
 73 
     | 
    
         
            +
              if playlist = jotify.playlist(params[:id])
         
     | 
| 
      
 74 
     | 
    
         
            +
                {
         
     | 
| 
      
 75 
     | 
    
         
            +
                  'status'=>'OK',
         
     | 
| 
      
 76 
     | 
    
         
            +
                  'result'=>playlist.to_h
         
     | 
| 
      
 77 
     | 
    
         
            +
                }.to_json
         
     | 
| 
      
 78 
     | 
    
         
            +
              else
         
     | 
| 
      
 79 
     | 
    
         
            +
                return 404, { 'status' => 'ERROR', 'message' => 'playlist not found' }.to_json
         
     | 
| 
      
 80 
     | 
    
         
            +
              end
         
     | 
| 
      
 81 
     | 
    
         
            +
            end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            Sinatra::Application.post('/playlists') do
         
     | 
| 
      
 84 
     | 
    
         
            +
              content_type :json
         
     | 
| 
      
 85 
     | 
    
         
            +
              name, collaborative = params[:name], params[:collaborative] == 'true'
         
     | 
| 
      
 86 
     | 
    
         
            +
              playlist = jotify.create_playlist(name, collaborative)
         
     | 
| 
      
 87 
     | 
    
         
            +
              if playlist
         
     | 
| 
      
 88 
     | 
    
         
            +
                redirect playlist.link, 201 # created
         
     | 
| 
      
 89 
     | 
    
         
            +
              else
         
     | 
| 
      
 90 
     | 
    
         
            +
                return 500, { 'status' => 'ERROR', 'message' => 'playlist could not be created' }.to_json
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
            end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            Sinatra::Application.put('/playlists/:id') do
         
     | 
| 
      
 95 
     | 
    
         
            +
              content_type :json
         
     | 
| 
      
 96 
     | 
    
         
            +
              playlist = jotify.playlist(params[:id])
         
     | 
| 
      
 97 
     | 
    
         
            +
              return 404, { 'status' => 'ERROR', 'message' => 'playlist not found' }.to_json unless playlist
         
     | 
| 
      
 98 
     | 
    
         
            +
              body = request.body.read
         
     | 
| 
      
 99 
     | 
    
         
            +
              data = JSON.parse(body)
         
     | 
| 
      
 100 
     | 
    
         
            +
              raise ArgumentError, "invalid format" unless data.is_a?(Hash) && data['tracks'].is_a?(Array)
         
     | 
| 
      
 101 
     | 
    
         
            +
              ids  = data['tracks'].map { |t| t['id'] }
         
     | 
| 
      
 102 
     | 
    
         
            +
              return 200, { 'status' => 'OK', 'message' => 'not modified' }.to_json if ids.empty?
         
     | 
| 
      
 103 
     | 
    
         
            +
              
         
     | 
| 
      
 104 
     | 
    
         
            +
              if jotify.add_tracks_to_playlist(playlist, ids)
         
     | 
| 
      
 105 
     | 
    
         
            +
                return 200, { 'status' => 'OK', 'message' => "successfully added #{ids.size} tracks" }.to_json
         
     | 
| 
      
 106 
     | 
    
         
            +
              else
         
     | 
| 
      
 107 
     | 
    
         
            +
                return 500, { 'status' => 'ERROR', 'message' => 'could not add to playlist' }.to_json
         
     | 
| 
      
 108 
     | 
    
         
            +
              end  
         
     | 
| 
      
 109 
     | 
    
         
            +
            end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
            if __FILE__ == $0
         
     | 
| 
      
 113 
     | 
    
         
            +
              Sinatra::Application.run! 
         
     | 
| 
      
 114 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/jotify/media.rb
    ADDED
    
    | 
         @@ -0,0 +1,99 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'java'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.expand_path(File.dirname(__FILE__) + '/../jars/jotify.jar')
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            #Make Jotify's native Java classes a bit more rubyish by implementing some mehods / modules
         
     | 
| 
      
 5 
     | 
    
         
            +
            module Java
         
     | 
| 
      
 6 
     | 
    
         
            +
              module DeFelixbrunsJotifyMedia
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Media
         
     | 
| 
      
 8 
     | 
    
         
            +
                  def inspect
         
     | 
| 
      
 9 
     | 
    
         
            +
                    self.to_s
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end  
         
     | 
| 
      
 11 
     | 
    
         
            +
              
         
     | 
| 
      
 12 
     | 
    
         
            +
                  def to_h
         
     | 
| 
      
 13 
     | 
    
         
            +
                    h = { :id=>self.getId(), :popularity=> popularity.nan? ? 0.0 : popularity.to_f }
         
     | 
| 
      
 14 
     | 
    
         
            +
                    h[:url] = self.link if self.respond_to?(:link)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    h
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              
         
     | 
| 
      
 19 
     | 
    
         
            +
                class Playlist
         
     | 
| 
      
 20 
     | 
    
         
            +
                  include Enumerable  
         
     | 
| 
      
 21 
     | 
    
         
            +
                  
         
     | 
| 
      
 22 
     | 
    
         
            +
                  def each(&block) 
         
     | 
| 
      
 23 
     | 
    
         
            +
                    tracks.each(&block)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def inspect
         
     | 
| 
      
 27 
     | 
    
         
            +
                    "[Playlist: #{self.getId()} #{getTracks.to_a}]"
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def to_h
         
     | 
| 
      
 31 
     | 
    
         
            +
                    {
         
     | 
| 
      
 32 
     | 
    
         
            +
                      :id => getId(),
         
     | 
| 
      
 33 
     | 
    
         
            +
                      :name=> name,
         
     | 
| 
      
 34 
     | 
    
         
            +
                      :url => link,
         
     | 
| 
      
 35 
     | 
    
         
            +
                      :tracks => tracks.map { |t| t.to_h },
         
     | 
| 
      
 36 
     | 
    
         
            +
                      :author => author,
         
     | 
| 
      
 37 
     | 
    
         
            +
                      :revision => revision,
         
     | 
| 
      
 38 
     | 
    
         
            +
                      :collaborative => collaborative
         
     | 
| 
      
 39 
     | 
    
         
            +
                    }
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              
         
     | 
| 
      
 43 
     | 
    
         
            +
                class PlaylistContainer
         
     | 
| 
      
 44 
     | 
    
         
            +
                  include Enumerable
         
     | 
| 
      
 45 
     | 
    
         
            +
                  
         
     | 
| 
      
 46 
     | 
    
         
            +
                  def each(&block) 
         
     | 
| 
      
 47 
     | 
    
         
            +
                    playlists.each(&block) 
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                class Result
         
     | 
| 
      
 52 
     | 
    
         
            +
                  include Enumerable
         
     | 
| 
      
 53 
     | 
    
         
            +
                  
         
     | 
| 
      
 54 
     | 
    
         
            +
                  def each(&block)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    artists.each(&block)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    tracks.each(&block)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    albums.each(&block)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                  
         
     | 
| 
      
 60 
     | 
    
         
            +
                  def inspect
         
     | 
| 
      
 61 
     | 
    
         
            +
                    { :artists=>self.artists.to_a, :albums=>self.albums.to_a, :tracks=>self.tracks.to_a }.inspect
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end  
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  def to_h
         
     | 
| 
      
 65 
     | 
    
         
            +
                    { 
         
     | 
| 
      
 66 
     | 
    
         
            +
                      :artists => self.artists.map { |a| a.to_h },
         
     | 
| 
      
 67 
     | 
    
         
            +
                      :albums => self.albums.map { |a| a.to_h },
         
     | 
| 
      
 68 
     | 
    
         
            +
                      :tracks => self.tracks.map { |t| t.to_h }
         
     | 
| 
      
 69 
     | 
    
         
            +
                    }
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
              
         
     | 
| 
      
 73 
     | 
    
         
            +
                class Track
         
     | 
| 
      
 74 
     | 
    
         
            +
                  def to_h
         
     | 
| 
      
 75 
     | 
    
         
            +
                    super.merge(:title=>title, :artist=>artist ? artist.name : nil, :album=>album ? album.name : nil)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              
         
     | 
| 
      
 79 
     | 
    
         
            +
                class Artist
         
     | 
| 
      
 80 
     | 
    
         
            +
                  def to_h
         
     | 
| 
      
 81 
     | 
    
         
            +
                    super.merge(:name=>name)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  end
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                class Album
         
     | 
| 
      
 86 
     | 
    
         
            +
                  include Enumerable
         
     | 
| 
      
 87 
     | 
    
         
            +
                  
         
     | 
| 
      
 88 
     | 
    
         
            +
                  def each(&block) 
         
     | 
| 
      
 89 
     | 
    
         
            +
                    tracks.each(&block) 
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
                    
         
     | 
| 
      
 92 
     | 
    
         
            +
                  def to_h
         
     | 
| 
      
 93 
     | 
    
         
            +
                    super.merge(:name=>name, :artist=>artist ? artist.name : nil, :year=>year, :type=>type)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
              end
         
     | 
| 
      
 97 
     | 
    
         
            +
            end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
    
        data/spec/api_spec.rb
    ADDED
    
    | 
         @@ -0,0 +1,179 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env jruby -S spec
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), 'spec_helper')
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'jotify/api'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'rack/test'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'sinatra'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            set :environment, :test
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            describe 'Api' do
         
     | 
| 
      
 11 
     | 
    
         
            +
              
         
     | 
| 
      
 12 
     | 
    
         
            +
              def app() Sinatra::Application end
         
     | 
| 
      
 13 
     | 
    
         
            +
              
         
     | 
| 
      
 14 
     | 
    
         
            +
              def json_response
         
     | 
| 
      
 15 
     | 
    
         
            +
                last_response.content_type.should == 'application/json'      
         
     | 
| 
      
 16 
     | 
    
         
            +
                JSON.parse(last_response.body)    
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              
         
     | 
| 
      
 20 
     | 
    
         
            +
              before do  
         
     | 
| 
      
 21 
     | 
    
         
            +
                @jotify = jotify = mock('Jotify')
         
     | 
| 
      
 22 
     | 
    
         
            +
                Sinatra::Application.send(:define_method, :jotify) { jotify }
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
              
         
     | 
| 
      
 25 
     | 
    
         
            +
              describe "/artists" do
         
     | 
| 
      
 26 
     | 
    
         
            +
                it "searches by artist name" do
         
     | 
| 
      
 27 
     | 
    
         
            +
                  res = Jotify::Media::Result.new
         
     | 
| 
      
 28 
     | 
    
         
            +
                  res.artists.add(Jotify::Media::Artist.new('4d921ebcdd8c80f32ce1ed5acafbb9c8', 'The Kinks'))
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @jotify.stub!(:search).and_return(res)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  get '/artists', :name=>'The Kinks'
         
     | 
| 
      
 31 
     | 
    
         
            +
                  last_response.should be_ok
         
     | 
| 
      
 32 
     | 
    
         
            +
                  json_response.should == {"status"=>"OK", "result"=>
         
     | 
| 
      
 33 
     | 
    
         
            +
                    [{"id"=>"4d921ebcdd8c80f32ce1ed5acafbb9c8", "popularity"=>0.0, "url"=>"http://open.spotify.com/artist/2mnbxTkghYtlHMdX3jdP9C", "name"=>"The Kinks"}]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  }
         
     | 
| 
      
 35 
     | 
    
         
            +
                end      
         
     | 
| 
      
 36 
     | 
    
         
            +
                
         
     | 
| 
      
 37 
     | 
    
         
            +
                it "should return an error message if no name is specified" do
         
     | 
| 
      
 38 
     | 
    
         
            +
                  lambda { get '/artists' }.should raise_error(ArgumentError)
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
              
         
     | 
| 
      
 42 
     | 
    
         
            +
              describe "/tracks" do
         
     | 
| 
      
 43 
     | 
    
         
            +
                 it "searches by track name" do
         
     | 
| 
      
 44 
     | 
    
         
            +
                   res = Jotify::Media::Result.new
         
     | 
| 
      
 45 
     | 
    
         
            +
                   res.tracks.add(Jotify::Media::Track.new('4d921ebcdd8c80f32ce1ed5acafbb9c8'))
         
     | 
| 
      
 46 
     | 
    
         
            +
                   @jotify.stub!(:search).and_return(res)
         
     | 
| 
      
 47 
     | 
    
         
            +
                   get '/tracks', :name=>'Waterloo Sunset'
         
     | 
| 
      
 48 
     | 
    
         
            +
                   last_response.should be_ok
         
     | 
| 
      
 49 
     | 
    
         
            +
                   json_response.should == {"status"=>"OK", "result"=>
         
     | 
| 
      
 50 
     | 
    
         
            +
                     [{"id"=>"4d921ebcdd8c80f32ce1ed5acafbb9c8", "popularity"=>0.0, "url"=>"http://open.spotify.com/track/2mnbxTkghYtlHMdX3jdP9C", "title"=>nil, "artist"=>nil, "album"=>nil}]
         
     | 
| 
      
 51 
     | 
    
         
            +
                   }
         
     | 
| 
      
 52 
     | 
    
         
            +
                 end
         
     | 
| 
      
 53 
     | 
    
         
            +
                       
         
     | 
| 
      
 54 
     | 
    
         
            +
                 it "should return an error message if no name is specified" do
         
     | 
| 
      
 55 
     | 
    
         
            +
                   lambda { get '/tracks' }.should raise_error(ArgumentError)
         
     | 
| 
      
 56 
     | 
    
         
            +
                 end
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
              
         
     | 
| 
      
 59 
     | 
    
         
            +
              describe "/albums" do
         
     | 
| 
      
 60 
     | 
    
         
            +
                it "searches by album name" do
         
     | 
| 
      
 61 
     | 
    
         
            +
                  res = Jotify::Media::Result.new
         
     | 
| 
      
 62 
     | 
    
         
            +
                  res.albums.add(Jotify::Media::Album.new('4d921ebcdd8c80f32ce1ed5acafbb9c8', 
         
     | 
| 
      
 63 
     | 
    
         
            +
                  'Something Else', 
         
     | 
| 
      
 64 
     | 
    
         
            +
                  Jotify::Media::Artist.new('4d921ebcdd8c80f32ce1ed5acafbb9c8', 'The Kinks')))
         
     | 
| 
      
 65 
     | 
    
         
            +
                  
         
     | 
| 
      
 66 
     | 
    
         
            +
                  @jotify.stub!(:search).and_return(res)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  get '/albums', :name=>'Something Else'
         
     | 
| 
      
 68 
     | 
    
         
            +
                  last_response.should be_ok
         
     | 
| 
      
 69 
     | 
    
         
            +
                  json_response.should == {"status"=>"OK", "result"=>
         
     | 
| 
      
 70 
     | 
    
         
            +
                    [{"id"=>"4d921ebcdd8c80f32ce1ed5acafbb9c8",
         
     | 
| 
      
 71 
     | 
    
         
            +
                      "popularity"=>0.0, 
         
     | 
| 
      
 72 
     | 
    
         
            +
                      "url"=>"http://open.spotify.com/album/2mnbxTkghYtlHMdX3jdP9C", 
         
     | 
| 
      
 73 
     | 
    
         
            +
                      "name"=>"Something Else", 
         
     | 
| 
      
 74 
     | 
    
         
            +
                      "artist"=>"The Kinks", "year"=>-1, "type"=>nil}]
         
     | 
| 
      
 75 
     | 
    
         
            +
                  }
         
     | 
| 
      
 76 
     | 
    
         
            +
                end      
         
     | 
| 
      
 77 
     | 
    
         
            +
                
         
     | 
| 
      
 78 
     | 
    
         
            +
                it "should return an error message if no name is specified" do
         
     | 
| 
      
 79 
     | 
    
         
            +
                  lambda { get '/albums' }.should raise_error(ArgumentError)
         
     | 
| 
      
 80 
     | 
    
         
            +
                end    
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
              
         
     | 
| 
      
 83 
     | 
    
         
            +
              describe "/playlists" do
         
     | 
| 
      
 84 
     | 
    
         
            +
                before do 
         
     | 
| 
      
 85 
     | 
    
         
            +
                  #String id, String name, String author, boolean collaborative
         
     | 
| 
      
 86 
     | 
    
         
            +
                  @playlist = Jotify::Media::Playlist.new("4d921ebcdd8c80f32ce1ed5acafbb9c8", "my shiny playlist", "test", false)
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
                  
         
     | 
| 
      
 89 
     | 
    
         
            +
                describe "get" do  
         
     | 
| 
      
 90 
     | 
    
         
            +
                  
         
     | 
| 
      
 91 
     | 
    
         
            +
                  it "should get all playlists created by the user" do
         
     | 
| 
      
 92 
     | 
    
         
            +
                    @jotify.should_receive(:playlists).and_return( [@playlist] )
         
     | 
| 
      
 93 
     | 
    
         
            +
                    get '/playlists'
         
     | 
| 
      
 94 
     | 
    
         
            +
                    last_response.should be_ok
         
     | 
| 
      
 95 
     | 
    
         
            +
                    json_response.should == {"status"=>"OK",
         
     | 
| 
      
 96 
     | 
    
         
            +
                      "result"=> { 
         
     | 
| 
      
 97 
     | 
    
         
            +
                        "playlists" => [
         
     | 
| 
      
 98 
     | 
    
         
            +
                          "id"=>"4d921ebcdd8c80f32ce1ed5acafbb9c8",
         
     | 
| 
      
 99 
     | 
    
         
            +
                          "url"=>"http://open.spotify.com/user/test/playlist/2mnbxTkghYtlHMdX3jdP9C",                     
         
     | 
| 
      
 100 
     | 
    
         
            +
                          "name"=>"my shiny playlist",
         
     | 
| 
      
 101 
     | 
    
         
            +
                          "tracks"=>[], "author"=>"test", "revision"=>-1, "collaborative"=>false
         
     | 
| 
      
 102 
     | 
    
         
            +
                        ] 
         
     | 
| 
      
 103 
     | 
    
         
            +
                      }
         
     | 
| 
      
 104 
     | 
    
         
            +
                    }
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  
         
     | 
| 
      
 107 
     | 
    
         
            +
                  
         
     | 
| 
      
 108 
     | 
    
         
            +
                  it "should retrieve a playlist by id" do
         
     | 
| 
      
 109 
     | 
    
         
            +
                    @jotify.should_receive(:playlist).with("4d921ebcdd8c80f32ce1ed5acafbb9c8").and_return(@playlist)
         
     | 
| 
      
 110 
     | 
    
         
            +
                    get '/playlists/4d921ebcdd8c80f32ce1ed5acafbb9c8'
         
     | 
| 
      
 111 
     | 
    
         
            +
                    last_response.should be_ok
         
     | 
| 
      
 112 
     | 
    
         
            +
                    json_response.should == {"status"=>"OK",
         
     | 
| 
      
 113 
     | 
    
         
            +
                     "result"=>{
         
     | 
| 
      
 114 
     | 
    
         
            +
                        "id"=>"4d921ebcdd8c80f32ce1ed5acafbb9c8",
         
     | 
| 
      
 115 
     | 
    
         
            +
                        "url"=>"http://open.spotify.com/user/test/playlist/2mnbxTkghYtlHMdX3jdP9C",                     
         
     | 
| 
      
 116 
     | 
    
         
            +
                        "name"=>"my shiny playlist",
         
     | 
| 
      
 117 
     | 
    
         
            +
                        "tracks"=>[], "author"=>"test", "revision"=>-1, "collaborative"=>false}
         
     | 
| 
      
 118 
     | 
    
         
            +
                    }
         
     | 
| 
      
 119 
     | 
    
         
            +
                  end
         
     | 
| 
      
 120 
     | 
    
         
            +
                
         
     | 
| 
      
 121 
     | 
    
         
            +
                  it "should except a base62 string as id" do
         
     | 
| 
      
 122 
     | 
    
         
            +
                    @jotify.should_receive(:playlist).with("2mnbxTkghYtlHMdX3jdP9C").and_return(@playlist)
         
     | 
| 
      
 123 
     | 
    
         
            +
                    get '/playlists/2mnbxTkghYtlHMdX3jdP9C'
         
     | 
| 
      
 124 
     | 
    
         
            +
                    last_response.should be_ok
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
                
         
     | 
| 
      
 127 
     | 
    
         
            +
                  it "should return 404 for non-existing playlist" do
         
     | 
| 
      
 128 
     | 
    
         
            +
                    @jotify.should_receive(:playlist).with("unknown").and_return(nil)
         
     | 
| 
      
 129 
     | 
    
         
            +
                    get '/playlists/unknown'
         
     | 
| 
      
 130 
     | 
    
         
            +
                    last_response.status.should == 404
         
     | 
| 
      
 131 
     | 
    
         
            +
                    json_response.should == {"status"=>"ERROR", "message"=>"playlist not found"}
         
     | 
| 
      
 132 
     | 
    
         
            +
                  end
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
                
         
     | 
| 
      
 135 
     | 
    
         
            +
                
         
     | 
| 
      
 136 
     | 
    
         
            +
                describe "create/update" do
         
     | 
| 
      
 137 
     | 
    
         
            +
                  it "should create a playlist when posting to /playlists" do
         
     | 
| 
      
 138 
     | 
    
         
            +
                    @jotify.should_receive(:create_playlist).with('my shiny playlist', true).and_return(@playlist)
         
     | 
| 
      
 139 
     | 
    
         
            +
                    post '/playlists', :name => 'my shiny playlist', :collaborative => 'true'
         
     | 
| 
      
 140 
     | 
    
         
            +
                    last_response.status.should == 201
         
     | 
| 
      
 141 
     | 
    
         
            +
                    last_response.headers['Location'].should == 'http://open.spotify.com/user/test/playlist/2mnbxTkghYtlHMdX3jdP9C'
         
     | 
| 
      
 142 
     | 
    
         
            +
                  end
         
     | 
| 
      
 143 
     | 
    
         
            +
                
         
     | 
| 
      
 144 
     | 
    
         
            +
                  it "should update playlist when putting to /playlists/id" do
         
     | 
| 
      
 145 
     | 
    
         
            +
                    @jotify.should_receive(:playlist).with("foo").and_return(@playlist)
         
     | 
| 
      
 146 
     | 
    
         
            +
                    @jotify.should_receive(:add_tracks_to_playlist).with(@playlist, ['1','2']).and_return(true)
         
     | 
| 
      
 147 
     | 
    
         
            +
                    put '/playlists/foo', { 'tracks' => [ {'id'=>'1' }, { 'id'=>'2' } ] }.to_json
         
     | 
| 
      
 148 
     | 
    
         
            +
                    last_response.should be_ok
         
     | 
| 
      
 149 
     | 
    
         
            +
                    json_response.should == {'status'=>'OK', 'message'=>'successfully added 2 tracks'}
         
     | 
| 
      
 150 
     | 
    
         
            +
                  end
         
     | 
| 
      
 151 
     | 
    
         
            +
                  
         
     | 
| 
      
 152 
     | 
    
         
            +
                  it "should return 404 if playlist to update cannot be found" do
         
     | 
| 
      
 153 
     | 
    
         
            +
                    @jotify.should_receive(:playlist).with("foo").and_return(nil)
         
     | 
| 
      
 154 
     | 
    
         
            +
                    put '/playlists/foo', { 'tracks' => [ {'id'=>'1' }, { 'id'=>'2' } ] }.to_json
         
     | 
| 
      
 155 
     | 
    
         
            +
                    last_response.status.should == 404
         
     | 
| 
      
 156 
     | 
    
         
            +
                    json_response.should == {"status"=>"ERROR", "message"=>"playlist not found"} 
         
     | 
| 
      
 157 
     | 
    
         
            +
                  end
         
     | 
| 
      
 158 
     | 
    
         
            +
                  
         
     | 
| 
      
 159 
     | 
    
         
            +
                  it "should return 500 if playlist could not be updated" do
         
     | 
| 
      
 160 
     | 
    
         
            +
                    @jotify.should_receive(:playlist).with("foo").and_return(@playlist)
         
     | 
| 
      
 161 
     | 
    
         
            +
                    @jotify.should_receive(:add_tracks_to_playlist).with(@playlist, ['1','2']).and_return(false)
         
     | 
| 
      
 162 
     | 
    
         
            +
                    put '/playlists/foo', { 'tracks' => [ {'id'=>'1' }, { 'id'=>'2' } ] }.to_json
         
     | 
| 
      
 163 
     | 
    
         
            +
                    last_response.status.should == 500
         
     | 
| 
      
 164 
     | 
    
         
            +
                    json_response.should == {"status"=>"ERROR", "message"=>"could not add to playlist"}         
         
     | 
| 
      
 165 
     | 
    
         
            +
                  end
         
     | 
| 
      
 166 
     | 
    
         
            +
                        
         
     | 
| 
      
 167 
     | 
    
         
            +
                  it "should return 403 if invalid data is supplied" do
         
     | 
| 
      
 168 
     | 
    
         
            +
                    @jotify.should_receive(:playlist).with("foo").and_return(@playlist)
         
     | 
| 
      
 169 
     | 
    
         
            +
                    lambda { put '/playlists/foo', { 'foo' => 'bar' }.to_json }.should raise_error(ArgumentError)
         
     | 
| 
      
 170 
     | 
    
         
            +
                  end
         
     | 
| 
      
 171 
     | 
    
         
            +
                  
         
     | 
| 
      
 172 
     | 
    
         
            +
                  it "shouldn't do anything if no track ids supplied" do
         
     | 
| 
      
 173 
     | 
    
         
            +
                    @jotify.should_receive(:playlist).with("foo").and_return(@playlist)
         
     | 
| 
      
 174 
     | 
    
         
            +
                    put '/playlists/foo', { 'tracks' => [] }.to_json
         
     | 
| 
      
 175 
     | 
    
         
            +
                    last_response.should be_ok
         
     | 
| 
      
 176 
     | 
    
         
            +
                  end
         
     | 
| 
      
 177 
     | 
    
         
            +
                end
         
     | 
| 
      
 178 
     | 
    
         
            +
              end
         
     | 
| 
      
 179 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env jruby -S spec
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), 'spec_helper')
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'jotify'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            # WARNING: these specs need a valid spotify (premium) account, otherwise they will fail
         
     | 
| 
      
 6 
     | 
    
         
            +
            describe "Integration" do
         
     | 
| 
      
 7 
     | 
    
         
            +
              
         
     | 
| 
      
 8 
     | 
    
         
            +
              before(:all) do
         
     | 
| 
      
 9 
     | 
    
         
            +
                @jotify = Jotify.new
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
              
         
     | 
| 
      
 12 
     | 
    
         
            +
              after(:all) do
         
     | 
| 
      
 13 
     | 
    
         
            +
                @jotify.close rescue nil
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
                
         
     | 
| 
      
 16 
     | 
    
         
            +
              describe "searching" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                it "should return a result for a search" do
         
     | 
| 
      
 18 
     | 
    
         
            +
                  result = @jotify.search("artist:Air")
         
     | 
| 
      
 19 
     | 
    
         
            +
                  result.should be_a(Jotify::Media::Result)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  
         
     | 
| 
      
 21 
     | 
    
         
            +
                  result.artists.should_not be_empty      
         
     | 
| 
      
 22 
     | 
    
         
            +
                  most_popular = result.artists.to_a.sort(&Jotify::ByPopularity).first
         
     | 
| 
      
 23 
     | 
    
         
            +
                  most_popular.name.should == 'Air'
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  result = @jotify.search("album:Moon Safari")
         
     | 
| 
      
 26 
     | 
    
         
            +
                  result.albums.should_not be_empty
         
     | 
| 
      
 27 
     | 
    
         
            +
                  most_popular = result.albums.to_a.sort(&Jotify::ByPopularity).first
         
     | 
| 
      
 28 
     | 
    
         
            +
                  most_popular.name.should == 'Moon Safari' 
         
     | 
| 
      
 29 
     | 
    
         
            +
                  most_popular.artist.name.should == 'Air'
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
              
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/jotify_spec.rb
    ADDED
    
    | 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env jruby -S spec
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), 'spec_helper')
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'jotify'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            describe Jotify do  
         
     | 
| 
      
 6 
     | 
    
         
            +
              
         
     | 
| 
      
 7 
     | 
    
         
            +
              before(:each) do
         
     | 
| 
      
 8 
     | 
    
         
            +
                @jotify_impl = mock('JotifyImpl')
         
     | 
| 
      
 9 
     | 
    
         
            +
                @jotify_impl.stub!(:login)
         
     | 
| 
      
 10 
     | 
    
         
            +
                @jotify = Jotify.new(@jotify_impl)
         
     | 
| 
      
 11 
     | 
    
         
            +
              end  
         
     | 
| 
      
 12 
     | 
    
         
            +
              
         
     | 
| 
      
 13 
     | 
    
         
            +
              it "should resolve ids" do    
         
     | 
| 
      
 14 
     | 
    
         
            +
                { "spotify:user:flumix:playlist:2mnbxTkghYtlHMdX3jdP9C" => "4d921ebcdd8c80f32ce1ed5acafbb9c8",
         
     | 
| 
      
 15 
     | 
    
         
            +
                  "http://open.spotify.com/user/flumix/playlist/2mnbxTkghYtlHMdX3jdP9C" => "4d921ebcdd8c80f32ce1ed5acafbb9c8",
         
     | 
| 
      
 16 
     | 
    
         
            +
                  "2mnbxTkghYtlHMdX3jdP9C" => "4d921ebcdd8c80f32ce1ed5acafbb9c8",
         
     | 
| 
      
 17 
     | 
    
         
            +
                  "4d921ebcdd8c80f32ce1ed5acafbb9c8" => "4d921ebcdd8c80f32ce1ed5acafbb9c8"
         
     | 
| 
      
 18 
     | 
    
         
            +
                }.each { |id, expected| Jotify.resolve_id(id).should == expected }
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
              
         
     | 
| 
      
 21 
     | 
    
         
            +
              it "should add tracks to playlist" do    
         
     | 
| 
      
 22 
     | 
    
         
            +
                @playlist = Jotify::Media::Playlist.new
         
     | 
| 
      
 23 
     | 
    
         
            +
                @jotify_impl.should_receive(:playlistAddTracks) do |playlist, tracks, pos|
         
     | 
| 
      
 24 
     | 
    
         
            +
                  playlist.should be_a(Jotify::Media::Playlist)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #playlist.should == @playlist
         
     | 
| 
      
 26 
     | 
    
         
            +
                  pos.should == 0
         
     | 
| 
      
 27 
     | 
    
         
            +
                  tracks.should be_an(Java::JavaUtil::List)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  tracks.size.should == 1
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
                @jotify.add_tracks_to_playlist(@playlist, ['4d921ebcdd8c80f32ce1ed5acafbb9c8'])
         
     | 
| 
      
 31 
     | 
    
         
            +
              end    
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/media_spec.rb
    ADDED
    
    | 
         @@ -0,0 +1,77 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env jruby -S spec
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), 'spec_helper')
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'jotify'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            describe Jotify::Media do
         
     | 
| 
      
 6 
     | 
    
         
            +
              
         
     | 
| 
      
 7 
     | 
    
         
            +
              describe "an artist" do
         
     | 
| 
      
 8 
     | 
    
         
            +
                before do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @artist = Jotify::Media::Artist.new
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
                
         
     | 
| 
      
 12 
     | 
    
         
            +
                it "should implement to_h" do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @artist.respond_to?(:to_h).should be_true
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
              
         
     | 
| 
      
 17 
     | 
    
         
            +
              describe "a track" do
         
     | 
| 
      
 18 
     | 
    
         
            +
                before do
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @track = Jotify::Media::Track.new
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
                
         
     | 
| 
      
 22 
     | 
    
         
            +
                it "should implement to_h" do
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @track.respond_to?(:to_h).should be_true
         
     | 
| 
      
 24 
     | 
    
         
            +
                end      
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
              
         
     | 
| 
      
 27 
     | 
    
         
            +
              describe "an album" do
         
     | 
| 
      
 28 
     | 
    
         
            +
                before do
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @album = Jotify::Media::Album.new
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
                
         
     | 
| 
      
 32 
     | 
    
         
            +
                it "should implement to_h" do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @album.respond_to?(:to_h).should be_true      
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
                
         
     | 
| 
      
 36 
     | 
    
         
            +
                it "should implement enumerable" do
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @album.class.included_modules.should include(Enumerable)
         
     | 
| 
      
 38 
     | 
    
         
            +
                end            
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
              
         
     | 
| 
      
 41 
     | 
    
         
            +
              describe "a result" do
         
     | 
| 
      
 42 
     | 
    
         
            +
                before do 
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @result = Jotify::Media::Result.new
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
                
         
     | 
| 
      
 46 
     | 
    
         
            +
                it "should implement to_h" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @result.respond_to?(:to_h).should be_true      
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
                
         
     | 
| 
      
 50 
     | 
    
         
            +
                it "should implement enumerable" do
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @result.class.included_modules.should include(Enumerable)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @result.respond_to?(:each).should be_true
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
              
         
     | 
| 
      
 56 
     | 
    
         
            +
              describe "playlists" do    
         
     | 
| 
      
 57 
     | 
    
         
            +
                it "should implement enumerable" do
         
     | 
| 
      
 58 
     | 
    
         
            +
                  p = Jotify::Media::Playlist.new
         
     | 
| 
      
 59 
     | 
    
         
            +
                  p.class.included_modules.should include(Enumerable)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  p.respond_to?(:each).should be_true
         
     | 
| 
      
 61 
     | 
    
         
            +
                  10.times { p.tracks.add(Jotify::Media::Track.new) }
         
     | 
| 
      
 62 
     | 
    
         
            +
                  p.to_a.size.should == 10      
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
              
         
     | 
| 
      
 66 
     | 
    
         
            +
              describe "playlist container" do
         
     | 
| 
      
 67 
     | 
    
         
            +
                before do
         
     | 
| 
      
 68 
     | 
    
         
            +
                  @container = Jotify::Media::PlaylistContainer.new
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
                
         
     | 
| 
      
 71 
     | 
    
         
            +
                it "should implement enumerable" do
         
     | 
| 
      
 72 
     | 
    
         
            +
                  @container.respond_to?(:each).should be_true    
         
     | 
| 
      
 73 
     | 
    
         
            +
                  @container.class.included_modules.should include(Enumerable)        
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
              
         
     | 
| 
      
 77 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec_helper.rb
    ADDED
    
    
    
        data/spotify-api.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 4 
     | 
    
         
            +
              s.name = %q{spotify-api}
         
     | 
| 
      
 5 
     | 
    
         
            +
              s.version = "0.0.1"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.authors = ["Jan Berkel"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.date = %q{2009-08-04}
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.default_executable = %q{spotify-api-server}
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.description = %q{an api for spotify, based on jotify}
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.email = %q{jan.berkel@gmail.com}
         
     | 
| 
      
 13 
     | 
    
         
            +
              s.executables = ["spotify-api-server"]
         
     | 
| 
      
 14 
     | 
    
         
            +
              s.extra_rdoc_files = [
         
     | 
| 
      
 15 
     | 
    
         
            +
                "LICENSE",
         
     | 
| 
      
 16 
     | 
    
         
            +
                 "README.md"
         
     | 
| 
      
 17 
     | 
    
         
            +
              ]
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.files = [
         
     | 
| 
      
 19 
     | 
    
         
            +
                ".gitignore",
         
     | 
| 
      
 20 
     | 
    
         
            +
                 "LICENSE",
         
     | 
| 
      
 21 
     | 
    
         
            +
                 "README.md",
         
     | 
| 
      
 22 
     | 
    
         
            +
                 "Rakefile",
         
     | 
| 
      
 23 
     | 
    
         
            +
                 "VERSION.yml",
         
     | 
| 
      
 24 
     | 
    
         
            +
                 "bin/spotify-api-server",
         
     | 
| 
      
 25 
     | 
    
         
            +
                 "examples/create_playlist.rb",
         
     | 
| 
      
 26 
     | 
    
         
            +
                 "examples/list_playlists.rb",
         
     | 
| 
      
 27 
     | 
    
         
            +
                 "examples/search.rb",
         
     | 
| 
      
 28 
     | 
    
         
            +
                 "lib/jars/jotify.jar",
         
     | 
| 
      
 29 
     | 
    
         
            +
                 "lib/jotify.rb",
         
     | 
| 
      
 30 
     | 
    
         
            +
                 "lib/jotify/api.rb",
         
     | 
| 
      
 31 
     | 
    
         
            +
                 "lib/jotify/media.rb",
         
     | 
| 
      
 32 
     | 
    
         
            +
                 "spec/api_spec.rb",
         
     | 
| 
      
 33 
     | 
    
         
            +
                 "spec/integration_spec.rb",
         
     | 
| 
      
 34 
     | 
    
         
            +
                 "spec/jotify_spec.rb",
         
     | 
| 
      
 35 
     | 
    
         
            +
                 "spec/media_spec.rb",
         
     | 
| 
      
 36 
     | 
    
         
            +
                 "spec/spec_helper.rb",
         
     | 
| 
      
 37 
     | 
    
         
            +
                 "spotify-api.gemspec"
         
     | 
| 
      
 38 
     | 
    
         
            +
              ]
         
     | 
| 
      
 39 
     | 
    
         
            +
              s.homepage = %q{http://github.com/jberkel/spotify-api}
         
     | 
| 
      
 40 
     | 
    
         
            +
              s.rdoc_options = ["--charset=UTF-8"]
         
     | 
| 
      
 41 
     | 
    
         
            +
              s.require_paths = ["lib"]
         
     | 
| 
      
 42 
     | 
    
         
            +
              s.rubygems_version = %q{1.3.5}
         
     | 
| 
      
 43 
     | 
    
         
            +
              s.summary = %q{an api for spotify, based on jotify}
         
     | 
| 
      
 44 
     | 
    
         
            +
              s.test_files = [
         
     | 
| 
      
 45 
     | 
    
         
            +
                "spec/api_spec.rb",
         
     | 
| 
      
 46 
     | 
    
         
            +
                 "spec/integration_spec.rb",
         
     | 
| 
      
 47 
     | 
    
         
            +
                 "spec/jotify_spec.rb",
         
     | 
| 
      
 48 
     | 
    
         
            +
                 "spec/media_spec.rb",
         
     | 
| 
      
 49 
     | 
    
         
            +
                 "spec/spec_helper.rb",
         
     | 
| 
      
 50 
     | 
    
         
            +
                 "examples/create_playlist.rb",
         
     | 
| 
      
 51 
     | 
    
         
            +
                 "examples/list_playlists.rb",
         
     | 
| 
      
 52 
     | 
    
         
            +
                 "examples/search.rb"
         
     | 
| 
      
 53 
     | 
    
         
            +
              ]
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              if s.respond_to? :specification_version then
         
     | 
| 
      
 56 
     | 
    
         
            +
                current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
         
     | 
| 
      
 57 
     | 
    
         
            +
                s.specification_version = 3
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
         
     | 
| 
      
 60 
     | 
    
         
            +
                  s.add_runtime_dependency(%q<rack>, [">= 0"])
         
     | 
| 
      
 61 
     | 
    
         
            +
                  s.add_runtime_dependency(%q<rack-test>, [">= 0"])
         
     | 
| 
      
 62 
     | 
    
         
            +
                  s.add_runtime_dependency(%q<sinatra>, [">= 0"])
         
     | 
| 
      
 63 
     | 
    
         
            +
                  s.add_runtime_dependency(%q<json-jruby>, [">= 0"])
         
     | 
| 
      
 64 
     | 
    
         
            +
                else
         
     | 
| 
      
 65 
     | 
    
         
            +
                  s.add_dependency(%q<rack>, [">= 0"])
         
     | 
| 
      
 66 
     | 
    
         
            +
                  s.add_dependency(%q<rack-test>, [">= 0"])
         
     | 
| 
      
 67 
     | 
    
         
            +
                  s.add_dependency(%q<sinatra>, [">= 0"])
         
     | 
| 
      
 68 
     | 
    
         
            +
                  s.add_dependency(%q<json-jruby>, [">= 0"])
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              else
         
     | 
| 
      
 71 
     | 
    
         
            +
                s.add_dependency(%q<rack>, [">= 0"])
         
     | 
| 
      
 72 
     | 
    
         
            +
                s.add_dependency(%q<rack-test>, [">= 0"])
         
     | 
| 
      
 73 
     | 
    
         
            +
                s.add_dependency(%q<sinatra>, [">= 0"])
         
     | 
| 
      
 74 
     | 
    
         
            +
                s.add_dependency(%q<json-jruby>, [">= 0"])
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,119 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification 
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: jberkel-spotify-api
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version 
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.1
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors: 
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Jan Berkel
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2009-08-04 00:00:00 -07:00
         
     | 
| 
      
 13 
     | 
    
         
            +
            default_executable: spotify-api-server
         
     | 
| 
      
 14 
     | 
    
         
            +
            dependencies: 
         
     | 
| 
      
 15 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 16 
     | 
    
         
            +
              name: rack
         
     | 
| 
      
 17 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 18 
     | 
    
         
            +
              version_requirement: 
         
     | 
| 
      
 19 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 20 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 21 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 22 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 23 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 24 
     | 
    
         
            +
                version: 
         
     | 
| 
      
 25 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 26 
     | 
    
         
            +
              name: rack-test
         
     | 
| 
      
 27 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 28 
     | 
    
         
            +
              version_requirement: 
         
     | 
| 
      
 29 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 34 
     | 
    
         
            +
                version: 
         
     | 
| 
      
 35 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 36 
     | 
    
         
            +
              name: sinatra
         
     | 
| 
      
 37 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 38 
     | 
    
         
            +
              version_requirement: 
         
     | 
| 
      
 39 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 40 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 41 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 42 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 43 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 44 
     | 
    
         
            +
                version: 
         
     | 
| 
      
 45 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 46 
     | 
    
         
            +
              name: json-jruby
         
     | 
| 
      
 47 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 48 
     | 
    
         
            +
              version_requirement: 
         
     | 
| 
      
 49 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 50 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 51 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 52 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 53 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 54 
     | 
    
         
            +
                version: 
         
     | 
| 
      
 55 
     | 
    
         
            +
            description: an api for spotify, based on jotify
         
     | 
| 
      
 56 
     | 
    
         
            +
            email: jan.berkel@gmail.com
         
     | 
| 
      
 57 
     | 
    
         
            +
            executables: 
         
     | 
| 
      
 58 
     | 
    
         
            +
            - spotify-api-server
         
     | 
| 
      
 59 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            extra_rdoc_files: 
         
     | 
| 
      
 62 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 63 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 64 
     | 
    
         
            +
            files: 
         
     | 
| 
      
 65 
     | 
    
         
            +
            - .gitignore
         
     | 
| 
      
 66 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 67 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 68 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 69 
     | 
    
         
            +
            - VERSION.yml
         
     | 
| 
      
 70 
     | 
    
         
            +
            - bin/spotify-api-server
         
     | 
| 
      
 71 
     | 
    
         
            +
            - examples/create_playlist.rb
         
     | 
| 
      
 72 
     | 
    
         
            +
            - examples/list_playlists.rb
         
     | 
| 
      
 73 
     | 
    
         
            +
            - examples/search.rb
         
     | 
| 
      
 74 
     | 
    
         
            +
            - lib/jars/jotify.jar
         
     | 
| 
      
 75 
     | 
    
         
            +
            - lib/jotify.rb
         
     | 
| 
      
 76 
     | 
    
         
            +
            - lib/jotify/api.rb
         
     | 
| 
      
 77 
     | 
    
         
            +
            - lib/jotify/media.rb
         
     | 
| 
      
 78 
     | 
    
         
            +
            - spec/api_spec.rb
         
     | 
| 
      
 79 
     | 
    
         
            +
            - spec/integration_spec.rb
         
     | 
| 
      
 80 
     | 
    
         
            +
            - spec/jotify_spec.rb
         
     | 
| 
      
 81 
     | 
    
         
            +
            - spec/media_spec.rb
         
     | 
| 
      
 82 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 83 
     | 
    
         
            +
            - spotify-api.gemspec
         
     | 
| 
      
 84 
     | 
    
         
            +
            has_rdoc: false
         
     | 
| 
      
 85 
     | 
    
         
            +
            homepage: http://github.com/jberkel/spotify-api
         
     | 
| 
      
 86 
     | 
    
         
            +
            licenses: 
         
     | 
| 
      
 87 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 88 
     | 
    
         
            +
            rdoc_options: 
         
     | 
| 
      
 89 
     | 
    
         
            +
            - --charset=UTF-8
         
     | 
| 
      
 90 
     | 
    
         
            +
            require_paths: 
         
     | 
| 
      
 91 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 92 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 93 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 94 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 95 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 96 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 97 
     | 
    
         
            +
              version: 
         
     | 
| 
      
 98 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 99 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 100 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 101 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 102 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 103 
     | 
    
         
            +
              version: 
         
     | 
| 
      
 104 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 107 
     | 
    
         
            +
            rubygems_version: 1.3.5
         
     | 
| 
      
 108 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 109 
     | 
    
         
            +
            specification_version: 3
         
     | 
| 
      
 110 
     | 
    
         
            +
            summary: an api for spotify, based on jotify
         
     | 
| 
      
 111 
     | 
    
         
            +
            test_files: 
         
     | 
| 
      
 112 
     | 
    
         
            +
            - spec/api_spec.rb
         
     | 
| 
      
 113 
     | 
    
         
            +
            - spec/integration_spec.rb
         
     | 
| 
      
 114 
     | 
    
         
            +
            - spec/jotify_spec.rb
         
     | 
| 
      
 115 
     | 
    
         
            +
            - spec/media_spec.rb
         
     | 
| 
      
 116 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 117 
     | 
    
         
            +
            - examples/create_playlist.rb
         
     | 
| 
      
 118 
     | 
    
         
            +
            - examples/list_playlists.rb
         
     | 
| 
      
 119 
     | 
    
         
            +
            - examples/search.rb
         
     |