Created
July 14, 2018 01:29
-
-
Save kballenegger/55c1cd9c5606876fe193f596b7b3d7d9 to your computer and use it in GitHub Desktop.
A script to add the currently playing track to a predefined playlist
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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