Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limit tracks per user, append "fallback" tracks, check x-forwarded-for header #28

Merged
merged 3 commits into from
Oct 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Configuration
[party]
enabled = true
votes_to_skip = 3
max_tracks = 0

Project resources
=================
Expand Down
56 changes: 51 additions & 5 deletions mopidy_party/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -24,22 +27,64 @@ 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...")
else:
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"]]):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's on purpose but just in case: if there is no song in the queue, and one user has already added max_songs, they cannot add any music anymore.

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})
]


Expand All @@ -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):
Expand Down
1 change: 1 addition & 0 deletions mopidy_party/ext.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[party]
enabled = true
votes_to_skip = 3
max_tracks = 0
36 changes: 10 additions & 26 deletions mopidy_party/static/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(){
Expand Down