simplespotify 0.0.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 +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.md +17 -0
- data/Rakefile +3 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/simplespotify/actions/albums.rb +30 -0
- data/lib/simplespotify/actions/artists.rb +47 -0
- data/lib/simplespotify/actions/browse.rb +74 -0
- data/lib/simplespotify/actions/playlists.rb +187 -0
- data/lib/simplespotify/actions/tracks.rb +67 -0
- data/lib/simplespotify/actions/users.rb +68 -0
- data/lib/simplespotify/authorization.rb +91 -0
- data/lib/simplespotify/client.rb +76 -0
- data/lib/simplespotify/constants.rb +14 -0
- data/lib/simplespotify/errors.rb +56 -0
- data/lib/simplespotify/models/album.rb +27 -0
- data/lib/simplespotify/models/artist.rb +42 -0
- data/lib/simplespotify/models/category.rb +19 -0
- data/lib/simplespotify/models/collection.rb +52 -0
- data/lib/simplespotify/models/image.rb +16 -0
- data/lib/simplespotify/models/playlist.rb +94 -0
- data/lib/simplespotify/models/track.rb +31 -0
- data/lib/simplespotify/models/user.rb +91 -0
- data/lib/simplespotify/request.rb +54 -0
- data/lib/simplespotify/resource/class_methods.rb +48 -0
- data/lib/simplespotify/resource/instance_methods.rb +102 -0
- data/lib/simplespotify/resource/resource.rb +14 -0
- data/lib/simplespotify/response.rb +22 -0
- data/lib/simplespotify/version.rb +3 -0
- data/lib/simplespotify.rb +72 -0
- data/readme.md +71 -0
- data/simplespotify.gemspec +26 -0
- metadata +122 -0
@@ -0,0 +1,102 @@
|
|
1
|
+
module Resource
|
2
|
+
|
3
|
+
module InstanceMethods
|
4
|
+
|
5
|
+
attr_accessor :id, :uri, :href, :external_urls
|
6
|
+
|
7
|
+
def initialize data, fetched: false
|
8
|
+
@__props = []
|
9
|
+
|
10
|
+
|
11
|
+
@fetched = fetched
|
12
|
+
# puts "-NEW #{self.class.to_s} #{self.class._template.keys.join(',')}"
|
13
|
+
[:id, :uri, :href, :external_urls].each do |k|
|
14
|
+
|
15
|
+
if data[k]
|
16
|
+
@__props << k
|
17
|
+
instance_variable_set("@#{k}", data[k])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
self.class._template.each do |k, v|
|
22
|
+
# puts "--EVAL #{self.class}"
|
23
|
+
if v.is_a? Symbol
|
24
|
+
_set(k, data[v])
|
25
|
+
else
|
26
|
+
key = v[:from]
|
27
|
+
klass = SimpleSpotify::Model.const_get(v[:kind]) if v[:kind]
|
28
|
+
|
29
|
+
data[key] = v[:default] if v[:default]
|
30
|
+
unless data[key]
|
31
|
+
next
|
32
|
+
end
|
33
|
+
|
34
|
+
case v[:type]
|
35
|
+
when :real
|
36
|
+
_set(k, (data[v] || v[:default]))
|
37
|
+
when :virtual
|
38
|
+
data[key].each(&method(:_set))
|
39
|
+
when :resource_collection
|
40
|
+
values = data[key]
|
41
|
+
values = SimpleSpotify::Model::Collection.of(klass, values) if v[:paginated]
|
42
|
+
_set(key, values)
|
43
|
+
when :resource
|
44
|
+
_set key, klass.new(data[key])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def fetch! client
|
53
|
+
response = client.get(@href)
|
54
|
+
self.class.new(response.body, true)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def link kind=:api
|
59
|
+
case kind
|
60
|
+
when :uri then @uri
|
61
|
+
when :api then @href
|
62
|
+
when :web then @external_urls && @external_urls[:spotify]
|
63
|
+
when :preview then @preview_url
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def to_h
|
69
|
+
tpls = self.class._template
|
70
|
+
|
71
|
+
@__props.map {|v|
|
72
|
+
value = send(v)
|
73
|
+
tpl = tpls[v]
|
74
|
+
|
75
|
+
if tpl.is_a?(Hash) && tpl[:type] != :virtual
|
76
|
+
value = case tpl[:type]
|
77
|
+
when :resource_collection then value.map(&:to_h)
|
78
|
+
when :resource then value.to_h
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
[v, value]
|
83
|
+
}.to_h
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def _set key, value
|
90
|
+
@__props << key
|
91
|
+
_define(key) unless respond_to? key.to_sym
|
92
|
+
send("#{key}=".to_sym, value)
|
93
|
+
end
|
94
|
+
|
95
|
+
def _define key
|
96
|
+
key = key.to_sym
|
97
|
+
self.class.__send__(:attr_accessor, key)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Resource
|
2
|
+
|
3
|
+
autoload :ClassMethods, 'simplespotify/resource/class_methods'
|
4
|
+
autoload :InstanceMethods, 'simplespotify/resource/instance_methods'
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
base.instance_variable_set("@_template", {})
|
9
|
+
|
10
|
+
# base.extend(ClassMethods.dup);
|
11
|
+
base.send :include, InstanceMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module SimpleSpotify
|
2
|
+
class Response
|
3
|
+
|
4
|
+
attr_reader :body, :code, :request
|
5
|
+
|
6
|
+
def initialize code, body, request
|
7
|
+
@code = code
|
8
|
+
@request = request
|
9
|
+
if (200..299).include? code
|
10
|
+
begin
|
11
|
+
@body = JSON.parse(body, symbolize_names: true)
|
12
|
+
rescue
|
13
|
+
raise SimpleSpotify::Error::BadResponse.new(code, body, request)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
body = JSON.parse(body, symbolize_names: true) rescue nil
|
17
|
+
raise SimpleSpotify::Error.for(code).new(code, body, request)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "simplespotify/version"
|
2
|
+
require "simplespotify/constants"
|
3
|
+
require 'httparty'
|
4
|
+
|
5
|
+
module SimpleSpotify
|
6
|
+
autoload :Authorization, 'simplespotify/authorization'
|
7
|
+
autoload :Client, 'simplespotify/client'
|
8
|
+
autoload :Request, 'simplespotify/request'
|
9
|
+
autoload :Response, 'simplespotify/response'
|
10
|
+
autoload :Error, 'simplespotify/errors'
|
11
|
+
autoload :Resource, 'simplespotify/resource/resource'
|
12
|
+
|
13
|
+
module Model
|
14
|
+
[:Album, :Artist, :Image, :Track, :Collection, :Playlist, :Category, :User].each do |model|
|
15
|
+
autoload model, "simplespotify/models/#{model}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def self.default_client= client
|
21
|
+
@@client = client
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.default_client
|
25
|
+
@@client
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def self.log msg
|
30
|
+
return true unless ENV['DEBUG']
|
31
|
+
if msg.is_a? String
|
32
|
+
$stdout.puts msg
|
33
|
+
else
|
34
|
+
$stdout.puts pp msg
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def self.dispatch request, session: nil
|
40
|
+
headers = request.headers
|
41
|
+
headers = headers.merge(session.headers) if session && request.private?
|
42
|
+
|
43
|
+
options = {headers: headers}.merge(request.options)
|
44
|
+
|
45
|
+
request.tries += 1;
|
46
|
+
|
47
|
+
log "#{request.method.to_s.upcase} <#{request.full_url}>"
|
48
|
+
log request.options
|
49
|
+
|
50
|
+
http = HTTParty.send(
|
51
|
+
request.method,
|
52
|
+
request.full_url,
|
53
|
+
options
|
54
|
+
)
|
55
|
+
|
56
|
+
log "HTTP #{http.code}"
|
57
|
+
log http.body
|
58
|
+
log "---"
|
59
|
+
|
60
|
+
if session && http.code == 401 && http.body =~ /The access token expired/
|
61
|
+
if request.tries < SimpleSpotify::MAX_RETRIES
|
62
|
+
session.refresh!
|
63
|
+
return self.dispatch(request, session: session)
|
64
|
+
else
|
65
|
+
raise SimpleSpotify::Error::AuthorizationError(JSON.parse(http.body, symbolize_names: true))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
return Response.new(http.code, http.body, request)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# SimpleSpotify
|
2
|
+
|
3
|
+
A lousy and very badly programmed Spotify API Client written in Ruby.
|
4
|
+
|
5
|
+
If you'd rather have a **proper, working, supported library** I do recommend [RSpotify](https://rubygems.org/gems/rspotify).
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Seriously, don't just run `gem install simplespotify`, it'll ruin your day.
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
You've suffered enough [registering an app with Spotify](https://developer.spotify.com/my-applications/#!/applications/create) and setting up your redirection URIs, why would you want to...?
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
client = SimpleSpotify::Client.new(client_id, client_secret)
|
17
|
+
redirect_uri = 'http://your-redirect-uri'
|
18
|
+
|
19
|
+
if ARGV[0] == 'login'
|
20
|
+
login_url = SimpleSpotify::Authorization.login_uri redirect_uri, client, scope: 'playlist-modify-public user-read-private'
|
21
|
+
puts login_url
|
22
|
+
elsif ARGV[0] == 'code'
|
23
|
+
# Copy the `code` param from your browser...
|
24
|
+
code = ARGV[1].strip
|
25
|
+
auth = SimpleSpotify::Authorization.from_code code, client: client, redirect: redirect_uri
|
26
|
+
|
27
|
+
puts auth.to_h
|
28
|
+
else
|
29
|
+
# now do the same for the `access_token` and `refresh_token`
|
30
|
+
token = ARGV[0]
|
31
|
+
refresh_token = ARGV[1]
|
32
|
+
client.session = SimpleSpotify::Authorization.new access_token: token, refresh_token: refresh_token, client: client
|
33
|
+
|
34
|
+
me = client.me
|
35
|
+
puts me.to_h
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
### Oh, joy...
|
40
|
+
|
41
|
+
#### API
|
42
|
+
|
43
|
+
It's all syntactic sugar, but not the right kind that makes you happy and stuff, but the distasteful one that comes with coffee in an airplane. Seriously, it's not even properly tested!
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
playlist = client.playlist(some_user_id, some_playlist_id)
|
47
|
+
if playlist.tracks.total >= 10
|
48
|
+
extra = (playlist.tracks.total - 10)
|
49
|
+
playlist.remove_tracks positions: (0..extra).to_a
|
50
|
+
end
|
51
|
+
|
52
|
+
playlist.add_tracks('spotify:track:1SWhZ2rIxTPv9UcexFnPSU')
|
53
|
+
# or
|
54
|
+
client.playlist_tracks_add(playlist, tracks: '1SWhZ2rIxTPv9UcexFnPSU'})
|
55
|
+
# or even
|
56
|
+
client.post "/user/#{_user_}/playlists/#{_playlist_id_}/tracks", {uris: ['spotify:track:1SWhZ2rIxTPv9UcexFnPSU']}
|
57
|
+
```
|
58
|
+
|
59
|
+
#### Dealing with refreshing tokens
|
60
|
+
```ruby
|
61
|
+
client.session.on_refresh do |sess|
|
62
|
+
# Then token was refreshed on the last call
|
63
|
+
cache[:spotify_session] = sess.to_h
|
64
|
+
end
|
65
|
+
|
66
|
+
# And maybe later...
|
67
|
+
credentials = cache[:spotify_session]
|
68
|
+
credentials[:client] = client
|
69
|
+
client.session = SimpleSpotify::Authorization.new(credentials)
|
70
|
+
|
71
|
+
```
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'simplespotify/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "simplespotify"
|
8
|
+
spec.version = SimpleSpotify::VERSION
|
9
|
+
spec.authors = ["Roberto Hidalgo"]
|
10
|
+
spec.email = ["un@rob.mx"]
|
11
|
+
|
12
|
+
spec.summary = "Yet another Spotify client"
|
13
|
+
spec.description = "Spotify API wrapper"
|
14
|
+
spec.homepage = "https://github.com/unRob/simplespotify"
|
15
|
+
spec.licenses = %w{WTFPL GPLv2}
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.8"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
|
25
|
+
spec.add_runtime_dependency 'httparty'
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simplespotify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roberto Hidalgo
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: httparty
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Spotify API wrapper
|
56
|
+
email:
|
57
|
+
- un@rob.mx
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- ".travis.yml"
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE.md
|
67
|
+
- Rakefile
|
68
|
+
- bin/console
|
69
|
+
- bin/setup
|
70
|
+
- lib/simplespotify.rb
|
71
|
+
- lib/simplespotify/actions/albums.rb
|
72
|
+
- lib/simplespotify/actions/artists.rb
|
73
|
+
- lib/simplespotify/actions/browse.rb
|
74
|
+
- lib/simplespotify/actions/playlists.rb
|
75
|
+
- lib/simplespotify/actions/tracks.rb
|
76
|
+
- lib/simplespotify/actions/users.rb
|
77
|
+
- lib/simplespotify/authorization.rb
|
78
|
+
- lib/simplespotify/client.rb
|
79
|
+
- lib/simplespotify/constants.rb
|
80
|
+
- lib/simplespotify/errors.rb
|
81
|
+
- lib/simplespotify/models/album.rb
|
82
|
+
- lib/simplespotify/models/artist.rb
|
83
|
+
- lib/simplespotify/models/category.rb
|
84
|
+
- lib/simplespotify/models/collection.rb
|
85
|
+
- lib/simplespotify/models/image.rb
|
86
|
+
- lib/simplespotify/models/playlist.rb
|
87
|
+
- lib/simplespotify/models/track.rb
|
88
|
+
- lib/simplespotify/models/user.rb
|
89
|
+
- lib/simplespotify/request.rb
|
90
|
+
- lib/simplespotify/resource/class_methods.rb
|
91
|
+
- lib/simplespotify/resource/instance_methods.rb
|
92
|
+
- lib/simplespotify/resource/resource.rb
|
93
|
+
- lib/simplespotify/response.rb
|
94
|
+
- lib/simplespotify/version.rb
|
95
|
+
- readme.md
|
96
|
+
- simplespotify.gemspec
|
97
|
+
homepage: https://github.com/unRob/simplespotify
|
98
|
+
licenses:
|
99
|
+
- WTFPL
|
100
|
+
- GPLv2
|
101
|
+
metadata: {}
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 2.4.6
|
119
|
+
signing_key:
|
120
|
+
specification_version: 4
|
121
|
+
summary: Yet another Spotify client
|
122
|
+
test_files: []
|