Skip to content

Instantly share code, notes, and snippets.

@kballenegger
Created July 14, 2018 01:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kballenegger/55c1cd9c5606876fe193f596b7b3d7d9 to your computer and use it in GitHub Desktop.
Save kballenegger/55c1cd9c5606876fe193f596b7b3d7d9 to your computer and use it in GitHub Desktop.
A script to add the currently playing track to a predefined playlist
#!/usr/bin/env ruby
require 'rubygems'
require 'rspotify'
require 'open3'
require 'uri'
require 'json'
# To use script
# 1/ Create an app at: https://developer.spotify.com/dashboard/applications
# 2/ Find your playlist ID (copy from the playlist Spotify URI's end)
PREF_PATH = File.expand_path('~/Library/Preferences/spotify_starrer_persistence.json')
REDIRECT_URL = 'https://example.com/callback'
# variable constants
def client_id
persistent('client_id') { as_prompt 'Enter your client_id' }
end
def client_secret
persistent('client_secret') { as_prompt 'Enter your client_secret' }
end
def playlist_id
persistent('playlist_id') { as_prompt 'Enter your playlist_id' }
end
# helpers
def persistent(k, force = false)
data = JSON.parse(File.read(PREF_PATH)) rescue {}
return data[k] if !force && data[k]
data[k] = yield
File.write(PREF_PATH, data.to_json)
data[k]
end
def osascript(script)
Open3.popen3('osascript', *script.split(/\n/).map { |line| ['-e', line] }.flatten) {|_, stdout, _, _|
return stdout.read.chomp
}
end
def pbpaste
Open3.popen3('pbpaste') {|_, stdout, _, _| return stdout.read.chomp }
end
def as_prompt(message)
out = osascript(%{tell app "System Events" to return text returned of (display dialog "#{message.gsub('"','\"')}" default answer "")})
raise if out.empty?
out
end
def as_message(message)
osascript(%{tell app "System Events" to display dialog "#{message.gsub('"','\"')}"})
end
# spotify
def oauth_flow
RSpotify.authenticate(client_id, client_secret)
scopes = 'user-read-private user-read-email playlist-modify-public playlist-modify-private'
system('open', "https://accounts.spotify.com/authorize/?client_id=#{client_id}&response_type=code&redirect_uri=#{CGI.escape(REDIRECT_URL)}&scope=#{CGI.escape(scopes)}")
sleep(1)
as_message("Copy the code from the URL to the clipboard")
code = pbpaste
request_data = {grant_type: 'authorization_code', code: code, redirect_uri: REDIRECT_URL}
auth = JSON.parse(RestClient.post(RSpotify::TOKEN_URI, request_data, RSpotify.send(:auth_header)))
user = JSON.parse(RestClient.get('https://api.spotify.com/v1/me', {
'Authorization' => "Bearer #{auth['access_token']}",
}))
auth['token'] = auth['access_token']
{'auth' => auth, 'user' => user}
end
def authenticated_user!(auth)
RSpotify.authenticate(client_id, client_secret)
user_args = auth['user'].merge('credentials' => auth['auth'])
RSpotify::User.new(user_args).tap do |u|
#u.class.send(:refresh_token, u.id)
end
end
def current_track_id
track_id = osascript(<<-END)
tell application "Spotify" to return the id of the current track
END
track_id.split(':').last
end
def add_to_starred_playlist(user, track_id)
RSpotify.authenticate(client_id, client_secret)
pl = RSpotify::Playlist.find(user.id, playlist_id)
t = RSpotify::Track.find(track_id)
pl.add_tracks!([t])
end
# code
if __FILE__ == $0
client_id
client_secret
playlist_id
auth = persistent('auth') { oauth_flow }
u = authenticated_user!(auth)
add_to_starred_playlist(u, current_track_id)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment