Class: Spotty::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/spotty/client.rb

Constant Summary collapse

SCOPES =
[
  "playlist-read-private",
  "playlist-read-collaborative",
  "playlist-modify-public",
  "playlist-modify-private",
  "streaming",
  "user-follow-modify",
  "user-follow-read",
  "user-library-read",
  "user-library-modify",
  "user-read-private",
  "user-read-birthdate",
  "user-read-email",
  "user-top-read"
]

Instance Method Summary collapse

Constructor Details

#initializeClient

Returns a new instance of Client.



25
26
27
# File 'lib/spotty/client.rb', line 25

def initialize
  refresh
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



112
113
114
115
116
117
118
119
# File 'lib/spotty/client.rb', line 112

def method_missing method, *args, &block
  if @http.respond_to? method
    refresh
    @http.send method, *args, &block
  else
    super method, @args, &block
  end
end

Instance Method Details

#configureObject



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/spotty/client.rb', line 29

def configure 
  require 'tty-prompt'
  prompt = TTY::Prompt.new

  prompt.puts "\nSpotty needs to be authorized as a Spotify Application to use Spotify's Web API. It only takes a minute to setup.\n\n"
  prompt.puts "First, create an new application at: \n\n"
  prompt.ok "    https://developer.spotify.com/my-applications\n"
  prompt.ask "Hit enter when you're ready to continue."

  config = {}
  config['id'] = prompt.ask "\nClient ID: " 
  config['secret'] = prompt.ask 'Client Secret: '

  port = rand((1025..9999))

  config['redirect'] = Addressable::URI.new(
    port: port,
    scheme: 'http',
    host: 'localhost',
  ).to_s

  url = Addressable::URI.new(
    scheme: 'https',
    path: '/authorize',
    host: 'accounts.spotify.com',
    query_values: {
      client_id: config['id'], 
      scope: SCOPES.join(' '),
      response_type: 'code',
      redirect_uri: config['redirect']
    }
  ).to_s

  prompt.puts "\nAdd the following URL to your application's list of callbacks:\n\n"
  prompt.ok "    #{config['redirect']}\n"
  prompt.ask "Remember to click 'Save' after adding the url. Hit enter when you're done."
  prompt.puts "Visit the following URL to finish authorizing Spotty:\n\n"
  prompt.ok "   #{url}\n"
  prompt.error "Waiting for authorization ..."

  server = WEBrick::HTTPServer.new :Port => port 

  server.mount_proc '/' do |req, res|
    if req.query['error']
      prompt.error req.query['error']
      res.body = req.query['error']
      server.shutdown
    elsif req.query['code']
      config['code'] = req.query['code']
      prompt.ok 'Authorization code received'
      res.body = 'Spotty has successfully authenticated! You can close this window'
      server.shutdown
    else
      res.body = 'Waiting for Spotify to send an authorization code ...'
    end
  end

  server.start

  unless config['code']
    raise 'Authorization failed: Spotify did not send an authorization code'
  end

  params = [config['id'],config['secret']]
  basic = Base64.strict_encode64(params.join(':'))
  client = HTTP.headers(Authorization: "Basic #{basic}")

  response = client.post('https://accounts.spotify.com/api/token', form: {
    grant_type: 'authorization_code',
    code: config['code'],
    redirect_uri: config['redirect']
  })

  if response.code != 200
    raise "Authorization failed: #{response.body}"
  end

  save response.parse.merge(
    'id': config['id'],
    'secret': config['secret']
  )
end