diff --git a/README.rst b/README.rst index f9dc87d..b19bb76 100644 --- a/README.rst +++ b/README.rst @@ -39,6 +39,7 @@ Configuration [party] enabled = true votes_to_skip = 3 + max_tracks = 0 Project resources ================= diff --git a/mopidy_party/__init__.py b/mopidy_party/__init__.py index b68c745..cc55a94 100644 --- a/mopidy_party/__init__.py +++ b/mopidy_party/__init__.py @@ -7,13 +7,16 @@ __version__ = '1.0.0' -class PartyRequestHandler(tornado.web.RequestHandler): +class VoteRequestHandler(tornado.web.RequestHandler): def initialize(self, core, data, config): self.core = core self.data = data self.requiredVotes = config["party"]["votes_to_skip"] + def _getip(self): + return self.request.headers.get("X-Forwarded-For", self.request.remote_ip) + def get(self): currentTrack = self.core.playback.get_current_track().get() if (currentTrack == None): return @@ -24,10 +27,10 @@ def get(self): self.data["track"] = currentTrackURI self.data["votes"] = [] - if (self.request.remote_ip in self.data["votes"]): # User has already voted + if (self._getip() in self.data["votes"]): # User has already voted self.write("You have already voted to skip this song =)") else: # Valid vote - self.data["votes"].append(self.request.remote_ip) + self.data["votes"].append(self._getip()) if (len(self.data["votes"]) == self.requiredVotes): self.core.playback.next() self.write("Skipping...") @@ -35,11 +38,53 @@ def get(self): self.write("You have voted to skip this song. ("+str(self.requiredVotes-len(self.data["votes"]))+" more votes needed)") +class AddRequestHandler(tornado.web.RequestHandler): + + def initialize(self, core, data, config): + self.core = core + self.data = data + + def _getip(self): + return self.request.headers.get("X-Forwarded-For", self.request.remote_ip) + + def post(self): + # when the last n tracks were added by the same user, abort. + if self.data["queue"] and all([e == self._getip() for e in self.data["queue"]]): + self.write("You have requested too many songs") + self.set_status(403) + return + + track_uri = self.request.body.decode() + if not track_uri: + self.set_status(400) + return + + self.data["queue"].append(self._getip()) + self.data["queue"].pop(0) + + pos = 0 + if self.data["last"]: + queue = self.core.tracklist.index(self.data["last"]).get() or 0 + current = self.core.tracklist.index().get() or 0 + pos = max(queue, current) # after lastly enqueued and after current track + + try: + self.data["last"] = self.core.tracklist.add(uris=[track_uri], at_position=pos+1).get()[0] + except: + self.write("Unable to add track, please try again...") + self.set_status(400) + return + + self.core.tracklist.set_consume(True) + if self.core.playback.get_state().get() == "stopped": + self.core.playback.play() + def party_factory(config, core): - data = {'track':"", 'votes':[]} + data = {'track':"", 'votes':[], 'queue': [None] * config["party"]["max_tracks"], 'last':None} return [ - ('/vote', PartyRequestHandler, {'core': core, 'data':data, 'config':config}) + ('/vote', VoteRequestHandler, {'core': core, 'data':data, 'config':config}), + ('/add', AddRequestHandler, {'core': core, 'data':data, 'config':config}) ] @@ -56,6 +101,7 @@ def get_default_config(self): def get_config_schema(self): schema = super(Extension, self).get_config_schema() schema['votes_to_skip'] = config.Integer(minimum=0) + schema['max_tracks'] = config.Integer(minimum=0) return schema def setup(self, registry): diff --git a/mopidy_party/ext.conf b/mopidy_party/ext.conf index 675bff8..1fbb822 100644 --- a/mopidy_party/ext.conf +++ b/mopidy_party/ext.conf @@ -1,3 +1,4 @@ [party] enabled = true votes_to_skip = 3 +max_tracks = 0 diff --git a/mopidy_party/static/controller.js b/mopidy_party/static/controller.js index e73075a..614d289 100644 --- a/mopidy_party/static/controller.js +++ b/mopidy_party/static/controller.js @@ -182,33 +182,17 @@ angular.module('partyApp', []) track.disabled = true; - mopidy.tracklist - .index() - .then(function(index){ - return mopidy.tracklist.add({uris: [track.uri]}); - }) - .then(function(){ - // Notify user - $scope.message = ['success', 'Next track: ' + track.name]; - $scope.$apply(); - return mopidy.tracklist.setConsume([true]); - }) - .then(function(){ - return mopidy.playback.getState(); - }) - .then(function(state){ - // Get current state - if(state !== 'stopped') - return; - // If stopped, start music NOW! - return mopidy.playback.play(); - }) - .catch(function(){ + var xmlHttp = new XMLHttpRequest(); + xmlHttp.open( "POST", "/party/add", false ); // false for synchronous request + xmlHttp.send(track.uri); + var msgtype = 'success' + if (xmlHttp.status >= 400) { track.disabled = false; - $scope.message = ['error', 'Unable to add track, please try again...']; - $scope.$apply(); - }) - .done(); + $scope.message = ['error', xmlHttp.responseText]; + } else { + $scope.message = ['success', 'Next track: ' + track.name]; + } + $scope.$apply(); }; $scope.nextTrack = function(){