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
@@ -1,76 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spotify
|
4
|
-
class SDK
|
5
|
-
##
|
6
|
-
# Spotify::SDK::Initialization deals with parsing input for the
|
7
|
-
# following code block `Spotify::SDK.new(input)` and extracting
|
8
|
-
# the access token, expiry and refresh token.
|
9
|
-
#
|
10
|
-
# You'll never have to interact with this, unless you have other
|
11
|
-
# objects you want us to parse the aforementioned variables from.
|
12
|
-
#
|
13
|
-
class Initialization
|
14
|
-
##
|
15
|
-
# This is where you mount new Initialization objects.
|
16
|
-
# Don't worry, we prefix Spotify::SDK::Initialization for you.
|
17
|
-
#
|
18
|
-
# @see /lib/spotify/sdk/initialization/url_string.rb
|
19
|
-
#
|
20
|
-
CLASSES = %i[
|
21
|
-
OAuthAccessToken
|
22
|
-
QueryString
|
23
|
-
URLString
|
24
|
-
PlainString
|
25
|
-
QueryHash
|
26
|
-
].freeze
|
27
|
-
|
28
|
-
class << self
|
29
|
-
##
|
30
|
-
# Initiate a new Spotify SDK Initialization object
|
31
|
-
#
|
32
|
-
# @example
|
33
|
-
# begin
|
34
|
-
# hash = Spotify::SDK::Initialization.detect("access_token")
|
35
|
-
# puts "Access Token: #{hash[:access_token]}"
|
36
|
-
# puts "Expires in: #{hash[:expires_in]}"
|
37
|
-
# puts "Refresh Token: #{hash[:refresh_token]}"
|
38
|
-
# rescue Spotify::Errors::InitializationObjectInvalidError => e
|
39
|
-
# puts "Can't recognise the input because: #{e.inspect}"
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# @param [String,Hash,OAuth2::AccessToken] subject An instance of Spotify::SDK as a reference point.
|
43
|
-
#
|
44
|
-
def detect(subject)
|
45
|
-
klasses = CLASSES.map do |klass_name|
|
46
|
-
("Spotify::SDK::Initialization::%s" % klass_name).constantize.new(subject)
|
47
|
-
end
|
48
|
-
|
49
|
-
matches = klasses.select(&:should_perform?)
|
50
|
-
|
51
|
-
case matches.size
|
52
|
-
when 1
|
53
|
-
matches.first.perform
|
54
|
-
when 0
|
55
|
-
raise Spotify::Errors::InitializationObjectInvalidError.new
|
56
|
-
else
|
57
|
-
raise Spotify::Errors::InitializationObjectDuplicationError.new
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
class Errors
|
65
|
-
##
|
66
|
-
# A Error class for when the initialization subject is not valid (see `initialize(subject)` for more info).
|
67
|
-
#
|
68
|
-
class InitializationObjectInvalidError < StandardError; end
|
69
|
-
|
70
|
-
##
|
71
|
-
# A Error class for when the initialization subject matches against multiple selectors.
|
72
|
-
# When this Error occurs, this becomes an internal bug. It should be filed on the GitHub issue tracker.
|
73
|
-
#
|
74
|
-
class InitializationObjectDuplicationError < StandardError; end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spotify
|
4
|
-
class SDK
|
5
|
-
class Initialization
|
6
|
-
##
|
7
|
-
# For each SDK Initialization type, we have a base class to inherit from.
|
8
|
-
#
|
9
|
-
class Base
|
10
|
-
##
|
11
|
-
# Initiate a Spotify SDK Initialization Base class.
|
12
|
-
# Note: You would not ever initiate this class, but rather inherit from it.
|
13
|
-
# See /lib/spotify/sdk/initialization/query_string.rb as an example.
|
14
|
-
#
|
15
|
-
# @example
|
16
|
-
# Spotify::SDK::Initialization::Base.new("access_token")
|
17
|
-
#
|
18
|
-
# @param [Object] subject Any object that can be used to identify an access token.
|
19
|
-
#
|
20
|
-
def initialize(subject)
|
21
|
-
@subject = subject
|
22
|
-
end
|
23
|
-
|
24
|
-
##
|
25
|
-
# Determine whether this initialization type is valid, and should be performed.
|
26
|
-
#
|
27
|
-
# @example
|
28
|
-
# instance = Spotify::SDK::Initialization::Base.new("access_token")
|
29
|
-
# instance.should_perform?
|
30
|
-
#
|
31
|
-
# @return [Boolean] A true or false answer as to whether to perform this initialization type.
|
32
|
-
#
|
33
|
-
def should_perform?
|
34
|
-
false
|
35
|
-
end
|
36
|
-
|
37
|
-
##
|
38
|
-
# Perform the class to extract the authentication details needed for the SDK class to run.
|
39
|
-
#
|
40
|
-
# @example
|
41
|
-
# instance = Spotify::SDK::Initialization::Base.new("access_token")
|
42
|
-
# instance.perform if instance.should_perform?
|
43
|
-
#
|
44
|
-
# @return [Hash] A hash containing only access_token, expires_in and refresh_token.
|
45
|
-
#
|
46
|
-
def perform
|
47
|
-
{
|
48
|
-
access_token: nil,
|
49
|
-
expires_in: nil,
|
50
|
-
refresh_token: nil
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
|
-
##
|
55
|
-
# The subject of the class. Usually what has been sent to Spotify::SDK.new() is the subject.
|
56
|
-
#
|
57
|
-
attr_reader :subject
|
58
|
-
|
59
|
-
# TODO: Delete this when tests are written.
|
60
|
-
# def sample_inputs
|
61
|
-
# nil
|
62
|
-
# end
|
63
|
-
|
64
|
-
# SAMPLE_TOKEN = """
|
65
|
-
# AQBjjlIYyEuyK2HuzqfA2ldj0B88d63KX2pgdOC0N4Pg4Iuw232M7gEgXjQS0Zdt3Y1r2J3G
|
66
|
-
# rCOf4fs1JndDbyGY_uaPWj5hpYE_dMS0G5ouJKLaapDT50EysfV3XdW6aQlbw51dYjgZU-Ce
|
67
|
-
# NCnj7bPsq4nXhZzbUkr0aTuR8MKEOXuW7-xaz1h8et-ZFYQDa788LTS08pLu--1waspBsmqh
|
68
|
-
# SxbOl0xG5QBQ0NnTbCn1SWi-T1B7J_6twmv7GWXsR9RqeBg_U5KcT6ciz85YFrkRQ6n47PpP
|
69
|
-
# HBfTFjmJxB91plroOOIZAE3fQ37-RDqdK7YzSw6gAm0
|
70
|
-
# """.strip
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spotify
|
4
|
-
class SDK
|
5
|
-
class Initialization
|
6
|
-
##
|
7
|
-
# This class implements accepting OAuth2::AccessToken as an initializer.
|
8
|
-
#
|
9
|
-
class OAuthAccessToken < Base
|
10
|
-
##
|
11
|
-
# This implements the #should_perform? method from the Base class.
|
12
|
-
#
|
13
|
-
# @see /lib/spotify/sdk/authorization/base.rb
|
14
|
-
#
|
15
|
-
def should_perform?
|
16
|
-
subject.instance_of? OAuth2::AccessToken
|
17
|
-
end
|
18
|
-
|
19
|
-
##
|
20
|
-
# This implements the #perform method from the Base class.
|
21
|
-
#
|
22
|
-
# @see /lib/spotify/sdk/authorization/base.rb
|
23
|
-
#
|
24
|
-
def perform
|
25
|
-
{
|
26
|
-
access_token: subject.token,
|
27
|
-
expires_in: subject.expires_in,
|
28
|
-
refresh_token: subject.refresh_token
|
29
|
-
}
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spotify
|
4
|
-
class SDK
|
5
|
-
class Initialization
|
6
|
-
class PlainString < Base
|
7
|
-
def should_perform?
|
8
|
-
subject.is_a?(String) && subject =~ /^[a-zA-Z0-9_-]+$/
|
9
|
-
end
|
10
|
-
|
11
|
-
def perform
|
12
|
-
{
|
13
|
-
access_token: subject,
|
14
|
-
expires_in: nil,
|
15
|
-
refresh_token: nil
|
16
|
-
}
|
17
|
-
end
|
18
|
-
|
19
|
-
# TODO: Delete this when tests are written.
|
20
|
-
# def sample_inputs
|
21
|
-
# [ SAMPLE_TOKEN ]
|
22
|
-
# end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spotify
|
4
|
-
class SDK
|
5
|
-
class Initialization
|
6
|
-
class QueryHash < Base
|
7
|
-
def subject_hash
|
8
|
-
subject.try(:with_indifferent_access) || {}
|
9
|
-
end
|
10
|
-
|
11
|
-
def should_perform?
|
12
|
-
subject_hash.has_key?(:token) || subject_hash.has_key?(:access_token)
|
13
|
-
end
|
14
|
-
|
15
|
-
def perform
|
16
|
-
subject_hash[:access_token] = subject_hash[:token] if subject_hash.has_key?(:token)
|
17
|
-
subject_hash.slice(:access_token, :expires_in, :refresh_token).symbolize_keys
|
18
|
-
end
|
19
|
-
|
20
|
-
# TODO: Delete this when tests are written.
|
21
|
-
# def sample_inputs
|
22
|
-
# [{
|
23
|
-
# token: SAMPLE_TOKEN
|
24
|
-
# }, {
|
25
|
-
# token: SAMPLE_TOKEN,
|
26
|
-
# expires_in: 1234567890
|
27
|
-
# }, {
|
28
|
-
# token: SAMPLE_TOKEN,
|
29
|
-
# expires_in: 1234567890,
|
30
|
-
# refresh_token: SAMPLE_TOKEN
|
31
|
-
# }, {
|
32
|
-
# access_token: SAMPLE_TOKEN
|
33
|
-
# }, {
|
34
|
-
# access_token: SAMPLE_TOKEN,
|
35
|
-
# expires_in: 1234567890
|
36
|
-
# }, {
|
37
|
-
# access_token: SAMPLE_TOKEN,
|
38
|
-
# expires_in: 1234567890,
|
39
|
-
# refresh_token: SAMPLE_TOKEN
|
40
|
-
# }]
|
41
|
-
# end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spotify
|
4
|
-
class SDK
|
5
|
-
class Initialization
|
6
|
-
class QueryString < Base
|
7
|
-
def params
|
8
|
-
CGI.parse(subject).with_indifferent_access
|
9
|
-
rescue NoMethodError
|
10
|
-
{}
|
11
|
-
end
|
12
|
-
|
13
|
-
def should_perform?
|
14
|
-
subject.is_a?(String) && (
|
15
|
-
params.has_key?(:token) && params.has_key?(:access_token)
|
16
|
-
)
|
17
|
-
end
|
18
|
-
|
19
|
-
def perform
|
20
|
-
{
|
21
|
-
access_token: params[access_token_key].to_a[0],
|
22
|
-
expires_in: params[:expires_in].to_a[0],
|
23
|
-
refresh_token: params[:refresh_token].to_a[0]
|
24
|
-
}
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def access_token_key
|
30
|
-
if params.has_key?(:token)
|
31
|
-
:token
|
32
|
-
elsif params.has_key?(:access_token)
|
33
|
-
:access_token
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# TODO: Delete this when tests are written.
|
38
|
-
# def sample_inputs
|
39
|
-
# [
|
40
|
-
# "token=#{SAMPLE_TOKEN}",
|
41
|
-
# "token=#{SAMPLE_TOKEN}&expires_in=1234567890",
|
42
|
-
# "token=#{SAMPLE_TOKEN}&expires_in=1234567890&refresh_token=#{SAMPLE_TOKEN}",
|
43
|
-
# "access_token=#{SAMPLE_TOKEN}",
|
44
|
-
# "access_token=#{SAMPLE_TOKEN}&expires_in=1234567890",
|
45
|
-
# "access_token=#{SAMPLE_TOKEN}&expires_in=1234567890&refresh_token=#{SAMPLE_TOKEN}"
|
46
|
-
# ]
|
47
|
-
# end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spotify
|
4
|
-
class SDK
|
5
|
-
class Initialization
|
6
|
-
class URLString < Base
|
7
|
-
def query_fragment_string
|
8
|
-
@query_fragment_string ||= begin
|
9
|
-
@uri = begin
|
10
|
-
URI.parse(subject)
|
11
|
-
rescue URI::InvalidURIError
|
12
|
-
URI.parse("")
|
13
|
-
end
|
14
|
-
[@uri.query, @uri.fragment].compact.join("&")
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def should_perform?
|
19
|
-
subject.is_a?(String) && query_fragment_string.present?
|
20
|
-
end
|
21
|
-
|
22
|
-
def perform
|
23
|
-
QueryString.new(query_fragment_string).perform
|
24
|
-
end
|
25
|
-
|
26
|
-
# TODO: Delete this when tests are written.
|
27
|
-
# rubocop:disable Metrics/LineLength
|
28
|
-
# def sample_inputs
|
29
|
-
# [
|
30
|
-
# "http://dev.localhost.com:443/?token=#{SAMPLE_TOKEN}",
|
31
|
-
# "http://dev.localhost.com:443/?token=#{SAMPLE_TOKEN}&expires_in=1234567890",
|
32
|
-
# "http://dev.localhost.com:443/?token=#{SAMPLE_TOKEN}&expires_in=1234567890&refresh_token=#{SAMPLE_TOKEN}",
|
33
|
-
# "http://dev.localhost.com:443/#token=#{SAMPLE_TOKEN}",
|
34
|
-
# "http://dev.localhost.com:443/#token=#{SAMPLE_TOKEN}&expires_in=1234567890",
|
35
|
-
# "http://dev.localhost.com:443/#token=#{SAMPLE_TOKEN}&expires_in=1234567890&refresh_token=#{SAMPLE_TOKEN}",
|
36
|
-
# "http://dev.localhost.com:443/?access_token=#{SAMPLE_TOKEN}",
|
37
|
-
# "http://dev.localhost.com:443/?access_token=#{SAMPLE_TOKEN}&expires_in=1234567890",
|
38
|
-
# "http://dev.localhost.com:443/?access_token=#{SAMPLE_TOKEN}&expires_in=1234567890&refresh_token=#{SAMPLE_TOKEN}",
|
39
|
-
# "http://dev.localhost.com:443/#access_token=#{SAMPLE_TOKEN}",
|
40
|
-
# "http://dev.localhost.com:443/#access_token=#{SAMPLE_TOKEN}&expires_in=1234567890",
|
41
|
-
# "http://dev.localhost.com:443/#access_token=#{SAMPLE_TOKEN}&expires_in=1234567890&refresh_token=#{SAMPLE_TOKEN}",
|
42
|
-
# "http://dev.localhost.com:443/?access_token=#{SAMPLE_TOKEN}&expires_in=1234567890#refresh_token=#{SAMPLE_TOKEN}"
|
43
|
-
# ]
|
44
|
-
# end
|
45
|
-
# rubocop:enable Metrics/LineLength
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|