soundcloud 0.3.1 → 0.3.2
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/README.md +147 -132
 - data/lib/soundcloud.rb +18 -204
 - data/lib/soundcloud/array_response_wrapper.rb +11 -7
 - data/lib/soundcloud/client.rb +199 -0
 - data/lib/soundcloud/hash_response_wrapper.rb +7 -5
 - data/lib/soundcloud/response_error.rb +44 -0
 - data/lib/soundcloud/version.rb +2 -2
 - metadata +22 -50
 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,155 +1,170 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            #  
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            It provides simple methods to handle authorization and to execute HTTP calls.
         
     | 
| 
      
 1 
     | 
    
         
            +
            # SoundCloud API Wrapper
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            [](https://travis-ci.org/soundcloud/soundcloud-ruby)
         
     | 
| 
       5 
4 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
            ##  
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
            * crack
         
     | 
| 
       10 
     | 
    
         
            -
            * multipart-upload
         
     | 
| 
       11 
     | 
    
         
            -
            * hashie
         
     | 
| 
      
 5 
     | 
    
         
            +
            ## Description
         
     | 
| 
      
 6 
     | 
    
         
            +
            The official SoundCloud API wrapper. It provides simple methods to handle
         
     | 
| 
      
 7 
     | 
    
         
            +
            authorization and to execute HTTP calls.
         
     | 
| 
       12 
8 
     | 
    
         | 
| 
       13 
9 
     | 
    
         
             
            ## Installation
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 10 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 11 
     | 
    
         
            +
            gem install soundcloud
         
     | 
| 
      
 12 
     | 
    
         
            +
            ```
         
     | 
| 
       15 
13 
     | 
    
         | 
| 
       16 
14 
     | 
    
         
             
            ## Examples
         
     | 
| 
       17 
15 
     | 
    
         
             
            #### Print links of the 10 hottest tracks
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
      
 16 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 17 
     | 
    
         
            +
            # register a client with YOUR_CLIENT_ID as client_id_
         
     | 
| 
      
 18 
     | 
    
         
            +
            client = SoundCloud.new(:client_id => YOUR_CLIENT_ID)
         
     | 
| 
      
 19 
     | 
    
         
            +
            # get 10 hottest tracks
         
     | 
| 
      
 20 
     | 
    
         
            +
            tracks = client.get('/tracks', :limit => 10, :order => 'hotness')
         
     | 
| 
      
 21 
     | 
    
         
            +
            # print each link
         
     | 
| 
      
 22 
     | 
    
         
            +
            tracks.each do |track|
         
     | 
| 
      
 23 
     | 
    
         
            +
              puts track.permalink_url
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
      
 25 
     | 
    
         
            +
            ```
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       27 
27 
     | 
    
         
             
            #### OAuth2 user credentials flow and print the username of the authenticated user
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                   
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 29 
     | 
    
         
            +
            # register a new client, which will exchange the username, password for an access_token
         
     | 
| 
      
 30 
     | 
    
         
            +
            # NOTE: the SoundCloud API Docs advise not to use the user credentials flow in a web app.
         
     | 
| 
      
 31 
     | 
    
         
            +
            # In any case, never store the password of a user.
         
     | 
| 
      
 32 
     | 
    
         
            +
            client = SoundCloud.new({
         
     | 
| 
      
 33 
     | 
    
         
            +
              :client_id     => YOUR_CLIENT_ID,
         
     | 
| 
      
 34 
     | 
    
         
            +
              :client_secret => YOUR_CLIENT_SECRET,
         
     | 
| 
      
 35 
     | 
    
         
            +
              :username      => 'some@email.com',
         
     | 
| 
      
 36 
     | 
    
         
            +
              :password      => 'userpass'
         
     | 
| 
      
 37 
     | 
    
         
            +
            })
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            # print logged in username
         
     | 
| 
      
 40 
     | 
    
         
            +
            puts client.get('/me').username
         
     | 
| 
      
 41 
     | 
    
         
            +
            ```
         
     | 
| 
       40 
42 
     | 
    
         | 
| 
       41 
43 
     | 
    
         
             
            #### OAuth2 authorization code flow
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
      
 44 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 45 
     | 
    
         
            +
            client = SoundCloud.new({
         
     | 
| 
      
 46 
     | 
    
         
            +
              :client_id     => YOUR_CLIENT_ID,
         
     | 
| 
      
 47 
     | 
    
         
            +
              :client_secret => YOUR_CLIENT_SECRET,
         
     | 
| 
      
 48 
     | 
    
         
            +
              :redirect_uri  => YOUR_REDIRECT_URI,
         
     | 
| 
      
 49 
     | 
    
         
            +
            })
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            redirect client.authorize_url()
         
     | 
| 
      
 52 
     | 
    
         
            +
            # the user should be redirected to "https://soundcloud.com/connect?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REDIRECT_URI"
         
     | 
| 
      
 53 
     | 
    
         
            +
            # after granting access he will be redirected back to YOUR_REDIRECT_URI
         
     | 
| 
      
 54 
     | 
    
         
            +
            # in your respective handler you can build an exchange token from the transmitted code
         
     | 
| 
      
 55 
     | 
    
         
            +
            client.exchange_token(:code => params[:code])
         
     | 
| 
      
 56 
     | 
    
         
            +
            ```
         
     | 
| 
       53 
57 
     | 
    
         | 
| 
       54 
58 
     | 
    
         
             
            #### OAuth2 refresh token flow, upload a track and print its link
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
                   
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
      
 59 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 60 
     | 
    
         
            +
            # register a new client which will exchange an existing refresh_token for an access_token
         
     | 
| 
      
 61 
     | 
    
         
            +
            client = SoundCloud.new({
         
     | 
| 
      
 62 
     | 
    
         
            +
              :client_id     => YOUR_CLIENT_ID,
         
     | 
| 
      
 63 
     | 
    
         
            +
              :client_secret => YOUR_CLIENT_SECRET,
         
     | 
| 
      
 64 
     | 
    
         
            +
              :refresh_token => SOME_REFRESH_TOKEN
         
     | 
| 
      
 65 
     | 
    
         
            +
            })
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            # upload a new track with track.mp3 as audio and image.jpg as artwork
         
     | 
| 
      
 68 
     | 
    
         
            +
            track = client.post('/tracks', :track => {
         
     | 
| 
      
 69 
     | 
    
         
            +
              :title      => 'a new track',
         
     | 
| 
      
 70 
     | 
    
         
            +
              :asset_data => File.new('audio.mp3')
         
     | 
| 
      
 71 
     | 
    
         
            +
            })
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            # print new tracks link
         
     | 
| 
      
 74 
     | 
    
         
            +
            puts track.permalink_url
         
     | 
| 
      
 75 
     | 
    
         
            +
            ```
         
     | 
| 
       70 
76 
     | 
    
         | 
| 
       71 
77 
     | 
    
         
             
            #### Resolve a track url and print its id
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
                # register a client for http://sandbox-soundcloud.com with existing access_token
         
     | 
| 
       83 
     | 
    
         
            -
                client = Soundcloud.new(:site => 'sandbox-soundcloud.com', :access_token => SOME_ACCESS_TOKEN)
         
     | 
| 
       84 
     | 
    
         
            -
                
         
     | 
| 
       85 
     | 
    
         
            -
                # create a new following
         
     | 
| 
       86 
     | 
    
         
            -
                user_id_to_follow = 123
         
     | 
| 
       87 
     | 
    
         
            -
                client.put("/me/followings/#{user_id_to_follow}")
         
     | 
| 
      
 78 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 79 
     | 
    
         
            +
            # register the client
         
     | 
| 
      
 80 
     | 
    
         
            +
            client = SoundCloud.new(:client_id => YOUR_CLIENT_ID)
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            # call the resolve endpoint with a track url
         
     | 
| 
      
 83 
     | 
    
         
            +
            track = client.get('/resolve', :url => "http://soundcloud.com/forss/flickermood")
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            # print the track id
         
     | 
| 
      
 86 
     | 
    
         
            +
            puts track.id
         
     | 
| 
      
 87 
     | 
    
         
            +
            ```
         
     | 
| 
       88 
88 
     | 
    
         | 
| 
       89 
89 
     | 
    
         
             
            ### Initializing a client with an access token and updating the users profile description
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
      
 90 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 91 
     | 
    
         
            +
            # initializing a client with an access token
         
     | 
| 
      
 92 
     | 
    
         
            +
            client = SoundCloud.new(:access_token => SOME_ACCESS_TOKEN)
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            # updating the users profile description
         
     | 
| 
      
 95 
     | 
    
         
            +
            client.put("/me", :user => {:description => "a new description"})
         
     | 
| 
      
 96 
     | 
    
         
            +
            ```
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
            ### Add a track to a playlist / set
         
     | 
| 
      
 99 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 100 
     | 
    
         
            +
            client = SoundCloud.new(:access_token => "A_VALID_TOKEN")
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
            # get my last playlist
         
     | 
| 
      
 103 
     | 
    
         
            +
            playlist = client.get("/me/playlists").first
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
            # get ids of contained tracks
         
     | 
| 
      
 106 
     | 
    
         
            +
            track_ids = playlist.tracks.map(&:id) # => [22448500, 21928809]
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            # adding a new track 21778201
         
     | 
| 
      
 109 
     | 
    
         
            +
            track_ids << 21778201 # => [22448500, 21928809, 21778201]
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            # map array of ids to array of track objects:
         
     | 
| 
      
 112 
     | 
    
         
            +
            tracks = track_ids.map{|id| {:id => id}} # => [{:id=>22448500}, {:id=>21928809}, {:id=>21778201}]
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            # send update/put request to playlist
         
     | 
| 
      
 115 
     | 
    
         
            +
            playlist = client.put(playlist.uri, :playlist => {
         
     | 
| 
      
 116 
     | 
    
         
            +
              :tracks => tracks
         
     | 
| 
      
 117 
     | 
    
         
            +
            })
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
            # print the list of track ids of the updated playlist:
         
     | 
| 
      
 120 
     | 
    
         
            +
            p playlist.tracks.map(&:id)
         
     | 
| 
      
 121 
     | 
    
         
            +
            ```
         
     | 
| 
       119 
122 
     | 
    
         | 
| 
       120 
123 
     | 
    
         
             
            ## Interface
         
     | 
| 
       121 
     | 
    
         
            -
            ####  
     | 
| 
       122 
     | 
    
         
            -
            Stores the passed options and call exchange_token in case options are passed 
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
      
 124 
     | 
    
         
            +
            #### SoundCloud.new(options={})
         
     | 
| 
      
 125 
     | 
    
         
            +
            Stores the passed options and call exchange_token in case options are passed
         
     | 
| 
      
 126 
     | 
    
         
            +
            that allow an exchange of tokens.
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
            #### SoundCloud#exchange_token(options={})
         
     | 
| 
      
 129 
     | 
    
         
            +
            Stores the passed options and try to exchange tokens if no access_token is
         
     | 
| 
      
 130 
     | 
    
         
            +
            present and:
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
            * `refresh_token`, `client_id` and `client_secret` is present.
         
     | 
| 
      
 133 
     | 
    
         
            +
            * `client_id`, `client_secret`, `username`, and `password` is present
         
     | 
| 
      
 134 
     | 
    
         
            +
            * `client_id`, `client_secret`, `redirect_uri`, and `code` is present
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            #### SoundCloud#authorize_url(options={})
         
     | 
| 
      
 137 
     | 
    
         
            +
            Stores the passed options except for `state` and `display` and return an
         
     | 
| 
      
 138 
     | 
    
         
            +
            authorize url. The `client_id` and `redirect_uri` options need to present to
         
     | 
| 
      
 139 
     | 
    
         
            +
            generate the authorize url. The `state` and `display` options can be used to
         
     | 
| 
      
 140 
     | 
    
         
            +
            set the parameters accordingly in the authorize url.
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
            #### SoundCloud#get, SoundCloud#post, SoundCloud#put, SoundCloud#delete, SoundCloud#head
         
     | 
| 
      
 143 
     | 
    
         
            +
            These methods expose all available HTTP methods. They all share the signature
         
     | 
| 
      
 144 
     | 
    
         
            +
            `(path_or_uri, query={}, options={})`. The query hash will be merged with the
         
     | 
| 
      
 145 
     | 
    
         
            +
            options hash and passed to httparty. Depending on if the client is authorized
         
     | 
| 
      
 146 
     | 
    
         
            +
            it will either add the client_id or the access_token as a query parameter. In
         
     | 
| 
      
 147 
     | 
    
         
            +
            case an access_token is expired and a `refresh_token`, `client_id` and
         
     | 
| 
      
 148 
     | 
    
         
            +
            `client_secret` is present it will try to refresh the `access_token` and retry
         
     | 
| 
      
 149 
     | 
    
         
            +
            the call. The response is either a Hashie::Mash or an array of Hashie::Mashes.
         
     | 
| 
      
 150 
     | 
    
         
            +
            The mashes expose all resource attributes as methods and the original response
         
     | 
| 
      
 151 
     | 
    
         
            +
            through `HashResponseWrapper#response`.
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
            #### SoundCloud#client_id, client_secret, access_token, refresh_token, use_ssl?
         
     | 
| 
       142 
154 
     | 
    
         
             
            These methods are accessors for the stored options.
         
     | 
| 
       143 
155 
     | 
    
         | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
            A Proc passed to on_exchange_token will be called each time a token was 
     | 
| 
      
 156 
     | 
    
         
            +
            #### SoundCloud#on_exchange_token
         
     | 
| 
      
 157 
     | 
    
         
            +
            A Proc passed to on_exchange_token will be called each time a token was
         
     | 
| 
      
 158 
     | 
    
         
            +
            successfully exchanged or refreshed
         
     | 
| 
       146 
159 
     | 
    
         | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
            Returns a date based on the expires_in attribute returned from a token 
     | 
| 
      
 160 
     | 
    
         
            +
            #### SoundCloud#expires_at
         
     | 
| 
      
 161 
     | 
    
         
            +
            Returns a date based on the `expires_in` attribute returned from a token
         
     | 
| 
      
 162 
     | 
    
         
            +
            exchange.
         
     | 
| 
       149 
163 
     | 
    
         | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
            Will return true or false depending on if expires_at is in the past.
         
     | 
| 
      
 164 
     | 
    
         
            +
            #### SoundCloud#expired?
         
     | 
| 
      
 165 
     | 
    
         
            +
            Will return true or false depending on if `expires_at` is in the past.
         
     | 
| 
       152 
166 
     | 
    
         | 
| 
       153 
167 
     | 
    
         
             
            #### Error Handling
         
     | 
| 
       154 
     | 
    
         
            -
            In case a request was not successful a  
     | 
| 
       155 
     | 
    
         
            -
            The original HTTParty response is available through 
     | 
| 
      
 168 
     | 
    
         
            +
            In case a request was not successful a SoundCloud::ResponseError will be
         
     | 
| 
      
 169 
     | 
    
         
            +
            raised. The original HTTParty response is available through
         
     | 
| 
      
 170 
     | 
    
         
            +
            `SoundCloud::ResponseError#response`.
         
     | 
    
        data/lib/soundcloud.rb
    CHANGED
    
    | 
         @@ -1,217 +1,31 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'httmultiparty'
         
     | 
| 
       2 
1 
     | 
    
         
             
            require 'hashie'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'httmultiparty'
         
     | 
| 
       3 
3 
     | 
    
         
             
            require 'uri'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'soundcloud/version'
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            class Soundcloud
         
     | 
| 
       7 
     | 
    
         
            -
              class ResponseError < HTTParty::ResponseError
         
     | 
| 
       8 
     | 
    
         
            -
                def message
         
     | 
| 
       9 
     | 
    
         
            -
                  error = response.parsed_response['error'] || response.parsed_response['errors']['error']
         
     | 
| 
       10 
     | 
    
         
            -
                  "HTTP status: #{StatusCodes.interpret_status(response.code)} Error: #{error}"
         
     | 
| 
       11 
     | 
    
         
            -
                rescue
         
     | 
| 
       12 
     | 
    
         
            -
                  "HTTP status: #{StatusCodes.interpret_status(response.code)}"
         
     | 
| 
       13 
     | 
    
         
            -
                end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                module StatusCodes
         
     | 
| 
       16 
     | 
    
         
            -
                  STATUS_CODES = {
         
     | 
| 
       17 
     | 
    
         
            -
                    100 => "Continue",
         
     | 
| 
       18 
     | 
    
         
            -
                    101 => "Switching Protocols",
         
     | 
| 
       19 
     | 
    
         
            -
                    102 => "Processing",
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                    200 => "OK",
         
     | 
| 
       22 
     | 
    
         
            -
                    201 => "Created",
         
     | 
| 
       23 
     | 
    
         
            -
                    202 => "Accepted",
         
     | 
| 
       24 
     | 
    
         
            -
                    203 => "Non-Authoritative Information",
         
     | 
| 
       25 
     | 
    
         
            -
                    204 => "No Content",
         
     | 
| 
       26 
     | 
    
         
            -
                    205 => "Reset Content",
         
     | 
| 
       27 
     | 
    
         
            -
                    206 => "Partial Content",
         
     | 
| 
       28 
     | 
    
         
            -
                    207 => "Multi-Status",
         
     | 
| 
       29 
     | 
    
         
            -
                    226 => "IM Used",
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                    300 => "Multiple Choices",
         
     | 
| 
       32 
     | 
    
         
            -
                    301 => "Moved Permanently",
         
     | 
| 
       33 
     | 
    
         
            -
                    302 => "Found",
         
     | 
| 
       34 
     | 
    
         
            -
                    303 => "See Other",
         
     | 
| 
       35 
     | 
    
         
            -
                    304 => "Not Modified",
         
     | 
| 
       36 
     | 
    
         
            -
                    305 => "Use Proxy",
         
     | 
| 
       37 
     | 
    
         
            -
                    307 => "Temporary Redirect",
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
                    400 => "Bad Request",
         
     | 
| 
       40 
     | 
    
         
            -
                    401 => "Unauthorized",
         
     | 
| 
       41 
     | 
    
         
            -
                    402 => "Payment Required",
         
     | 
| 
       42 
     | 
    
         
            -
                    403 => "Forbidden",
         
     | 
| 
       43 
     | 
    
         
            -
                    404 => "Not Found",
         
     | 
| 
       44 
     | 
    
         
            -
                    405 => "Method Not Allowed",
         
     | 
| 
       45 
     | 
    
         
            -
                    406 => "Not Acceptable",
         
     | 
| 
       46 
     | 
    
         
            -
                    407 => "Proxy Authentication Required",
         
     | 
| 
       47 
     | 
    
         
            -
                    408 => "Request Timeout",
         
     | 
| 
       48 
     | 
    
         
            -
                    409 => "Conflict",
         
     | 
| 
       49 
     | 
    
         
            -
                    410 => "Gone",
         
     | 
| 
       50 
     | 
    
         
            -
                    411 => "Length Required",
         
     | 
| 
       51 
     | 
    
         
            -
                    412 => "Precondition Failed",
         
     | 
| 
       52 
     | 
    
         
            -
                    413 => "Request Entity Too Large",
         
     | 
| 
       53 
     | 
    
         
            -
                    414 => "Request-URI Too Long",
         
     | 
| 
       54 
     | 
    
         
            -
                    415 => "Unsupported Media Type",
         
     | 
| 
       55 
     | 
    
         
            -
                    416 => "Requested Range Not Satisfiable",
         
     | 
| 
       56 
     | 
    
         
            -
                    417 => "Expectation Failed",
         
     | 
| 
       57 
     | 
    
         
            -
                    422 => "Unprocessable Entity",
         
     | 
| 
       58 
     | 
    
         
            -
                    423 => "Locked",
         
     | 
| 
       59 
     | 
    
         
            -
                    424 => "Failed Dependency",
         
     | 
| 
       60 
     | 
    
         
            -
                    426 => "Upgrade Required",
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
                    500 => "Internal Server Error",
         
     | 
| 
       63 
     | 
    
         
            -
                    501 => "Not Implemented",
         
     | 
| 
       64 
     | 
    
         
            -
                    502 => "Bad Gateway",
         
     | 
| 
       65 
     | 
    
         
            -
                    503 => "Service Unavailable",
         
     | 
| 
       66 
     | 
    
         
            -
                    504 => "Gateway Timeout",
         
     | 
| 
       67 
     | 
    
         
            -
                    505 => "HTTP Version Not Supported",
         
     | 
| 
       68 
     | 
    
         
            -
                    507 => "Insufficient Storage",
         
     | 
| 
       69 
     | 
    
         
            -
                    510 => "Not Extended"
         
     | 
| 
       70 
     | 
    
         
            -
                  }
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
                  def self.interpret_status(status)
         
     | 
| 
       73 
     | 
    
         
            -
                    "#{status} #{STATUS_CODES[status.to_i]}".strip
         
     | 
| 
       74 
     | 
    
         
            -
                  end
         
     | 
| 
       75 
     | 
    
         
            -
                end
         
     | 
| 
       76 
     | 
    
         
            -
              end
         
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
              class UnauthorizedResponseError < ResponseError; end
         
     | 
| 
       79 
     | 
    
         
            -
              USER_AGENT            = "SoundCloud Ruby Wrapper #{VERSION}"
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
              include HTTMultiParty
         
     | 
| 
       82 
     | 
    
         
            -
              CLIENT_ID_PARAM_NAME  = :client_id
         
     | 
| 
       83 
     | 
    
         
            -
              API_SUBHOST           = 'api'
         
     | 
| 
       84 
     | 
    
         
            -
              AUTHORIZE_PATH        = '/connect'
         
     | 
| 
       85 
     | 
    
         
            -
              TOKEN_PATH            = '/oauth2/token'
         
     | 
| 
       86 
     | 
    
         
            -
              DEFAULT_OPTIONS       = {
         
     | 
| 
       87 
     | 
    
         
            -
                :site              => 'soundcloud.com',
         
     | 
| 
       88 
     | 
    
         
            -
                :on_exchange_token => lambda {}
         
     | 
| 
       89 
     | 
    
         
            -
              }
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
              attr_accessor :options
         
     | 
| 
       92 
     | 
    
         
            -
              headers({"User-Agent" => USER_AGENT})
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
              def initialize(options={})
         
     | 
| 
       95 
     | 
    
         
            -
                store_options(options)
         
     | 
| 
       96 
     | 
    
         
            -
                if access_token.nil? && (options_for_refresh_flow_present? ||
         
     | 
| 
       97 
     | 
    
         
            -
                                         options_for_credentials_flow_present? || options_for_code_flow_present?)
         
     | 
| 
       98 
     | 
    
         
            -
                  exchange_token
         
     | 
| 
       99 
     | 
    
         
            -
                end
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                raise ArgumentError, "At least a client_id or an access_token must be present" if client_id.nil? && access_token.nil?
         
     | 
| 
       102 
     | 
    
         
            -
              end
         
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
     | 
    
         
            -
              def get   (path, query={}, options={}); handle_response { self.class.get(    *construct_query_arguments(path, options.merge(:query => query)) ) } end
         
     | 
| 
       105 
     | 
    
         
            -
              def post  (path, body={},  options={}); handle_response { self.class.post(   *construct_query_arguments(path, options.merge(:body  => body), :body) ) } end
         
     | 
| 
       106 
     | 
    
         
            -
              def put   (path, body={},  options={}); handle_response { self.class.put(    *construct_query_arguments(path, options.merge(:body  => body), :body) ) } end
         
     | 
| 
       107 
     | 
    
         
            -
              def delete(path, query={}, options={}); handle_response { self.class.delete( *construct_query_arguments(path, options.merge(:query => query)) ) } end
         
     | 
| 
       108 
     | 
    
         
            -
              def head  (path, query={}, options={}); handle_response { self.class.head(   *construct_query_arguments(path, options.merge(:query => query)) ) } end
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
              # accessors for options
         
     | 
| 
       111 
     | 
    
         
            -
              def client_id;      @options[:client_id];     end
         
     | 
| 
       112 
     | 
    
         
            -
              def client_secret;  @options[:client_secret]; end
         
     | 
| 
       113 
     | 
    
         
            -
              def access_token;   @options[:access_token];  end
         
     | 
| 
       114 
     | 
    
         
            -
              def refresh_token;  @options[:refresh_token]; end
         
     | 
| 
       115 
     | 
    
         
            -
              def redirect_uri;   @options[:redirect_uri];  end
         
     | 
| 
       116 
     | 
    
         
            -
              def expires_at;     @options[:expires_at];    end
         
     | 
| 
       117 
4 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
                !! @options[:use_ssl?] || access_token
         
     | 
| 
       124 
     | 
    
         
            -
              end
         
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
              def site; @options[:site]; end
         
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
              def host; site; end
         
     | 
| 
       129 
     | 
    
         
            -
              def api_host; [API_SUBHOST, host].join('.'); end
         
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
              def authorize_url(options={})
         
     | 
| 
       132 
     | 
    
         
            -
                additional_params = [:display, :state, :scope].map do |param_name|
         
     | 
| 
       133 
     | 
    
         
            -
                  value = options.delete(param_name)
         
     | 
| 
       134 
     | 
    
         
            -
                  "#{param_name}=#{CGI.escape value}" unless value.nil?
         
     | 
| 
       135 
     | 
    
         
            -
                end.compact.join("&")
         
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
       137 
     | 
    
         
            -
                store_options(options)
         
     | 
| 
       138 
     | 
    
         
            -
                "https://#{host}#{AUTHORIZE_PATH}?response_type=code_and_token&client_id=#{client_id}&redirect_uri=#{URI.escape redirect_uri}&#{additional_params}"
         
     | 
| 
       139 
     | 
    
         
            -
              end
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'soundcloud/array_response_wrapper'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'soundcloud/client'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'soundcloud/hash_response_wrapper'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'soundcloud/response_error'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'soundcloud/version'
         
     | 
| 
       140 
10 
     | 
    
         | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
                store_options(options)
         
     | 
| 
       143 
     | 
    
         
            -
                raise ArgumentError, 'client_id and client_secret is required to retrieve an access_token' if client_id.nil? || client_secret.nil?
         
     | 
| 
       144 
     | 
    
         
            -
                client_params = {:client_id => client_id, :client_secret => client_secret}
         
     | 
| 
       145 
     | 
    
         
            -
                params = if options_for_refresh_flow_present?
         
     | 
| 
       146 
     | 
    
         
            -
                  {:grant_type => 'refresh_token',      :refresh_token => refresh_token}
         
     | 
| 
       147 
     | 
    
         
            -
                elsif options_for_credentials_flow_present?
         
     | 
| 
       148 
     | 
    
         
            -
                  {:grant_type => 'password',           :username      => @options[:username],     :password => @options[:password]}
         
     | 
| 
       149 
     | 
    
         
            -
                elsif options_for_code_flow_present?
         
     | 
| 
       150 
     | 
    
         
            -
                  {:grant_type => 'authorization_code', :redirect_uri  => @options[:redirect_uri], :code => @options[:code]}
         
     | 
| 
       151 
     | 
    
         
            -
                end
         
     | 
| 
       152 
     | 
    
         
            -
                params.merge!(client_params)
         
     | 
| 
       153 
     | 
    
         
            -
                response = handle_response(false) {
         
     | 
| 
       154 
     | 
    
         
            -
                  self.class.post("https://#{api_host}#{TOKEN_PATH}", :query => params)
         
     | 
| 
       155 
     | 
    
         
            -
                }
         
     | 
| 
       156 
     | 
    
         
            -
                @options.merge!(:access_token => response.access_token, :refresh_token => response.refresh_token)
         
     | 
| 
       157 
     | 
    
         
            -
                @options[:expires_at] = Time.now + response.expires_in if response.expires_in
         
     | 
| 
       158 
     | 
    
         
            -
                @options[:on_exchange_token].call(*[(self if @options[:on_exchange_token].arity == 1)].compact)
         
     | 
| 
       159 
     | 
    
         
            -
                response
         
     | 
| 
       160 
     | 
    
         
            -
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
            module SoundCloud
         
     | 
| 
       161 
12 
     | 
    
         | 
| 
       162 
     | 
    
         
            -
              def  
     | 
| 
       163 
     | 
    
         
            -
                 
     | 
| 
      
 13 
     | 
    
         
            +
              def new(options={})
         
     | 
| 
      
 14 
     | 
    
         
            +
                Client.new(options)
         
     | 
| 
       164 
15 
     | 
    
         
             
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
              module_function :new
         
     | 
| 
       165 
17 
     | 
    
         | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
             
     | 
| 
       168 
     | 
    
         
            -
                 
     | 
| 
       169 
     | 
    
         
            -
                if response && !response.success?
         
     | 
| 
       170 
     | 
    
         
            -
                  if response.code == 401 && refreshing_enabled && options_for_refresh_flow_present?
         
     | 
| 
       171 
     | 
    
         
            -
                    exchange_token
         
     | 
| 
       172 
     | 
    
         
            -
                    # TODO it should return the original
         
     | 
| 
       173 
     | 
    
         
            -
                    handle_response(false, &block)
         
     | 
| 
       174 
     | 
    
         
            -
                  else
         
     | 
| 
       175 
     | 
    
         
            -
                    raise ResponseError.new(response)
         
     | 
| 
       176 
     | 
    
         
            -
                  end
         
     | 
| 
       177 
     | 
    
         
            -
                elsif response.is_a? Hash
         
     | 
| 
       178 
     | 
    
         
            -
                  HashResponseWrapper.new(response)
         
     | 
| 
       179 
     | 
    
         
            -
                elsif response.is_a? Array
         
     | 
| 
       180 
     | 
    
         
            -
                  ArrayResponseWrapper.new(response)
         
     | 
| 
       181 
     | 
    
         
            -
                elsif response && response.success?
         
     | 
| 
       182 
     | 
    
         
            -
                  response
         
     | 
| 
       183 
     | 
    
         
            -
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              def method_missing(method_name, *args, &block)
         
     | 
| 
      
 19 
     | 
    
         
            +
                return super unless respond_to_missing?(method_name)
         
     | 
| 
      
 20 
     | 
    
         
            +
                Client.send(method_name, *args, &block)
         
     | 
| 
       184 
21 
     | 
    
         
             
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
              module_function :method_missing
         
     | 
| 
       185 
23 
     | 
    
         | 
| 
       186 
     | 
    
         
            -
              def  
     | 
| 
       187 
     | 
    
         
            -
             
     | 
| 
       188 
     | 
    
         
            -
              def options_for_code_flow_present?;        !! @options[:code] && @options[:redirect_uri]; end
         
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
              def store_options(options={})
         
     | 
| 
       191 
     | 
    
         
            -
                @options ||= DEFAULT_OPTIONS.dup
         
     | 
| 
       192 
     | 
    
         
            -
                @options.merge! options
         
     | 
| 
      
 24 
     | 
    
         
            +
              def respond_to_missing?(method_name, include_private=false)
         
     | 
| 
      
 25 
     | 
    
         
            +
                Client.respond_to?(method_name, include_private)
         
     | 
| 
       193 
26 
     | 
    
         
             
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
              module_function :respond_to_missing?
         
     | 
| 
       194 
28 
     | 
    
         | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
              def construct_query_arguments(path_or_uri, options={}, body_or_query=:query)
         
     | 
| 
       197 
     | 
    
         
            -
                uri = URI.parse(path_or_uri)
         
     | 
| 
       198 
     | 
    
         
            -
                path = uri.path
         
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
                scheme = use_ssl? ? 'https' : 'http'
         
     | 
| 
       201 
     | 
    
         
            -
                options = options.dup
         
     | 
| 
       202 
     | 
    
         
            -
                options[body_or_query] ||= {}
         
     | 
| 
       203 
     | 
    
         
            -
                options[body_or_query][:format] = "json"
         
     | 
| 
       204 
     | 
    
         
            -
                if access_token
         
     | 
| 
       205 
     | 
    
         
            -
                  options[body_or_query][:oauth_token] = access_token
         
     | 
| 
       206 
     | 
    
         
            -
                else
         
     | 
| 
       207 
     | 
    
         
            -
                  options[body_or_query][CLIENT_ID_PARAM_NAME] = client_id
         
     | 
| 
       208 
     | 
    
         
            -
                end
         
     | 
| 
       209 
     | 
    
         
            -
                [
         
     | 
| 
       210 
     | 
    
         
            -
                  "#{scheme}://#{api_host}#{path}#{uri.query ? "?#{uri.query}" : ""}",
         
     | 
| 
       211 
     | 
    
         
            -
                  options
         
     | 
| 
       212 
     | 
    
         
            -
                ]
         
     | 
| 
       213 
     | 
    
         
            -
              end
         
     | 
| 
       214 
29 
     | 
    
         
             
            end
         
     | 
| 
       215 
30 
     | 
    
         | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
       217 
     | 
    
         
            -
            require 'soundcloud/hash_response_wrapper'
         
     | 
| 
      
 31 
     | 
    
         
            +
            Soundcloud = SoundCloud
         
     | 
| 
         @@ -1,8 +1,12 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
               
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
                 
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            module SoundCloud
         
     | 
| 
      
 2 
     | 
    
         
            +
              class ArrayResponseWrapper < Array
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :response
         
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize(response=[])
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @response = response
         
     | 
| 
      
 6 
     | 
    
         
            +
                  mashes = response.map do |object|
         
     | 
| 
      
 7 
     | 
    
         
            +
                    Hashie::Mash.new(object)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
                  replace(mashes)
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
       7 
11 
     | 
    
         
             
              end
         
     | 
| 
       8 
     | 
    
         
            -
            end
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,199 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SoundCloud
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Client
         
     | 
| 
      
 3 
     | 
    
         
            +
                include HTTMultiParty
         
     | 
| 
      
 4 
     | 
    
         
            +
                USER_AGENT            = "SoundCloud Ruby Wrapper #{VERSION}"
         
     | 
| 
      
 5 
     | 
    
         
            +
                CLIENT_ID_PARAM_NAME  = :client_id
         
     | 
| 
      
 6 
     | 
    
         
            +
                API_SUBHOST           = 'api'
         
     | 
| 
      
 7 
     | 
    
         
            +
                AUTHORIZE_PATH        = '/connect'
         
     | 
| 
      
 8 
     | 
    
         
            +
                TOKEN_PATH            = '/oauth2/token'
         
     | 
| 
      
 9 
     | 
    
         
            +
                DEFAULT_OPTIONS       = {
         
     | 
| 
      
 10 
     | 
    
         
            +
                  :site              => 'soundcloud.com',
         
     | 
| 
      
 11 
     | 
    
         
            +
                  :on_exchange_token => lambda {}
         
     | 
| 
      
 12 
     | 
    
         
            +
                }
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                attr_accessor :options
         
     | 
| 
      
 15 
     | 
    
         
            +
                headers({"User-Agent" => USER_AGENT})
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def initialize(options={})
         
     | 
| 
      
 18 
     | 
    
         
            +
                  store_options(options)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  if access_token.nil? && (options_for_refresh_flow_present? || options_for_credentials_flow_present? || options_for_code_flow_present?)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    exchange_token
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  raise ArgumentError, "At least a client_id or an access_token must be present" if client_id.nil? && access_token.nil?
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def get(path, query={}, options={})
         
     | 
| 
      
 26 
     | 
    
         
            +
                  handle_response {
         
     | 
| 
      
 27 
     | 
    
         
            +
                    self.class.get(*construct_query_arguments(path, options.merge(:query => query)))
         
     | 
| 
      
 28 
     | 
    
         
            +
                  }
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def post(path, body={},  options={})
         
     | 
| 
      
 32 
     | 
    
         
            +
                  handle_response {
         
     | 
| 
      
 33 
     | 
    
         
            +
                    self.class.post(*construct_query_arguments(path, options.merge(:body => body), :body))
         
     | 
| 
      
 34 
     | 
    
         
            +
                  }
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def put(path, body={},  options={})
         
     | 
| 
      
 38 
     | 
    
         
            +
                  handle_response {
         
     | 
| 
      
 39 
     | 
    
         
            +
                    self.class.put(*construct_query_arguments(path, options.merge(:body => body), :body))
         
     | 
| 
      
 40 
     | 
    
         
            +
                  }
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                def delete(path, query={}, options={})
         
     | 
| 
      
 44 
     | 
    
         
            +
                  handle_response {
         
     | 
| 
      
 45 
     | 
    
         
            +
                    self.class.delete(*construct_query_arguments(path, options.merge(:query => query)))
         
     | 
| 
      
 46 
     | 
    
         
            +
                  }
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def head(path, query={}, options={})
         
     | 
| 
      
 50 
     | 
    
         
            +
                  handle_response {
         
     | 
| 
      
 51 
     | 
    
         
            +
                    self.class.head(*construct_query_arguments(path, options.merge(:query => query)))
         
     | 
| 
      
 52 
     | 
    
         
            +
                  }
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                # accessors for options
         
     | 
| 
      
 56 
     | 
    
         
            +
                def client_id
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @options[:client_id]
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def client_secret
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @options[:client_secret]
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def access_token
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @options[:access_token]
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def refresh_token
         
     | 
| 
      
 69 
     | 
    
         
            +
                  @options[:refresh_token]
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def redirect_uri
         
     | 
| 
      
 73 
     | 
    
         
            +
                  @options[:redirect_uri]
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def expires_at
         
     | 
| 
      
 77 
     | 
    
         
            +
                  @options[:expires_at]
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def expired?
         
     | 
| 
      
 81 
     | 
    
         
            +
                  (expires_at.nil? || expires_at < Time.now)
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                def use_ssl?
         
     | 
| 
      
 85 
     | 
    
         
            +
                  !!(@options[:use_ssl?] || access_token)
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                def site
         
     | 
| 
      
 89 
     | 
    
         
            +
                  @options[:site]
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
                alias host site
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                def api_host
         
     | 
| 
      
 94 
     | 
    
         
            +
                  [API_SUBHOST, host].join('.')
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                def authorize_url(options={})
         
     | 
| 
      
 98 
     | 
    
         
            +
                  additional_params = [:display, :state, :scope].map do |param_name|
         
     | 
| 
      
 99 
     | 
    
         
            +
                    value = options.delete(param_name)
         
     | 
| 
      
 100 
     | 
    
         
            +
                    "#{param_name}=#{CGI.escape value}" unless value.nil?
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end.compact.join("&")
         
     | 
| 
      
 102 
     | 
    
         
            +
                  store_options(options)
         
     | 
| 
      
 103 
     | 
    
         
            +
                  "https://#{host}#{AUTHORIZE_PATH}?response_type=code_and_token&client_id=#{client_id}&redirect_uri=#{URI.escape(redirect_uri)}&#{additional_params}"
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                def exchange_token(options={})
         
     | 
| 
      
 107 
     | 
    
         
            +
                  store_options(options)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  raise ArgumentError, 'client_id and client_secret is required to retrieve an access_token' if client_id.nil? || client_secret.nil?
         
     | 
| 
      
 109 
     | 
    
         
            +
                  client_params = {:client_id => client_id, :client_secret => client_secret}
         
     | 
| 
      
 110 
     | 
    
         
            +
                  params = if options_for_refresh_flow_present?
         
     | 
| 
      
 111 
     | 
    
         
            +
                    {
         
     | 
| 
      
 112 
     | 
    
         
            +
                      :grant_type => 'refresh_token',
         
     | 
| 
      
 113 
     | 
    
         
            +
                      :refresh_token => refresh_token,
         
     | 
| 
      
 114 
     | 
    
         
            +
                    }
         
     | 
| 
      
 115 
     | 
    
         
            +
                  elsif options_for_credentials_flow_present?
         
     | 
| 
      
 116 
     | 
    
         
            +
                    {
         
     | 
| 
      
 117 
     | 
    
         
            +
                      :grant_type => 'password',
         
     | 
| 
      
 118 
     | 
    
         
            +
                      :username => @options[:username],
         
     | 
| 
      
 119 
     | 
    
         
            +
                      :password => @options[:password],
         
     | 
| 
      
 120 
     | 
    
         
            +
                    }
         
     | 
| 
      
 121 
     | 
    
         
            +
                  elsif options_for_code_flow_present?
         
     | 
| 
      
 122 
     | 
    
         
            +
                    {
         
     | 
| 
      
 123 
     | 
    
         
            +
                      :grant_type => 'authorization_code',
         
     | 
| 
      
 124 
     | 
    
         
            +
                      :redirect_uri => @options[:redirect_uri],
         
     | 
| 
      
 125 
     | 
    
         
            +
                      :code => @options[:code],
         
     | 
| 
      
 126 
     | 
    
         
            +
                    }
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
                  params.merge!(client_params)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  response = handle_response(false) {
         
     | 
| 
      
 130 
     | 
    
         
            +
                    self.class.post("https://#{api_host}#{TOKEN_PATH}", :query => params)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  }
         
     | 
| 
      
 132 
     | 
    
         
            +
                  @options.merge!(:access_token => response.access_token, :refresh_token => response.refresh_token)
         
     | 
| 
      
 133 
     | 
    
         
            +
                  @options[:expires_at] = Time.now + response.expires_in if response.expires_in
         
     | 
| 
      
 134 
     | 
    
         
            +
                  @options[:on_exchange_token].call(*[(self if @options[:on_exchange_token].arity == 1)].compact)
         
     | 
| 
      
 135 
     | 
    
         
            +
                  response
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                def on_exchange_token(&block)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  store_options(:on_exchange_token => block)
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
              private
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                def handle_response(refreshing_enabled=true, &block)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  response = block.call
         
     | 
| 
      
 146 
     | 
    
         
            +
                  if response && !response.success?
         
     | 
| 
      
 147 
     | 
    
         
            +
                    if response.code == 401 && refreshing_enabled && options_for_refresh_flow_present?
         
     | 
| 
      
 148 
     | 
    
         
            +
                      exchange_token
         
     | 
| 
      
 149 
     | 
    
         
            +
                      # TODO it should return the original
         
     | 
| 
      
 150 
     | 
    
         
            +
                      handle_response(false, &block)
         
     | 
| 
      
 151 
     | 
    
         
            +
                    else
         
     | 
| 
      
 152 
     | 
    
         
            +
                      raise ResponseError.new(response)
         
     | 
| 
      
 153 
     | 
    
         
            +
                    end
         
     | 
| 
      
 154 
     | 
    
         
            +
                  elsif response.is_a?(Hash)
         
     | 
| 
      
 155 
     | 
    
         
            +
                    HashResponseWrapper.new(response)
         
     | 
| 
      
 156 
     | 
    
         
            +
                  elsif response.is_a?(Array)
         
     | 
| 
      
 157 
     | 
    
         
            +
                    ArrayResponseWrapper.new(response)
         
     | 
| 
      
 158 
     | 
    
         
            +
                  elsif response && response.success?
         
     | 
| 
      
 159 
     | 
    
         
            +
                    response
         
     | 
| 
      
 160 
     | 
    
         
            +
                  end
         
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                def options_for_refresh_flow_present?
         
     | 
| 
      
 164 
     | 
    
         
            +
                  !!@options[:refresh_token]
         
     | 
| 
      
 165 
     | 
    
         
            +
                end
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                def options_for_credentials_flow_present?
         
     | 
| 
      
 168 
     | 
    
         
            +
                  !!(@options[:username] && @options[:password])
         
     | 
| 
      
 169 
     | 
    
         
            +
                end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                def options_for_code_flow_present?
         
     | 
| 
      
 172 
     | 
    
         
            +
                  !!(@options[:code] && @options[:redirect_uri])
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                def store_options(options={})
         
     | 
| 
      
 176 
     | 
    
         
            +
                  @options ||= DEFAULT_OPTIONS.dup
         
     | 
| 
      
 177 
     | 
    
         
            +
                  @options.merge!(options)
         
     | 
| 
      
 178 
     | 
    
         
            +
                end
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                def construct_query_arguments(path_or_uri, options={}, body_or_query=:query)
         
     | 
| 
      
 181 
     | 
    
         
            +
                  uri = URI.parse(path_or_uri)
         
     | 
| 
      
 182 
     | 
    
         
            +
                  path = uri.path
         
     | 
| 
      
 183 
     | 
    
         
            +
                  scheme = use_ssl? ? 'https' : 'http'
         
     | 
| 
      
 184 
     | 
    
         
            +
                  options = options.dup
         
     | 
| 
      
 185 
     | 
    
         
            +
                  options[body_or_query] ||= {}
         
     | 
| 
      
 186 
     | 
    
         
            +
                  options[body_or_query][:format] = "json"
         
     | 
| 
      
 187 
     | 
    
         
            +
                  if access_token
         
     | 
| 
      
 188 
     | 
    
         
            +
                    options[body_or_query][:oauth_token] = access_token
         
     | 
| 
      
 189 
     | 
    
         
            +
                  else
         
     | 
| 
      
 190 
     | 
    
         
            +
                    options[body_or_query][CLIENT_ID_PARAM_NAME] = client_id
         
     | 
| 
      
 191 
     | 
    
         
            +
                  end
         
     | 
| 
      
 192 
     | 
    
         
            +
                  [
         
     | 
| 
      
 193 
     | 
    
         
            +
                    "#{scheme}://#{api_host}#{path}#{uri.query ? "?#{uri.query}" : ""}",
         
     | 
| 
      
 194 
     | 
    
         
            +
                    options
         
     | 
| 
      
 195 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 196 
     | 
    
         
            +
                end
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
              end
         
     | 
| 
      
 199 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,7 +1,9 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
               
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
                 
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            module SoundCloud
         
     | 
| 
      
 2 
     | 
    
         
            +
              class HashResponseWrapper < Hashie::Mash
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :response
         
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize(response=nil, *args)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @response = response
         
     | 
| 
      
 6 
     | 
    
         
            +
                  super(response, *args)
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
       6 
8 
     | 
    
         
             
              end
         
     | 
| 
       7 
9 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SoundCloud
         
     | 
| 
      
 2 
     | 
    
         
            +
              class ResponseError < HTTParty::ResponseError
         
     | 
| 
      
 3 
     | 
    
         
            +
                STATUS_CODES = {
         
     | 
| 
      
 4 
     | 
    
         
            +
                  400 => "Bad Request",
         
     | 
| 
      
 5 
     | 
    
         
            +
                  401 => "Unauthorized",
         
     | 
| 
      
 6 
     | 
    
         
            +
                  402 => "Payment Required",
         
     | 
| 
      
 7 
     | 
    
         
            +
                  403 => "Forbidden",
         
     | 
| 
      
 8 
     | 
    
         
            +
                  404 => "Not Found",
         
     | 
| 
      
 9 
     | 
    
         
            +
                  405 => "Method Not Allowed",
         
     | 
| 
      
 10 
     | 
    
         
            +
                  406 => "Not Acceptable",
         
     | 
| 
      
 11 
     | 
    
         
            +
                  407 => "Proxy Authentication Required",
         
     | 
| 
      
 12 
     | 
    
         
            +
                  408 => "Request Timeout",
         
     | 
| 
      
 13 
     | 
    
         
            +
                  409 => "Conflict",
         
     | 
| 
      
 14 
     | 
    
         
            +
                  410 => "Gone",
         
     | 
| 
      
 15 
     | 
    
         
            +
                  411 => "Length Required",
         
     | 
| 
      
 16 
     | 
    
         
            +
                  412 => "Precondition Failed",
         
     | 
| 
      
 17 
     | 
    
         
            +
                  413 => "Request Entity Too Large",
         
     | 
| 
      
 18 
     | 
    
         
            +
                  414 => "Request-URI Too Long",
         
     | 
| 
      
 19 
     | 
    
         
            +
                  415 => "Unsupported Media Type",
         
     | 
| 
      
 20 
     | 
    
         
            +
                  416 => "Requested Range Not Satisfiable",
         
     | 
| 
      
 21 
     | 
    
         
            +
                  417 => "Expectation Failed",
         
     | 
| 
      
 22 
     | 
    
         
            +
                  422 => "Unprocessable Entity",
         
     | 
| 
      
 23 
     | 
    
         
            +
                  423 => "Locked",
         
     | 
| 
      
 24 
     | 
    
         
            +
                  424 => "Failed Dependency",
         
     | 
| 
      
 25 
     | 
    
         
            +
                  426 => "Upgrade Required",
         
     | 
| 
      
 26 
     | 
    
         
            +
                  500 => "Internal Server Error",
         
     | 
| 
      
 27 
     | 
    
         
            +
                  501 => "Not Implemented",
         
     | 
| 
      
 28 
     | 
    
         
            +
                  502 => "Bad Gateway",
         
     | 
| 
      
 29 
     | 
    
         
            +
                  503 => "Service Unavailable",
         
     | 
| 
      
 30 
     | 
    
         
            +
                  504 => "Gateway Timeout",
         
     | 
| 
      
 31 
     | 
    
         
            +
                  505 => "HTTP Version Not Supported",
         
     | 
| 
      
 32 
     | 
    
         
            +
                  507 => "Insufficient Storage",
         
     | 
| 
      
 33 
     | 
    
         
            +
                  510 => "Not Extended"
         
     | 
| 
      
 34 
     | 
    
         
            +
                }
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def message
         
     | 
| 
      
 37 
     | 
    
         
            +
                  error = response.parsed_response['error'] || response.parsed_response['errors']['error']
         
     | 
| 
      
 38 
     | 
    
         
            +
                  "HTTP status: #{response.code} #{STATUS_CODES[response.code]} Error: #{error}"
         
     | 
| 
      
 39 
     | 
    
         
            +
                rescue
         
     | 
| 
      
 40 
     | 
    
         
            +
                  "HTTP status: #{response.code} #{STATUS_CODES[response.code]}"
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/soundcloud/version.rb
    CHANGED
    
    | 
         @@ -1,3 +1,3 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
              VERSION = '0.3. 
     | 
| 
      
 1 
     | 
    
         
            +
            module SoundCloud
         
     | 
| 
      
 2 
     | 
    
         
            +
              VERSION = '0.3.2'
         
     | 
| 
       3 
3 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: soundcloud
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.3. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.3.2
         
     | 
| 
       5 
5 
     | 
    
         
             
              prerelease: 
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors:
         
     | 
| 
         @@ -9,64 +9,48 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date:  
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2013-08-19 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
     | 
    
         
            -
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
     | 
    
         
            -
              name: httparty
         
     | 
| 
       16 
     | 
    
         
            -
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       17 
     | 
    
         
            -
                none: false
         
     | 
| 
       18 
     | 
    
         
            -
                requirements:
         
     | 
| 
       19 
     | 
    
         
            -
                - - ! '>='
         
     | 
| 
       20 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       21 
     | 
    
         
            -
                    version: 0.7.3
         
     | 
| 
       22 
     | 
    
         
            -
              type: :runtime
         
     | 
| 
       23 
     | 
    
         
            -
              prerelease: false
         
     | 
| 
       24 
     | 
    
         
            -
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       25 
     | 
    
         
            -
                none: false
         
     | 
| 
       26 
     | 
    
         
            -
                requirements:
         
     | 
| 
       27 
     | 
    
         
            -
                - - ! '>='
         
     | 
| 
       28 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       29 
     | 
    
         
            -
                    version: 0.7.3
         
     | 
| 
       30 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       31 
15 
     | 
    
         
             
              name: httmultiparty
         
     | 
| 
       32 
16 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       33 
17 
     | 
    
         
             
                none: false
         
     | 
| 
       34 
18 
     | 
    
         
             
                requirements:
         
     | 
| 
       35 
     | 
    
         
            -
                - -  
     | 
| 
      
 19 
     | 
    
         
            +
                - - ~>
         
     | 
| 
       36 
20 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       37 
     | 
    
         
            -
                    version:  
     | 
| 
      
 21 
     | 
    
         
            +
                    version: 0.3.0
         
     | 
| 
       38 
22 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       39 
23 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       40 
24 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       41 
25 
     | 
    
         
             
                none: false
         
     | 
| 
       42 
26 
     | 
    
         
             
                requirements:
         
     | 
| 
       43 
     | 
    
         
            -
                - -  
     | 
| 
      
 27 
     | 
    
         
            +
                - - ~>
         
     | 
| 
       44 
28 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       45 
     | 
    
         
            -
                    version:  
     | 
| 
      
 29 
     | 
    
         
            +
                    version: 0.3.0
         
     | 
| 
       46 
30 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       47 
31 
     | 
    
         
             
              name: hashie
         
     | 
| 
       48 
32 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       49 
33 
     | 
    
         
             
                none: false
         
     | 
| 
       50 
34 
     | 
    
         
             
                requirements:
         
     | 
| 
       51 
     | 
    
         
            -
                - -  
     | 
| 
      
 35 
     | 
    
         
            +
                - - ~>
         
     | 
| 
       52 
36 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       53 
     | 
    
         
            -
                    version: '0'
         
     | 
| 
      
 37 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
       54 
38 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       55 
39 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       56 
40 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       57 
41 
     | 
    
         
             
                none: false
         
     | 
| 
       58 
42 
     | 
    
         
             
                requirements:
         
     | 
| 
       59 
     | 
    
         
            -
                - -  
     | 
| 
      
 43 
     | 
    
         
            +
                - - ~>
         
     | 
| 
       60 
44 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       61 
     | 
    
         
            -
                    version: '0'
         
     | 
| 
      
 45 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
       62 
46 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       63 
     | 
    
         
            -
              name:  
     | 
| 
      
 47 
     | 
    
         
            +
              name: bundler
         
     | 
| 
       64 
48 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       65 
49 
     | 
    
         
             
                none: false
         
     | 
| 
       66 
50 
     | 
    
         
             
                requirements:
         
     | 
| 
       67 
51 
     | 
    
         
             
                - - ~>
         
     | 
| 
       68 
52 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       69 
     | 
    
         
            -
                    version:  
     | 
| 
      
 53 
     | 
    
         
            +
                    version: '1.0'
         
     | 
| 
       70 
54 
     | 
    
         
             
              type: :development
         
     | 
| 
       71 
55 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       72 
56 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -74,24 +58,9 @@ dependencies: 
     | 
|
| 
       74 
58 
     | 
    
         
             
                requirements:
         
     | 
| 
       75 
59 
     | 
    
         
             
                - - ~>
         
     | 
| 
       76 
60 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       77 
     | 
    
         
            -
                    version:  
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
               
     | 
| 
       80 
     | 
    
         
            -
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       81 
     | 
    
         
            -
                none: false
         
     | 
| 
       82 
     | 
    
         
            -
                requirements:
         
     | 
| 
       83 
     | 
    
         
            -
                - - ! '>='
         
     | 
| 
       84 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       85 
     | 
    
         
            -
                    version: '0'
         
     | 
| 
       86 
     | 
    
         
            -
              type: :development
         
     | 
| 
       87 
     | 
    
         
            -
              prerelease: false
         
     | 
| 
       88 
     | 
    
         
            -
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       89 
     | 
    
         
            -
                none: false
         
     | 
| 
       90 
     | 
    
         
            -
                requirements:
         
     | 
| 
       91 
     | 
    
         
            -
                - - ! '>='
         
     | 
| 
       92 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       93 
     | 
    
         
            -
                    version: '0'
         
     | 
| 
       94 
     | 
    
         
            -
            description: A simple Soundcloud API wrapper based of httparty, multipart-post, httmultiparty
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '1.0'
         
     | 
| 
      
 62 
     | 
    
         
            +
            description: The official SoundCloud API wrapper. It provides simple methods to handle
         
     | 
| 
      
 63 
     | 
    
         
            +
              authorization and to execute HTTP calls.
         
     | 
| 
       95 
64 
     | 
    
         
             
            email:
         
     | 
| 
       96 
65 
     | 
    
         
             
            - johannes@soundcloud.com
         
     | 
| 
       97 
66 
     | 
    
         
             
            executables: []
         
     | 
| 
         @@ -99,7 +68,9 @@ extensions: [] 
     | 
|
| 
       99 
68 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       100 
69 
     | 
    
         
             
            files:
         
     | 
| 
       101 
70 
     | 
    
         
             
            - lib/soundcloud/array_response_wrapper.rb
         
     | 
| 
      
 71 
     | 
    
         
            +
            - lib/soundcloud/client.rb
         
     | 
| 
       102 
72 
     | 
    
         
             
            - lib/soundcloud/hash_response_wrapper.rb
         
     | 
| 
      
 73 
     | 
    
         
            +
            - lib/soundcloud/response_error.rb
         
     | 
| 
       103 
74 
     | 
    
         
             
            - lib/soundcloud/version.rb
         
     | 
| 
       104 
75 
     | 
    
         
             
            - lib/soundcloud.rb
         
     | 
| 
       105 
76 
     | 
    
         
             
            - README.md
         
     | 
| 
         @@ -120,11 +91,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       120 
91 
     | 
    
         
             
              requirements:
         
     | 
| 
       121 
92 
     | 
    
         
             
              - - ! '>='
         
     | 
| 
       122 
93 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       123 
     | 
    
         
            -
                  version: 1.3. 
     | 
| 
      
 94 
     | 
    
         
            +
                  version: 1.3.5
         
     | 
| 
       124 
95 
     | 
    
         
             
            requirements: []
         
     | 
| 
       125 
     | 
    
         
            -
            rubyforge_project:  
     | 
| 
       126 
     | 
    
         
            -
            rubygems_version: 1.8. 
     | 
| 
      
 96 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 97 
     | 
    
         
            +
            rubygems_version: 1.8.23
         
     | 
| 
       127 
98 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       128 
99 
     | 
    
         
             
            specification_version: 3
         
     | 
| 
       129 
     | 
    
         
            -
            summary:  
     | 
| 
      
 100 
     | 
    
         
            +
            summary: The official SoundCloud API wrapper.
         
     | 
| 
       130 
101 
     | 
    
         
             
            test_files: []
         
     | 
| 
      
 102 
     | 
    
         
            +
            has_rdoc: 
         
     |