Skip to content

Instantly share code, notes, and snippets.

@mattpolito
Last active March 16, 2021 13:35
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 mattpolito/6144796e61880029545f186adcbbe6c6 to your computer and use it in GitHub Desktop.
Save mattpolito/6144796e61880029545f186adcbbe6c6 to your computer and use it in GitHub Desktop.
Update Slack status with Spotify track
#!/bin/ruby
require "pathname"
module UpdateSlackStatusWithSpotifyTrack
module_function
DBFILE = Pathname.new("/tmp/current_track")
class Spotify
SpotifyData = Struct.new(
:player_position,
:player_state,
:track_artist,
:track_name,
:track_duration
)
attr_accessor :data
def initialize
hydrate_from_osascript
end
def hydrate_from_osascript
output = %x[
osascript \
-e 'tell application "Spotify" to set playerPosition to player position' \
-e 'tell application "Spotify" to set playerState to player state' \
-e 'tell application "Spotify" to set trackArtist to artist of current track' \
-e 'tell application "Spotify" to set trackName to name of current track' \
-e 'tell application "Spotify" to set trackDuration to duration of current track' \
-e 'set d to "|"' \
-e '{playerPosition, d, playerState, d, trackArtist, d, trackName, d, trackDuration}'
].chomp
self.data = SpotifyData.new(*output.split(", |, "))
end
def player_position
data.player_position.to_f
end
def playing?
data.player_state == "playing"
end
def track_title
return "" unless playing?
[data.track_artist, data.track_name].join(" - ")
end
def track_duration
data.track_duration.to_i / 1000
end
def track_duration_remaining
track_duration - player_position
end
end
require "net/http"
require "uri"
require "json"
module Slack
module_function
API_KEY = ARGV[0]
def update_status(text:, emoji:, expiration: 0)
payload = {
profile: {
status_emoji: emoji,
status_expiration: expiration,
status_text: text
}
}
uri = URI("https://slack.com/api/users.profile.set")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri)
request.add_field("Content-Type", "application/json; charset=utf-8")
request.add_field("Authorization", "Bearer #{API_KEY}")
request.body = JSON.dump(payload)
http.request(request)
end
end
def call
current = spotify.track_title
previous = read_track_title
return if current == previous
current == "" ? reset : update(current)
rescue SignalException
reset
end
def spotify
@spotify ||= Spotify.new
end
def reset
store_track_title ""
Slack.update_status(
emoji: "",
text: ""
)
end
def update(track_title)
store_track_title track_title
Slack.update_status(
emoji: ":headphones:",
expiration: (Time.new + spotify.track_duration_remaining + 60).to_i,
text: track_title
)
end
def store_track_title(song)
File.write(DBFILE, song)
end
def read_track_title
File.exist?(DBFILE) ? File.read(DBFILE) : ""
end
end
UpdateSlackStatusWithSpotifyTrack.call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment