The developer-friendly, opinionated Ruby SDK for Spotify. Works on Ruby 2.4+
๐จ Website | ๐ Contributing | ๐ SDK Reference | ๐ Code of Conduct
Hey! I'm a Developer Advocate at Spotify, and I wrote this Ruby SDK to explore how to build a SDK that is TADA:
-
๐ง Thoughtfully inclusive for beginners. Everything we do should think about beginners from the start. From having an enforced Code of Conduct policy to building great documentation, tooling, and an empathetic feedback process. Designing for beginners is designing for longevity.
-
โ๏ธ Agnostic to minor changes. APIs change all the time. We should be opinionated enough that our software should break with major changes, but flexible enough to work perfectly fine with minor changes. Our code should only depend on critical data, such as IDs.
-
๐ Delightful for developers. Writing the SDK and using the SDK should be equally delightful. Granted, this is a challenging goal; but with solid information architecture, well-crafted opinions, clear and helpful error messages, and software that doesn't get in your way - we will create quite lovely software.
-
โจ A maintained production-level. It doesn't take experts to write production-level code; all it takes is considerate guidance from the community. We should write software that we and others trust to do what it is intended to do. We care about Semantic Versioning for clear version changes.
Disclaimer: This SDK is NOT owned or supported by Spotify. It remains a personal project of mine. If you are a commercial partner of Spotify and wish to use this SDK, be aware you are using it at your own risk.
Add this line to your application's Gemfile
:
gem "spotify-ruby"
And then execute in your Terminal:
$ bundle install
Finally you can include the SDK via Bundler.require
:
require "bundler"
Bundler.require
Or, you can install manually by executing this in your Terminal:
$ gem install spotify-ruby
Then you can include the SDK in your Ruby project:
require "spotify-ruby"
You'll firstly need to register your client ID on developer.spotify.com. You should receive a Client ID and Client Secret which we'll need to continue.
As mentioned above, you'll need to register your client ID. We recommend you that you use a different set of client IDs for development and production. We'll need to use those credentials in order to use any of Spotify's APIs.
To define your app credentials, you'll need to create an instance of Spotify::Accounts
:
@accounts = Spotify::Accounts.new
@accounts.client_id = "spotify client ID"
@accounts.client_secret = "spotify client secret"
@accounts.redirect_uri = "redirect URI"
Alternatively, these credentials can be supplied as environment variables when running your application:
@accounts = Spotify::Accounts.new # fetches configuration from ENV
The respective environment variables you'll need to set are:
Environment Variable | Description | Required? |
---|---|---|
SPOTIFY_CLIENT_ID |
Your Spotify Client ID | Yes |
SPOTIFY_CLIENT_SECRET |
Your Spotify Client Secret | Yes |
SPOTIFY_REDIRECT_URI |
Your Spotify Redirect URI (must be exact) | Yes |
In order to use Spotify's APIs on a user's behalf, you'll need to use the Spotify Accounts API to redirect them to https://accounts.spotify.com
. They will then need to explicitly approve your application and what data you're asking for (technically referred to as authorization scopes).
Recommended for production: To request specific data, read our Authorization Scopes reference, and then execute:
@accounts.authorize_url({
scope: "user-read-private user-read-email user-top-read"
}) # => "https://accounts.spotify.com/oauth/authorize?..."
Recommended for exploration / local development: Or, to request all data, you can execute:
@accounts.authorize_url # => "https://accounts.spotify.com/oauth/authorize?..."
Each session lasts 60 minutes. New sessions can be generated when you have a valid refresh_token
(they become invalid if a user revokes your application).
After a user has authorized your application, they'll be sent to your redirect_uri
defined in Your App Credentials with a code
parameter. We can use this to create a Spotify::Session
:
@session = @accounts.exchange_for_session(params[:code])
We can check when the session expires, and when we should refresh:
@session.expires_at # => 2018-07-08 22:40:15 +0200
if @session.expired?
@session.refresh!
end
You'll then be able to use @session
in the Spotify::SDK
object. See the Using the SDK section below.
We don't want to send the user to https://accounts.spotify.com/...
every time they want to use your application. For this case, we'll need to export the refresh_token
and persist it somewhere:
@session.refresh_token # => "BQASNDMelPsTdJMNMZfWdbxsuuM1FiBxvVzasqWkwYtgpjXJO60Gm51R0LO_-3Q5MfzCU0xIrbIFs7ZlMQrVJeRwN1_Ffa3sIJn_KW6LO8vA44fYc85oz48TuBuZsT2gzr4L"
Then you can repeatedly create a session with just a refresh token and running refresh!
:
@session = Spotify::Session.from_refresh_token(@accounts, "refresh_token here")
@session.expired? # => true
@session.refresh!
@session.expired? # => false
To create an instance of the Spotify SDK, you'll need the @session
from above and pass it to Spotify::SDK
as follows:
@session = Spotify::Session.from_refresh_token(@accounts, "refresh_token here")
@session.refresh!
@sdk = Spotify::SDK.new(@session)
With Spotify Connect, you can take your music experience anywhere on over 300 devices. And you can read and control most devices programmatically through the SDK:
@sdk.connect.devices # => [#<Spotify::SDK::Connect::Device:...>, ...]
@sdk.connect.devices[0].active?
@sdk.connect.devices[0].private_session?
@sdk.connect.devices[0].volume
@sdk.connect.devices[0].restricted?
@sdk.connect.playback
@sdk.connect.playback.playing? # => true
@sdk.connect.playback.device.private_session? # => false
@sdk.connect.playback.shuffling? # => false
@sdk.connect.playback.repeat_mode # => :context
@sdk.connect.playback.position_percentage # => 4.53
@sdk.connect.playback.artist.name # => "Ed Sheeran"
@sdk.connect.playback.item.album.name # => "รท"
@sdk.connect.devices[0].play!({
uri: "spotify:track:0tgVpDi06FyKpA1z0VMD4v",
position_ms: 0
})
@sdk.connect.devices[0].pause!
@sdk.connect.devices[0].resume!
@sdk.connect.devices[0].volume = 80
@sdk.connect.devices[0].previous!
@sdk.connect.devices[0].next!
@sdk.connect.devices[0].position_ms = 3_000
@sdk.connect.devices[0].shuffle = false
@sdk.connect.devices[0].repeat_mode = :context
This will transfer state, and start playback.
@sdk.connect.devices[0].transfer_playback!
This will transfer state, and pause playback.
@sdk.connect.devices[0].transfer_state!
This allows you to perform specific actions on behalf of a user.
@sdk.me.info
@sdk.me.info.free? # => false
@sdk.me.info.premium? # => true
@sdk.me.info.birthdate # => 1980-01-01
@sdk.me.info.display_name? # => true
@sdk.me.info.display_name # => "ABC Smith"
@sdk.me.info.images[0].url # => "https://profile-images.scdn.co/userprofile/default/..."
@sdk.me.info.followers # => 4913313
@sdk.me.info.spotify_uri # => "spotify:user:abcsmith"
@sdk.me.info.spotify_url # => "https://open.spotify.com/user/abcsmith"
@sdk.me.history(10) # => [#<Spotify::SDK::Item...>, ...]
@sdk.me.history(10).size # => 10
@sdk.me.history(50) # => [#<Spotify::SDK::Item...>, ...]
@sdk.me.history(50).size # => 50
@sdk.playback.item.artist.follow!
@sdk.playback.item.artist.unfollow!
@sdk.me.following_artists?(%w(3TVXtAsR1Inumwj472S9r4 6LuN9FCkKOj5PcnpouEgny 69GGBxA162lTqCwzJG5jLp))
# => {
# "3TVXtAsR1Inumwj472S9r4" => false,
# "6LuN9FCkKOj5PcnpouEgny" => true,
# "69GGBxA162lTqCwzJG5jLp" => false
# }
@sdk.me.following_users?(%w(3TVXtAsR1Inumwj472S9r4 6LuN9FCkKOj5PcnpouEgny 69GGBxA162lTqCwzJG5jLp))
# => {
# "3TVXtAsR1Inumwj472S9r4" => false,
# "6LuN9FCkKOj5PcnpouEgny" => true,
# "69GGBxA162lTqCwzJG5jLp" => false
# }
@sdk.me.following(5) # => [#<Spotify::SDK::Artist...>, ...]
@sdk.me.following(5).size # => 5
@sdk.me.following(50) # => [#<Spotify::SDK::Artist...>, ...]
@sdk.me.following(50).size # => 50
* Requires specific user permissions/scopes. See Authorization Scopes for more information.
On the website, we have a full guide on contributing for beginners.
Bug reports and pull requests are welcome on GitHub at https://github.com/bih/spotify-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
Everyone interacting with this project's codebases, issue trackers, discussions, chat rooms, and mailing lists is required to follow the Code of Conduct.
Whilst we try to always assume good intentions, any clear violations or bad actors will be warned and subsequently banned from this project indefinitely.
Firstly, you'll need Git and Ruby installed. You can then install the dependencies as following:
$ git clone ssh://git@github.com/bih/spotify-ruby.git
$ bin/setup
You can run rake ci
to validate your Ruby syntax, our RSpec tests, and code coverage.
For local development, you can run bin/console
for an interactive prompt for experimentation.
- To install this gem onto your local machine, run
bundle exec rake install
. - Ensure versions are in line with the Semantic Versioning convention.
- To release a new version:
- Update the version number in
lib/spotify/version.rb
- Run
bundle exec rake release
(which will create a git tag for the version) - Push git commits and tags
- Push the
.gem
file to rubygems.org.
- Update the version number in
The gem is available as open source under the terms of the MIT License.