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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +1 -1
  4. data/lib/rspotify/episode.rb +84 -0
  5. data/lib/rspotify/oauth.rb +5 -0
  6. data/lib/rspotify/playlist.rb +1 -1
  7. data/lib/rspotify/show.rb +100 -0
  8. data/lib/rspotify/version.rb +1 -1
  9. data/lib/rspotify.rb +2 -0
  10. data/rspotify.gemspec +1 -1
  11. data/spec/lib/rspotify/episode_spec.rb +118 -0
  12. data/spec/lib/rspotify/show_spec.rb +138 -0
  13. data/spec/vcr_cassettes/episode_find_512ojhOuo1ktJprKbVcKyQ.yml +66 -0
  14. data/spec/vcr_cassettes/episode_find_5NxzDE5TmviUV8te2eZjMP_market_ES.yml +66 -0
  15. data/spec/vcr_cassettes/episode_find_5NxzDE5TmviUV8te2eZjMP_market_KG.yml +66 -0
  16. data/spec/vcr_cassettes/episode_find_array_18RPZgmvEGKtEC2WMTHghd.yml +66 -0
  17. data/spec/vcr_cassettes/episode_find_array_512ojhOuo1ktJprKbVcKyQ.yml +66 -0
  18. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas.yml +64 -0
  19. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_limit_10.yml +64 -0
  20. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_limit_10_offset_10.yml +64 -0
  21. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_market_CA.yml +694 -0
  22. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_offset_10.yml +64 -0
  23. data/spec/vcr_cassettes/show_find_5CfCWKI5pZ28U0uOzXkDHe.yml +66 -0
  24. data/spec/vcr_cassettes/show_find_5CfCWKI5pZ28U0uOzXkDHe_episodes.yml +66 -0
  25. data/spec/vcr_cassettes/show_find_5CfCWKI5pZ28U0uOzXkDHe_episodes_market_ES.yml +66 -0
  26. data/spec/vcr_cassettes/show_find_many_5CfCWKI5pZ28U0uOzXkDHe.yml +64 -0
  27. data/spec/vcr_cassettes/show_find_many_5CfCWKI5pZ28U0uOzXkDHe_5as3aKmN2k11yfDDDSrvaZ.yml +64 -0
  28. data/spec/vcr_cassettes/show_find_many_5CfCWKI5pZ28U0uOzXkDHe_5as3aKmN2k11yfDDDSrvaZ_market_CA.yml +64 -0
  29. data/spec/vcr_cassettes/show_search_without_fail.yml +64 -0
  30. data/spec/vcr_cassettes/show_search_without_fail_limit_10.yml +64 -0
  31. data/spec/vcr_cassettes/show_search_without_fail_market_ES.yml +64 -0
  32. data/spec/vcr_cassettes/show_search_without_fail_offset_10.yml +64 -0
  33. data/spec/vcr_cassettes/show_search_without_fail_offset_10_limit_10.yml +64 -0
  34. metadata +52 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d19f6d23158c4ece9b8ede71d1b0ed2ed71598baad04895b62dc209f0147f556
4
- data.tar.gz: 0c3b328c9b8f3ff4d87041c0d749fef09689bf922b4f7f4c9f5aa958a2d27587
3
+ metadata.gz: 0d9d7a49993e755934d77091d568c04862f676c0b52ffe14ab80355cf38c17c1
4
+ data.tar.gz: 13d0709271280fb895df8f8941915a3090e426d020013552fb0af50656e21f3d
5
5
  SHA512:
6
- metadata.gz: 636252d2d8d95caf3f8b07187b97fcefe22f6e6a052400d48ab200c2db47451934e37e7c4b25aa08bfddf1c0c1daf6b61fc7b0f2af19e54f25edcc0836da8731
7
- data.tar.gz: fed825f00b36af6c3c9e2df6a6312b09219ea6d68b8136085b13ddcfa0764b747b1489a7afb1d73236a769f2fe1571617c49d709e199f7e58f1990a9bb4272e9
6
+ metadata.gz: def7d61e7f73af6ff9f03bdfbe562c21b462a6820778d76437a6c660bbeb3d3e4f23f11e6ab6c349abb8458da6ad769545e2edc0de3caf563c653ff069c14ee0
7
+ data.tar.gz: d79c15a25e18878e3a27cba75e0e41a7fab88ecd430e25ae9183c97a88a6d6ff46d9001326d848fe16ed77094a7e8e4a680dd1e0ace6b6271684b728131fc4c4
data/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
1
  .bundle
2
+ .idea
3
+ .rakeTasks
2
4
  .yardoc
3
5
  doc
4
6
  pkg
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/web-api/using-scopes).
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
@@ -18,6 +18,11 @@ module OmniAuth
18
18
  def raw_info
19
19
  @raw_info ||= access_token.get('me').parsed
20
20
  end
21
+
22
+ # Fix for: https://github.com/guilhermesad/rspotify/issues/189
23
+ def callback_url
24
+ full_host + script_name + callback_path
25
+ end
21
26
  end
22
27
  end
23
28
  end
@@ -315,7 +315,7 @@ module RSpotify
315
315
 
316
316
  params = {
317
317
  method: :delete,
318
- url: URI::encode(RSpotify::API_URI + @path + '/tracks'),
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
@@ -1,3 +1,3 @@
1
1
  module RSpotify
2
- VERSION = '2.10.1'.freeze
2
+ VERSION = '2.11.1'.freeze
3
3
  end
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.5.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
+ H4sIAAAAAAAAAOxY3XIaOxK+36dQce3gGRhgcG1tVcA2/gFMDHHOemuL0ow0IDN/NRLksKfyNskr5GrveLFtfTNwbMfO+vpUbrqwpvvrr1utVst//I2xGl8Llc3zQm6U/DxfF3GNnbDa0phcnxwf53UdirQeZsdJ3nxXaR232u0oDLtex/GjZjcIhQidrvRC6Xvcly0R+JHTEZ6oHVkPQuqwULlRWQrss5SlW2a2esWCbMUWBU/1ihcs2n0vhTacLXbf0oVM2ayQ4kGyQq2k0UwU2SKQRSZTIY9YVJASO9/9d1nIItVslfJixekTMyqO2ZJwmc5iwY0sWL77xnQupaizm3DJVruvqVDauou4MbwgX+9TkxGznpSbzDL5VrB0zVaFMmrF+IaRit5IIstWWRzLBa8zdqFMTOgb4r8nZlW1SlmsNvHuK0VGVHWWsAWtL7OUfiXkfCHIjFYs58woygCj9Oa84OaIZcQwiJX5Dzlf6H0MKbch5gUnH80WS1T8kKWEgrAMD2JpbKTr1EKrdMM1pZxIk5dzSvLKJpG5Xc+ps0smpN2GtVllCeHSRtDfp2Q3ywyPJbvlax0uj2jJMGOXOCvWWhK3hSx36ZC2cVYkPGU3y1i+sok2cTyJuWCBioXlc9gqw9STPa6z0TZcWadbUe0a+XmcZqqXjUEl0MeNJBhRhRyRCif0BblHGQRSx2tTfbWptPz17qsNgaqjzDP2OZFiuftGRUPc6LcKVbpU2mSWU5GyibSJnRqp0hVPcmwnUPXu+4rISJQzZ3/ulKYNMFQrakOM0o2tNl7VRi6LDZUUuae8UESKp8auh8WWkhaTf7Osn0qt14bc7MvQ7heKVtqNV2b3tagYWsc/qeOqfrExNpXlsZBE0UgcQHLyviB4KqUsisCZQChxlGytFozHsYG1WacLw5KM2CaSMoNza0nFcVaUyRR72orgkFHKW2LLgDjKmK+Mol+07Tx+kEUd5ZUQl8clVR2ulPWXFJxNfE8WC22K3fekPEn6gXzSIaPQKJM2jVUcpKQEDoo6xJTy+oSKpaAClILywyhzVOWBoj2abngqYyXqVada0+mjMzNPtO1UbstpdLotfJK/5zFVhbHrEY+1rFax2bHtmzD5g1ZpXed0pKPtk1aa5TKtVx+ooSbHMlc6E/K45Tayh+XNOnNX5iovroO78Hr7oUZIX+CEulv0BInn6gnQxt1j6dfASiCTxPO/cjf+e1Ac/wPiV1/+1Zd/9eW/Sl9WAq3qZ71NJXwh0YL/tW/CS6kWSzTstucclWvP51t1mG8BcCykx1uR67Z42I7aIfdCLr0o6HAeNToBD3nY4U7g81qF91kJs6xcoGH/6LzpvNV5FPgiDETghEHki6DB2+2u7Ibk23ODRjNweTdoCb/5g3Ny8YrztvdG30Hg8E6z3fKafqfr+zJqN9u86XKfh023ETlu2PEiWnohcOua/bvcBT3fX4nxdr7MqErE0xuTNPKYb21TtB9MsS7XY54u1kQEJPWm9mSx2le7XjlKqdKh+vRG+vPOqe4xXQIVMpZcy7ltAjBrOG7rneu8c9wfFexjKFR6f0EKvt3r6HVCXzPqII/u+mhtY7VBPYv1sYlWj+YK53C162X2+REU33AV29TME4qDAqrifn9aOyJ5BjmAHEKOIG8gbyFnkB8h763svYfsQQKhdw4JnN4F5CXkFeQYEpg9YPamkEDufYIEch/IfSD0gdAHqz5Y9YHQB0L/DhK2/X9CAuEUfE7h9/QaEransD2FzlkfEppn4HwGPufweA7bc1idw9cArAaId4C8DWA7AM8BNAeIcfABsrRCdAMwHIDhBfhcQPMCOhfQuUBuL4F8CeRLRH0JzUtwu4TmFXxdIZariZXX0L8Gk2vwv4bONWyv4X0I/kPwHyL2ITSH4DAE/hD4QzAZIrcjWI2gP4KXEXI1gq8RYhmB5wi+RmA1AuYIaCOgjUo0MBn9BolsjLAXY3gZA38M/DG4jYE8BuYYkY6BPIbVDWKcwHYC2wlsJ+A2ge0EcU3AZALvE/j9AKtbIN9C5xY8b6EzxdcpcjVF7FPgT4E/BbcpYp/CyxRMpsjAFAyn8DhF1FOwnWFnZ0CYgeEMtjNYzcBkBtsZbGewnYHPDAgfwfMj+H/Eyh243QHhDvw/Qec3cLtHFPfgdv+p6nDUDcIs3xa2kVdtYL/+fIK/U7g6hRXV6EE3L/1Vp4lD20FmwdZmQRNPIU/YWNEtPKDOqvet/MWnzeuPm7c+b2xvO276wdTzfn8I7u7um+Os2dueu+KqBqAvlZ+3vG8smH4NbY/z0vPm9eTgnfCmBFXjx8+9/ziAvDyCvOEu9r2AblunQ7NG25W+02r4XtP1Ahn5QVeKFu/Qnew12rUD4rMx5NEs8PIo8gYSXuB3I7/d5rzdaIWR04i6fuQ7QbftC95qBO1W1/OCqPECiXIceY3EfiR5A4cwdKVHaZBN2eJuuysazVZD+q4IXd72XRrGgiB0AvFiIkoKh1Pzf0eTn80b9M2+PvjcbPNygMC/Tfd7f5hG7qR9W6x4rukxSCVI7yOU3GFsytf0fNRLWUB9Ss8kevxoetU9QsOzbr5/0VvF1mGEPPjH5HCY7VS5Vp6ZE/vt5PWTV44eB6TKUTnjPIeqPp689j+KL/8DAAD//wMAB48e8EQWAAA=
64
+ http_version:
65
+ recorded_at: Wed, 20 Oct 2021 22:38:08 GMT
66
+ recorded_with: VCR 3.0.3