Support playback of local files
- Recursive listing of available files - Protected against path traversal attacks - Does not follow symlinks - Possibility to ignore directories or files with specific names - If no exact match for the requested track can be found, the bot plays the track with the best match - If multiple tracks match the user gets a message listing all candidates
This commit is contained in:
parent
4ae9c1cdb7
commit
7910f23d0d
@ -4,6 +4,8 @@ volume = 0.1
|
|||||||
admin = BafTac
|
admin = BafTac
|
||||||
music_folder = /home/fabian/music/mumblebot/
|
music_folder = /home/fabian/music/mumblebot/
|
||||||
tmp_folder = /tmp/
|
tmp_folder = /tmp/
|
||||||
|
ignored_folders = tmp
|
||||||
|
ignored_files = Thumbs.db
|
||||||
is_proxified = True
|
is_proxified = True
|
||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
@ -35,6 +37,7 @@ not_playing = Aucun stream en lecture
|
|||||||
bad_file = Bad file asked
|
bad_file = Bad file asked
|
||||||
no_file = Not file here
|
no_file = Not file here
|
||||||
bad_url = Bad URL asked
|
bad_url = Bad URL asked
|
||||||
|
multiple_matches = Track not found! Possible candidates:
|
||||||
|
|
||||||
help = Command available:
|
help = Command available:
|
||||||
<br />!play_file <path>
|
<br />!play_file <path>
|
||||||
|
49
mumbleBot.py
49
mumbleBot.py
@ -110,9 +110,20 @@ class MumbleBot:
|
|||||||
|
|
||||||
if command == self.config.get('command', 'play_file') and parameter:
|
if command == self.config.get('command', 'play_file') and parameter:
|
||||||
music_folder = self.config.get('bot', 'music_folder')
|
music_folder = self.config.get('bot', 'music_folder')
|
||||||
|
# sanitize "../" and so on
|
||||||
path = os.path.abspath(os.path.join(music_folder, parameter))
|
path = os.path.abspath(os.path.join(music_folder, parameter))
|
||||||
if path.startswith(music_folder) and os.path.isfile(path):
|
if path.startswith(music_folder):
|
||||||
self.launch_play_file(path)
|
if os.path.isfile(path):
|
||||||
|
self.launch_play_file(path)
|
||||||
|
else:
|
||||||
|
# try to do a partial match
|
||||||
|
matches = [file for file in self.__get_recursive_filelist_sorted(music_folder) if parameter in file]
|
||||||
|
if len(matches) == 1:
|
||||||
|
self.launch_play_file(music_folder + matches[0])
|
||||||
|
else:
|
||||||
|
msg = self.config.get('strings', 'multiple_matches') + '<br />'
|
||||||
|
msg += '<br />'.join(matches)
|
||||||
|
self.mumble.users[text.actor].send_message(msg)
|
||||||
else:
|
else:
|
||||||
self.mumble.users[text.actor].send_message(self.config.get('strings', 'bad_file'))
|
self.mumble.users[text.actor].send_message(self.config.get('strings', 'bad_file'))
|
||||||
|
|
||||||
@ -164,9 +175,27 @@ class MumbleBot:
|
|||||||
var.current_music = var.playlist[0]
|
var.current_music = var.playlist[0]
|
||||||
var.playlist.pop(0)
|
var.playlist.pop(0)
|
||||||
self.launch_next()
|
self.launch_next()
|
||||||
|
elif command == self.config.get('command', 'list'):
|
||||||
|
folder_path = self.config.get('bot', 'music_folder')
|
||||||
|
|
||||||
|
files = self.__get_recursive_filelist_sorted(folder_path)
|
||||||
|
if files :
|
||||||
|
self.mumble.users[text.actor].send_message('<br>'.join(files))
|
||||||
|
else :
|
||||||
|
self.mumble.users[text.actor].send_message(self.config.get('strings', 'no_file'))
|
||||||
else:
|
else:
|
||||||
self.mumble.users[text.actor].send_message(self.config.get('strings', 'bad_command'))
|
self.mumble.users[text.actor].send_message(self.config.get('strings', 'bad_command'))
|
||||||
|
|
||||||
|
def launch_play_file(self, path):
|
||||||
|
self.stop()
|
||||||
|
if self.config.getboolean('debug', 'ffmpeg'):
|
||||||
|
ffmpeg_debug = "debug"
|
||||||
|
else:
|
||||||
|
ffmpeg_debug = "warning"
|
||||||
|
command = ["ffmpeg", '-v', ffmpeg_debug, '-nostdin', '-i', path, '-ac', '1', '-f', 's16le', '-ar', '48000', '-']
|
||||||
|
self.thread = sp.Popen(command, stdout=sp.PIPE, bufsize=480)
|
||||||
|
self.playing = True
|
||||||
|
|
||||||
def is_admin(self, user):
|
def is_admin(self, user):
|
||||||
username = self.mumble.users[user]['name']
|
username = self.mumble.users[user]['name']
|
||||||
list_admin = self.config.get('bot', 'admin').split(';')
|
list_admin = self.config.get('bot', 'admin').split(';')
|
||||||
@ -272,6 +301,22 @@ class MumbleBot:
|
|||||||
channel = self.mumble.channels[self.mumble.users.myself['channel_id']]
|
channel = self.mumble.channels[self.mumble.users.myself['channel_id']]
|
||||||
channel.send_text_message(msg)
|
channel.send_text_message(msg)
|
||||||
|
|
||||||
|
def __get_recursive_filelist_sorted(self, path):
|
||||||
|
filelist = []
|
||||||
|
for root, dirs, files in os.walk(path):
|
||||||
|
relroot = root.replace(path, '')
|
||||||
|
if relroot in self.config.get('bot', 'ignored_folders'):
|
||||||
|
continue
|
||||||
|
if len(relroot):
|
||||||
|
relroot += '/'
|
||||||
|
for file in files:
|
||||||
|
if file in self.config.get('bot', 'ignored_files'):
|
||||||
|
continue
|
||||||
|
filelist.append(relroot + file)
|
||||||
|
|
||||||
|
filelist.sort()
|
||||||
|
return filelist
|
||||||
|
|
||||||
|
|
||||||
def start_web_interface():
|
def start_web_interface():
|
||||||
interface.web.run(port=8181, host="127.0.0.1")
|
interface.web.run(port=8181, host="127.0.0.1")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user