class PartyGoerClient
Connects to a partygoer instance, performs an initial poll, and then polls every 5 minutes. In between polls the client stays in sync using faye to recieve push updates
Attributes
played[R]
playing[R]
queued[R]
Public Class Methods
new(server)
click to toggle source
# File lib/partygoer-client.rb, line 21 def initialize(server) @server = server @played = [] @queued = [] @playing = nil @played_lock = Mutex.new @queued_lock = Mutex.new @playing_lock = Mutex.new @event_loop = nil @api = RestClient::Resource.new("#{@server}/api/queue", headers: { content_type: 'application/json', accept: 'application/json' }) @client = Faye::Client.new("#{@server}:9292/faye") logger.info { "Client initialized with server: #{server}" } @is_playing = false start end
Public Instance Methods
currently_queued()
click to toggle source
# File lib/partygoer-client.rb, line 105 def currently_queued queued end
logger()
click to toggle source
# File lib/partygoer-client.rb, line 113 def logger @@logger end
now_playing()
click to toggle source
Aliases
# File lib/partygoer-client.rb, line 101 def now_playing playing end
playing=(track)
click to toggle source
# File lib/partygoer-client.rb, line 42 def playing=(track) payload = { track: track } @api['/playing'].put(payload) logger.info { "Set now playing to #{track['name']}" } rescue logger.error { "Could not set now playing to #{track.inspect}:\n\t#{$!}\n\t#{$@.join("\n\t")}" } end
recently_played()
click to toggle source
# File lib/partygoer-client.rb, line 109 def recently_played played end
skip?()
click to toggle source
# File lib/partygoer-client.rb, line 65 def skip? if @playing['num_upvotes'] == 0 @playing['num_downvotes'] >= 2 else @playing['num_downvotes'] >= (2 * @playing['num_upvotes']) end rescue logger.error("Failed to check skip criteria:\n#{$!}\n#{$@.join("\n\t")}") end
start()
click to toggle source
# File lib/partygoer-client.rb, line 81 def start pull_update return if @event_loop logger.info { 'Starting event loop' } start_event_loop at_exit do stop end end
stop()
click to toggle source
# File lib/partygoer-client.rb, line 92 def stop return unless @event_loop logger.info { 'Stopping event loop' } EM.stop_event_loop @event_loop.kill @event_loop = nil end
suggest(track)
click to toggle source
# File lib/partygoer-client.rb, line 52 def suggest(track) case track when String payload = { track: { spotify_uri: track } } when Hash payload = { track: track } end EM.defer(proc { @api['/tracks'].post(payload) }) logger.info { "Suggested #{track.inspect}" } rescue logger.error("Failed to suggest track: #{track.inspect}\n#{$!}\n#{$@.join("\n\t")}") end
up_next()
click to toggle source
# File lib/partygoer-client.rb, line 75 def up_next @queued[1] rescue logger.error("Failed to check up next:\n#{$!}\n#{$@.join("\n\t")}") end
Private Instance Methods
on_created(track)
click to toggle source
# File lib/partygoer-client.rb, line 167 def on_created(track) proc { logger.debug { "Track created: #{track.inspect}" } begin @queued_lock.synchronize{ @queued << track } rescue logger.error { "Error in on_created:\n\t#{$!}\n\t#{$@.join("\n\t")}" } ensure sort! end } end
on_next(track)
click to toggle source
# File lib/partygoer-client.rb, line 182 def on_next(track) proc { logger.debug { "Next track called: #{track.inspect}" } begin @playing_lock.synchronize { @playing['playing'] = false @played_lock.synchronize { @played << @playing } @queued_lock.synchronize { @queued.delete_if { |item| item['id'] == @playing['id'] } index = @queued.find_index { |item| item['id'] == track['id'] } @queued[index] = track } @playing = track } rescue logger.error { "Error in on_next:\n\t#{$!}\n\t#{$@.join("\n\t")}" } ensure sort! end } end
on_voted(track)
click to toggle source
# File lib/partygoer-client.rb, line 149 def on_voted(track) proc { logger.debug { "Track voted on: #{track.inspect}" } begin @queued_lock.synchronize{ index = @queued.find_index { |item| item['id'] == track['id'] } @queued[index] = track } rescue logger.error { "Error in on_voted:\n\t#{$!}\n\t#{$@.join("\n\t")}" } ensure sort! end } end
pull_update()
click to toggle source
# File lib/partygoer-client.rb, line 208 def pull_update logger.info { "Polling for update" } begin body = JSON.parse(@api['/recently_played'].get.body) @played_lock.synchronize { @played = body } rescue logger.error { "Could not fetch recently played:\n\t#{$!}\n\t#{$@.join("\n\t")}" } end begin body = JSON.parse(@api['/tracks'].get.body) @queued_lock.synchronize { @queued = body } rescue logger.error { "Could not fetch queue:\n\t#{$!}\n\t#{$@.join("\n\t")}" } end begin body = JSON.parse(@api['/playing'].get.body) @playing_lock.synchronize { @playing = body } rescue logger.error { "Could not fetch now playing:\n\t#{$!}\n\t#{$@.join("\n\t")}" } end sort! end
sort!()
click to toggle source
# File lib/partygoer-client.rb, line 231 def sort! begin @played_lock.synchronize{ @played.sort_by! { |track| track['id'] } } logger.debug { 'Sorted recently played' } rescue logger.error { "Could not sort recently played:\n\t#{$!}\n\t#{$@.join("\n\t")}" } end begin @queued_lock.synchronize{ @queued.sort_by! { |track| i = track['playing'] ? 0 : 1 [i, -1 * track['score'], track['id']] } } logger.debug { 'Sorted queued' } rescue logger.error { "Could not sort the queue:\n\t#{$!}\n\t#{$@.join("\n\t")}" } end begin @playing_lock.synchronize{ @playing = @queued.select { |track| track['playing'] }.first } logger.debug { 'Updated now playing' } rescue logger.error { "Could not update now playing:\n\t#{$!}\n\t#{$@.join("\n\t")}" } end end
start_event_loop()
click to toggle source
# File lib/partygoer-client.rb, line 118 def start_event_loop @event_loop = Thread.new do begin EM.run do EM.add_periodic_timer(300) { EM.defer { pull_update } } @client.subscribe('/track/vote') do |message| EM.defer(on_voted(message)) end @client.subscribe('/track/create') do |message| EM.defer(on_created(message)) end @client.subscribe('/queue/next') do |message| EM.defer(on_next(message)) end end rescue logger.critical { "Could not start event loop:\n\t#{$!}\n\t#{$@.join("\n\t")}" } stop raise $! end end rescue logger.critical { "Could not start event loop:\n\t#{$!}\n\t#{$@.join("\n\t")}" } stop raise $! end