Class: SpotifyWeb::Client

Inherits:
Object
  • Object
show all
Includes:
Assertions, Loggable
Defined in:
lib/spotify_web/client.rb

Overview

Provides access to the Spotify Web API

Constant Summary collapse

KEEPALIVE_INTERVAL =

The interval with which to send keepalives

180

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Assertions

#assert_valid_keys, #assert_valid_values

Constructor Details

#initialize(username, password, options = {}) { ... } ⇒ Client

Creates a new client for communicating with Spotify with the given username / password.

Parameters:

  • username (String)

    The username to authenticate with

  • password (String)

    The Spotify password associated with the username

  • options (Hash) (defaults to: {})

    The configuration options for the client

Options Hash (options):

  • :timeout (Fixnum) — default: 10

    The amount of seconds to allow to elapse for requests before timing out

  • :reconnect (Boolean) — default: false

    Whether to allow the client to automatically reconnect when disconnected either by Spotify or by the network

  • :reconnect_wait (Fixnum) — default: 5

    The amount of seconds to wait before reconnecting

Yields:

  • Runs the given block within the context if the client (for DSL-type usage)

Raises:



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/spotify_web/client.rb', line 43

def initialize(username, password, options = {}, &block)
  options = {
    :timeout => 10,
    :reconnect => false,
    :reconnect_wait => 5
  }.merge(options)
  assert_valid_keys(options, :timeout, :reconnect, :reconnect_wait)

  @user = AuthorizedUser.new(self, :username => username, :password => password)
  @event_handlers = {}
  @timeout = options[:timeout]
  @reconnect = options[:reconnect]
  @reconnect_wait = options[:reconnect_wait]

  # Setup default event handlers
  on(:work_requested) {|work| on_work_requested(work) }
  on(:session_ended)  { on_session_ended }

  reconnect_from(ConnectionError, APIError) do
    connect
  end

  instance_eval(&block) if block_given?
end

Instance Attribute Details

#timeoutFixnum (readonly)

The response timeout configured for the connection

Returns:

  • (Fixnum)


30
31
32
# File 'lib/spotify_web/client.rb', line 30

def timeout
  @timeout
end

#userSpotifyWeb::User (readonly)

The current authorized user

Returns:



26
27
28
# File 'lib/spotify_web/client.rb', line 26

def user
  @user
end

Instance Method Details

#album(attributes) ⇒ SpotifyWeb::Album

Builds a new album bound to the given id / attributes.

Examples:

client.album("\x03\xC0...")   # => #<SpotifyWeb::Album id="\x03\xC0..." ...>

Parameters:

  • attributes (String, Hash)

    The id of the album to build or a hash of attributes

Returns:



214
215
216
217
# File 'lib/spotify_web/client.rb', line 214

def album(attributes)
  attributes = {:gid => attributes} unless attributes.is_a?(Hash)
  Album.new(self, attributes)
end

#api(command, args = nil) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Runs the given API command.

Parameters:

  • command (String)

    The name of the command to execute

  • args (Object) (defaults to: nil)

    The arguments to pass into the command

Returns:

  • (Hash)

    The data returned from the Spotify service

Raises:

  • (SpotifyWeb::Error)

    if the connection is not open or the command fails to execute



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/spotify_web/client.rb', line 137

def api(command, args = nil)
  raise(ConnectionError, 'Connection is not open') unless @connection && @connection.connected?

  if command == 'request' && args.delete(:batch)
    batch(command, args) do |batch_command, batch_args|
      api(batch_command, batch_args)
    end
  else
    # Process this as a mercury request
    if command == 'request'
      response_schema = args.delete(:response_schema)
    end

    message_id = @connection.publish(command, args)

    # Wait until we get a response for the given message
    data = wait do |&resume|
      on(:response_received, :once => true, :if => {'id' => message_id}) {|data| resume.call(data)}
    end

    if command == 'request' && !data['error']
      # Parse the response bsed on the schema provided
      header, body = data['result']
      request = Schema::Mercury::MercuryRequest.decode(Base64.decode64(header))

      if (400..599).include?(request.status_code)
        data['error'] = "Failed response: #{request.status_code}"
      else
        data['result'] = response_schema.decode(Base64.decode64(body))
      end
    end

    if error = data['error']
      raise APIError, "Command \"#{command}\" failed with message: \"#{error}\""
    else
      data
    end
  end
end

#artist(attributes) ⇒ SpotifyWeb::Artist

Builds a new artist bound to the given id.

Examples:

client.artist("\xC1\x8Fr...")   # => #<SpotifyWeb::Artist gid="\xC1\x8Fr..." ...>

Parameters:

  • attributes (String, Hash)

    The id of the artist to build or a hash of attributes

Returns:



203
204
205
206
# File 'lib/spotify_web/client.rb', line 203

def artist(attributes)
  attributes = {:gid => attributes} unless attributes.is_a?(Hash)
  Artist.new(self, attributes)
end

#close(allow_reconnect = false) ⇒ true

Closes the current connection to Spotify if one was previously opened.

Returns:

  • (true)


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/spotify_web/client.rb', line 109

def close(allow_reconnect = false)
  if @connection
    # Disable reconnects if specified
    reconnect = @reconnect
    @reconnect = reconnect && allow_reconnect

    # Clean up timers / connections
    @keepalive_timer.cancel if @keepalive_timer
    @keepalive_timer = nil
    @connection.close

    # Revert change to reconnect config once the final signal is received
    wait do |&resume|
      on(:session_ended, :once => true) { resume.call }
    end
    @reconnect = reconnect
  end
  
  true
end

#connecttrue

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

This will only open a new connection if the client isn’t already connected to the given url

Initiates a connection with the given url. Once a connection is started, this will also attempt to authenticate the user.

Parameters:

  • url (String)

    The url to open a connection to

Returns:

  • (true)

Raises:



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/spotify_web/client.rb', line 76

def connect
  if !@connection || !@connection.connected?
    # Close any existing connection
    close

    # Create a new connection to the given url
    @connection = Connection.new(access_point_url, :timeout => timeout)
    @connection.handler = lambda {|data| trigger(data.delete('command'), data)}
    @connection.start

    # Wait for connection to open
    wait do |&resume|
      on(:session_started, :once => true) { resume.call }
    end

    # Send the user's credentials
    creds = user.settings['credentials'][0].split(':')
    message = [creds[0], creds[1], creds[2..-1] * ':']
    api('connect', message)

    wait do |&resume|
      on(:session_authenticated, :once => true) { resume.call }
    end

    start_keepalives
  end

  true
end

#song(attributes) ⇒ SpotifyWeb::Song

Builds a new song bound to the given id.

Examples:

client.song("\x92\xA9...")   # => #<SpotifyWeb::Song id="\x92\xA9..." ...>

Parameters:

  • attributes (String, Hash)

    The id of the song to build or a hash of attributes

Returns:



192
193
194
195
# File 'lib/spotify_web/client.rb', line 192

def song(attributes)
  attributes = {:gid => attributes} unless attributes.is_a?(Hash)
  Song.new(self, attributes)
end

#start_keepalivesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Starts the keepalive timer for ensure the connection remains open.



179
180
181
182
183
184
# File 'lib/spotify_web/client.rb', line 179

def start_keepalives
  @keepalive_timer.cancel if @keepalive_timer
  @keepalive_timer = EM::Synchrony.add_periodic_timer(KEEPALIVE_INTERVAL) do
    SpotifyWeb.run { api('sp/echo', 'h') }
  end
end