spotify-ruby 0.1.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +10 -2
- data/.rubocop.yml +16 -5
- data/.travis.yml +10 -1
- data/CODE_OF_CONDUCT.md +1 -1
- data/COVERAGE.md +98 -92
- data/LICENSE +1 -1
- data/README.md +223 -63
- data/Rakefile +5 -12
- data/lib/spotify.rb +2 -2
- data/lib/spotify/accounts.rb +130 -0
- data/lib/spotify/accounts/session.rb +173 -0
- data/lib/spotify/sdk.rb +43 -60
- data/lib/spotify/sdk/album.rb +84 -0
- data/lib/spotify/sdk/artist.rb +162 -0
- data/lib/spotify/sdk/base.rb +34 -16
- data/lib/spotify/sdk/connect.rb +51 -2
- data/lib/spotify/sdk/connect/device.rb +282 -7
- data/lib/spotify/sdk/connect/playback_state.rb +141 -0
- data/lib/spotify/sdk/image.rb +44 -0
- data/lib/spotify/sdk/item.rb +134 -0
- data/lib/spotify/sdk/me.rb +83 -0
- data/lib/spotify/sdk/me/info.rb +108 -0
- data/lib/spotify/sdk/model.rb +40 -23
- data/lib/spotify/version.rb +8 -5
- data/spotify-ruby.gemspec +24 -9
- metadata +87 -38
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/lib/spotify/auth.rb +0 -111
- data/lib/spotify/sdk/initialization.rb +0 -76
- data/lib/spotify/sdk/initialization/base.rb +0 -74
- data/lib/spotify/sdk/initialization/oauth_access_token.rb +0 -34
- data/lib/spotify/sdk/initialization/plain_string.rb +0 -26
- data/lib/spotify/sdk/initialization/query_hash.rb +0 -45
- data/lib/spotify/sdk/initialization/query_string.rb +0 -51
- data/lib/spotify/sdk/initialization/url_string.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 893c1debac589722daaf32f384443dc0b86e3c4e
|
4
|
+
data.tar.gz: 89243db3dacb7ed306d4203190f9bdf9d8301eb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c454ff02af792edb795c2fb62c17a35cbfba27267b83c9631be4ca5be64c17b3f2308cd04c7e95a651457af7582b04e9b5024e8cd07c164a622abcb2de448461
|
7
|
+
data.tar.gz: 3e598cbfa0b8f8430b127aab1fa441b6f50350acf547c27ac7bdcb5eb54a9b791eb7e03fc1007c838415bf70bfeb23e7c4c8dfebc76c5492b6c2389ea0fe3bbc
|
data/.gitignore
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
/.bundle/
|
2
1
|
/.yardoc
|
3
2
|
/Gemfile.lock
|
3
|
+
/.bundle/
|
4
4
|
/_yardoc/
|
5
5
|
/coverage/
|
6
6
|
/doc/
|
@@ -10,7 +10,15 @@
|
|
10
10
|
/tmp/
|
11
11
|
/.local/
|
12
12
|
|
13
|
+
# local console
|
14
|
+
/bin/console_local
|
15
|
+
|
16
|
+
# jekyll rendered site
|
17
|
+
/docs/_site
|
18
|
+
/docs/.sass-cache
|
19
|
+
/docs/.jekyll-metadata
|
20
|
+
|
13
21
|
# rspec failure tracking
|
14
22
|
.rspec_status
|
15
23
|
.coveralls.yml
|
16
|
-
.DS_Store
|
24
|
+
.DS_Store
|
data/.rubocop.yml
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- 'bin/console'
|
4
|
+
- 'bin/console_local'
|
5
|
+
- 'bin/generate_model'
|
6
|
+
- 'bin/generate_component'
|
7
|
+
|
1
8
|
# Commonly used screens these days easily fit more than 80 characters.
|
2
9
|
Metrics/LineLength:
|
3
10
|
Max: 120
|
@@ -6,7 +13,7 @@ Metrics/LineLength:
|
|
6
13
|
|
7
14
|
# Too short methods lead to extraction of single-use methods, which can make
|
8
15
|
# the code easier to read (by naming things), but can also clutter the class
|
9
|
-
Metrics/MethodLength:
|
16
|
+
Metrics/MethodLength:
|
10
17
|
Max: 20
|
11
18
|
|
12
19
|
# The guiding principle of classes is SRP, SRP can't be accurately measured by LoC
|
@@ -72,7 +79,7 @@ Lint/AssignmentInCondition:
|
|
72
79
|
AllowSafeAssignment: false
|
73
80
|
|
74
81
|
# A specialized exception class will take one or more arguments and construct the message from it.
|
75
|
-
# So both variants make sense.
|
82
|
+
# So both variants make sense.
|
76
83
|
Style/RaiseArgs:
|
77
84
|
Enabled: false
|
78
85
|
|
@@ -87,6 +94,10 @@ Layout/MultilineOperationIndentation:
|
|
87
94
|
Style/SignalException:
|
88
95
|
EnforcedStyle: only_raise
|
89
96
|
|
97
|
+
# Use of alias_method in a class body context.
|
98
|
+
Style/Alias:
|
99
|
+
Enabled: false
|
100
|
+
|
90
101
|
# Suppressing exceptions can be perfectly fine, and be it to avoid to
|
91
102
|
# explicitly type nil into the rescue since that's what you want to return,
|
92
103
|
# or suppressing LoadError for optional dependencies
|
@@ -130,11 +141,11 @@ Lint/ShadowingOuterLocalVariable:
|
|
130
141
|
|
131
142
|
# Check with yard instead.
|
132
143
|
Style/Documentation:
|
133
|
-
Enabled: false
|
144
|
+
Enabled: false
|
134
145
|
|
135
146
|
# This is just silly. Calling the argument `other` in all cases makes no sense.
|
136
147
|
Naming/BinaryOperatorParameterName:
|
137
|
-
Enabled: false
|
148
|
+
Enabled: false
|
138
149
|
|
139
150
|
# There are valid cases, for example debugging Cucumber steps,
|
140
151
|
# also they'll fail CI anyway
|
@@ -143,4 +154,4 @@ Lint/Debugger:
|
|
143
154
|
|
144
155
|
# Style preference
|
145
156
|
Style/MethodDefParentheses:
|
146
|
-
Enabled: false
|
157
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
+
- 2.4.0
|
4
5
|
- 2.4.1
|
5
|
-
|
6
|
+
- 2.5.0
|
7
|
+
before_install: >
|
8
|
+
gem install bundler -v 1.15.1
|
9
|
+
before_script:
|
10
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
11
|
+
- chmod +x ./cc-test-reporter
|
12
|
+
- ./cc-test-reporter before-build
|
6
13
|
script:
|
7
14
|
- rake ci
|
15
|
+
after_script:
|
16
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
data/CODE_OF_CONDUCT.md
CHANGED
data/COVERAGE.md
CHANGED
@@ -1,142 +1,148 @@
|
|
1
|
-
|
1
|
+
# Spotify API Coverage
|
2
2
|
|
3
3
|
This covers all the Spotify API endpoints that are covered.
|
4
4
|
|
5
5
|
### Albums Endpoints
|
6
6
|
|
7
|
-
| Endpoint
|
8
|
-
|
|
9
|
-
| GET /v1/albums
|
10
|
-
| GET /v1/albums/{id}/tracks | Get an Album's Tracks | × |
|
7
|
+
| Endpoint | Description | Coverage Status |
|
8
|
+
| -------------------------- | --------------------- | --------------- |
|
9
|
+
| GET /v1/albums | Get Several Albums | × Not Started |
|
10
|
+
| GET /v1/albums/{id}/tracks | Get an Album's Tracks | × Not Started |
|
11
11
|
|
12
12
|
### Artists Endpoints
|
13
13
|
|
14
|
-
| Endpoint
|
15
|
-
|
|
16
|
-
| GET /v1/artists
|
17
|
-
| GET /v1/artists/{id}/albums
|
18
|
-
| GET /v1/artists/{id}/top-tracks
|
19
|
-
| GET /v1/artists/{id}/related-artists | Get an Artist's Related Artists | × |
|
14
|
+
| Endpoint | Description | Coverage Status |
|
15
|
+
| ------------------------------------ | ------------------------------- | --------------- |
|
16
|
+
| GET /v1/artists | Get Several Artists | × Not Started |
|
17
|
+
| GET /v1/artists/{id}/albums | Get an Artist's Albums | × Not Started |
|
18
|
+
| GET /v1/artists/{id}/top-tracks | Get an Artist's Top Tracks | × Not Started |
|
19
|
+
| GET /v1/artists/{id}/related-artists | Get an Artist's Related Artists | × Not Started |
|
20
20
|
|
21
21
|
### Tracks Endpoints
|
22
22
|
|
23
|
-
| Endpoint
|
24
|
-
|
|
25
|
-
| GET /v1/tracks | Get Several Tracks | × |
|
23
|
+
| Endpoint | Description | Coverage Status |
|
24
|
+
| -------------- | ------------------ | --------------- |
|
25
|
+
| GET /v1/tracks | Get Several Tracks | × Not Started |
|
26
26
|
|
27
27
|
### Audio Features Endpoints
|
28
28
|
|
29
|
-
| Endpoint
|
30
|
-
|
|
31
|
-
| GET /v1/audio-features/{id} | Get Audio Features for a Track
|
32
|
-
| GET /v1/audio-features
|
29
|
+
| Endpoint | Description | Coverage Status |
|
30
|
+
| --------------------------- | ------------------------------------- | --------------- |
|
31
|
+
| GET /v1/audio-features/{id} | Get Audio Features for a Track | × Not Started |
|
32
|
+
| GET /v1/audio-features | Get Audio Features for Several Tracks | × Not Started |
|
33
33
|
|
34
34
|
### Analysis Endpoints
|
35
35
|
|
36
|
-
| Endpoint
|
37
|
-
|
|
38
|
-
|
|
36
|
+
| Endpoint | Description | Coverage Status |
|
37
|
+
| --------------------------- | ------------------------------ | --------------- |
|
38
|
+
| GET /v1/audio-analysis/{id} | Get Audio Analysis for a Track | × Not Started |
|
39
39
|
|
40
40
|
### Search Endpoints
|
41
41
|
|
42
|
-
| Endpoint
|
43
|
-
|
|
44
|
-
|
|
42
|
+
| Endpoint | Description | Coverage Status |
|
43
|
+
| -------------- | ------------------ | --------------- |
|
44
|
+
| GET /v1/search | Search for an Item | × Not Started |
|
45
45
|
|
46
46
|
### Users Endpoints
|
47
47
|
|
48
|
-
| Endpoint
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
| Endpoint | Description | Coverage Status |
|
49
|
+
| ----------------------- | -------------------------- | --------------- |
|
50
|
+
| GET /v1/users/{user_id} | Get a User's Profile | × |
|
51
|
+
| GET /v1/me | Get Current User's Profile | [me/info.rb] |
|
52
52
|
|
53
53
|
### Saved Content Endpoints
|
54
54
|
|
55
|
-
| Endpoint
|
56
|
-
|
|
57
|
-
| GET /v1/me/tracks
|
58
|
-
| GET /v1/me/tracks/contains | Check Current User's Saved Tracks | × |
|
59
|
-
| PUT /v1/me/tracks
|
60
|
-
| DELETE /v1/me/tracks
|
61
|
-
| GET /v1/me/albums
|
62
|
-
| GET /v1/me/albums/contains | Check Current User's Saved Albums | × |
|
63
|
-
| PUT /v1/me/albums
|
64
|
-
| DELETE /v1/me/albums
|
55
|
+
| Endpoint | Description | Coverage Status |
|
56
|
+
| -------------------------- | --------------------------------- | --------------- |
|
57
|
+
| GET /v1/me/tracks | Get Current User's Saved Tracks | × Not Started |
|
58
|
+
| GET /v1/me/tracks/contains | Check Current User's Saved Tracks | × Not Started |
|
59
|
+
| PUT /v1/me/tracks | Save Tracks for Current User | × Not Started |
|
60
|
+
| DELETE /v1/me/tracks | Remove Tracks for Current User | × Not Started |
|
61
|
+
| GET /v1/me/albums | Get Current User's Saved Albums | × Not Started |
|
62
|
+
| GET /v1/me/albums/contains | Check Current User's Saved Albums | × Not Started |
|
63
|
+
| PUT /v1/me/albums | Save Albums for Current User | × Not Started |
|
64
|
+
| DELETE /v1/me/albums | Remove Albums for Current User | × Not Started |
|
65
65
|
|
66
66
|
### Discovery Endpoints
|
67
67
|
|
68
|
-
| Endpoint
|
69
|
-
|
|
70
|
-
| GET /v1/browse/new-releases
|
71
|
-
| GET /v1/browse/featured-playlists | Get a List of Featured Playlists | × |
|
68
|
+
| Endpoint | Description | Coverage Status |
|
69
|
+
| --------------------------------- | -------------------------------- | --------------- |
|
70
|
+
| GET /v1/browse/new-releases | Get a List of New Releases | × Not Started |
|
71
|
+
| GET /v1/browse/featured-playlists | Get a List of Featured Playlists | × Not Started |
|
72
72
|
|
73
73
|
### Categories Endpoints
|
74
74
|
|
75
|
-
| Endpoint
|
76
|
-
|
|
77
|
-
| GET /v1/browse/categories
|
78
|
-
| GET /v1/browse/categories/{category_id}
|
79
|
-
| GET /v1/browse/categories/{category_id}/playlists | Get a Category's playlists
|
75
|
+
| Endpoint | Description | Coverage Status |
|
76
|
+
| ------------------------------------------------- | ------------------------------- | --------------- |
|
77
|
+
| GET /v1/browse/categories | Get a List of Browse Categories | × Not Started |
|
78
|
+
| GET /v1/browse/categories/{category_id} | Get a Single Browse Category | × Not Started |
|
79
|
+
| GET /v1/browse/categories/{category_id}/playlists | Get a Category's playlists | × Not Started |
|
80
80
|
|
81
81
|
### Recommendation Endpoints
|
82
82
|
|
83
|
-
| Endpoint
|
84
|
-
|
|
85
|
-
| GET /v1/recommendations
|
86
|
-
| GET /v1/recommendations/available-genre-seeds | Get Available Genre Seeds
|
83
|
+
| Endpoint | Description | Coverage Status |
|
84
|
+
| --------------------------------------------- | ---------------------------------- | --------------- |
|
85
|
+
| GET /v1/recommendations | Get Recommendations Based on Seeds | × Not Started |
|
86
|
+
| GET /v1/recommendations/available-genre-seeds | Get Available Genre Seeds | × Not Started |
|
87
87
|
|
88
88
|
### Follow Endpoints
|
89
89
|
|
90
|
-
| Endpoint
|
91
|
-
|
|
92
|
-
| GET /v1/me/following
|
93
|
-
| GET /v1/me/following/contains
|
94
|
-
| PUT /v1/me/following
|
95
|
-
| DELETE /v1/me/following
|
96
|
-
| GET /v1/users/{user_id}/playlists/{playlist_id}/followers/contains | Check if Users Follow a Playlist
|
97
|
-
| PUT /v1/users/{user_id}/playlists/{playlist_id}/followers
|
98
|
-
| DELETE /v1/users/{user_id}/playlists/{playlist_id}/followers
|
90
|
+
| Endpoint | Description | Coverage Status |
|
91
|
+
| ------------------------------------------------------------------ | ---------------------------------------------- | ---------------------------------------------------------------------- |
|
92
|
+
| GET /v1/me/following | Get Followed Artists | [me.rb] |
|
93
|
+
| GET /v1/me/following/contains | Check if Current User Follows Artists or Users | [me.rb] |
|
94
|
+
| PUT /v1/me/following | Follow Artists or Users | [🔘 Partial Support][artist.rb] (Following multiple isn't supported) |
|
95
|
+
| DELETE /v1/me/following | Unfollow Artists or Users | [🔘 Partial Support][artist.rb] (Unfollowing multiple isn't supported) |
|
96
|
+
| GET /v1/users/{user_id}/playlists/{playlist_id}/followers/contains | Check if Users Follow a Playlist | × Not Started |
|
97
|
+
| PUT /v1/users/{user_id}/playlists/{playlist_id}/followers | Follow a Playlist | × Not Started |
|
98
|
+
| DELETE /v1/users/{user_id}/playlists/{playlist_id}/followers | Unfollow a Playlist | × Not Started |
|
99
99
|
|
100
100
|
### Playlists Endpoints
|
101
101
|
|
102
|
-
| Endpoint
|
103
|
-
|
|
104
|
-
| GET /v1/users/{user_id}/playlists
|
105
|
-
| GET /v1/me/playlists
|
106
|
-
| GET /v1/users/{user_id}/playlists/{playlist_id}
|
107
|
-
| GET /v1/users/{user_id}/playlists/{playlist_id}/tracks
|
108
|
-
| POST /v1/users/{user_id}/playlists
|
109
|
-
| POST /v1/users/{user_id}/playlists/{playlist_id}/tracks
|
110
|
-
| DELETE /v1/users/{user_id}/playlists/{playlist_id}/tracks | Remove Tracks from a Playlist
|
111
|
-
| PUT /v1/users/{user_id}/playlists/{playlist_id}/tracks
|
112
|
-
| PUT /v1/users/{user_id}/playlists/{playlist_id}
|
102
|
+
| Endpoint | Description | Coverage Status |
|
103
|
+
| --------------------------------------------------------- | -------------------------------------- | --------------- |
|
104
|
+
| GET /v1/users/{user_id}/playlists | Get a List of a User's Playlists | × Not Started |
|
105
|
+
| GET /v1/me/playlists | Get a List of Current User's Playlists | × Not Started |
|
106
|
+
| GET /v1/users/{user_id}/playlists/{playlist_id} | Get a Playlist | × Not Started |
|
107
|
+
| GET /v1/users/{user_id}/playlists/{playlist_id}/tracks | Get a Playlist's Tracks | × Not Started |
|
108
|
+
| POST /v1/users/{user_id}/playlists | Create a Playlist | × Not Started |
|
109
|
+
| POST /v1/users/{user_id}/playlists/{playlist_id}/tracks | Add Tracks to a Playlist | × Not Started |
|
110
|
+
| DELETE /v1/users/{user_id}/playlists/{playlist_id}/tracks | Remove Tracks from a Playlist | × Not Started |
|
111
|
+
| PUT /v1/users/{user_id}/playlists/{playlist_id}/tracks | Reorder or replace a Playlist's Tracks | × Not Started |
|
112
|
+
| PUT /v1/users/{user_id}/playlists/{playlist_id} | Change a Playlist's Details | × Not Started |
|
113
113
|
|
114
114
|
### History Endpoints
|
115
115
|
|
116
|
-
| Endpoint
|
117
|
-
|
|
118
|
-
| GET /v1/me/top/{type}
|
119
|
-
| GET /v1/me/player/recently-played | Get the Current User's Recently Played Tracks | × |
|
116
|
+
| Endpoint | Description | Coverage Status |
|
117
|
+
| --------------------------------- | --------------------------------------------- | --------------- |
|
118
|
+
| GET /v1/me/top/{type} | Get User's Top Artists and Tracks | × Not Started |
|
119
|
+
| GET /v1/me/player/recently-played | Get the Current User's Recently Played Tracks | × Not Started |
|
120
120
|
|
121
121
|
### Connect Endpoints
|
122
122
|
|
123
|
-
| Endpoint
|
124
|
-
|
|
125
|
-
| GET /v1/me/player
|
126
|
-
| GET /v1/me/player/devices | Get a User's Available Devices
|
127
|
-
| PUT /v1/me/player
|
123
|
+
| Endpoint | Description | Coverage Status |
|
124
|
+
| ------------------------- | ------------------------------------------------- | ------------------------------------------- |
|
125
|
+
| GET /v1/me/player | Get Information About The User's Current Playback | [Full support ✔][connect/playback_state.rb] |
|
126
|
+
| GET /v1/me/player/devices | Get a User's Available Devices | [Full support ✔][connect.rb] |
|
127
|
+
| PUT /v1/me/player | Transfer a User's Playback | [Full support ✔][connect/device.rb] |
|
128
128
|
|
129
129
|
### Player Endpoints
|
130
130
|
|
131
|
-
| Endpoint
|
132
|
-
|
|
133
|
-
| GET /v1/me/player/currently-playing | Get the User's Currently Playing Track
|
134
|
-
| PUT /v1/me/player/play
|
135
|
-
| PUT /v1/me/player/pause
|
136
|
-
| POST /v1/me/player/next
|
137
|
-
| POST /v1/me/player/previous
|
138
|
-
| PUT /v1/me/player/seek
|
139
|
-
| PUT /v1/me/player/repeat
|
140
|
-
| PUT /v1/me/player/volume
|
141
|
-
| PUT /v1/me/player/shuffle
|
142
|
-
|
131
|
+
| Endpoint | Description | Coverage Status |
|
132
|
+
| ----------------------------------- | ------------------------------------------- | ----------------------------------- |
|
133
|
+
| GET /v1/me/player/currently-playing | Get the User's Currently Playing Track | × Not implementing |
|
134
|
+
| PUT /v1/me/player/play | Start/Resume a User's Playback | [Full support ✔][connect/device.rb] |
|
135
|
+
| PUT /v1/me/player/pause | Pause a User's Playback | [Full support ✔][connect/device.rb] |
|
136
|
+
| POST /v1/me/player/next | Skip User's Playback To Next Track | [Full support ✔][connect/device.rb] |
|
137
|
+
| POST /v1/me/player/previous | Skip User's Playback To Previous Track | [Full support ✔][connect/device.rb] |
|
138
|
+
| PUT /v1/me/player/seek | Seek To Position In Currently Playing Track | [Full support ✔][connect/device.rb] |
|
139
|
+
| PUT /v1/me/player/repeat | Set Repeat Mode On User's Playback | [Full support ✔][connect/device.rb] |
|
140
|
+
| PUT /v1/me/player/volume | Set Volume For User's Playback | [Full support ✔][connect/device.rb] |
|
141
|
+
| PUT /v1/me/player/shuffle | Toggle Shuffle For User's Playback | [Full support ✔][connect/device.rb] |
|
142
|
+
|
143
|
+
[connect.rb]: /lib/spotify/sdk/connect.rb
|
144
|
+
[connect/playback_state.rb]: /lib/spotify/sdk/connect/playback_state.rb
|
145
|
+
[connect/device.rb]: /lib/spotify/sdk/connect/device.rb
|
146
|
+
[artist.rb]: /lib/spotify/sdk/artist.rb
|
147
|
+
[me.rb]: /lib/spotify/sdk/me.rb
|
148
|
+
[me/info.rb]: /lib/spotify/sdk/me/info.rb
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,127 +1,287 @@
|
|
1
|
-
|
1
|
+
<!-- prettier-ignore-start -->
|
2
|
+
<img src="docs/theme/assets/images/logo.png" width="400" />
|
2
3
|
|
3
|
-
|
4
|
+
[![Build Status](https://travis-ci.org/bih/spotify-ruby.svg?branch=master)][Build Status]
|
5
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/89410e6302b5562c658a/maintainability)][Maintainability]
|
6
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/89410e6302b5562c658a/test_coverage)][Test Coverage]
|
7
|
+
[![Gem Version](https://badge.fury.io/rb/spotify-ruby.svg)][Gem Version]
|
8
|
+
[![Code Triagers Badge](https://www.codetriage.com/bih/spotify-ruby/badges/users.svg)][Code Triagers Badge]
|
4
9
|
|
5
|
-
|
10
|
+
The developer-friendly, opinionated Ruby SDK for [Spotify]. Works on Ruby 2.4+
|
6
11
|
|
7
|
-
[
|
8
|
-
[![Coverage Status](https://coveralls.io/repos/github/bih/spotify-ruby/badge.svg)](https://coveralls.io/github/bih/spotify-ruby)
|
9
|
-
[![Gem Version](https://badge.fury.io/rb/spotify-ruby.svg)](https://badge.fury.io/rb/spotify-ruby)
|
10
|
-
[![Code Triagers Badge](https://www.codetriage.com/bih/spotify-ruby/badges/users.svg)](https://www.codetriage.com/bih/spotify-ruby)
|
12
|
+
🎨 [Website] | 💖 [Contributing] | 📖 [SDK Reference] | 🔒 [Code of Conduct](#code-of-conduct)
|
11
13
|
|
12
|
-
##
|
14
|
+
## Contents
|
13
15
|
|
14
|
-
|
16
|
+
- [Introduction](#introduction)
|
17
|
+
- [Install](#install)
|
18
|
+
- [With Bundler](#with-bundler)
|
19
|
+
- [Manual Install](#manual-install)
|
20
|
+
- [Configuration](#configuration)
|
21
|
+
- [Your App Credentials](#your-app-credentials)
|
22
|
+
- [Authorization](#authorization)
|
23
|
+
- [Creating a Session](#creating-a-session)
|
24
|
+
- [Recreating a Session](#recreating-a-session)
|
25
|
+
- [Using the SDK](#using-the-sdk)
|
26
|
+
- [Spotify Connect](#spotify-connect)
|
27
|
+
- [Contributing](#contributing)
|
28
|
+
- [Community Guidelines](#community-guidelines)
|
29
|
+
- [Code of Conduct](#code-of-conduct)
|
30
|
+
- [Getting Started](#getting-started)
|
31
|
+
- [Releasing a Change](#releasing-a-change)
|
32
|
+
- [Changelog](#changelog)
|
33
|
+
- [License](#license)
|
34
|
+
|
35
|
+
## Introduction
|
36
|
+
|
37
|
+
Hey! I'm a Developer Advocate at [Spotify], and I wrote this Ruby SDK to explore how to build a SDK that is TADA:
|
38
|
+
|
39
|
+
1. **🧒 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.
|
40
|
+
|
41
|
+
1. **☁️ 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.
|
42
|
+
|
43
|
+
1. **🌈 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.
|
44
|
+
|
45
|
+
1. **✨ 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](https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5). We care about [Semantic Versioning] for clear version changes.
|
46
|
+
|
47
|
+
_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._
|
48
|
+
|
49
|
+
## Install
|
50
|
+
|
51
|
+
### With Bundler
|
52
|
+
|
53
|
+
Add this line to your application's `Gemfile`:
|
15
54
|
|
16
55
|
```ruby
|
17
|
-
gem
|
56
|
+
gem "spotify-ruby"
|
18
57
|
```
|
19
58
|
|
20
|
-
And then execute:
|
59
|
+
And then execute in your Terminal:
|
21
60
|
|
22
|
-
|
61
|
+
```bash
|
62
|
+
$ bundle install
|
63
|
+
```
|
23
64
|
|
24
|
-
|
65
|
+
Finally you can include the SDK via `Bundler.require`:
|
25
66
|
|
26
|
-
|
67
|
+
```ruby
|
68
|
+
require "bundler"
|
69
|
+
Bundler.require
|
70
|
+
```
|
27
71
|
|
28
|
-
|
72
|
+
### Manual Install
|
29
73
|
|
30
|
-
|
74
|
+
Or, you can install manually by executing this in your Terminal:
|
31
75
|
|
32
|
-
```
|
33
|
-
|
76
|
+
```bash
|
77
|
+
$ gem install spotify-ruby
|
78
|
+
```
|
34
79
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
})
|
80
|
+
Then you can include the SDK in your Ruby project:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
require "spotify-ruby"
|
40
84
|
```
|
41
85
|
|
42
|
-
##
|
86
|
+
## Configuration
|
87
|
+
|
88
|
+
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.
|
43
89
|
|
44
|
-
|
90
|
+
### Your App Credentials
|
45
91
|
|
46
|
-
|
92
|
+
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.
|
47
93
|
|
48
|
-
|
94
|
+
To define your app credentials, you'll need to create an instance of `Spotify::Accounts`:
|
49
95
|
|
50
96
|
```ruby
|
51
|
-
@
|
97
|
+
@accounts = Spotify::Accounts.new
|
98
|
+
@accounts.client_id = ENV["SPOTIFY_CLIENT_ID"]
|
99
|
+
@accounts.client_secret = ENV["SPOTIFY_CLIENT_SECRET"]
|
100
|
+
@accounts.redirect_uri = ENV["SPOTIFY_REDIRECT_URI"]
|
52
101
|
```
|
53
102
|
|
54
|
-
|
103
|
+
### Authorization
|
104
|
+
|
105
|
+
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).
|
106
|
+
|
107
|
+
**Recommended for production:** To request specific data, read our [Authorization Scopes] reference, and then execute:
|
55
108
|
|
56
109
|
```ruby
|
57
|
-
@
|
110
|
+
@accounts.authorize_url({
|
111
|
+
scope: "user-read-private user-read-email user-top-read"
|
112
|
+
}) # => "https://accounts.spotify.com/oauth/authorize?..."
|
58
113
|
```
|
59
114
|
|
60
|
-
|
115
|
+
**Recommended for exploration / local development:** Or, to request all data, you can execute:
|
116
|
+
|
61
117
|
```ruby
|
62
|
-
@
|
63
|
-
@sdk.to_hash # => { access_token: "...", expires_in: 1234567890, refresh_token: "..." }
|
118
|
+
@accounts.authorize_url # => "https://accounts.spotify.com/oauth/authorize?..."
|
64
119
|
```
|
65
120
|
|
66
|
-
|
121
|
+
### Creating a Session
|
122
|
+
|
123
|
+
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](https://support.spotify.com/uk/account_payment_help/privacy/revoke-access-from-3rd-party-app/)).
|
124
|
+
|
125
|
+
After a user has authorized your application, they'll be sent to your `redirect_uri` defined in [Your App Credentials](#your-app-credentials) with a `code` parameter. We can use this to create a `Spotify::Session`:
|
126
|
+
|
67
127
|
```ruby
|
68
|
-
@
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
128
|
+
@session = @accounts.exchange_for_session(params[:code])
|
129
|
+
```
|
130
|
+
|
131
|
+
We can check when the session expires, and when we should refresh:
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
@session.expires_at # => 2018-07-08 22:40:15 +0200
|
135
|
+
|
136
|
+
if @session.expired?
|
137
|
+
@session.refresh!
|
138
|
+
end
|
73
139
|
```
|
74
140
|
|
75
|
-
|
141
|
+
You'll then be able to use `@session` in the `Spotify::SDK` object. See the [Using the SDK](#using-the-sdk) section below.
|
142
|
+
|
143
|
+
### Recreating a Session
|
144
|
+
|
145
|
+
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:
|
76
146
|
|
77
147
|
```ruby
|
78
|
-
@
|
148
|
+
@session.refresh_token # => "BQASNDMelPsTdJMNMZfWdbxsuuM1FiBxvVzasqWkwYtgpjXJO60Gm51R0LO_-3Q5MfzCU0xIrbIFs7ZlMQrVJeRwN1_Ffa3sIJn_KW6LO8vA44fYc85oz48TuBuZsT2gzr4L"
|
79
149
|
```
|
80
150
|
|
81
|
-
|
151
|
+
Then you can repeatedly create a session with just a refresh token and running `refresh!`:
|
82
152
|
|
83
153
|
```ruby
|
84
|
-
@
|
154
|
+
@session = Spotify::Session.from_refresh_token(@accounts, "refresh_token here")
|
155
|
+
@session.expired? # => true
|
156
|
+
@session.refresh!
|
157
|
+
@session.expired? # => false
|
85
158
|
```
|
86
159
|
|
87
|
-
|
160
|
+
## Using the SDK
|
161
|
+
|
162
|
+
To create an instance of the Spotify SDK, you'll need the `@session` from above and pass it to `Spotify::SDK` as follows:
|
88
163
|
|
89
164
|
```ruby
|
90
|
-
@
|
165
|
+
@session = Spotify::Session.from_refresh_token(@accounts, "refresh_token here")
|
166
|
+
@session.refresh!
|
167
|
+
|
168
|
+
@sdk = Spotify::SDK.new(@session)
|
91
169
|
```
|
92
170
|
|
93
|
-
###
|
171
|
+
### Spotify Connect
|
94
172
|
|
95
|
-
|
173
|
+
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:
|
174
|
+
|
175
|
+
#### Read your devices\*
|
96
176
|
|
97
177
|
```ruby
|
98
|
-
@
|
178
|
+
@sdk.connect.devices # => [#<Spotify::SDK::Connect::Device:...>, ...]
|
179
|
+
|
180
|
+
@sdk.connect.devices[0].active?
|
181
|
+
@sdk.connect.devices[0].private_session?
|
182
|
+
@sdk.connect.devices[0].volume
|
183
|
+
@sdk.connect.devices[0].restricted?
|
99
184
|
```
|
100
185
|
|
101
|
-
|
186
|
+
#### Read current playback\*
|
102
187
|
|
103
|
-
|
188
|
+
```ruby
|
189
|
+
@sdk.connect.playback
|
190
|
+
@sdk.connect.playback.playing? # => true
|
191
|
+
@sdk.connect.playback.device.private_session? # => false
|
192
|
+
@sdk.connect.playback.shuffling? # => false
|
193
|
+
@sdk.connect.playback.repeat_mode # => :context
|
194
|
+
@sdk.connect.playback.position_percentage # => 4.53
|
195
|
+
@sdk.connect.playback.artist.name # => "Ed Sheeran"
|
196
|
+
@sdk.connect.playback.item.album.name # => "÷"
|
197
|
+
```
|
104
198
|
|
105
|
-
|
199
|
+
#### Control playback\*
|
106
200
|
|
107
|
-
|
201
|
+
```ruby
|
202
|
+
@sdk.connect.devices[0].play!({
|
203
|
+
uri: "spotify:track:0tgVpDi06FyKpA1z0VMD4v"
|
204
|
+
})
|
108
205
|
|
109
|
-
|
206
|
+
@sdk.connect.devices[0].pause!
|
207
|
+
@sdk.connect.devices[0].resume!
|
208
|
+
@sdk.connect.devices[0].volume = 80
|
209
|
+
@sdk.connect.devices[0].previous!
|
210
|
+
@sdk.connect.devices[0].next!
|
211
|
+
@sdk.connect.devices[0].position_ms = 3_000
|
212
|
+
@sdk.connect.devices[0].shuffle = false
|
213
|
+
@sdk.connect.devices[0].repeat_mode = :context
|
214
|
+
```
|
215
|
+
|
216
|
+
<small><i>\* Requires specific user permissions/scopes. See [Authorization Scopes] for more information.</i></small>
|
110
217
|
|
111
218
|
## Contributing
|
112
219
|
|
113
|
-
|
220
|
+
### Community Guidelines
|
114
221
|
|
115
|
-
|
222
|
+
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.
|
116
223
|
|
117
|
-
|
224
|
+
### Code of Conduct
|
118
225
|
|
119
|
-
|
226
|
+
Everyone interacting with this project's codebases, issue trackers, discussions, chat rooms, and mailing lists is required to follow the [Code of Conduct].
|
120
227
|
|
121
|
-
|
228
|
+
Whilst we try to always assume good intentions, any clear violations or bad actors will be warned and subsequently banned from this project indefinitely.
|
229
|
+
|
230
|
+
### Getting Started
|
231
|
+
|
232
|
+
Firstly, you'll need Git and Ruby installed. You can then install the dependencies as following:
|
233
|
+
|
234
|
+
```bash
|
235
|
+
$ git clone ssh://git@github.com/bih/spotify-ruby.git
|
236
|
+
$ bin/setup
|
237
|
+
```
|
238
|
+
|
239
|
+
You can run `rake ci` to validate your Ruby syntax, our RSpec tests, and code coverage.
|
240
|
+
|
241
|
+
For local development, you can run `bin/console` for an interactive prompt for experimentation.
|
242
|
+
|
243
|
+
### Releasing a Change
|
244
|
+
|
245
|
+
- To install this gem onto your local machine, run `bundle exec rake install`.
|
246
|
+
- Ensure versions are in line with the [Semantic Versioning] convention.
|
247
|
+
- To release a new version:
|
248
|
+
- Update the version number in `lib/spotify/version.rb`
|
249
|
+
- Run `bundle exec rake release` (which will create a git tag for the version)
|
250
|
+
- Push git commits and tags
|
251
|
+
- Push the `.gem` file to [rubygems.org].
|
252
|
+
|
253
|
+
### Changelog
|
254
|
+
|
255
|
+
```
|
256
|
+
[2018-07-21] (0.2.1) First major release.
|
257
|
+
- Support for Connect and User API endpoints.
|
258
|
+
- Transitioned to YARD for documentation.
|
259
|
+
- Website built using Jekyll with Contributing guide.
|
260
|
+
- Removed Coveralls in favour for CodeClimate
|
261
|
+
```
|
262
|
+
|
263
|
+
## License
|
122
264
|
|
123
|
-
[
|
124
|
-
|
125
|
-
[
|
126
|
-
[
|
127
|
-
[
|
265
|
+
The gem is available as open source under the terms of the [MIT License].
|
266
|
+
|
267
|
+
[Spotify]: https://developer.spotify.com
|
268
|
+
[Spotify Connect]: https://www.spotify.com/connect/
|
269
|
+
[developer.spotify.com]: https://developer.spotify.com
|
270
|
+
[Accounts API]: https://developer.spotify.com/documentation/general/guides/authorization-guide/
|
271
|
+
[Authorization Scopes]: https://developer.spotify.com/documentation/general/guides/scopes/
|
272
|
+
|
273
|
+
[Website]: https://bih.github.io/spotify-ruby
|
274
|
+
[Contributing]: https://bih.github.io/spotify-ruby/documentation/contributing/
|
275
|
+
[SDK Reference]: http://www.rubydoc.info/github/bih/spotify-ruby
|
276
|
+
[Code of Conduct]: https://github.com/bih/spotify-ruby/blob/master/CODE_OF_CONDUCT.md
|
277
|
+
[Contributor Covenant]: http://contributor-covenant.org
|
278
|
+
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
|
279
|
+
|
280
|
+
[Build Status]: https://travis-ci.org/bih/spotify-ruby
|
281
|
+
[Maintainability]: https://codeclimate.com/github/bih/spotify-ruby/maintainability
|
282
|
+
[Test Coverage]: https://codeclimate.com/github/bih/spotify-ruby/test_coverage
|
283
|
+
[Gem Version]: https://badge.fury.io/rb/spotify-ruby
|
284
|
+
[Code Triagers Badge]: https://www.codetriage.com/bih/spotify-ruby
|
285
|
+
[MIT License]: http://opensource.org/licenses/MIT
|
286
|
+
[rubygems.org]: https://rubygems.org
|
287
|
+
<!-- prettier-ignore-end -->
|