rspotify 2.10.1 → 2.11.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 +4 -4
- data/.gitignore +2 -0
- data/README.md +1 -1
- data/lib/rspotify/episode.rb +84 -0
- data/lib/rspotify/oauth.rb +5 -0
- data/lib/rspotify/playlist.rb +1 -1
- data/lib/rspotify/show.rb +100 -0
- data/lib/rspotify/version.rb +1 -1
- data/lib/rspotify.rb +2 -0
- data/rspotify.gemspec +1 -1
- data/spec/lib/rspotify/episode_spec.rb +118 -0
- data/spec/lib/rspotify/show_spec.rb +138 -0
- data/spec/vcr_cassettes/episode_find_512ojhOuo1ktJprKbVcKyQ.yml +66 -0
- data/spec/vcr_cassettes/episode_find_5NxzDE5TmviUV8te2eZjMP_market_ES.yml +66 -0
- data/spec/vcr_cassettes/episode_find_5NxzDE5TmviUV8te2eZjMP_market_KG.yml +66 -0
- data/spec/vcr_cassettes/episode_find_array_18RPZgmvEGKtEC2WMTHghd.yml +66 -0
- data/spec/vcr_cassettes/episode_find_array_512ojhOuo1ktJprKbVcKyQ.yml +66 -0
- data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas.yml +64 -0
- data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_limit_10.yml +64 -0
- data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_limit_10_offset_10.yml +64 -0
- data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_market_CA.yml +694 -0
- data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_offset_10.yml +64 -0
- data/spec/vcr_cassettes/show_find_5CfCWKI5pZ28U0uOzXkDHe.yml +66 -0
- data/spec/vcr_cassettes/show_find_5CfCWKI5pZ28U0uOzXkDHe_episodes.yml +66 -0
- data/spec/vcr_cassettes/show_find_5CfCWKI5pZ28U0uOzXkDHe_episodes_market_ES.yml +66 -0
- data/spec/vcr_cassettes/show_find_many_5CfCWKI5pZ28U0uOzXkDHe.yml +64 -0
- data/spec/vcr_cassettes/show_find_many_5CfCWKI5pZ28U0uOzXkDHe_5as3aKmN2k11yfDDDSrvaZ.yml +64 -0
- data/spec/vcr_cassettes/show_find_many_5CfCWKI5pZ28U0uOzXkDHe_5as3aKmN2k11yfDDDSrvaZ_market_CA.yml +64 -0
- data/spec/vcr_cassettes/show_search_without_fail.yml +64 -0
- data/spec/vcr_cassettes/show_search_without_fail_limit_10.yml +64 -0
- data/spec/vcr_cassettes/show_search_without_fail_market_ES.yml +64 -0
- data/spec/vcr_cassettes/show_search_without_fail_offset_10.yml +64 -0
- data/spec/vcr_cassettes/show_search_without_fail_offset_10_limit_10.yml +64 -0
- metadata +52 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d9d7a49993e755934d77091d568c04862f676c0b52ffe14ab80355cf38c17c1
|
4
|
+
data.tar.gz: 13d0709271280fb895df8f8941915a3090e426d020013552fb0af50656e21f3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: def7d61e7f73af6ff9f03bdfbe562c21b462a6820778d76437a6c660bbeb3d3e4f23f11e6ab6c349abb8458da6ad769545e2edc0de3caf563c653ff069c14ee0
|
7
|
+
data.tar.gz: d79c15a25e18878e3a27cba75e0e41a7fab88ecd430e25ae9183c97a88a6d6ff46d9001326d848fe16ed77094a7e8e4a680dd1e0ace6b6271684b728131fc4c4
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -155,7 +155,7 @@ Rails.application.config.middleware.use OmniAuth::Builder do
|
|
155
155
|
end
|
156
156
|
```
|
157
157
|
|
158
|
-
You should replace the scope values for the ones your own app will require from the user. You can see the list of available scopes in [here](https://developer.spotify.com/
|
158
|
+
You should replace the scope values for the ones your own app will require from the user. You can see the list of available scopes in [here](https://developer.spotify.com/documentation/general/guides/authorization/scopes/).
|
159
159
|
|
160
160
|
Next, make a link so the user can log in with his Spotify account:
|
161
161
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module RSpotify
|
2
|
+
|
3
|
+
# @attr [String] audio_preview_url A URL to a 30 second preview (MP3 format) of the episode. null if not available.
|
4
|
+
# @attr [String] description A description of the episode. HTML tags are stripped away from this field, use html_description field in case HTML tags are needed.
|
5
|
+
# @attr [Integer] duration_ms The episode length in milliseconds.
|
6
|
+
# @attr [Boolean] explicit Whether or not the episode has explicit content (true = yes it does; false = no it does not OR unknown).
|
7
|
+
# @attr [String] href A link to the Web API endpoint providing full details of the episode.
|
8
|
+
# @attr [String] html_description A description of the episode. This field may contain HTML tags.
|
9
|
+
# @attr [Array<Hash>] images The cover art for the episode in various sizes, widest first.
|
10
|
+
# @attr [Boolean] is_externally_hosted True if the episode is hosted outside of Spotify’s CDN.
|
11
|
+
# @attr [Boolean] is_playable True if the episode is playable in the given market. Otherwise false.
|
12
|
+
# @attr [String] language The language used in the episode, identified by a ISO 639 code. This field is deprecated and might be removed in the future. Please use the languages field instead.
|
13
|
+
# @attr [Array<String>] languages A list of the languages used in the episode, identified by their ISO 639-1 code.
|
14
|
+
# @attr [String] name The name of the episode.
|
15
|
+
# @attr [String] release_date The date the episode was first released, for example "1981-12-15". Depending on the precision, it might be shown as "1981" or "1981-12".
|
16
|
+
# @attr [String] release_date_precision The precision with which release_date value is known.
|
17
|
+
# @attr [Hash] restrictions Included in the response when a content restriction is applied.
|
18
|
+
# @attr [Hash] resume_point The user’s most recent position in the episode. Set if the supplied access token is a user token and has the scope ‘user-read-playback-position’.
|
19
|
+
class Episode < Base
|
20
|
+
|
21
|
+
# Returns Episode object(s) with id(s) provided
|
22
|
+
#
|
23
|
+
# @param ids [String, Array] Maximum: 50 IDs
|
24
|
+
# @param market [String] Optional. An {http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
|
25
|
+
# @return [Episode, Array<Episode>]
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# episode = RSpotify::Episode.find('512ojhOuo1ktJprKbVcKyQ')
|
29
|
+
# episode.class #=> RSpotify::Episode
|
30
|
+
# episode.name #=> "Do I Wanna Know?"
|
31
|
+
#
|
32
|
+
# ids = %w(512ojhOuo1ktJprKbVcKyQ 15tHEpY9pwbKC0QjpYCRB1)
|
33
|
+
# episodes = RSpotify::Base.find(ids, 'episode')
|
34
|
+
# episodes.class #=> Array
|
35
|
+
# episodes.first.class #=> RSpotify::Episode
|
36
|
+
def self.find(ids, market: nil)
|
37
|
+
super(ids, 'episode', market: market)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns array of Episode objects matching the query. It's also possible to find the total number of search results for the query
|
41
|
+
#
|
42
|
+
# @param query [String] The search query's keywords. For details access {https://developer.spotify.com/web-api/search-item here} and look for the q parameter description.
|
43
|
+
# @param limit [Integer] Maximum number of episodes to return. Maximum: 50. Default: 20.
|
44
|
+
# @param offset [Integer] The index of the first episode to return. Use with limit to get the next set of episodes. Default: 0.
|
45
|
+
# @param market [String, Hash] Optional. An {http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code} or the hash { from: user }, where user is a RSpotify user authenticated using OAuth with scope *user-read-private*. This will take the user's country as the market value. For details access {https://developer.spotify.com/web-api/search-item here} and look for the market parameter description.
|
46
|
+
# @return [Array<Episode>]
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# episodes = RSpotify::Episode.search('Vetenskapsradion Historia')
|
50
|
+
# episodes = RSpotify::Episode.search('Vetenskapsradion Historia', limit: 10, market: 'US')
|
51
|
+
# episodes = RSpotify::Episode.search('Vetenskapsradion Historia', market: { from: user })
|
52
|
+
#
|
53
|
+
# RSpotify::Episode.search('Vetenskapsradion Historia').total #=> 711
|
54
|
+
def self.search(query, limit: 20, offset: 0, market: nil )
|
55
|
+
super(query, 'episode', limit: limit, offset: offset, market: market)
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize(options = {})
|
59
|
+
@audio_preview_url = options['audio_preview_url']
|
60
|
+
@description = options['description']
|
61
|
+
@duration_ms = options['duration_ms']
|
62
|
+
@explicit = options['explicit']
|
63
|
+
@href = options['href']
|
64
|
+
@html_description = options['html_description']
|
65
|
+
@images = options['images']
|
66
|
+
@is_externally_hosted = options['is_externally_hosted']
|
67
|
+
@is_playable = options['is_playable']
|
68
|
+
@language = options['language']
|
69
|
+
@languages = options['languages']
|
70
|
+
@name = options['name']
|
71
|
+
@release_date = options['release_date']
|
72
|
+
@release_date_precision = options['release_date_precision']
|
73
|
+
@restrictions = options['restrictions'] || {}
|
74
|
+
@resume_point = options['resume_point'] || {}
|
75
|
+
@uri = options['uri']
|
76
|
+
|
77
|
+
@show = if options['show']
|
78
|
+
Show.new options['show']
|
79
|
+
end
|
80
|
+
|
81
|
+
super(options)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/rspotify/oauth.rb
CHANGED
data/lib/rspotify/playlist.rb
CHANGED
@@ -315,7 +315,7 @@ module RSpotify
|
|
315
315
|
|
316
316
|
params = {
|
317
317
|
method: :delete,
|
318
|
-
url: URI
|
318
|
+
url: Addressable::URI.encode(RSpotify::API_URI + @path + '/tracks'),
|
319
319
|
headers: User.send(:oauth_header, @owner.id),
|
320
320
|
payload: positions ? { positions: positions } : { tracks: tracks }
|
321
321
|
}
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module RSpotify
|
2
|
+
|
3
|
+
# @attr [Array<String>] available_markets A list of the countries in which the show can be played, identified by their ISO 3166-1 alpha-2 code.
|
4
|
+
# @attr [Array<Hash>] copyrights The copyright statements of the show.
|
5
|
+
# @attr [String] description A description of the show. HTML tags are stripped away from this field, use html_description field in case HTML tags are needed.
|
6
|
+
# @attr [Boolean] explicit Whether or not the show has explicit content (true = yes it does; false = no it does not OR unknown).
|
7
|
+
# @attr [String] html_description A description of the show. This field may contain HTML tags.
|
8
|
+
# @attr [Array<Hash>] images The cover art for the show in various sizes, widest first.
|
9
|
+
# @attr [Boolean] is_externally_hosted True if all of the show’s episodes are hosted outside of Spotify’s CDN. This field might be null in some cases.
|
10
|
+
# @attr [Array<String>] languages A list of the languages used in the show, identified by their ISO 639 code.
|
11
|
+
# @attr [String] media_type The media type of the show.
|
12
|
+
# @attr [String] name The name of the show.
|
13
|
+
# @attr [String] publisher The publisher of the show.
|
14
|
+
class Show < Base
|
15
|
+
|
16
|
+
# Returns Show object(s) with id(s) provided
|
17
|
+
#
|
18
|
+
# @param id [String, Array] Maximum: 50 IDs
|
19
|
+
# @param market [String] An {https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
|
20
|
+
# @return [Show, Array<Show>]
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# show = RSpotify::Show.find('3Z6JdCS2d0eFEpXHKI6WqH')
|
24
|
+
# show.class #=> RSpotify::Show
|
25
|
+
# show.name #=> "Consider This from NPR"
|
26
|
+
def self.find(ids, market: nil )
|
27
|
+
super(ids, 'show', market: market)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns array of Show objects matching the query. It's also possible to find the total number of search results for the query
|
31
|
+
#
|
32
|
+
# @param query [String] The search query's keywords. See the q description in {https://developer.spotify.com/web-api/search-item here} for details.
|
33
|
+
# @param limit [Integer] Maximum number of shows to return. Maximum: 50. Default: 20.
|
34
|
+
# @param offset [Integer] The index of the first show to return. Use with limit to get the next set of shows. Default: 0.
|
35
|
+
# @param market [String] An {https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
|
36
|
+
# @return [Array<Show>]
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# shows = RSpotify::Show.search('NPR')
|
40
|
+
# shows = RSpotify::Show.search('NPR', market: 'US', limit: 10)
|
41
|
+
#
|
42
|
+
# RSpotify::Show.search('NPR').total #=> 357
|
43
|
+
def self.search(query, limit: 20, offset: 0, market: nil)
|
44
|
+
super(query, 'show', limit: limit, offset: offset, market: market)
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(options = {})
|
48
|
+
@available_markets = options['available_markets']
|
49
|
+
@copyrights = options['copyrights']
|
50
|
+
@description = options['description']
|
51
|
+
@explicit = options['explicit']
|
52
|
+
@html_description = options['html_description']
|
53
|
+
@images = options['images']
|
54
|
+
@is_externally_hosted = options['is_externally_hosted']
|
55
|
+
@languages = options['languages']
|
56
|
+
@media_type = options['media_type']
|
57
|
+
@name = options['name']
|
58
|
+
@publisher = options['publisher']
|
59
|
+
|
60
|
+
episodes = options['episodes']['items'] if options['episodes']
|
61
|
+
|
62
|
+
@episodes_cache = if episodes
|
63
|
+
episodes.map { |e| Episode.new e }
|
64
|
+
end
|
65
|
+
|
66
|
+
super(options)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns array of episodes from the show
|
70
|
+
#
|
71
|
+
# @param limit [Integer] Maximum number of episodes to return. Maximum: 50. Default: 20.
|
72
|
+
# @param offset [Integer] The index of the first track to return. Use with limit to get the next set of objects. Default: 0.
|
73
|
+
# @param market [String] An {https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
|
74
|
+
# @return [Array<Episode>]
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# show = RSpotify::Show.find('3Z6JdCS2d0eFEpXHKI6WqH')
|
78
|
+
# show.episodes.first.name #=> "Colin Powell's Complicated Legacy"
|
79
|
+
def episodes(limit: 20, offset: 0, market: nil )
|
80
|
+
last_episode = offset + limit - 1
|
81
|
+
if @episodes_cache && last_episode < 20 && !RSpotify.raw_response
|
82
|
+
return @episodes_cache[offset..last_episode]
|
83
|
+
end
|
84
|
+
|
85
|
+
url = "#{@href}/episodes?limit=#{limit}&offset=#{offset}"
|
86
|
+
url << "&market=#{market}" if market
|
87
|
+
|
88
|
+
response = RSpotify.get url
|
89
|
+
|
90
|
+
json = RSpotify.raw_response ? JSON.parse(response) : response
|
91
|
+
episodes = json['items']
|
92
|
+
|
93
|
+
episodes.map! { |e| Episode.new e }
|
94
|
+
@episodes_cache = episodes if limit == 20 && offset == 0
|
95
|
+
return response if RSpotify.raw_response
|
96
|
+
episodes
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
data/lib/rspotify/version.rb
CHANGED
data/lib/rspotify.rb
CHANGED
@@ -8,10 +8,12 @@ module RSpotify
|
|
8
8
|
autoload :Base, 'rspotify/base'
|
9
9
|
autoload :Category, 'rspotify/category'
|
10
10
|
autoload :Device, 'rspotify/device'
|
11
|
+
autoload :Episode, 'rspotify/episode'
|
11
12
|
autoload :Player, 'rspotify/player'
|
12
13
|
autoload :Playlist, 'rspotify/playlist'
|
13
14
|
autoload :Recommendations, 'rspotify/recommendations'
|
14
15
|
autoload :RecommendationSeed, 'rspotify/recommendation_seed'
|
16
|
+
autoload :Show, 'rspotify/show'
|
15
17
|
autoload :Track, 'rspotify/track'
|
16
18
|
autoload :TrackLink, 'rspotify/track_link'
|
17
19
|
autoload :User, 'rspotify/user'
|
data/rspotify.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.add_dependency 'omniauth-oauth2', '>= 1.6'
|
20
20
|
spec.add_dependency 'rest-client', '~> 2.0.2'
|
21
|
-
spec.add_dependency 'addressable', '~> 2.
|
21
|
+
spec.add_dependency 'addressable', '~> 2.8.0'
|
22
22
|
|
23
23
|
spec.add_development_dependency 'bundler'
|
24
24
|
spec.add_development_dependency 'webmock'
|
@@ -0,0 +1,118 @@
|
|
1
|
+
describe RSpotify::Episode do
|
2
|
+
describe 'Episode::find receiving id as a string' do
|
3
|
+
before(:each) do
|
4
|
+
@episode = VCR.use_cassette('episode:find:512ojhOuo1ktJprKbVcKyQ') do
|
5
|
+
RSpotify::Episode.find('512ojhOuo1ktJprKbVcKyQ')
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should find track with correct attributes' do
|
10
|
+
expect(@episode.audio_preview_url) .to eq "https://p.scdn.co/mp3-preview/566fcc94708f39bcddc09e4ce84a8e5db8f07d4d"
|
11
|
+
expect(@episode.description) .to start_with "En ny tysk bok granskar för första gången Tredje rikets drogberoende"
|
12
|
+
expect(@episode.duration_ms) .to eq 1_502_795
|
13
|
+
expect(@episode.explicit) .to eq false
|
14
|
+
expect(@episode.href) .to eq 'https://api.spotify.com/v1/episodes/512ojhOuo1ktJprKbVcKyQ'
|
15
|
+
expect(@episode.html_description) .to start_with "En ny tysk bok granskar för första gången Tredje rikets drogberoende"
|
16
|
+
expect(@episode.id) .to eq '512ojhOuo1ktJprKbVcKyQ'
|
17
|
+
expect(@episode.images.first["url"]) .to eq "https://i.scdn.co/image/de4a5f115ac6f6ca4cae4fb7aaf27bacac7a0b8a"
|
18
|
+
expect(@episode.images.size) .to eq 3
|
19
|
+
expect(@episode.is_externally_hosted) .to eq false
|
20
|
+
expect(@episode.is_playable) .to eq true
|
21
|
+
expect(@episode.language) .to eq 'sv'
|
22
|
+
expect(@episode.languages) .to eq ["sv"]
|
23
|
+
expect(@episode.name) .to eq 'Tredje rikets knarkande granskas'
|
24
|
+
expect(@episode.release_date_precision) .to eq 'day'
|
25
|
+
expect(@episode.release_date) .to eq '2015-10-01'
|
26
|
+
expect(@episode.restrictions) .to eq Hash.new
|
27
|
+
expect(@episode.resume_point) .to eq({"fully_played"=>false, "resume_position_ms"=>0})
|
28
|
+
expect(@episode.uri) .to eq 'spotify:episode:512ojhOuo1ktJprKbVcKyQ'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should find the episode with correct show' do
|
32
|
+
show = @episode.show
|
33
|
+
expect(show) .to be_an RSpotify::Show
|
34
|
+
expect(show.id) .to eq '38bS44xjbVVZ3No3ByF1dJ'
|
35
|
+
expect(show.name) .to eq 'Vetenskapsradion Historia'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should find an episode which is available in the given market' do
|
39
|
+
episode = VCR.use_cassette('episode:find:5NxzDE5TmviUV8te2eZjMP:market:ES') do
|
40
|
+
RSpotify::Episode.find('5NxzDE5TmviUV8te2eZjMP', market: 'ES')
|
41
|
+
end
|
42
|
+
|
43
|
+
expect(episode.id).to eq '5NxzDE5TmviUV8te2eZjMP'
|
44
|
+
expect(episode.is_playable). to eq true
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should not find an episode which is unavailable in the given market' do
|
48
|
+
episode = VCR.use_cassette('episode:find:5NxzDE5TmviUV8te2eZjMP:market:KG') do
|
49
|
+
RSpotify::Episode.find('5NxzDE5TmviUV8te2eZjMP', market: 'KG')
|
50
|
+
end
|
51
|
+
|
52
|
+
expect(episode.id).to eq '5NxzDE5TmviUV8te2eZjMP'
|
53
|
+
expect(episode.is_playable). to eq false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'Episode::find receiving array of ids' do
|
58
|
+
it 'should find the right episodes' do
|
59
|
+
ids = ['512ojhOuo1ktJprKbVcKyQ']
|
60
|
+
episodes = VCR.use_cassette('episode:find_array:512ojhOuo1ktJprKbVcKyQ') do
|
61
|
+
RSpotify::Episode.find(ids)
|
62
|
+
end
|
63
|
+
expect(episodes) .to be_an Array
|
64
|
+
expect(episodes.size) .to eq 1
|
65
|
+
expect(episodes.first.name) .to eq 'Tredje rikets knarkande granskas'
|
66
|
+
|
67
|
+
ids << '18RPZgmvEGKtEC2WMTHghd'
|
68
|
+
episodes = VCR.use_cassette('episode:find_array:18RPZgmvEGKtEC2WMTHghd') do
|
69
|
+
RSpotify::Episode.find(ids)
|
70
|
+
end
|
71
|
+
expect(episodes) .to be_an Array
|
72
|
+
expect(episodes.size) .to eq 2
|
73
|
+
expect(episodes.first.name) .to eq 'Tredje rikets knarkande granskas'
|
74
|
+
expect(episodes.last.name) .to eq 'Han upptäckte vikingastaden Birka'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe 'Episode::search' do
|
79
|
+
it 'should search for the right episodes' do
|
80
|
+
episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas') do
|
81
|
+
RSpotify::Episode.search('Tredje rikets knarkande granskas')
|
82
|
+
end
|
83
|
+
|
84
|
+
expect(episodes) .to be_an Array
|
85
|
+
expect(episodes.size) .to eq 20
|
86
|
+
expect(episodes.total) .to eq 527
|
87
|
+
expect(episodes.first) .to be_an RSpotify::Episode
|
88
|
+
expect(episodes.map(&:name)) .to include('Tredje rikets knarkande granskas', '"Tre skadade i grovt våldsbrott i Lycksele"')
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should accept additional options' do
|
92
|
+
episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas:limit:10') do
|
93
|
+
RSpotify::Episode.search('Tredje rikets knarkande granskas', limit: 10)
|
94
|
+
end
|
95
|
+
expect(episodes.size) .to eq 10
|
96
|
+
expect(episodes.map(&:name)) .to include('Tredje rikets knarkande granskas', '14. Första världskrigets BÄSTA generaler ... och Conrad')
|
97
|
+
|
98
|
+
episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas:offset:10') do
|
99
|
+
RSpotify::Episode.search('Tredje rikets knarkande granskas', offset: 10)
|
100
|
+
end
|
101
|
+
expect(episodes.size) .to eq 20
|
102
|
+
expect(episodes.map(&:name)) .to include('GIIA-avsnitt 2: Stefan Kronanders avsnitt – tyska underrättelse-fuckups')
|
103
|
+
|
104
|
+
episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas:limit:10:offset:10') do
|
105
|
+
RSpotify::Episode.search('Tredje rikets knarkande granskas', limit: 10, offset: 10)
|
106
|
+
end
|
107
|
+
expect(episodes.size) .to eq 10
|
108
|
+
expect(episodes.map(&:name)) .to include('GIIA-avsnitt 2: Stefan Kronanders avsnitt – tyska underrättelse-fuckups')
|
109
|
+
|
110
|
+
episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas:market:CA') do
|
111
|
+
RSpotify::Episode.search('Tredje rikets knarkande granskas', market: 'CA')
|
112
|
+
CA_episodes = episodes.map { |e| e.show.available_markets == 'CA'}
|
113
|
+
end
|
114
|
+
|
115
|
+
expect(CA_episodes.length).to eq(episodes.length)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
describe RSpotify::Show do
|
2
|
+
describe 'Show::find receiving id as a string' do
|
3
|
+
|
4
|
+
before(:each) do
|
5
|
+
@show = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe') do
|
6
|
+
RSpotify::Show.find('5CfCWKI5pZ28U0uOzXkDHe')
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should find show with correct attributes' do
|
11
|
+
expect(@show.available_markets) .to be_an Array
|
12
|
+
expect(@show.copyrights) .to eq []
|
13
|
+
expect(@show.external_urls['spotify']) .to eq 'https://open.spotify.com/show/5CfCWKI5pZ28U0uOzXkDHe'
|
14
|
+
expect(@show.description) .to eq 'Candid conversations with entrepreneurs, artists, athletes, visionaries of all kinds—about their successes, and their failures, and what they learned from both. Hosted by Alex Blumberg, from Gimlet Media.'
|
15
|
+
expect(@show.explicit) .to eq true
|
16
|
+
expect(@show.html_description) .to eq '<p>Candid conversations with entrepreneurs, artists, athletes, visionaries of all kinds—about their successes, and their failures, and what they learned from both. Hosted by Alex Blumberg, from Gimlet Media.</p>'
|
17
|
+
expect(@show.href) .to eq 'https://api.spotify.com/v1/shows/5CfCWKI5pZ28U0uOzXkDHe'
|
18
|
+
expect(@show.id) .to eq '5CfCWKI5pZ28U0uOzXkDHe'
|
19
|
+
expect(@show.images) .to include ({'height' => 640, 'width' => 640, 'url' => 'https://i.scdn.co/image/ab6765630000ba8a9d827f6e7e311b5947cce059'})
|
20
|
+
expect(@show.is_externally_hosted) .to eq false
|
21
|
+
expect(@show.languages) .to eq ["en"]
|
22
|
+
expect(@show.media_type) .to eq "audio"
|
23
|
+
expect(@show.name) .to eq "Without Fail"
|
24
|
+
expect(@show.publisher) .to eq "Gimlet"
|
25
|
+
expect(@show.type) .to eq 'show'
|
26
|
+
expect(@show.uri) .to eq 'spotify:show:5CfCWKI5pZ28U0uOzXkDHe'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should find show with correct episodes' do
|
30
|
+
episodes = @show.episodes
|
31
|
+
expect(episodes) .to be_an Array
|
32
|
+
expect(episodes.size) .to eq 20
|
33
|
+
expect(episodes.first) .to be_an RSpotify::Episode
|
34
|
+
expect(episodes.map(&:name)) .to include("Introducing Michelle Obama and Her Mentees")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'Show::find receiving array of ids' do
|
39
|
+
it 'should find the right shows' do
|
40
|
+
ids = ['5CfCWKI5pZ28U0uOzXkDHe']
|
41
|
+
shows = VCR.use_cassette('show:find_many:5CfCWKI5pZ28U0uOzXkDHe') do
|
42
|
+
RSpotify::Show.find(ids)
|
43
|
+
end
|
44
|
+
expect(shows) .to be_an Array
|
45
|
+
expect(shows.size) .to eq 1
|
46
|
+
expect(shows.first) .to be_an RSpotify::Show
|
47
|
+
expect(shows.map(&:name)) .to include("Without Fail")
|
48
|
+
|
49
|
+
ids << '5as3aKmN2k11yfDDDSrvaZ'
|
50
|
+
shows = VCR.use_cassette('show:find_many:5CfCWKI5pZ28U0uOzXkDHe:5as3aKmN2k11yfDDDSrvaZ') do
|
51
|
+
RSpotify::Show.find(ids)
|
52
|
+
end
|
53
|
+
expect(shows) .to be_an Array
|
54
|
+
expect(shows.size) .to eq 2
|
55
|
+
expect(shows.first) .to be_an RSpotify::Show
|
56
|
+
expect(shows.map(&:name)) .to include("Giant Bombcast")
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should find shows available in the given market' do
|
60
|
+
ids = ['5CfCWKI5pZ28U0uOzXkDHe', '5as3aKmN2k11yfDDDSrvaZ']
|
61
|
+
shows = VCR.use_cassette('show:find_many:5CfCWKI5pZ28U0uOzXkDHe:5as3aKmN2k11yfDDDSrvaZ:market:CA') do
|
62
|
+
RSpotify::Show.find(ids, market: 'CA')
|
63
|
+
end
|
64
|
+
|
65
|
+
expect(shows) .to be_an Array
|
66
|
+
expect(shows.map(&:id)) .to include '5CfCWKI5pZ28U0uOzXkDHe'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'Show::search' do
|
71
|
+
it 'should search for the right shows' do
|
72
|
+
shows = VCR.use_cassette('show:search:without fail') do
|
73
|
+
RSpotify::Show.search('Without Fail')
|
74
|
+
end
|
75
|
+
expect(shows) .to be_an Array
|
76
|
+
expect(shows.size) .to eq 20
|
77
|
+
expect(shows.total) .to eq 233
|
78
|
+
expect(shows.first) .to be_an RSpotify::Show
|
79
|
+
expect(shows.map(&:name)) .to include('Without Fail', 'Teach Without a Burden')
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should accept additional options' do
|
83
|
+
shows = VCR.use_cassette('show:search:without fail:limit:10') do
|
84
|
+
RSpotify::Show.search('Without Fail', limit: 10)
|
85
|
+
end
|
86
|
+
expect(shows.size) .to eq 10
|
87
|
+
expect(shows.map(&:name)) .to include('Without Fail', 'Teach Without a Burden')
|
88
|
+
|
89
|
+
shows = VCR.use_cassette('show:search:without fail:offset:10') do
|
90
|
+
RSpotify::Show.search('Without Fail', offset: 10)
|
91
|
+
end
|
92
|
+
expect(shows.size) .to eq 20
|
93
|
+
expect(shows.map(&:name)) .to include('Weight Loss Mindset', 'Two In The Think Tank')
|
94
|
+
|
95
|
+
shows = VCR.use_cassette('show:search:without fail:offset:10:limit:10') do
|
96
|
+
RSpotify::Show.search('Without Fail', limit: 10, offset: 10)
|
97
|
+
end
|
98
|
+
expect(shows.size) .to eq 10
|
99
|
+
expect(shows.map(&:name)) .to include('Two In The Think Tank')
|
100
|
+
|
101
|
+
shows = VCR.use_cassette('show:search:without fail:market:ES') do
|
102
|
+
RSpotify::Show.search('Without Fail', market: 'ES')
|
103
|
+
end
|
104
|
+
ES_shows = shows.select { |a| a.available_markets.include?('ES') }
|
105
|
+
expect(ES_shows.length).to eq(shows.length)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#episodes' do
|
110
|
+
it 'should fetch more episodes' do
|
111
|
+
show = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe') do
|
112
|
+
RSpotify::Show.find('5CfCWKI5pZ28U0uOzXkDHe')
|
113
|
+
end
|
114
|
+
|
115
|
+
episodes = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe:episodes') do
|
116
|
+
show.episodes(offset: 20, limit: 20)
|
117
|
+
end
|
118
|
+
|
119
|
+
expect(episodes) .to be_an Array
|
120
|
+
expect(episodes.size) .to eq 20
|
121
|
+
expect(episodes.first.name) .to eq 'Being an A$$hole: The Final Frontier for Women on the Screen'
|
122
|
+
expect(episodes.first.id) .to eq '0DD6d3lmUjkIHzC13Z6fbs'
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should find episodes available in the given market" do
|
126
|
+
show = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe') do
|
127
|
+
RSpotify::Show.find('5CfCWKI5pZ28U0uOzXkDHe')
|
128
|
+
end
|
129
|
+
|
130
|
+
episodes = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe:episodes:market:ES') do
|
131
|
+
show.episodes(offset: 20, limit: 20, market: 'ES')
|
132
|
+
end
|
133
|
+
|
134
|
+
expect(episodes.first.name) .to eq 'Being an A$$hole: The Final Frontier for Women on the Screen'
|
135
|
+
expect(episodes.first.id) .to eq '0DD6d3lmUjkIHzC13Z6fbs'
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://api.spotify.com/v1/episodes/512ojhOuo1ktJprKbVcKyQ
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- "*/*"
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
User-Agent:
|
15
|
+
- rest-client/2.0.2 (darwin20 x86_64) ruby/3.0.2p107
|
16
|
+
Authorization:
|
17
|
+
- Bearer BQBj_AiSFlKCkNIMbCWEYjuJLl6n76QmVsHU6MGDgTUBLZqNiKZ4ALs6Kvm6ulbsW9O81JDdIHyXBndXyhUOxg
|
18
|
+
Host:
|
19
|
+
- api.spotify.com
|
20
|
+
response:
|
21
|
+
status:
|
22
|
+
code: 200
|
23
|
+
message: OK
|
24
|
+
headers:
|
25
|
+
Content-Type:
|
26
|
+
- application/json; charset=utf-8
|
27
|
+
Cache-Control:
|
28
|
+
- public, max-age=60
|
29
|
+
Etag:
|
30
|
+
- '"MC-IjA4NWQ2NDMxNjBiYjVmZjBiZmU1NTQxMGNmZjc3Y2Y3Ig=="'
|
31
|
+
X-Robots-Tag:
|
32
|
+
- noindex, nofollow
|
33
|
+
Access-Control-Allow-Origin:
|
34
|
+
- "*"
|
35
|
+
Access-Control-Allow-Headers:
|
36
|
+
- Accept, App-Platform, Authorization, Content-Type, Origin, Retry-After, Spotify-App-Version,
|
37
|
+
X-Cloud-Trace-Context, client-token, content-access-token
|
38
|
+
Access-Control-Allow-Methods:
|
39
|
+
- GET, POST, OPTIONS, PUT, DELETE, PATCH
|
40
|
+
Access-Control-Allow-Credentials:
|
41
|
+
- 'true'
|
42
|
+
Access-Control-Max-Age:
|
43
|
+
- '604800'
|
44
|
+
Content-Encoding:
|
45
|
+
- gzip
|
46
|
+
Strict-Transport-Security:
|
47
|
+
- max-age=31536000
|
48
|
+
X-Content-Type-Options:
|
49
|
+
- nosniff
|
50
|
+
Date:
|
51
|
+
- Wed, 20 Oct 2021 22:38:08 GMT
|
52
|
+
Server:
|
53
|
+
- envoy
|
54
|
+
Via:
|
55
|
+
- HTTP/2 edgeproxy, 1.1 google
|
56
|
+
Alt-Svc:
|
57
|
+
- clear
|
58
|
+
Transfer-Encoding:
|
59
|
+
- chunked
|
60
|
+
body:
|
61
|
+
encoding: ASCII-8BIT
|
62
|
+
string: !binary |-
|
63
|
+
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
|
64
|
+
http_version:
|
65
|
+
recorded_at: Wed, 20 Oct 2021 22:38:08 GMT
|
66
|
+
recorded_with: VCR 3.0.3
|