diff --git a/interface.py b/interface.py index db8e303..85878b2 100644 --- a/interface.py +++ b/interface.py @@ -2,12 +2,12 @@ from flask import Flask, render_template, request, redirect import variables as var +import util import os.path from os import listdir import random from werkzeug.utils import secure_filename - class ReverseProxied(object): '''Wrap the application in this middleware and configure the front-end server to add these headers, to let you quietly bind @@ -58,17 +58,33 @@ def init_proxy(): @web.route("/", methods=['GET', 'POST']) def index(): folder_path = var.music_folder - files = {} - dirs = [f for f in listdir(folder_path) if os.path.isdir(os.path.join(folder_path, f))] - for director in dirs: - files[director] = [f for f in listdir(folder_path + director) if os.path.isfile(os.path.join(folder_path + director, f))] + files = util.get_recursive_filelist_sorted(var.music_folder) + music_library = util.Dir(folder_path) + for file in files: + music_library.add_file(file) if request.method == 'POST': - if 'add_file' in request.form and ".." not in request.form['add_music']: - var.playlist.append((request.form['type'], request.form['add_music'])) - if 'add_folder' in request.form and ".." not in request.form['add_folder']: - dir_files = [("file", request.form['add_folder'] + '/' + i) for i in files[request.form['add_folder']]] - var.playlist.extend(dir_files) + print(request.form) + if 'add_file' in request.form and ".." not in request.form['add_file']: + item = ('file', request.form['add_file']) + var.playlist.append(item) + if ('add_folder' in request.form and ".." not in request.form['add_folder']) or ('add_folder_recursively' in request.form and ".." not in request.form['add_folder_recursively']) : + try: + folder = request.form['add_folder'] + except: + folder = request.form['add_folder_recursively'] + + if not folder.endswith('/'): + folder += '/' + + print('folder:', folder) + if 'add_folder_recursively' in request.form: + files = music_library.get_files_recursively(folder) + else: + files = music_library.get_files(folder) + files = list(map(lambda file: ('file', folder + '/' + file), files)) + print('Adding to playlist: ', files) + var.playlist.extend(files) elif 'delete_music' in request.form: try: var.playlist.remove("file", request.form['delete_music']) @@ -87,7 +103,8 @@ def index(): current_music=current_music, user=var.user, playlist=var.playlist, - all_files=files) + all_files=files, + music_library=music_library) @web.route('/download', methods=["POST"]) diff --git a/mumbleBot.py b/mumbleBot.py index d2aeb53..fc86c35 100644 --- a/mumbleBot.py +++ b/mumbleBot.py @@ -18,23 +18,17 @@ import variables as var import hashlib import youtube_dl import media +import util class MumbleBot: - def __init__(self): + def __init__(self, args): signal.signal(signal.SIGINT, self.ctrl_caught) self.config = configparser.ConfigParser(interpolation=None) self.config.read("configuration.ini", encoding='latin-1') - parser = argparse.ArgumentParser(description='Bot for playing radio stream on Mumble') - parser.add_argument("-s", "--server", dest="host", type=str, required=True, help="The server's hostame of a mumble server") - parser.add_argument("-u", "--user", dest="user", type=str, required=True, help="Username you wish, Default=abot") - parser.add_argument("-P", "--password", dest="password", type=str, default="", help="Password if server requires one") - parser.add_argument("-p", "--port", dest="port", type=int, default=64738, help="Port for the mumble server") - parser.add_argument("-c", "--channel", dest="channel", type=str, default="", help="Default chanel for the bot") - args = parser.parse_args() self.volume = self.config.getfloat('bot', 'volume') self.channel = args.channel @@ -64,11 +58,11 @@ class MumbleBot: self.nb_exit = 0 self.thread = None - interface.init_proxy() - - # t = threading.Thread(target=start_web_interface) - # t.daemon = True - # t.start() + if args.wi_addr: + interface.init_proxy() + tt = threading.Thread(target=start_web_interface, args=(args.wi_addr, args.wi_port)) + tt.daemon = True + tt.start() self.mumble = pymumble.Mumble(args.host, user=args.user, port=args.port, password=args.password, debug=self.config.getboolean('debug', 'mumbleConnection')) @@ -114,16 +108,14 @@ class MumbleBot: path = os.path.abspath(os.path.join(music_folder, parameter)) if path.startswith(music_folder): if os.path.isfile(path): - #self.launch_play_file(path) filename = path.replace(music_folder, '') var.playlist.append(["file", filename]) else: # try to do a partial match - matches = [file for file in self.__get_recursive_filelist_sorted(music_folder) if parameter.lower() in file.lower()] + matches = [file for file in util.get_recursive_filelist_sorted(music_folder) if parameter.lower() in file.lower()] if len(matches) == 0: self.mumble.users[text.actor].send_message(self.config.get('strings', 'no_file')) elif len(matches) == 1: - #self.launch_play_file(music_folder + matches[0]) var.playlist.append(["file", matches[0]]) else: msg = self.config.get('strings', 'multiple_matches') + '
' @@ -183,7 +175,7 @@ class MumbleBot: elif command == self.config.get('command', 'list'): folder_path = self.config.get('bot', 'music_folder') - files = self.__get_recursive_filelist_sorted(folder_path) + files = util.get_recursive_filelist_sorted(folder_path) if files : self.mumble.users[text.actor].send_message('
'.join(files)) else : @@ -248,8 +240,8 @@ class MumbleBot: command = ["ffmpeg", '-v', ffmpeg_debug, '-nostdin', '-i', path, '-ac', '1', '-f', 's16le', '-ar', '48000', '-'] self.thread = sp.Popen(command, stdout=sp.PIPE, bufsize=480) - var.current_music.append(title) - var.current_music.append(path) + #var.current_music[2] = title + #var.current_music[3] = path def download_music(self, url): url_hash = hashlib.md5(url.encode()).hexdigest() @@ -316,26 +308,25 @@ class MumbleBot: channel = self.mumble.channels[self.mumble.users.myself['channel_id']] 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(): - interface.web.run(port=8181, host="127.0.0.1") +def start_web_interface(addr, port): + print('Starting web interface on {}:{}'.format(addr, port)) + interface.web.run(port=port, host=addr) if __name__ == '__main__': - botamusique = MumbleBot() + parser = argparse.ArgumentParser(description='Bot for playing radio stream on Mumble') + + # Mumble arguments + parser.add_argument("-s", "--server", dest="host", type=str, required=True, help="The server's hostame of a mumble server") + parser.add_argument("-u", "--user", dest="user", type=str, required=True, help="Username you wish, Default=abot") + parser.add_argument("-P", "--password", dest="password", type=str, default="", help="Password if server requires one") + parser.add_argument("-p", "--port", dest="port", type=int, default=64738, help="Port for the mumble server") + parser.add_argument("-c", "--channel", dest="channel", type=str, default="", help="Default chanel for the bot") + + # web interface arguments + parser.add_argument('--wi-port', dest='wi_port', type=int, default=8181, help='Listening port of the web interface') + parser.add_argument('--wi-addr', dest='wi_addr', type=str, default=None, help='Listening address of the web interface') + + args = parser.parse_args() + botamusique = MumbleBot(args) diff --git a/templates/index.html b/templates/index.html index 2550d46..e180217 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,3 +1,28 @@ +{% macro dirlisting(path='') -%} + +{%- endmacro %} + @@ -38,19 +63,8 @@ {% endfor %} -
- {% for dir in all_files %} - {{ dir }} -
-
- - {% endfor %} +

Music library:

+ {{ dirlisting() }} @@ -61,4 +75,4 @@ - \ No newline at end of file + diff --git a/util.py b/util.py new file mode 100644 index 0000000..2fbcac1 --- /dev/null +++ b/util.py @@ -0,0 +1,87 @@ +#!/usr/bin/python3 + +import configparser +import os +import variables as var + +__CONFIG = configparser.ConfigParser(interpolation=None) +__CONFIG.read("configuration.ini", encoding='latin-1') + +def get_recursive_filelist_sorted(path): + filelist = [] + for root, dirs, files in os.walk(path): + relroot = root.replace(path, '') + if relroot != '' and relroot in __CONFIG.get('bot', 'ignored_folders'): + continue + if len(relroot): + relroot += '/' + for file in files: + if file in __CONFIG.get('bot', 'ignored_files'): + continue + filelist.append(relroot + file) + + filelist.sort() + return filelist + +class Dir(object): + def __init__(self, name): + self.name = name + self.subdirs = {} + self.files = [] + + def add_file(self, file): + if file.startswith(self.name + '/'): + file = file.replace(self.name + '/', '') + + if '/' in file: + # This file is in a subdir + subdir = file.split('/')[0] + if subdir in self.subdirs: + self.subdirs[subdir].add_file(file) + else: + self.subdirs[subdir] = Dir(subdir) + self.subdirs[subdir].add_file(file) + else: + self.files.append(file) + return True + + def get_subdirs(self, path=None): + if path and path != '': + subdir = path.split('/')[0] + if subdir in self.subdirs: + searchpath = '/'.join(path.split('/')[1::]) + return self.subdirs[subdir].get_subdirs(searchpath) + else: + return self.subdirs + + + def get_files(self, path=None): + if path and path != '': + subdir = path.split('/')[0] + if subdir in self.subdirs: + searchpath = '/'.join(path.split('/')[1::]) + return self.subdirs[subdir].get_files(searchpath) + else: + return self.files + + def get_files_recursively(self, path=None): + print('in get_files_recursively', path) + if path and path != '': + subdir = path.split('/')[0] + if subdir in self.subdirs: + searchpath = '/'.join(path.split('/')[1::]) + return self.subdirs[subdir].get_files_recursively(searchpath) + else: + files = self.files + + for key, val in self.subdirs.items(): + files.extend(map(lambda file: key + '/' + file,val.get_files_recursively())) + + return files + + def render_text(self, ident=0): + print('{}{}/'.format(' ' * (ident * 4), self.name)) + for key, val in self.subdirs.items(): + val.render_text(ident+1) + for file in self.files: + print('{}{}'.format(' ' * ((ident + 1)) * 4, file))