simplespotify 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.md +17 -0
- data/Rakefile +3 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/simplespotify/actions/albums.rb +30 -0
- data/lib/simplespotify/actions/artists.rb +47 -0
- data/lib/simplespotify/actions/browse.rb +74 -0
- data/lib/simplespotify/actions/playlists.rb +187 -0
- data/lib/simplespotify/actions/tracks.rb +67 -0
- data/lib/simplespotify/actions/users.rb +68 -0
- data/lib/simplespotify/authorization.rb +91 -0
- data/lib/simplespotify/client.rb +76 -0
- data/lib/simplespotify/constants.rb +14 -0
- data/lib/simplespotify/errors.rb +56 -0
- data/lib/simplespotify/models/album.rb +27 -0
- data/lib/simplespotify/models/artist.rb +42 -0
- data/lib/simplespotify/models/category.rb +19 -0
- data/lib/simplespotify/models/collection.rb +52 -0
- data/lib/simplespotify/models/image.rb +16 -0
- data/lib/simplespotify/models/playlist.rb +94 -0
- data/lib/simplespotify/models/track.rb +31 -0
- data/lib/simplespotify/models/user.rb +91 -0
- data/lib/simplespotify/request.rb +54 -0
- data/lib/simplespotify/resource/class_methods.rb +48 -0
- data/lib/simplespotify/resource/instance_methods.rb +102 -0
- data/lib/simplespotify/resource/resource.rb +14 -0
- data/lib/simplespotify/response.rb +22 -0
- data/lib/simplespotify/version.rb +3 -0
- data/lib/simplespotify.rb +72 -0
- data/readme.md +71 -0
- data/simplespotify.gemspec +26 -0
- metadata +122 -0
| @@ -0,0 +1,76 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              class Client
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                attr_accessor :id, :secret, :session, :market
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                [:Albums, :Tracks, :Artists, :Users, :Browse, :Playlists].each do |action|
         | 
| 7 | 
            +
                  require "simplespotify/actions/#{action.downcase}"
         | 
| 8 | 
            +
                  include Actions.const_get(action)
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def initialize client_id, client_secret, default: true
         | 
| 12 | 
            +
                  @id = client_id
         | 
| 13 | 
            +
                  @secret = client_secret
         | 
| 14 | 
            +
                  @session = nil
         | 
| 15 | 
            +
                  @market = nil
         | 
| 16 | 
            +
                  SimpleSpotify.default_client = self if default
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                [:get, :post, :put, :delete].each do |verb|
         | 
| 20 | 
            +
                  define_method(verb) do |msg, data={}|
         | 
| 21 | 
            +
                    unless msg.is_a? SimpleSpotify::Request
         | 
| 22 | 
            +
                      msg = Request.new(msg, {method: verb, data: data})
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                    SimpleSpotify.dispatch msg, session: session
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
             | 
| 29 | 
            +
                def search type, term, market: nil, limit: 20, offset: 0, filters: {}
         | 
| 30 | 
            +
                  type = type.to_s.gsub(/s$/, '').to_sym
         | 
| 31 | 
            +
                  types = [:album, :artist, :playlist, :track]
         | 
| 32 | 
            +
                  raise "Can't search for <#{type}> only: #{types.join(',')}" unless types.include?(type)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  params = {q: term}
         | 
| 35 | 
            +
                  params[:market] = market || @market
         | 
| 36 | 
            +
                  params[:limit] = limit if limit
         | 
| 37 | 
            +
                  params[:offset] = offset if offset
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  filters = filters.map { |filter, value|
         | 
| 40 | 
            +
                    value = value.join(',') if value.is_a?(Array)
         | 
| 41 | 
            +
                    value = [value.min, value.max].map(&:to_s).join('-') if value.is_a?(Range)
         | 
| 42 | 
            +
                    %{#{filter}:"#{value}"}
         | 
| 43 | 
            +
                  }
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  params[:q] = ([term]+filters).join(' ')
         | 
| 46 | 
            +
                  params[:type] = type
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  params = params.reject {|k,v| v.nil?}.to_h
         | 
| 49 | 
            +
                  response = get "search", params
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  Model::Collection.of(type, response.body["#{type}s".to_sym])
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
             | 
| 55 | 
            +
                def to_h
         | 
| 56 | 
            +
                  {
         | 
| 57 | 
            +
                    client_secret: secret,
         | 
| 58 | 
            +
                    client_id: id
         | 
| 59 | 
            +
                  }
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
             | 
| 63 | 
            +
                private
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                def id_for object
         | 
| 66 | 
            +
                  return object.id if object.is_a? Resource
         | 
| 67 | 
            +
                  object
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                def options_with_market user_market, options={}
         | 
| 71 | 
            +
                  options[:market] = user_market || @market
         | 
| 72 | 
            +
                  options.reject {|k,v| v.nil? || v=='' }.to_h
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              #--------------
         | 
| 3 | 
            +
              # Constants
         | 
| 4 | 
            +
              #--------------
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              AUTHORIZATION_URL = 'https://accounts.spotify.com/authorize'
         | 
| 7 | 
            +
              TOKEN_URL = 'https://accounts.spotify.com/api/token'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              ENDPOINT = 'https://api.spotify.com/v1/'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              # Upper bound when trying to refresh the authentication token
         | 
| 12 | 
            +
              MAX_RETRIES = 2
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              module Error
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                def self.for status_code
         | 
| 5 | 
            +
                  case status_code
         | 
| 6 | 
            +
                    when 401 then Unauthorized
         | 
| 7 | 
            +
                    when 404 then NotFound
         | 
| 8 | 
            +
                    when (500..599) then API
         | 
| 9 | 
            +
                    else
         | 
| 10 | 
            +
                      DefaultError
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
                class AuthorizationError < StandardError
         | 
| 16 | 
            +
                  attr_reader :message
         | 
| 17 | 
            +
                  def initialize body
         | 
| 18 | 
            +
                    @message = body[:error_description]
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
             | 
| 23 | 
            +
                class DefaultError < StandardError
         | 
| 24 | 
            +
                  attr_reader :code, :body, :message, :request
         | 
| 25 | 
            +
                  def initialize code, body, request
         | 
| 26 | 
            +
                    @code = code
         | 
| 27 | 
            +
                    @body = body
         | 
| 28 | 
            +
                    @request = request
         | 
| 29 | 
            +
                    @message = body[:error][:message] unless body.nil?
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                class BadResponse < StandardError
         | 
| 34 | 
            +
                  attr_reader :code, :message, :request, :body
         | 
| 35 | 
            +
                  def initialize code, body, request
         | 
| 36 | 
            +
                    @code = code
         | 
| 37 | 
            +
                    @message = 'Unreadable JSON data returned from SimpleSpotify API'
         | 
| 38 | 
            +
                    @request = request
         | 
| 39 | 
            +
                    @body = body
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                class API < DefaultError
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                class NotFound < DefaultError
         | 
| 47 | 
            +
                  def initialize code, body, request
         | 
| 48 | 
            +
                    @message = "#{request.full_url} not found"
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                class Unauthorized < DefaultError
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              module Model
         | 
| 3 | 
            +
                class Album
         | 
| 4 | 
            +
                  include Resource
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  prop :type, from: :album_type
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  many :artists
         | 
| 9 | 
            +
                  prop :markets
         | 
| 10 | 
            +
                  prop :copyrights
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  merge :external_ids
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  prop :genres, default: []
         | 
| 15 | 
            +
                  many :images
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  prop :name
         | 
| 18 | 
            +
                  prop :popularity
         | 
| 19 | 
            +
                  prop :release_date
         | 
| 20 | 
            +
                  prop :release_date_precision
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  many :tracks, paginated: true
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              module Model
         | 
| 3 | 
            +
                class Artist
         | 
| 4 | 
            +
                  include Resource
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  merge :external_ids
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  prop :genres
         | 
| 9 | 
            +
                  many :images
         | 
| 10 | 
            +
                  prop :name
         | 
| 11 | 
            +
                  prop :popularity
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  prop :followers
         | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def related_artists! client=nil
         | 
| 17 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 18 | 
            +
                    @related_artists = client.related_artists(id)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def related_artists client=nil
         | 
| 22 | 
            +
                    @related_artists || related_artists!(client)
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def top_tracks! client=nil
         | 
| 27 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 28 | 
            +
                    @top_tracks = client.top_tracks(id)
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def top_tracks client=nil
         | 
| 32 | 
            +
                    @top_tracks || top_tracks!(client)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def albums! client=nil
         | 
| 36 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 37 | 
            +
                    @albums = client.artist_albums(id)
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              module Models
         | 
| 3 | 
            +
                class Category
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                  many :icons, kind: :image
         | 
| 6 | 
            +
                  prop :name
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def playlists client=nil, country: nil, limit: 20, offset: 0
         | 
| 9 | 
            +
                    @playlists || playlists!(client, country: country, limit: limit, offset: offset)
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def playlists! client=nil, country: nil, limit: 20, offset: 0
         | 
| 13 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 14 | 
            +
                    @playlists = client.category_playlists(id, country: country, limit: limit, offset: offset)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,52 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              module Model
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                class Collection < Array
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  attr_accessor :total
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def self.of type, data
         | 
| 9 | 
            +
                    if type.is_a? Class
         | 
| 10 | 
            +
                      model = type;
         | 
| 11 | 
            +
                      prop = type.to_s.split('::').last.downcase+'s'
         | 
| 12 | 
            +
                    else
         | 
| 13 | 
            +
                      model_name = type.to_s.gsub(/s$/, '')
         | 
| 14 | 
            +
                      model = Model.const_get(model_name.capitalize)
         | 
| 15 | 
            +
                      prop = model_name+'s'
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    prop = prop.to_sym
         | 
| 19 | 
            +
                    prop = :items unless data.has_key?(prop)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    data[prop].map! {|item| model.new(item) }
         | 
| 22 | 
            +
                    self.new(data)
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def initialize data, property=:items
         | 
| 27 | 
            +
                    values = data[property]
         | 
| 28 | 
            +
                    super values
         | 
| 29 | 
            +
                    @total = data[:total] || self.count
         | 
| 30 | 
            +
                    @next = data[:next]
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def total
         | 
| 35 | 
            +
                    @total
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def more?
         | 
| 40 | 
            +
                    !@next.nil?
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def more
         | 
| 45 | 
            +
                    return [] unless more?
         | 
| 46 | 
            +
                    req = Request.new({endpoint: @next, private: false})
         | 
| 47 | 
            +
                    SimpleSpotify.dispatch(req)
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end #/class
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
            end
         | 
| @@ -0,0 +1,94 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              module Model
         | 
| 3 | 
            +
                class Playlist
         | 
| 4 | 
            +
                  include Resource
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  prop :name
         | 
| 7 | 
            +
                  prop :description
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  prop :collaborative
         | 
| 10 | 
            +
                  prop :public
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  many :images
         | 
| 13 | 
            +
                  one :owner, kind: :user
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  prop :snapshot_id
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  many :tracks, kind: :playlist_track, paginated: true
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def public?
         | 
| 20 | 
            +
                    @public == true
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def change_details! client=nil
         | 
| 25 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 26 | 
            +
                    client.change_details(self, name: name, public: @public)
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  #--------------
         | 
| 30 | 
            +
                  # Tracks
         | 
| 31 | 
            +
                  #--------------
         | 
| 32 | 
            +
                  def tracks! client=nil, options={}
         | 
| 33 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 34 | 
            +
                    client.playlist_tracks(self, options)
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def add_tracks tracks, position=nil, client=nil
         | 
| 38 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 39 | 
            +
                    client.playlist_tracks_add(self, tracks: tracks, position: position)
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def remove_tracks client=nil, tracks: nil, positions: nil, snapshot_id: nil
         | 
| 43 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 44 | 
            +
                    snapshot_id ||= @snapshot_id unless positions.nil?
         | 
| 45 | 
            +
                    client.playlist_tracks_remove(self, tracks: tracks, positions: positions, snapshot_id: snapshot_id)
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def reorder_tracks client=nil, payload
         | 
| 49 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 50 | 
            +
                    client.playlist_tracks_reorder(self, payload)
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  def replace_tracks client=nil, tracks: []
         | 
| 54 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 55 | 
            +
                    client.playlist_tracks_reorder(self, tracks: tracks)
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
             | 
| 59 | 
            +
                  #--------------
         | 
| 60 | 
            +
                  # Follows
         | 
| 61 | 
            +
                  #--------------
         | 
| 62 | 
            +
                  def follow client=nil, public: true
         | 
| 63 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 64 | 
            +
                    client.playlist_follow(self, public: public)
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  def unfollow
         | 
| 68 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 69 | 
            +
                    client.playlist_unfollow(self)
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
             | 
| 73 | 
            +
                  #--------------
         | 
| 74 | 
            +
                  # Create
         | 
| 75 | 
            +
                  #--------------
         | 
| 76 | 
            +
                  def self.create user, name, client=nil, public:true
         | 
| 77 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 78 | 
            +
                    client.playlist_create(user, name, public: public)
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
             | 
| 84 | 
            +
                class PlaylistTrack
         | 
| 85 | 
            +
                  include Resource
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  prop :added_at
         | 
| 88 | 
            +
                  prop :added_by
         | 
| 89 | 
            +
                  prop :is_local
         | 
| 90 | 
            +
                  one :track
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              module Model
         | 
| 3 | 
            +
                class Track
         | 
| 4 | 
            +
                  include Resource
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  many :albums
         | 
| 7 | 
            +
                  many :artists
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  prop :markets, from: :available_markets
         | 
| 10 | 
            +
                  prop :disc_number
         | 
| 11 | 
            +
                  prop :duration_ms
         | 
| 12 | 
            +
                  prop :explicit
         | 
| 13 | 
            +
                  merge :external_ids
         | 
| 14 | 
            +
                  prop :playable, from: :is_playable
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  prop :name
         | 
| 17 | 
            +
                  prop :popularity
         | 
| 18 | 
            +
                  prop :preview_url
         | 
| 19 | 
            +
                  prop :track_number
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def duration
         | 
| 22 | 
            +
                    Time.at(@duration_ms/1000).utc.strftime("%H:%M:%S")
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def playable?
         | 
| 26 | 
            +
                    playable == true
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,91 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              module Model
         | 
| 3 | 
            +
                class User
         | 
| 4 | 
            +
                  include Resource
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  prop :birthdate
         | 
| 7 | 
            +
                  prop :country
         | 
| 8 | 
            +
                  prop :display_name
         | 
| 9 | 
            +
                  prop :email
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  prop :external_urls
         | 
| 12 | 
            +
                  prop :followers
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  many :images
         | 
| 15 | 
            +
                  prop :product
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def name
         | 
| 18 | 
            +
                    display_name
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def premium?
         | 
| 22 | 
            +
                    @product == 'premium'
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
             | 
| 26 | 
            +
                  #--------------
         | 
| 27 | 
            +
                  # Saved tracks
         | 
| 28 | 
            +
                  #--------------
         | 
| 29 | 
            +
                  def save_tracks ids, client=nil
         | 
| 30 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 31 | 
            +
                    client.save_tracks(ids)
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def remove_tracks ids, client=nil
         | 
| 36 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 37 | 
            +
                    client.remove_tracks(ids)
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def saved_tracks_include? ids, client=nil
         | 
| 42 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 43 | 
            +
                    client.saved_tracks_include?(ids)
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
             | 
| 47 | 
            +
                  #--------------
         | 
| 48 | 
            +
                  # Follows
         | 
| 49 | 
            +
                  #--------------
         | 
| 50 | 
            +
                  def follow type, ids, client=nil
         | 
| 51 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 52 | 
            +
                    client.user_follow(type, ids)
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
             | 
| 56 | 
            +
                  def unfollow type, ids, client=nil
         | 
| 57 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 58 | 
            +
                    client.user_unfollow(type, ids)
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def following? type, ids, client=nil
         | 
| 63 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 64 | 
            +
                    client.user_following(type, ids)
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
             | 
| 68 | 
            +
                  #--------------
         | 
| 69 | 
            +
                  # Playlists
         | 
| 70 | 
            +
                  #--------------
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  def playlists! client=nil, fields: {}, market: nil, limit: 20, offset: 0
         | 
| 73 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 74 | 
            +
                    client.playlists(self, fields: fields, market: market, limit: limit, offset: offset)
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
             | 
| 78 | 
            +
                  def follow_playlist owner, playlist=nil, client=nil, public: true
         | 
| 79 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 80 | 
            +
                    client.playlist_follow(owner, playlist, public: public)
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
             | 
| 84 | 
            +
                  def follow_playlist owner, playlist=nil, client=nil
         | 
| 85 | 
            +
                    client ||= SimpleSpotify.default_client
         | 
| 86 | 
            +
                    client.playlist_unfollow(owner, playlist)
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
            end
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            module SimpleSpotify
         | 
| 2 | 
            +
              class Request
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                attr_accessor :endpoint, :method, :json, :data, :tries
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                def initialize endpoint, opts = {}
         | 
| 7 | 
            +
                  endpoint = endpoint.join('/') if endpoint.respond_to? :join
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  @endpoint = endpoint
         | 
| 10 | 
            +
                  @headers = opts[:headers] || {}
         | 
| 11 | 
            +
                  @method = opts[:method] || :get
         | 
| 12 | 
            +
                  @json = opts[:json] || (@method != :get)
         | 
| 13 | 
            +
                  @tries = 0
         | 
| 14 | 
            +
                  @data = opts[:data]
         | 
| 15 | 
            +
                  @query = opts[:query]
         | 
| 16 | 
            +
                  @private = opts[:private] || true
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
             | 
| 20 | 
            +
                def private?
         | 
| 21 | 
            +
                  @private;
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
                def method
         | 
| 26 | 
            +
                  @method.to_sym
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
             | 
| 30 | 
            +
                def options
         | 
| 31 | 
            +
                  return {} unless data
         | 
| 32 | 
            +
                  if method == :get
         | 
| 33 | 
            +
                    {query: data}
         | 
| 34 | 
            +
                  else
         | 
| 35 | 
            +
                    opts = {body: data.to_json}
         | 
| 36 | 
            +
                    opts[:query] = @query if @query
         | 
| 37 | 
            +
                    opts
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
             | 
| 42 | 
            +
                def headers
         | 
| 43 | 
            +
                  h = @headers
         | 
| 44 | 
            +
                  h['Content-type'] = 'application/json' if json
         | 
| 45 | 
            +
                  h
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
             | 
| 49 | 
            +
                def full_url
         | 
| 50 | 
            +
                  SimpleSpotify::ENDPOINT + endpoint.to_s.gsub(SimpleSpotify::ENDPOINT, '')
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            module Resource
         | 
| 2 | 
            +
              module ClassMethods
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                def self.extended(base)
         | 
| 5 | 
            +
                  super base
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def prop name, o={}
         | 
| 9 | 
            +
                  p = (o[:from] || name)
         | 
| 10 | 
            +
                  p = {type: :real, from: p, default: o[:default]} if o[:default]
         | 
| 11 | 
            +
                  @_template[name] = p
         | 
| 12 | 
            +
                  attr_accessor name.to_sym
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def many name, o={}
         | 
| 16 | 
            +
                  attr_accessor name.to_sym
         | 
| 17 | 
            +
                  kind = o[:kind] || name
         | 
| 18 | 
            +
                  @_template[name] = {
         | 
| 19 | 
            +
                    type: :resource_collection,
         | 
| 20 | 
            +
                    kind: _constant(kind),
         | 
| 21 | 
            +
                    from: name,
         | 
| 22 | 
            +
                    paginated: o[:paginated] || false
         | 
| 23 | 
            +
                  }
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def one name, o={}
         | 
| 27 | 
            +
                  attr_accessor name.to_sym
         | 
| 28 | 
            +
                  kind = o[:kind] || name
         | 
| 29 | 
            +
                  @_template[name] = {
         | 
| 30 | 
            +
                    type: :resource,
         | 
| 31 | 
            +
                    kind: _constant(kind),
         | 
| 32 | 
            +
                    from: (o[:from] || name)
         | 
| 33 | 
            +
                  }
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def merge name
         | 
| 37 | 
            +
                  @_template[name] = {type: :virtual, from: name}
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def _template
         | 
| 41 | 
            +
                  @_template
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def _constant name
         | 
| 45 | 
            +
                  "#{name}".gsub(/s$/, '').split('_').map(&:capitalize).join.to_sym
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         |